Python 根据BPM和每次测量的节拍旋转一条线
我正在创建一个基于圆的鼓机,需要一个雷达一样的线以由节奏调制的速度旋转,周期等于每小节拍数。通过这种方式,它以一定的速度旋转,并在一次测量的等效持续时间内完成一次旋转Python 根据BPM和每次测量的节拍旋转一条线,python,python-3.x,Python,Python 3.x,我正在创建一个基于圆的鼓机,需要一个雷达一样的线以由节奏调制的速度旋转,周期等于每小节拍数。通过这种方式,它以一定的速度旋转,并在一次测量的等效持续时间内完成一次旋转 .5bps * 4bbpm = 2spm 我很难用代数建模。据我所知: 每拍秒数=60秒/bpm 60secs/120bpm = .5spb Spb*bbpm(每小节拍数)产生spm(每小节秒数) 这就是我被困的地方。我知道在2秒钟内,为了完成一个四拍的测量,线需要旋转360度。我很难对此进行建模,更不用说将其提交到代码
.5bps * 4bbpm = 2spm
我很难用代数建模。据我所知:
每拍秒数=60秒/bpm
60secs/120bpm = .5spb
Spb*bbpm(每小节拍数)产生spm(每小节秒数)
这就是我被困的地方。我知道在2秒钟内,为了完成一个四拍的测量,线需要旋转360度。我很难对此进行建模,更不用说将其提交到代码中了
我开始猜测的是,将帧率除以spm,得到每秒每测量帧数。然而,我试图将其除以360,以确定每次测量每帧每秒的度数,但与真正的节拍器相比,我的滴答臂是不准确的
如有任何见解,将不胜感激
我的代码:
import pygame
from pygame.locals import *
import math
SIZE = 800, 800
pygame.init()
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
framerate = 40
done = False
bpm = int(input("Enter a BPM: ")) #beats per minute
bbpm = int(input("How many Beats Per Measure?: ")) #beats per measure
spb = (60/bpm)
spm = spb*bbpm #speed per measure; a measure is made every x seconds
frames = (framerate/spm)
rev = 360/frames # degrees per frame
deg = 0
secs = 0
while not done:
screen.fill(0)
for e in pygame.event.get():
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
done = True
break
line = (400,400)
line_len = 400
x = line[0] + math.cos(math.radians(deg)) * line_len
y = line[1] + math.sin(math.radians(deg)) * line_len
# then render the line ->(x,y)
pygame.draw.line(screen, Color("red"), line, (x,y), 1)
pygame.display.flip()
print(secs)
print(deg)
deg+=rev
secs+= 1
clock.tick(framerate)
1) 在运动渲染中,切勿依赖硬编码帧速率或任何恒定的每帧速度。测量自某个参考位置起的时间增量(例如,在本例中,自上次转弯或初始),并根据时间增量计算当前位置。即使启用vsync,您也可能会错过某些帧,并且帧速率并不总是等于60
2) 不要基于假定的帧率同步延迟渲染,而是使用硬件vsync(在本例中使用pygame.display.set_模式(…,pygame.HWSURFACE | pygame.DOUBLEBUF)
)
你的计算似乎是正确的。不需要以度为单位将转数转换为弧度
更正的示例:
import pygame
from pygame.locals import *
import math
SIZE = 800, 800
pygame.init()
screen = pygame.display.set_mode(SIZE, pygame.HWSURFACE | pygame.DOUBLEBUF)
done = False
bpm = 120# int(input("Enter a BPM: ")) #beats per minute
bbpm = 4# int(input("How many Beats Per Measure?: ")) #beats per measure
spm = bbpm*60/bpm #seconds per measure; a measure is made every x seconds
turnsPerMs = 1/(1000*spm) #turns per millisecond
startTime = pygame.time.get_ticks()
color = Color("red")
lineStart = (400,400)
line_len = 400
while not done:
for e in pygame.event.get():
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
done = True
break
screen.fill(0)
pygame.draw.circle(screen, color, lineStart, line_len, 2)
timeDelta = pygame.time.get_ticks() - startTime
revDelta = timeDelta*turnsPerMs;
deltaRadian = revDelta*2*math.pi;
x = lineStart[0] + math.cos(deltaRadian) * line_len
y = lineStart[1] + math.sin(deltaRadian) * line_len
# then render the line ->(x,y)
pygame.draw.line(screen, color, lineStart, (x,y), 1)
pygame.display.flip()
1) 在运动渲染中,切勿依赖硬编码帧速率或任何恒定的每帧速度。测量自某个参考位置起的时间增量(例如,在本例中,自上次转弯或初始),并根据时间增量计算当前位置。即使启用vsync,您也可能会错过某些帧,并且帧速率并不总是等于60
2) 不要基于假定的帧率同步延迟渲染,而是使用硬件vsync(在本例中使用pygame.display.set_模式(…,pygame.HWSURFACE | pygame.DOUBLEBUF)
)
你的计算似乎是正确的。不需要以度为单位将转数转换为弧度
更正的示例:
import pygame
from pygame.locals import *
import math
SIZE = 800, 800
pygame.init()
screen = pygame.display.set_mode(SIZE, pygame.HWSURFACE | pygame.DOUBLEBUF)
done = False
bpm = 120# int(input("Enter a BPM: ")) #beats per minute
bbpm = 4# int(input("How many Beats Per Measure?: ")) #beats per measure
spm = bbpm*60/bpm #seconds per measure; a measure is made every x seconds
turnsPerMs = 1/(1000*spm) #turns per millisecond
startTime = pygame.time.get_ticks()
color = Color("red")
lineStart = (400,400)
line_len = 400
while not done:
for e in pygame.event.get():
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
done = True
break
screen.fill(0)
pygame.draw.circle(screen, color, lineStart, line_len, 2)
timeDelta = pygame.time.get_ticks() - startTime
revDelta = timeDelta*turnsPerMs;
deltaRadian = revDelta*2*math.pi;
x = lineStart[0] + math.cos(deltaRadian) * line_len
y = lineStart[1] + math.sin(deltaRadian) * line_len
# then render the line ->(x,y)
pygame.draw.line(screen, color, lineStart, (x,y), 1)
pygame.display.flip()
非常感谢。我理解用时间增量来影响运动。我想我知道你将revDelta乘以2pi得到一个弧度值(deltaRadian)。我正在努力理解当前的revDelta变量。从计算开始到当前力矩的时间变化乘以毫秒内的圈数。这就给出了手臂在经过的时间段内应该转多少圈,对吗?然后Deltaradian将这个值转换成弧度。我理解正确吗?是的。非常简单:对于线性运动
距离=速度*时间
(对于角度=角速度*时间
)。所以,我们只需计算循环前和循环中的角速度,将经过的时间乘以速度,就可以得到最终的角度。为了示例的清晰性,我定义了以圈数/毫秒为单位的角速度,并在角度计算之前将其转换为弧度。事实上,您可以用弧度来预先计算直线,而不是revPerMs:radPerMs=(2*math.pi)(/1000*spm)
,那么弧度内循环的(距离)角度将是radDelta=radPerMs*timeDelta
和x=…cos(radDelta)
谢谢!我理解用时间增量来影响运动。我想我知道你将revDelta乘以2pi得到一个弧度值(deltaRadian)。我正在努力理解当前的revDelta变量。从计算开始到当前力矩的时间变化乘以毫秒内的圈数。这就给出了手臂在经过的时间段内应该转多少圈,对吗?然后Deltaradian将这个值转换成弧度。我理解正确吗?是的。非常简单:对于线性运动距离=速度*时间
(对于角度=角速度*时间
)。所以,我们只需计算循环前和循环中的角速度,将经过的时间乘以速度,就可以得到最终的角度。为了示例的清晰性,我定义了以圈数/毫秒为单位的角速度,并在角度计算之前将其转换为弧度。事实上,您可以用弧度来预先计算直线,而不是revPerMs:radPerMs=(2*math.pi)(/1000*spm)
,那么弧度内循环的(距离)角度将是radDelta=radPerMs*timeDelta
和x=…cos(radDelta)