如何在Pygame中实现计时器,添加飞船被击中后10秒禁移功能?
问题描述
我是Pygame编程新手,跟着教程做完了一款太空侵略者游戏,现在想给游戏加新功能:当敌人发射的激光(已有对应图片)击中飞船时,飞船10秒内无法移动。同时想搞懂Pygame里怎么用时间和做计时器。
游戏概述
这款太空侵略者游戏的核心逻辑:
- 敌人沿X轴移动并缓慢下落
- 底部飞船可沿X轴移动,能射击子弹消灭敌人
- 敌人被消灭后会重生,敌人抵达底部则游戏结束
现有代码
# importing modules import pygame import random import math from pygame import mixer # initialize pygame pygame.init() # creating a window screen = pygame.display.set_mode((800, 600)) # Background Music mixer.music.load('background.wav') mixer.music.play(-1) # Background bg_img = pygame.image.load("background3.png") bg = pygame.transform.scale(bg_img, (800, 600)) # Title and Icon pygame.display.set_caption("Space Shooters") icon = pygame.image.load('spaceship.png') pygame.display.set_icon(icon) # Player player = pygame.image.load('spaceship2.png') playerX = 370 playerY = 500 playerX_change = 0 # Enemy enemyImg = [] enemyX = [] enemyY = [] enemyX_change = [] enemyY_change = [] num_of_enemies = 6 for i in range(num_of_enemies): enemyImg.append(pygame.image.load('enemy.png')) enemyX.append(random.randint(6, 730)) enemyY.append(random.randint(45, 150)) enemyX_change.append(0.3) enemyY_change.append(40) # Bullet # Ready - The bullet can't be seen # Fire - The bullet has been shot bulletImg = pygame.image.load('bullet.png') bulletX = 0 bulletY = 480 bulletX_change = 0 bulletY_change = 1.5 bullet_state = "Ready" # Score score_value = 0 font = pygame.font.Font('freesansbold.ttf', 32) textX = 10 textY = 10 # Game Over over_font = pygame.font.Font('freesansbold.ttf', 64) # Function for displaying text def show_score(x, y): score = font.render("Score : " + str(score_value), True, (255, 255, 255)) screen.blit(score, (x, y)) def game_over_text(): over_text = over_font.render("GAME OVER", True, (255, 255, 255)) screen.blit(over_text, (200, 250)) # Defining and drawing spaceship def spaceship(x, y): screen.blit(player, (x, y)) # Defining and drawing enemy def enemy(x, y, i): screen.blit(enemyImg[i], (x, y)) def fire_bullet(x, y): global bullet_state bullet_state = "Fire" screen.blit(bulletImg, (x + 16, y + 10)) def Iscollision(enemyX, enemyY, bulletX, bulletY): distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2))) if distance < 27: return True else: return False # making the game window run endlessly and game loop running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Keystroke check (right, left) if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: playerX_change = -0.3 if event.key == pygame.K_RIGHT: playerX_change = 0.3 if event.key == pygame.K_SPACE: # Checking whether bullet is there on screen, if not making it ready, if yes disabling spacebar if bullet_state == "Ready": # Get the current X cordinate of spaceship bulletX = playerX fire_bullet(bulletX, bulletY) bullet_sound = mixer.Sound('laser.wav') bullet_sound.play() if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: playerX_change = 0 # Changing X coordinates to move spaceship playerX += playerX_change if playerX <= 6: playerX = 6 elif playerX >= 730: playerX = 730 screen.fill(0) screen.blit(bg, (0, 0)) # Enemy Movement for i in range(num_of_enemies): # Game Over if enemyY[i] > 440: for j in range(num_of_enemies): enemyY[j] = 2000 game_over_text() break for i in range(num_of_enemies): enemyX[i] += enemyX_change[i] if enemyX[i] <= 6: enemyX_change[i] = 0.3 enemyY[i] += enemyY_change[i] elif enemyX[i] >= 730: enemyX_change[i] = -0.3 enemyY[i] += enemyY_change[i] # Collision collision = Iscollision(enemyX[i], enemyY[i], bulletX, bulletY) # if collision and if collision is true are both the same if collision: collision_sound = mixer.Sound('explosion.wav') collision_sound.play() bulletY = 480 bullet_state = "Ready" score_value += 1 enemyX[i] = random.randint(6, 730) enemyY[i] = random.randint(45, 150) enemy(enemyX[i], enemyY[i], i) # Deleting each frame of enemy moving so that it runs smoothly # Bullet Movement if bulletY <= 0: bulletY = 480 bullet_state = "Ready" if bullet_state == "Fire": fire_bullet(bulletX, bulletY) bulletY -= bulletY_change spaceship(playerX, playerY) show_score(textX, textY) # updating display pygame.display.update()
需求说明
- 添加敌人激光系统:敌人随机发射激光(已有激光图片)
- 激光击中飞船后,飞船10秒内无法移动
- 理解Pygame中时间管理和计时器的实现方式
解决方案
一、Pygame时间与计时器基础
Pygame中常用pygame.time.get_ticks()获取从初始化到当前的毫秒数(1秒=1000毫秒),通过记录两个时间点的差值来计算时间间隔,这是实现计时器的核心方法。
二、分步实现功能
1. 添加敌人激光的相关变量
在敌人变量定义后,添加激光的全局变量:
# Enemy Laser enemy_laserImg = pygame.image.load('enemy_laser.png') # 替换成你的激光图片路径 enemy_lasers = [] # 存储所有活跃的敌人激光,每个元素是(x, y)坐标和移动速度 enemy_laser_speed = 0.8 # 敌人激光下落速度 laser_cooldown = 2000 # 敌人发射激光的冷却时间(毫秒) last_laser_time = 0 # 记录上次发射激光的时间
2. 添加敌人发射激光的逻辑
在游戏循环里,每次循环检查是否到了发射激光的时间:
# 敌人随机发射激光 current_time = pygame.time.get_ticks() if current_time - last_laser_time > laser_cooldown: # 随机选一个敌人发射激光 random_enemy = random.randint(0, num_of_enemies - 1) enemy_x = enemyX[random_enemy] enemy_y = enemyY[random_enemy] enemy_lasers.append([enemy_x + 16, enemy_y + 32]) # 调整坐标让激光从敌人中心发出 last_laser_time = current_time # 可以添加发射激光的音效 # enemy_laser_sound = mixer.Sound('enemy_laser.wav') # enemy_laser_sound.play()
3. 添加激光移动和碰撞检测逻辑
在子弹移动逻辑后添加:
# 敌人激光移动与碰撞检测 for laser in enemy_lasers[:]: # 用[:]复制列表,避免循环中修改列表出错 laser[1] += enemy_laser_speed # 绘制激光 screen.blit(enemy_laserImg, (laser[0], laser[1])) # 激光超出屏幕则移除 if laser[1] > 600: enemy_lasers.remove(laser) # 检测激光是否击中飞船 distance = math.sqrt((math.pow(laser[0] - playerX, 2)) + (math.pow(laser[1] - playerY, 2))) if distance < 27: enemy_lasers.remove(laser) # 触发飞船无法移动的状态 player_stunned = True stunned_start_time = current_time # 记录被击中的时间 # 可以添加被击中的音效 # hit_sound = mixer.Sound('hit.wav') # hit_sound.play()
4. 添加飞船被眩晕的状态管理
首先在玩家变量定义处添加状态变量:
# Player player = pygame.image.load('spaceship2.png') playerX = 370 playerY = 500 playerX_change = 0 player_stunned = False # 标记是否被眩晕 stunned_duration = 10000 # 眩晕时长10秒(10000毫秒) stunned_start_time = 0 # 记录开始眩晕的时间
然后修改玩家移动的按键逻辑,只有在未被眩晕时才响应移动:
# Keystroke check (right, left) if event.type == pygame.KEYDOWN: if not player_stunned: # 未被眩晕时才允许移动 if event.key == pygame.K_LEFT: playerX_change = -0.3 if event.key == pygame.K_RIGHT: playerX_change = 0.3 if event.key == pygame.K_SPACE: if bullet_state == "Ready": bulletX = playerX fire_bullet(bulletX, bulletY) bullet_sound = mixer.Sound('laser.wav') bullet_sound.play() if event.type == pygame.KEYUP: if not player_stunned: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: playerX_change = 0
最后在游戏循环里检查眩晕是否结束:
# 检查眩晕状态是否结束 current_time = pygame.time.get_ticks() if player_stunned and current_time - stunned_start_time > stunned_duration: player_stunned = False
5. 修复原代码的缩进问题
原代码中playerX += playerX_change、边界判断、screen.fill(0)等代码都在while running循环外面,这会导致逻辑错误,需要把这些代码缩进,放到循环内部。
三、完整修改后的代码
# importing modules import pygame import random import math from pygame import mixer # initialize pygame pygame.init() # creating a window screen = pygame.display.set_mode((800, 600)) # Background Music mixer.music.load('background.wav') mixer.music.play(-1) # Background bg_img = pygame.image.load("background3.png") bg = pygame.transform.scale(bg_img, (800, 600)) # Title and Icon pygame.display.set_caption("Space Shooters") icon = pygame.image.load('spaceship.png') pygame.display.set_icon(icon) # Player player = pygame.image.load('spaceship2.png') playerX = 370 playerY = 500 playerX_change = 0 player_stunned = False stunned_duration = 10000 stunned_start_time = 0 # Enemy enemyImg = [] enemyX = [] enemyY = [] enemyX_change = [] enemyY_change = [] num_of_enemies = 6 for i in range(num_of_enemies): enemyImg.append(pygame.image.load('enemy.png')) enemyX.append(random.randint(6, 730)) enemyY.append(random.randint(45, 150)) enemyX_change.append(0.3) enemyY_change.append(40) # Enemy Laser enemy_laserImg = pygame.image.load('enemy_laser.png') # 替换为你的激光图片路径 enemy_lasers = [] enemy_laser_speed = 0.8 laser_cooldown = 2000 last_laser_time = 0 # Bullet bulletImg = pygame.image.load('bullet.png') bulletX = 0 bulletY = 480 bulletX_change = 0 bulletY_change = 1.5 bullet_state = "Ready" # Score score_value = 0 font = pygame.font.Font('freesansbold.ttf', 32) textX = 10 textY = 10 # Game Over over_font = pygame.font.Font('freesansbold.ttf', 64) def show_score(x, y): score = font.render("Score : " + str(score_value), True, (255, 255, 255)) screen.blit(score, (x, y)) def game_over_text(): over_text = over_font.render("GAME OVER", True, (255, 255, 255)) screen.blit(over_text, (200, 250)) def spaceship(x, y): screen.blit(player, (x, y)) def enemy(x, y, i): screen.blit(enemyImg[i], (x, y)) def fire_bullet(x, y): global bullet_state bullet_state = "Fire" screen.blit(bulletImg, (x + 16, y + 10)) def Iscollision(enemyX, enemyY, bulletX, bulletY): distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2))) return distance < 27 running = True while running: current_time = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Keystroke check (right, left) if event.type == pygame.KEYDOWN: if not player_stunned: if event.key == pygame.K_LEFT: playerX_change = -0.3 if event.key == pygame.K_RIGHT: playerX_change = 0.3 if event.key == pygame.K_SPACE: if bullet_state == "Ready": bulletX = playerX fire_bullet(bulletX, bulletY) bullet_sound = mixer.Sound('laser.wav') bullet_sound.play() if event.type == pygame.KEYUP: if not player_stunned: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: playerX_change = 0 # Check if stunned state is over if player_stunned and current_time - stunned_start_time > stunned_duration: player_stunned = False # Enemy laser spawn logic if current_time - last_laser_time > laser_cooldown: random_enemy_idx = random.randint(0, num_of_enemies - 1) laser_x = enemyX[random_enemy_idx] + 16 laser_y = enemyY[random_enemy_idx] + 32 enemy_lasers.append([laser_x, laser_y]) last_laser_time = current_time # Player movement if not player_stunned: playerX += playerX_change # Player boundary check if playerX <= 6: playerX = 6 elif playerX >= 730: playerX = 730 screen.fill(0) screen.blit(bg, (0, 0)) # Enemy Movement and collision game_over = False for i in range(num_of_enemies): if enemyY[i] > 440: game_over = True break enemyX[i] += enemyX_change[i] if enemyX[i] <= 6: enemyX_change[i] = 0.3 enemyY[i] += enemyY_change[i] elif enemyX[i] >= 730:
相关产品推荐
相关产品推荐

