飞机大战(pygame)

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

第一部分:常量

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

打包命令
在这里插入图片描述
在这里插入图片描述
最终效果
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值