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()