作为新手自学Python的第二十天,技术低微,希望可以通过这种方式督促自己学习。
个人学习环境:python3.9,PyCharm 2021.3.2 (Community Edition)
利用python完成飞机大战是一个非常经典的练手项目,本次主要内容是完善飞机及添加子弹。
从这一节开始我们为了后续开发快捷,创建Hero类和Bullet类分别控制飞机和子弹。
这里我们要先了解一个很重要的模块——精灵模块(pygame.sprite)。
通过使用精灵模块,我们可以将游戏中的一类元素进行编辑。
# 导入pygame库
import pygame
# 导入pygame库中的一些常量
from pygame.locals import *
# 导入sys库中的exit函数
from sys import exit
# 定义窗口的分辨率
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 640
# 使用精灵模块(pygame.sprite),将游戏内的一类元素进行编组
# 玩家类
class Hero(pygame.sprite.Sprite):
def __init__(self, hero_surface, hero_init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = hero_surface
self.rect = self.image.get_rect()
self.rect.topleft = hero_init_pos
self.speed = 6
# 子弹1的Group
self.bullets1 = pygame.sprite.Group()
# 控制射击行为
def single_shoot(self, bullet1_surface):
buttle1 = Buttle(bullet1_surface, self.rect.midtop)
self.bullets1.add(buttle1)
# 控制飞机移动
def move(self, offset):
x = self.rect.left + offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]
y = self.rect.top + offset[pygame.K_DOWN] - offset[pygame.K_UP]
if x < 0:
self.rect.left = 0
elif x > SCREEN_WIDTH - self.rect.width:
self.rect.left = SCREEN_WIDTH - self.rect.width
else:
self.rect.left = x
if y < 0:
self.rect.top = 0
elif y > SCREEN_HEIGHT - self.rect.height:
self.rect.top = SCREEN_HEIGHT - self.rect.height
else:
self.rect.top = y
# 子弹类
class Buttle(pygame.sprite.Sprite):
def __init__(self, buttle_surface, buttle_init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = buttle_surface
self.rect = self.image.get_rect()
self.rect.topleft = buttle_init_pos
self.speed = 8
# 控制子弹移动
def update(self):
self.rect.top -= self.speed
# 子弹超出屏幕范围后,调用kill()移除
if self.rect.top < -self.rect.height:
self.kill()
def run_game():
# 定义画面帧率
FRAME_RATE = 60
#定义动画周期(帧率)
ANIMATE_CYCLE = 30
ticks = 0
clock = pygame.time.Clock()
# dict 字典
offset = {pygame.K_LEFT: 0, pygame.K_RIGHT: 0, pygame.K_UP: 0, pygame.K_DOWN: 0}
# 初始化游戏
pygame.init() # 初始化 pygame
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT]) # 初始化窗口
pygame.display.set_caption('飞机大战') # 设置窗口标题
# 载入背景图
background = pygame.image.load('./image/background.png')
# 载入飞机图片
hero1 = pygame.image.load('./image/me1.png')
hero2 = pygame.image.load('./image/me2.png')
# 载入子弹模型
buttle1_surface = pygame.image.load('./image/bullet1.png')
hero_surface = [hero1, hero2]
hero_pos = [200, 500]
# 创建玩家
hero = Hero(hero_surface[0], hero_pos)
# 事件循环(main loop)
while True:
# 控制游戏最大帧率
clock.tick(FRAME_RATE)
# 绘制背景
screen.blit(background,(0, 0))
#改变飞机图片制造动画
if ticks >= ANIMATE_CYCLE:
ticks = 0
hero.image = hero_surface[ticks//(ANIMATE_CYCLE//2)]
# 绘制飞机
screen.blit(hero.image, hero.rect)
ticks += 1
# 射击
if ticks % 10 == 0:
hero.single_shoot(buttle1_surface)
# 控制子弹
hero.bullets1.update()
# 绘制子弹
hero.bullets1.draw(screen)
# 更新屏幕
pygame.display.update()
# 处理游戏退出
# 从消息队列中循环取
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# 控制方向
if event.type == pygame.KEYDOWN:
if event.key in offset:
offset[event.key] = hero.speed
elif event.type == pygame.KEYUP:
if event.key in offset:
offset[event.key] = 0
# 移动飞机
hero.move(offset)
run_game()
注意:
- clock.tick()函数是限制刷新率,通过限制刷新率为60,避免CPU资源浪费。
- 当子弹超出屏幕范围后,调用kill()移除
有一点不知道大家是否清楚,整体游戏是如何“动起来”的,毕竟所有的东西都是静态图片。
我们要注意,我们在run_game()中定义了一个ticks变量,它就是我们项目“动起来”的关键。它相当于定义了一个关键帧,每一秒刷新屏幕上的元素及元素的位置,通过它不断的变大,位置的不断移动,我们的项目最终达到了“动起来”的效果。