一、子弹模块
import pygame WINDOW_WIDTH = 512 # 根据实际需求调整窗口大小 WINDOW_HEIGHT = 768 class Bullet(object): def __init__(self): # 图片,矩形对象,速度 self.bullet_img = pygame.image.load('res/bullet_11.png') # 资源文件自己选择 self.enemy_bullet_img = pygame.image.load('res/bullet_4.png') self.bullet_rect = self.bullet_img.get_rect() self.enemy_bullet_rect = self.enemy_bullet_img.get_rect() self.speed = 5 self.enemy_speed = 3 # 开关 #开:表示可以移动可以绘制可以杀敌人 # 关闭:当子弹移动到窗口外面的时候回:表示不移动不绘制也不杀敌人 # 开关的默认状态:关:当用户发射子弹的时候才打开开关 self.is_shot = False self.enemy_is_shot = False def move(self): self.bullet_rect.move_ip(0, -self.speed) self.enemy_bullet_rect.move_ip(0, self.enemy_speed) # 当子弹移动到窗口上面的外面,开关关闭 if self.bullet_rect[1] < 0: self.is_shot = False if self.enemy_bullet_rect[1] > 600: self.enemy_is_shot = False
二、敌人模块
import pygame import random import bullet WINDOW_WIDTH = 512 # 这里由于我电脑分辨率有问题,我把界面调小了。。 WINDOW_HEIGHT = 600 class Enemy(object): def __init__(self): # 图片、矩形对象(设置敌机的默认位置)、速度 img-plane_1.png num = str(random.randint(1, 7)) self.enemy_img = pygame.image.load('res/img-plane_'+ num +'.png') self.enemy_rect = self.enemy_img.get_rect() # 默认位置水平是随机,垂直窗口外面 self.enemy_rect[0] = random.randint(0, WINDOW_WIDTH-self.enemy_rect[2]) self.enemy_rect[1] = -self.enemy_rect[3] # 0, 0, 宽度,高 self.speed = random.randint(2, 4) self.enemy_bullet_list = [bullet.Bullet() for _ in range(10)] def move(self): # 移动矩形对象move_ip (0,+speed) self.enemy_rect.move_ip(0, self.speed) # 因为敌机需要循环使用,判断如果移动到窗口下面的外面,把敌机放到初始位置 if self.enemy_rect[1] > WINDOW_HEIGHT: self.reset() def reset(self): self.enemy_rect[0] = random.randint(0, WINDOW_WIDTH - self.enemy_rect[2]) self.enemy_rect[1] = -self.enemy_rect[3] # 0, 0, 宽度,高 self.speed = random.randint(2, 3) def shot(self): # 摆子弹位置 -- 10 list for bullet in self.enemy_bullet_list: # 如果子弹是为发射状态的才摆位置 -- 开关false # if bullet.is_shot == False if not bullet.enemy_is_shot: #水平 bullet.enemy_bullet_rect[0] = self.enemy_rect[0] + self.enemy_rect[2]/2 - bullet.enemy_bullet_rect[2]/2 bullet.enemy_bullet_rect[1] = self.enemy_rect[1] + self.enemy_rect[3] # 之所以摆位置是因为要发射了 bullet.enemy_is_shot = True break # 取一发子弹就可以了,当下次用户按j或者空格的时候再调用这个shot函数
三、游戏地图模块
import pygame import random WINDOW_WIDTH = 512 WINDOW_HEIGHT = 768 class GameMap(object): def __init__(self): # 加载两个图片,设置图片的初始位置、移动的速度 self.num = str(random.randint(1,5)) # 保证随机的是同一个数字 self.bg_img1 = pygame.image.load('res/img_bg_level_' + self.num + '.jpg') self.bg_img2 = pygame.image.load('res/img_bg_level_' + self.num + '.jpg') self.bg_img1_y = -WINDOW_HEIGHT self.bg_img2_y = 0 self.speed = 1 def map_scroll(self): if self.bg_img1_y >= 0: self.bg_img1_y = -WINDOW_HEIGHT if self.bg_img2_y >= WINDOW_HEIGHT: self.bg_img2_y = 0 self.bg_img1_y += self.speed self.bg_img2_y += self.speed
四、我方英雄战机模块
import pygame import bullet WINDOW_WIDTH = 512 WINDOW_HEIGHT = 600 class Hero(object): def __init__(self): # 图、矩形对象、速度、设置飞机初始位置 self.hero_img = pygame.image.load('res/hero.png') self.hero_rect = self.hero_img.get_rect() # (0, 0, 120, 78) self.hero_rect.move_ip(WINDOW_WIDTH/2-self.hero_rect[2]/2, WINDOW_HEIGHT-self.hero_rect[3]) # (水平中间, 垂直底部, 120 ,78) self.speed = 2 # 因为是飞机发射子弹,创建子弹对象:10 -- 创建一个子弹列表 # self.bullet = bullet.Bullet() self.bullet_list = [bullet.Bullet() for _ in range(1000)] def move_up(self): # 上移动 -- y -speed -- >0 if self.hero_rect[1] > 0: self.hero_rect.move_ip(0, -self.speed) def move_down(self): # y +speed < 最低坐标 if self.hero_rect[1] < WINDOW_HEIGHT-self.hero_rect[3]: self.hero_rect.move_ip(0, self.speed) def move_left(self): if self.hero_rect[0] > 0: self.hero_rect.move_ip(-self.speed, 0) def move_right(self): if self.hero_rect[0] < WINDOW_WIDTH- self.hero_rect[2]: self.hero_rect.move_ip(self.speed, 0) def shot(self): # 摆子弹位置 -- 10 list for bullet in self.bullet_list: # 如果子弹是为发射状态的才摆位置 -- 开关false # if bullet.is_shot == False if not bullet.is_shot: #水平 bullet.bullet_rect[0] = self.hero_rect[0] + self.hero_rect[2]/2 - bullet.bullet_rect[2]/2 bullet.bullet_rect[1] = self.hero_rect[1] - bullet.bullet_rect[3] # 之所以摆位置是因为要发射了 bullet.is_shot = True break # 取一发子弹就可以了,当下次用户按j或者空格的时候再调用这个shot函数
五、飞机大战主模块
# 创建窗口对象,显示 import pygame import sys # 为了关闭游戏窗口 import game_map import hero import bullet import enemy # import time # 经验:但凡变量名全都大写,表示的后期不做这个数据的修改了 WINDOW_WIDTH = 512 WINDOW_HEIGHT = 600 class GameWindow(object): def __init__(self): pygame.init() # 尺寸,标题。标志 self.window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT]) pygame.display.set_caption('飞机大战V1.1') self.ico = pygame.image.load('res/app.ico') pygame.display.set_icon(self.ico) # 创建地图对象 self.map = game_map.GameMap() # 先有动画还是先绘制图片 -- # 创建飞机对象 self.hero = hero.Hero() # 创建敌机对象 self.enemy_list = [enemy.Enemy() for _ in range(5)] # 加载背景音乐 pygame.mixer.music.load("./res/bg2.ogg") # 循环播放背景音乐 pygame.mixer.music.play(-1) def run(self): while True: self.action() self.draw() self.event() self.bullet_hit_enemy() if self.enemy_hit_hero(): break self.update() # 函数 -- 做动画 def action(self): # 地图动画调进来 self.map.map_scroll() # 调用子弹移动动画 for bullet in self.hero.bullet_list: if bullet.is_shot: bullet.move() for enemy in self.enemy_list: for bullet in enemy.enemy_bullet_list: if bullet.enemy_is_shot: bullet.move() for enemy in self.enemy_list: enemy.move() # 函数 -- 绘制图片 def draw(self): self.window.blit(self.map.bg_img1, (0,self.map.bg_img1_y)) self.window.blit(self.map.bg_img2, (0,self.map.bg_img2_y)) # 绘制飞机 self.window.blit(self.hero.hero_img, (self.hero.hero_rect[0], self.hero.hero_rect[1])) # 绘制子弹:开关是true的 for bullet in self.hero.bullet_list: if bullet.is_shot is True: self.window.blit(bullet.bullet_img, (bullet.bullet_rect[0], bullet.bullet_rect[1])) for enemy in self.enemy_list: for bullet in enemy.enemy_bullet_list: if bullet.enemy_is_shot is True: self.window.blit(bullet.enemy_bullet_img, (bullet.bullet_rect[0], bullet.bullet_rect[1])) # 绘制敌机 for enemy in self.enemy_list: self.window.blit(enemy.enemy_img, (enemy.enemy_rect[0], enemy.enemy_rect[1])) # 碰撞检测 -- 子弹碰撞敌机 def bullet_hit_enemy(self): # 取每个子弹,看所有敌机,到底看哪个子弹(必须是发射状态开关是True)碰撞了哪个敌机 for bullet in self.hero.bullet_list: if bullet.is_shot == True: for enemy in self.enemy_list: if pygame.Rect.colliderect(bullet.bullet_rect, enemy.enemy_rect): # 加载音效 boom_sound = pygame.mixer.Sound("./res/baozha.ogg") # 播放音效 boom_sound.play() # 敌机消失 -- 放到顶部 等下次向下移动reset enemy.reset() # 子弹消失-- false bullet.is_shot = False break # 碰撞检测 -- 敌机碰撞英雄飞机 def enemy_hit_hero(self): for enemy in self.enemy_list: if pygame.Rect.colliderect(enemy.enemy_rect, self.hero.hero_rect): # 退出主循环 return True return False # 英雄飞机人为控制移动,添加事件(event)函数 def event(self): # 单次事件 -- 返回的是列表 self.event_list = pygame.event.get() for event in self.event_list: # 叉号 if event.type == pygame.QUIT: # 关闭游戏窗口 # sys.exit() # # 退出pygame # pygame.quit() self.gameOver() # 判断键盘按下类型 if event.type == pygame.KEYDOWN: # 判断按下的到底是哪个键 if event.key == pygame.K_ESCAPE: self.gameOver() if event.key == pygame.K_r: for enemy in self.enemy_list: enemy.shot() # 连续、多次事件 连续按键 -- 判断按下的是哪个key # time.sleep(3) self.pressed = pygame.key.get_pressed() if self.pressed[pygame.K_SPACE] or self.pressed[pygame.K_j]: self.hero.shot() # print(self.pressed) (0,0,0,1,0,0) if self.pressed[pygame.K_UP]: self.hero.move_up() if self.pressed[pygame.K_DOWN]: self.hero.move_down() if self.pressed[pygame.K_LEFT]: self.hero.move_left() if self.pressed[pygame.K_RIGHT]: self.hero.move_right() def gameOver(self): pygame.quit() sys.exit() # 函数更新 def update(self): pygame.display.update() if __name__ == '__main__': game = GameWindow() game.run()