第一部分:常量
WINDOW_W, WINDOW_H = 512, 768 # 窗口宽高
第二部分:子弹类
"""
class 子弹类
属性
image 子弹图片
x,y 坐标
move(self): 上移
"""
import pygame
class Bullet: # 子弹类
def __init__(self, x, y):
self.image = pygame.image.load("res/bullet_8.png") # 图片
self.x = x
self.y = y
def move(self): # 上移
self.y -= 1
# def __del__(self):
# print("子弹被删除")
第三部分:飞机类(包含英雄飞机和敌机)
"""
class 英雄飞机类
属性
image 飞机图片
x,y 坐标
方法
move_left(self): 左移
fire(self): 发射子弹
"""
import random
import pygame
from bullet import Bullet
from common import WINDOW_W
class HeroPlane: # 英雄飞机类
def __init__(self):
self.image = pygame.image.load("res/hero2.png") # 图片
self.x = 300 # 坐标
self.y = 500
self.bullet_list = [] # 记录所有发出的子弹
def fire(self): # 发射子弹
# 子弹下x = 飞机x + 飞机宽度*0.5 - 子弹宽度*0.5 ; 子弹y = 飞机y - 子弹高度
bullet = Bullet(self.x + 50, self.y - 31)
self.bullet_list.append(bullet) # 记录发出的子弹
def move_left(self): # 左移
self.x -= 12 # 让飞机的x减小
def move_right(self): # 右移
self.x += 12 # 让飞机的x增大
def move_up(self): # 上移
self.y -= 12 # 让飞机的y减小
def move_down(self): # 下移
self.y += 12 # 让飞机的y增大
"""
class 敌机类
属性
image 敌机图片
x,y 坐标
方法
move(self): 下移
reset(self): 重置数据
"""
class EnemyPlane: # 敌机类
def __init__(self):
self.image = pygame.image.load("res/img-plane_%d.png" % random.randint(1, 7)) # 敌机图片
self.x = random.randint(0, WINDOW_W - 100)
self.y = random.randint(-700, -70)
def move(self): # 下移
self.y += 8
def reset(self): # 重置数据
self.__init__() # 对象不改变,但对属性重新赋值
第四部分:地图类
"""
class 地图类
属性
image 地图图片1
x,y 坐标1
image2 地图图标2
x2,y2 坐标2
方法
move(self): 下移
reset(self): # 地图位置重置
"""
import random
import pygame
from common import WINDOW_H
class Map: # 地图类
def __init__(self):
self.image = pygame.image.load("res/img_bg_level_%d.jpg" % random.randint(1, 5)) # 图片1
self.x = 0 # 图片1 的坐标
self.y = 0
self.image2 = self.image # 图片2
self.x2 = 0 # 图片0 的坐标
self.y2 = -WINDOW_H
def move(self): # 下移
self.y += 2
self.y2 += 2
def reset(self): # 地图位置重置
self.x = 0 # 图片1 的坐标
self.y = 0
self.x2 = 0 # 图片0 的坐标
self.y2 = -WINDOW_H
第五部分:游戏类(主函数进入)
# pygame是第三方的游戏开发包
import pygame, random, sys, time # pygame内部实现啦批量导入处理
from common import WINDOW_W, WINDOW_H
from map import Map
from plane import HeroPlane, EnemyPlane
"""
class 游戏类
属性
window 窗口
bg_img 背景图
方法
draw(self): 贴图
update(self): 刷新
event(self): 事件检测
is_hit(self, rect1, rect2): # 碰撞检测,碰撞则返回True,否则返回False
run(self): 运行
"""
class Game: # 游戏类
def __init__(self):
pygame.init() # 初始化pygame库,文本和音效需要
self.window = pygame.display.set_mode((WINDOW_W, WINDOW_H)) # 窗口
self.map = Map() # 创建地图对象
self.hero_plane = HeroPlane() # 创建飞机对象
self.enemy_planes = [] # 记录所有的敌机
for _ in range(5):
enemy = EnemyPlane() # 创建敌机对象
self.enemy_planes.append(enemy) # 记录创建的敌机
self.score = 0 # 得分
def draw_map(self): # 贴地图
if self.map.y2 > 0:
self.map.reset() # 地图重置
self.window.blit(self.map.image, (self.map.x, self.map.y)) # 贴背景图1
self.window.blit(self.map.image2, (self.map.x2, self.map.y2)) # 贴背景图2
def draw_hero(self): # 贴英雄飞机图
for enemy in self.enemy_planes:
enemy_rect = pygame.Rect(enemy.x, enemy.y, 80, 46)
hero_rect = pygame.Rect(self.hero_plane.x, self.hero_plane.y, 120, 78)
if self.is_hit(enemy_rect, hero_rect): # 英雄被击中,程序结束
sys.exit()
else:
self.window.blit(self.hero_plane.image, (self.hero_plane.x, self.hero_plane.y)) # 贴飞机图
def draw_bullets(self): # 贴子弹图
delete_bullets = [] # 记录需要被删除的子弹
for bullet in self.hero_plane.bullet_list: # 取出每颗子弹,贴图
if bullet.y >= -31: # 在边界内,贴图
for enemy in self.enemy_planes: # 取出每架敌机,分别和子弹进行碰撞检测
bullet_rect = pygame.Rect(bullet.x, bullet.y, 25, 56)
enemy_rect = pygame.Rect(enemy.x, enemy.y, 100, 68)
if self.is_hit(bullet_rect, enemy_rect): # 如果发生碰撞,双方对应的处理
# 发生碰撞,子弹删除,敌机重置
delete_bullets.append(bullet)
enemy.reset()
self.score += 10 # 累加得分
break # 子弹已经击中了某架敌机,就不需要和其他的敌机再进行碰撞检测(不需要遍历其他的敌机了)
else: # 敌机全部遍历完,该子弹没和任何一架敌机发生碰撞,就贴图
self.window.blit(bullet.image, (bullet.x, bullet.y))
else: # 飞出边界,记录需要删除的子弹
delete_bullets.append(bullet)
# 从列表属性中删除子弹对象,这样系统就会回收子弹占用的内存
for delete_bullet in delete_bullets:
self.hero_plane.bullet_list.remove(delete_bullet)
def draw_enemy(self): # 贴敌机图
for enemy in self.enemy_planes: # 取出每架敌机
if enemy.y > WINDOW_H: # 飞出边界
enemy.reset() # 敌机重置数据
else:
self.window.blit(enemy.image, (enemy.x, enemy.y)) # 贴敌机图
def draw_text(self, font_size, content, x, y): # 贴文本
# 加载自定义字体,返回字体对象
font = pygame.font.Font("res/SIMHEI.TTF", font_size)
# 设置文本,返回文本对象 render(文本内容,抗锯齿,颜色)
text = font.render(content, 1, (255, 255, 255))
# 在指定位置和尺寸绘制指定文字对象
self.window.blit(text, (x, y))
def draw(self):
self.draw_map() # 贴地图
self.draw_hero() # 贴英雄飞机图
self.draw_bullets() # 贴子弹图
self.draw_enemy() # 贴敌机图
self.draw_text(35, "得分:%d" % self.score, 30, 30) # 贴得分
def update(self): # 刷新
pygame.display.update()
def event(self): # 事件检测
# 按下事件,控制发射子弹
for event in pygame.event.get(): # iter会自动生成for遍历的代码块
if event.type == pygame.QUIT: # python中字母都是大写的变量,称为常量
print("点击了关闭事件")
sys.exit() # 退出程序
elif event.type == pygame.KEYDOWN: # 键盘按下事件
if event.key == pygame.K_SPACE:
self.hero_plane.fire()
# 长按事件,控制飞机移动
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_a] or pressed_keys[pygame.K_LEFT]:
self.hero_plane.move_left()
if pressed_keys[pygame.K_d] or pressed_keys[pygame.K_RIGHT]:
self.hero_plane.move_right()
if pressed_keys[pygame.K_w] or pressed_keys[pygame.K_UP]:
self.hero_plane.move_up()
if pressed_keys[pygame.K_s] or pressed_keys[pygame.K_DOWN]:
self.hero_plane.move_down()
def action(self): # 主动处理,比如子弹移动,敌机移动
for bullet in self.hero_plane.bullet_list: # 取出每颗子弹,子弹移动
if bullet.y >= -31:
bullet.move()
for enemy in self.enemy_planes:
enemy.move() # 敌机移动
self.map.move() # 地图移动
def is_hit(self, rect1, rect2): # 碰撞检测,碰撞则返回True,否则返回False
# 有交点就会返回True
return pygame.Rect.colliderect(rect1, rect2)
def run(self): # 运行
while True:
# 贴图
self.draw()
# 刷新
self.update()
# 事件检测
self.event()
# 主动处理
self.action()
# 让程序每个循环休息0.02秒,cpu就可以减少计算,参与其他软件的处理
time.sleep(0.02)
def main(): # 主函数,设置为程序的入口
# 创建游戏对象
game = Game()
# 运行
game.run()
if __name__ == '__main__':
main()
打包命令


最终效果

本文详细介绍了如何利用pygame库创建一款飞机大战游戏,涵盖了常量定义、子弹、飞机(包括英雄飞机和敌机)、地图以及游戏主逻辑的实现。同时,还提供了游戏打包的命令。
3923

被折叠的 条评论
为什么被折叠?



