陨石动效完成!从零开始用Python编程制作飞机大战游戏 P07

'''编完之后回头看有看不懂代码的意义?来看看我的加注释版吧,标记了各个代码的意义,如有问题敬请指出'''
# Time : 2023/6/30 22:08
# !/user/bin/env python3
# -*- coding: utf-8 -*-
import random # 导入random库,进行随机运算
import pygame # 导入pygame库
import os # 导入os库进行文件操作
# 定义常量
WIDTH = 500 # 窗口的宽
HEIGHT = 600 # 窗口的高
WHITE = (255, 255, 255) # 白色RGB常量
GREEN = (0, 255, 0) # 绿色RGB常量
RED = (255, 0, 0) # 红石RGB常量
YELLOW = (255, 255, 0) # 黄色RGB常量
BLACK = (0, 0, 0) # 黑色RGB常量
# 游戏初始化
pygame.init() # 游戏初始化
pygame.mixer.init() # 音频初始化
screen = pygame.display.set_mode((WIDTH, HEIGHT)) # 设置界面宽高
pygame.display.set_caption('飞机大战(plane_war)') # 设置标题
clock = pygame.time.Clock() # 创建时钟对象
# 加载图片
background_img = pygame.image.load(os.path.join('img', 'background.png')).convert() # 背景图
player_img = pygame.image.load(os.path.join('img', 'player.png')).convert() # 加载飞机图片
rock_img = pygame.image.load(os.path.join('img', 'rock.png')).convert() # 加载陨石图片
bullet_img = pygame.image.load(os.path.join('img', 'bullet.png')).convert() # 加载子弹图片
rock_imges = [] # 创建陨石图片列表
for i in range(7): # for循环遍历
rock_imges.append(pygame.image.load(os.path.join('img', f'rock{i}.png')).convert())
# 格式化字符串,遍历出每一个图片素材并加进陨石图片列表
# 加载声音
shoot_sound = pygame.mixer.Sound(os.path.join('sound', 'shoot.wav')) # 加载射击音效
# 加载陨石爆炸音效,组成列表
expl_sounds = [
pygame.mixer.Sound(os.path.join('sound', 'expl0.wav')),
pygame.mixer.Sound(os.path.join('sound', 'expl1.wav'))
]
pygame.mixer.music.load(os.path.join('sound', 'background.ogg')) # 加载背景音乐
pygame.mixer.music.set_volume(0.5) # 调整背景音乐音量
class Player(pygame.sprite.Sprite): # 创建玩家类
def __init__(self): # 初始化函数
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(player_img, (50, 40)) # 角色设置成飞机图片,并调整图片大小
self.image.set_colorkey(BLACK) # 将素材中的黑色改透明
self.rect = self.image.get_rect() # 获得轮廓
self.radius = 23 # 设置半径
# pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.centerx = WIDTH / 2 # 设置x中心
self.rect.bottom = HEIGHT - 20 # 底部坐标
self.speedx = 8 # 设置x速度
def update(self): # 位置更新
key_pressed = pygame.key.get_pressed() # 键状态的列表
if key_pressed[pygame.K_RIGHT]: # 按下右方向键向右移动
self.rect.x += self.speedx
if key_pressed[pygame.K_LEFT]: # 检测按下左方向键
self.rect.x -= self.speedx # 将x减speedx,相当于向左移动
if self.rect.right > WIDTH: # 检测是否超过右边缘
self.rect.right = WIDTH # 条件达成则回到右边缘
if self.rect.left < 0: # 检测是否超过左边缘
self.rect.left = 0 # 条件达成则回到左边缘
def shoot(self):
bullet = Bullet(
self.rect.centerx, self.rect.centery) # 创建子弹对象
all_sprites.add(bullet) # 将子弹对象加进角色列表中
bullets.add(bullet) # 将子弹对象加进子弹角色列表中
shoot_sound.play() # 播放子弹发射的声音
class Rock(pygame.sprite.Sprite): # 创建陨石类
def __init__(self): # 初始化函数
pygame.sprite.Sprite.__init__(self)
self.image_origin = random.choice(rock_imges) # 将角色设置成陨石图片
self.image_origin.set_colorkey(BLACK) # 将素材中的黑色改为透明
self.image = self.image_origin.copy() # 拷贝原本图片到变量
self.rect = self.image.get_rect() # 获得轮廓
self.radius = self.rect.width / 2.3 # 设置半径
# pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = random.randrange(0, WIDTH - self.rect.width) # 设置陨石掉下来的x
self.rect.y = random.randrange(-180, -100) # 设置陨石初始y
# self.speedy = random.randrange(2, 5) # 随机设置掉下速度
self.speedy = 1
self.speedx = random.randrange(-3, 3) # 随机左右移动
self.rot_degree = random.randrange(-3, 3) # 随机设置累加速度的值
self.total_degree = 0 # 初始化旋转的速度
def rotate(self):
self.total_degree += self.rot_degree # 累加速度
self.total_degree = self.total_degree % 360 # 将旋转速递设为旋转速度除360的余数,以防旋转速递超过360
self.image = pygame.transform.rotate(self.image_origin, self.total_degree) # 图片转动
center = self.rect.center # 将中心点位置保存在变量中
self.rect = self.image.get_rect() # 获取长方形轮廓
self.rect.center = center # 将之前保存的中心点重新赋值给self.rect.center,以保持图像的中心位置不变。
def update(self): # 位置更新
self.rotate() # 调用陨石转动方法
self.rect.y += self.speedy # 陨石不断增加y坐标
self.rect.x += self.speedx # 陨石不断更新x坐标
if self.rect.top > HEIGHT or self.rect.left > WIDTH or self.rect.right < 0: # 判断轮廓超出边缘就重新回到上面
self.rect.x = random.randrange(0, WIDTH - self.rect.width) # 设置陨石掉下来的x
self.rect.y = random.randrange(-100, -40) # 设置陨石初始y
self.speedy = random.randrange(2, 10) # 随机设置掉下速度
self.speedx = random.randrange(-3, 3) # 随机左右移动
class Bullet(pygame.sprite.Sprite): # 创建子弹类
def __init__(self, x, y): # 初始化函数
pygame.sprite.Sprite.__init__(self)
self.image = bullet_img # 将角色设置成子弹图片
self.image.set_colorkey(BLACK) # 将素材中的黑色改为透明
self.rect = self.image.get_rect() # 获得轮廓
self.rect.x = x # 设置子弹初始的的x,与飞机x一样
self.rect.y = y # 设置子弹初始的的y,与飞机y一样
self.speedy = -10 # 子弹飞行速度(y变化的跨度)
def update(self): # 位置更新
self.rect.y += self.speedy # 子弹不断增加y坐标
if self.rect.bottom < 0: # 检测子弹超过边缘,则清除
self.kill() # 清除角色
all_sprites = pygame.sprite.Group() # 创建所有角色表
rocks = pygame.sprite.Group() # 创建陨石角色表
bullets = pygame.sprite.Group() # 创建子弹角色表
player = Player() # 创建玩家类对象
all_sprites.add(player) # 将创建的玩家类对象放入角色列表
pygame.mixer.music.play(-1) # 循环播放背景音乐
for item in range(10): # 循环10次,共创建10个陨石对象
rock = Rock() # 创建陨石对象
all_sprites.add(rock) # add:增加,将陨石对象加进角色列表
rocks.add(rock) # 将陨石对象加进陨石列表
running = True # 定义工具变量用于控制循环
while running: # 主循环,循环至关闭窗口
clock.tick(60) # 设置帧数
for event in pygame.event.get(): # 获取事件
if event.type == pygame.QUIT: # 判断是否为退出事件
running = False # 如果是,则将变量设为False,停止循环
elif event.type == pygame.KEYDOWN: # 检测有按键按下
if event.key == pygame.K_SPACE: # 判断是否为空格
player.shoot() # 如果是,则调用射击函数射出子弹
all_sprites.update() # 调用角色池里面的位置更新方法
hits_rock_and_bullet = pygame.sprite.groupcollide(rocks, bullets, True, True) # 检测陨石是否碰到子弹,
# 如果碰到则删除并新建一个陨石
for hit in hits_rock_and_bullet:
random.choice(expl_sounds).play() # 播放陨石被击碎的音频
r = Rock() # 新建一个陨石对象并赋值到r
all_sprites.add(r) # 在所有角色表中增加陨石对象
rocks.add(r) # 在陨石角色表中增加陨石对象
hits_rock_and_player = pygame.sprite.spritecollide(player, rocks, False, pygame.sprite.collide_circle) # 检测陨石碰到飞机
if hits_rock_and_player:
running = False # 将工具变量设为False,停止游戏
screen.fill(BLACK) # 设置窗口界面颜色,显示画面
screen.blit(background_img, (0, 0)) # 填充背景图片
all_sprites.draw(screen) # 绘制角色
pygame.display.update() # 更新状态
pygame.quit() # 退出