开发仿Line游戏:实现可变振幅无间隙水平波形的问题
问题描述
我想开发一款类似Line的游戏,但采用水平波形而非垂直波形。目前遇到的问题是,改变波形振幅(后续还要调整频率)后,无法让波形保持连续无间隙。
以下是我目前的实现代码:
import pygame import pygame.gfxdraw import math import time DISPLAY_W, DISPLAY_H = 400, 800 clock = pygame.time.Clock() pygame.init() SCREEN = pygame.Surface((DISPLAY_W, DISPLAY_H)) GAME_DISPLAY = pygame.display.set_mode((DISPLAY_W, DISPLAY_H)) class Line(): def __init__(self): self.pointsList = [0]*800 self.listIndex = 0 def game(self): while True: clock.tick(60) SCREEN.fill((0, 0, 0)) self.listIndex += +1 self.generateWave() self.drawWave() for event in pygame.event.get(): if (event.type == pygame.QUIT): quit() pygame.display.update() GAME_DISPLAY.blit(SCREEN, (0, 0)) def drawWave(self): for Y_CORD in range(len(self.pointsList)): pygame.gfxdraw.pixel( GAME_DISPLAY, self.pointsList[Y_CORD]-55, DISPLAY_H-Y_CORD, (255, 255, 255)) pygame.gfxdraw.pixel( GAME_DISPLAY, self.pointsList[Y_CORD]-350, DISPLAY_H-Y_CORD, (255, 255, 255)) def generateWave(self): waveAmplitude = 50 waveFrequency = 1 XCord = int((DISPLAY_H/2) + waveAmplitude*math.sin( waveFrequency * ((float(0)/-DISPLAY_W)*(2*math.pi) + (time.time())))) if self.pointsList[-1] != 0: self.pointsList.pop(0) self.pointsList.append(XCord) else: self.pointsList[self.listIndex] = XCord if __name__ == "__main__": game = Line() game.game()
我曾尝试新增修改振幅的函数,但会导致波形出现间隙:
解决方案
问题出在你当前的波形生成逻辑:每次只生成单个点,通过滚动列表来更新波形。这种方式在参数(振幅/频率)变化时,新生成的点和历史点不属于同一条连续的函数曲线,自然会出现断层。
换个思路,每一帧重新计算所有点的位置,让每个点的坐标由它在Y轴的位置和累计的时间偏移共同决定,这样无论参数怎么变,波形都是连续的函数曲线。
修改后的完整代码:
import pygame import pygame.gfxdraw import math DISPLAY_W, DISPLAY_H = 400, 800 clock = pygame.time.Clock() pygame.init() SCREEN = pygame.Surface((DISPLAY_W, DISPLAY_H)) GAME_DISPLAY = pygame.display.set_mode((DISPLAY_W, DISPLAY_H)) class Line(): def __init__(self): self.pointsList = [0]*DISPLAY_H self.time_offset = 0 # 累计时间偏移,代替实时时间避免波动 self.wave_amplitude = 50 # 可动态修改的振幅 self.wave_frequency = 1 # 可动态修改的频率 def game(self): while True: dt = clock.tick(60) / 1000 # 每帧的时间间隔(秒) self.time_offset += dt # 更新累计时间偏移 SCREEN.fill((0, 0, 0)) self.generateWave() self.drawWave() # 示例:按上下方向键修改振幅 keys = pygame.key.get_pressed() if keys[pygame.K_UP] and self.wave_amplitude < 150: self.wave_amplitude += 1 if keys[pygame.K_DOWN] and self.wave_amplitude > 10: self.wave_amplitude -= 1 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() GAME_DISPLAY.blit(SCREEN, (0, 0)) pygame.display.update() def drawWave(self): for y in range(len(self.pointsList)): x = self.pointsList[y] # 绘制两条波形线 pygame.gfxdraw.pixel(GAME_DISPLAY, x - 55, DISPLAY_H - y, (255, 255, 255)) pygame.gfxdraw.pixel(GAME_DISPLAY, x - 350, DISPLAY_H - y, (255, 255, 255)) def generateWave(self): # 遍历每个Y坐标,计算对应的X值 for y in range(DISPLAY_H): # 将Y坐标归一化到0~2π范围,结合时间偏移计算正弦值 normalized_y = (y / DISPLAY_H) * 2 * math.pi x = int((DISPLAY_W / 2) + self.wave_amplitude * math.sin(self.wave_frequency * normalized_y + self.time_offset)) self.pointsList[y] = x if __name__ == "__main__": game = Line() game.game()
关键修改说明
- 用累计时间偏移代替实时时间:避免
time.time()的系统时间波动影响,保证波形平滑滚动。 - 全量计算波形点:每一帧重新计算所有Y坐标对应的X值,确保波形始终是连续的正弦函数曲线。
- 支持动态参数调整:示例中加入了上下方向键修改振幅的逻辑,你可以扩展为修改频率的功能,此时波形依然保持连续无间隙。
内容的提问来源于stack exchange,提问作者Mahfouz
相关产品推荐
相关产品推荐

