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)