游戏框架分为两部分
1.创建一个plane_main.py的主文件,写出一个PlaneGame的主类。
import pygame
class PlaneGmae(object):
def __init__(self):
print('游戏初始化...')
def start_game(self):
print('游戏开始...')
if __name__ == '__main__':
# 创建游戏对象
game = PlaneGmae()
# 启动游戏
game.start_game()
运行结果为
D:\python\python36\python.exe D:/PycharmProjects/feijidazhan_1/feiji.py
游戏初始化...
游戏开始...
2.另新建一个plane_sprite.py 的模块
import pygame
class Game_Sprite(pygame.sprite.Sprite):#派生精灵子类
'''飞机大战游戏精灵'''
def __init__(self,image_name,speed = 1):
# 继承父类的__init__()
super().__init__()
# 定义对象的属性
self.image =pygame.image.load(image_name)
self.rect = self.image.get_rect()
'''self.image的get_rect()返回pygame.Rect(0,0,width,height)'''
self.speed = speed
def update(self):
self.rect.y += self.speed
3. 主程序中设置游戏初始化的步骤
class PlaneGmae(object):
def __init__(self):
print('游戏初始化...')
# 1.创建游戏屏幕
self.screen = pygame.display.set_mode(SCREEN_RECT.size) #引入的常量
# 2.创建游戏时钟
self.clock = pygame.time.Clock()
# 3.私有方法创建精灵和精灵组
self.__creat_sprite()
def __creat_sprite(self):
pass
4主程序中游戏的开始部分的步骤
class PlaneGmae(object):
游戏初始化部分...
.......
def start_game(self):
print('游戏开始...')
while True:
# 1.设置帧率
self.clock.tick(60)
# 2. 事件监听
self.__event_monitor()
# 3. 碰撞检测
self.__check_collide()
# 4. 绘制图像
self.__blit_photo()
# 5.刷新显示
pygame.display.update()
5.为了让程序可读性高,便于维护,建议是使用私有方法,由于上面的四个步骤都是私有方法,所以接下来在上面的主要类开始布置私有方法
def __event_monitor(self):
pass
def __check_collide(self):
pass
def __blit_photo(self):
pass
@staticmethod
def __game_over():
print('退出游戏')
# 卸载所有模块
pygame.quit()
# 退出程序
exit()
- 需要注意的上面有一个静态方法,由于这个方法调用这个类里的任何方法和属性,所以要把它编程静态方法,加修饰符@staticmethod 不用加self参数
- 代码走到上面的这些就已经把飞机大战的游戏的整体框架搞定了
shift+f10 执行一下代码,显示为:
6.接下来我们开始布置背景图(这里用到一个小套路,让背景图在垂直方向上移动,这样就可以让英雄飞机相对运动了)
1.在模块文档那里开始写背景类
class Background(Game_Sprite):
def __init__(self,is_alt = False):
super().__init__('./images/background.png')
if is_alt:
self.rect.bottom = 0
def update(self):
# 让屏幕往下移动,所以可以用到父类的方法。所以可以继承
super().update()
# 判断底部照片是否超出屏幕
if self.rect.y > SCREEN_RECT.height:
self.rect.y =-SCREEN_RECT.height
2.回到主程序中的初始化部分那里,开始填写__creat_sprite()私有方法
def __creat_sprite(self):
# 创造背景精灵和精灵组
bg1 = Background()
bg2 = Background(True)
self.bg_group = pygame.sprite.Group(bg1,bg2)
3.回到主程序中游戏开始部分那里,self.__blit_photo() 图像绘制更新那里
def __blit_photo(self):
# 背景图片的绘制
self.bg_group.update()
self.bg_group.draw(self.screen)
shift+f10 运行的效果是一向下移动的背景图
7.为了方便后面测试程序,我们在这里就开始写事件监听的代码,一旦检测到退出的信号就直接退出
def __event_monitor(self):
for event in pygame.event.get():
# 判断监听是否有退出动作
if event.type == pygame.QUIT:
PlaneGmae. __game_over()
- 注意静态方法的调用是直接类名.方法名
8.敌机的类的填写以及精灵类和精灵组的填写(由于敌机较多,要用到定时器)
class Enemy(Game_Sprite):
def __init__(self):
super().__init__('./images/enemy1')
# 敌机初始化位置
# 1.x轴上的随机位置
Max_x = SCREEN_RECT.width-self.rect.width
self.rect.x = random.randint(0,Max_x)
# 2.y轴上的随机位置
self.rect.bottom = 0
# 初始速度的设置
self.speed = random.randint(1,3)
def update(self):
# 继承父类的update让敌机向下移动
super().update()
# 判断敌机是否超出屏幕
if self.rect.y > SCREEN_RECT.height:
self.kill()
def __del__(self):
print('敌机挂了%s' % self.rect)
1.敌机定时器的三步骤:
a.在模块文件中写出定时器常量 eg:XXX = pygame.USEREVENT
b.在主程序的初始化中
pygame.time.set_timer(CREAT_TIMER,1000)
其中1000指的1000毫秒也就是1秒执行一个定时器的动作
c.在事件监听里
elif event.type == CREAT_TIMER:
print('产生敌机...')
那样就可以1秒一个敌机出现
2.开始在初始化位置创建精灵组
# 创建敌机精灵组
self.enemy_group = pygame.sprite.Group()
3.在事件监听那里去写精灵组,因为这是持续不断的要精灵组的
elif event.type == CREAT_TIMER:
print('产生敌机...')
# 敌机精灵
enemy = Enemy()
# 敌机精灵组
self.enemy_group.add(enemy)
4.将敌机精灵组进行绘制
# 敌机的绘制
self.enemy_group.update()
self.enemy_group.draw(self.screen)
-
此时屏幕开始持续出现敌机
9.开始英雄的类已经精灵的布置
class Hero(Game_Sprite):
# 继承父类,设置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 确定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
- 在创建精灵的私有方法里开始创建英雄的精灵和精灵组
# 创建英雄精灵和精灵组
self. hero_sprite = Hero() #此对象要在其他方法被调用所以加self
self.hero_sprite_group = pygame.sprite.Group(hero_sprite)
- 绘制图像
# 英雄的绘制
self.hero_sprite_group.update()
self.hero_sprite_group.draw(self.screen)
-
shift + f10
10.开始让飞机在左右移动但是不能超出左右边界
- 1.使用键盘按键获取按键元组
# 使用键盘方法获取按键元组
keys_pressed = pygame.key.get_pressed()
# 判断元组中对应按键索引值
if keys_pressed[pygame.K_RIGHT]:
self.hero_sprite.speed = 2
elif keys_pressed[pygame.K_LEFT]:
self.hero_sprite.speed = -2
else:
self.hero_sprite.speed = 0
这个按键元组的value值是1时键值就是左右的一种
此时的Hero类
class Hero(Game_Sprite):
# 继承父类,设置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 确定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
def update(self):
# 因为是左右移动,所以可以完全改写父类方法
self.rect.x += self.speed
# 判断英雄飞机是否飞出屏幕外
if self.rect.x < 0:
self.rect.x = 0
elif self.rect.x > SCREEN_RECT.width-self.rect.width:
self.rect.right = SCREEN_RECT.right
-
此时的效果为,英雄可以左右移动但不会超出边界
11.开始设置子弹
- 1.设置子弹的类
class Bullet(Game_Sprite):
def __init__(self):
# 继承父类,加载图片
super().__init__('./images/bullet1.png',-2)
# 初始位置先不要管,等到英雄类里再去弄
def update(self):
# 继承父类方法,让子弹移动
super().update()
# 判断子弹是否超出屏幕
if self.rect.bottom < 0:
self.kill()
def __del__(self):
print('超出子弹被销毁%s'%self.rect)
注意下,这里不要设置子弹的初始位置,因为子弹的初始位置是要和英雄一起弄得
- 2.设置子弹的定时器
# 子弹常量
HERO_FIRE = pygame.USEREVENT+1
# 5. 发射子弹的定时器调用
pygame.time.set_timer(HERO_FIRE,500)
elif event.type == HERO_FIRE:
self.hero_sprite.fire()
考虑到子弹是要和英雄一起弄的,我们把创建子弹精灵和精灵组放到英雄类中去
- 在英雄的类初始化方法里设置子弹精灵组
class Hero(Game_Sprite):
# 继承父类,设置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 确定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
# 创建子弹精灵组
self.bullets = pygame.sprite.Group()
- 4 .开始设置在英雄类里设置fire()方法
elif event.type == HERO_FIRE:
self.hero_sprite.fire()
def fire(self):
print('发射子弹...')
for i in range(3):
# 创建子弹精灵
bullet = Bullet()
# 设置子弹的初始位置
bullet.rect.bottom = self.rect.y- i*20
bullet.rect.centerx = self.rect.centerx
# 设置子弹的精灵组
self.bullets.add(bullet)
- 5 .开始将子弹精灵组放到绘制图像的方法里
# 子弹的绘制
self.hero_sprite.bullets.update()
self.hero_sprite.bullets.draw(self.screen)
呈现的效果为
12.开始碰撞检测
def __check_collide(self):
# 子弹碰到飞机
pygame.sprite.groupcollide(self.hero_sprite.bullets,self.enemy_group,True,True)
# 敌机撞毁飞机
enemies = pygame.sprite.spritecollide(self.hero_sprite, self.enemy_group, True)
# 判断列表是否有内容
if len(enemies) > 0:
# 让英雄牺牲
self.hero_sprite.kill()
# 结束游戏
PlaneGmae.__game_over()
shift +f10
碰撞的基础知识