Pygame实现空格键单发子弹:避免连发与游戏循环冻结
解决Pygame中按空格键连续发射子弹的问题
嘿,我明白你遇到的麻烦了——用time.sleep()确实会搞砸整个游戏循环,因为它会让整个程序彻底暂停,而不是只限制子弹发射的频率。咱们来搞定这个问题,这里有两种靠谱的解决方案:
方法1:改用键盘事件触发(单次发射)
你现在用的pygame.key.get_pressed()会在按住空格键的每一个游戏帧都返回True,所以每帧都会生成一颗子弹,自然变成了连续流。换成KEYDOWN事件就不一样了,它只会在按键第一次按下的时候触发一次,完美实现“按一次发一颗”的效果。
修改你的游戏循环代码,把发射子弹的逻辑移到事件监听的循环里:
def game_loop(): global pause x = (display_width * 0.2) y = (display_height * 0.2) x_change = 0 y_change = 0 blob_speed = 3 velocity = [2, 2] pos_x = display_width/1.2 pos_y = display_height/1.2 gameExit = False while not gameExit: for event in pygame.event.get():#monitors hardware movement/ clicks if event.type == pygame.QUIT: pygame.quit() quit() # 在这里添加空格键的KEYDOWN事件处理 if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: bullets.append([x+25, y+24]) if event.key == pygame.K_p: pause = True paused() # 剩下的代码保持不变... pos_x += velocity[0] pos_y += velocity[1] if pos_x + blob_width > display_width or pos_x < 601: velocity[0] = -velocity[0] if pos_y + blob_height > display_height or pos_y < 0: velocity[1] = -velocity[1] keys = pygame.key.get_pressed() for b in range(len(bullets)): bullets[b][0] += 6 for bullet in bullets: if bullet[0] > 1005: bullets.remove(bullet) # 移除原来用keys检测空格键的代码 # if keys[pygame.K_SPACE]: # bullets.append([x+25, y+24]) # 剩下的移动逻辑保持不变... if x < 0: x = 0 if keys[pygame.K_a]: x_change = -blob_speed if x > 401 - blob_width: x = 401 - blob_width if keys[pygame.K_d]: x_change = blob_speed # 移除原来用keys检测K_p的代码,已经移到事件里了 # if keys[pygame.K_p]: # pause = True # paused() # 剩下的代码继续保持不变... if keys[pygame.K_a] and keys[pygame.K_d]: x_change = 0 if not keys[pygame.K_a] and not keys[pygame.K_d]: x_change = 0 if y < 0: y = 0 if keys[pygame.K_w]: y_change = -blob_speed if y > display_height - blob_height: y = display_height - blob_height if keys[pygame.K_s]: y_change = blob_speed if keys[pygame.K_w] and keys[pygame.K_s]: y_change = 0 if not keys[pygame.K_w] and not keys[pygame.K_s]: y_change = 0 x += x_change y += y_change gameDisplay.fill(blue) #changes background surface pygame.draw.line(gameDisplay, black, (601, display_height), (601, 0), 3) pygame.draw.line(gameDisplay, black, (401, display_height), (401, 0), 3) blob(pos_x, pos_y) blob(x, y) for bullet in bullets: gameDisplay.blit(bulletpicture, pygame.Rect(bullet[0], bullet[1], 0, 0)) pygame.display.update() #update screen clock.tick(120)#moves frame on (fps in parameters)
这样修改后,每次按下空格键只会发射一颗子弹,完全不会触发连续流,也不会冻结游戏。
方法2:添加冷却计时器(支持连射但有间隔)
如果你想要按住空格键可以连续发射,但不想每秒120发(毕竟你的帧率是120),可以加一个冷却计时器,控制两次发射的最小间隔。这种方法不会阻塞游戏循环,只会限制子弹生成的频率。
在game_loop函数开头初始化一个记录上次发射时间的变量,然后在检测空格键的时候判断时间差:
def game_loop(): global pause x = (display_width * 0.2) y = (display_height * 0.2) x_change = 0 y_change = 0 blob_speed = 3 velocity = [2, 2] pos_x = display_width/1.2 pos_y = display_height/1.2 gameExit = False # 初始化上次发射时间,用pygame的时间戳(毫秒) last_shot_time = 0 # 设置冷却时间,比如200毫秒(每秒5发) shot_cooldown = 200 while not gameExit: for event in pygame.event.get():#monitors hardware movement/ clicks if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.K_p: pause = True paused() pos_x += velocity[0] pos_y += velocity[1] if pos_x + blob_width > display_width or pos_x < 601: velocity[0] = -velocity[0] if pos_y + blob_height > display_height or pos_y < 0: velocity[1] = -velocity[1] keys = pygame.key.get_pressed() for b in range(len(bullets)): bullets[b][0] += 6 for bullet in bullets: if bullet[0] > 1005: bullets.remove(bullet) # 检测空格键并判断冷却时间 current_time = pygame.time.get_ticks() if keys[pygame.K_SPACE] and current_time - last_shot_time > shot_cooldown: bullets.append([x+25, y+24]) last_shot_time = current_time # 剩下的移动逻辑保持不变... if x < 0: x = 0 if keys[pygame.K_a]: x_change = -blob_speed if x > 401 - blob_width: x = 401 - blob_width if keys[pygame.K_d]: x_change = blob_speed if keys[pygame.K_p]: pause = True paused() if keys[pygame.K_a] and keys[pygame.K_d]: x_change = 0 if not keys[pygame.K_a] and not keys[pygame.K_d]: x_change = 0 if y < 0: y = 0 if keys[pygame.K_w]: y_change = -blob_speed if y > display_height - blob_height: y = display_height - blob_height if keys[pygame.K_s]: y_change = blob_speed if keys[pygame.K_w] and keys[pygame.K_s]: y_change = 0 if not keys[pygame.K_w] and not keys[pygame.K_s]: y_change = 0 x += x_change y += y_change gameDisplay.fill(blue) #changes background surface pygame.draw.line(gameDisplay, black, (601, display_height), (601, 0), 3) pygame.draw.line(gameDisplay, black, (401, display_height), (401, 0), 3) blob(pos_x, pos_y) blob(x, y) for bullet in bullets: gameDisplay.blit(bulletpicture, pygame.Rect(bullet[0], bullet[1], 0, 0)) pygame.display.update() #update screen clock.tick(120)#moves frame on (fps in parameters)
你可以调整shot_cooldown的值来控制发射频率,比如设为500就是每秒2发,完全不会影响游戏的流畅度。
内容的提问来源于stack exchange,提问作者Rokas98765
相关产品推荐
相关产品推荐

