简单的飞机大战(非常详细,学会自己动手做游戏)

目录

导包

界面设置

窗口

背景

绘制飞机

绘制敌机

子弹类

战机子弹类

敌机子弹类

按键设置

飞机按键设置

敌机的移动

敌机子弹

碰撞事件

加载飞机击毁图片

碰撞实现

封装


导包

首先,我们需要导入所需的模块。这包括time、pygame和random模块。time模块用于控制游戏中的时间,pygame是用于游戏开发的主模块,random用于生成随机数,例如随机生成敌机子弹。

import time
import pygame
import random

界面设置

窗口

创建一个有戏窗口大小按自己喜好来定义

# 显示窗口
screen = pygame.display.set_mode((480,650))

背景

把准备好的背景图片加载在python中,并将其放置到窗口中,其中(0,0)对应背景放置位置,以背景左上角为主,将左上角放置到坐标(0,0)位置,坐标(0,0)也对应窗口的左上角

# 加载背景
bg_img = pygame.image.load("../飞机大战/img/background.png")
# 显示背景
screen.blit(bg_img, (0, 0))

绘制飞机

这里我们需要加载两个飞机图片,是两个飞机图片循环切换来实现飞机的动态效果,定义一个变量作为飞机切换的条件

  1. 首先,它检查战机的当前状态self.a是否为"小喷"。

  2. 如果self.a为"小喷",那么它使用self.hero_img1作为战机图像,并将该图像绘制到游戏窗口的(self.x, self.y)位置。同时,它将战机的当前状态更新为"大喷",以便在下一次绘制时使用self.hero_img2

  3. 如果self.a不为"小喷",那么它使用self.hero_img2作为战机图像,并将该图像绘制到游戏窗口的(self.x, self.y)位置。同时,它将战机的当前状态更新为"小喷",以便在下一次绘制时使用self.hero_img1

通过这种方式,英雄战机的图像会在"小喷"和"大喷"之间循环切换,从而在游戏窗口上显示两种不同状态下的战机图像。这种状态切换的实现增加了游戏的趣味性和视觉效果。

self.a = "小喷"
self.hero_img1 = pygame.image.load("../飞机大战/img/me1.png")
self.hero_img2 = pygame.image.load("../飞机大战/img/me2.png")
if self.a == "小喷":
   screen.blit(self.hero_img1, (self.x,self.y))
   self.a = "大喷"
else:
   screen.blit(self.hero_img2, (self.x,self.y))
   self.a = "小喷"

绘制敌机

和飞机一样我们也是加载两个敌机图片实现敌机切换

self.hit == 1
self.enemy_img = pygame.image.load("../飞机大战/img/enemy2.png")
self.enemy1_img = pygame.image.load("../飞机大战/img/enemy2_hit.png")
if self.hit == 0:
   screen.blit(self.enemy_img, (self.x,self.y))
   self.hit = 1
else:
   screen.blit(self.enemy1_img, (self.x,self.y))
   self.hit = 0

子弹类

用来定义飞机和敌机子弹的类

战机子弹类

这段代码定义了一个名为HeroBullet的类,用于表示英雄战机的子弹。在这个类中,__init__方法用于初始化子弹的属性,而drawmove方法分别用于在屏幕上绘制子弹和更新子弹的位置。

让我们详细解释这段代码:

  1. __init__方法:

    • self.x = x:这行代码将传入的x值赋给子弹对象的x属性,表示子弹的初始水平位置。
    • self.y = y:这行代码将传入的y值赋给子弹对象的y属性,表示子弹的初始垂直位置。
    • self.show = screen:这行代码将传入的screen对象赋给子弹对象的show属性,这个属性是用于在游戏窗口上绘制图像的屏幕对象。
    • self.pic = pygame.image.load("../飞机大战/img/bullet1.png"):这行代码使用Pygame的image.load函数加载了一张图片,这张图片是子弹的图像,并将其存储在子弹对象的pic属性中。
  2. draw方法:

    • self.show.blit(self.pic,(self.x,self.y)):这行代码使用blit方法将子弹的图像绘制到游戏窗口上,其中self.pic是子弹的图像,而(self.x, self.y)是子弹的当前位置。
    • self.move():这行代码调用move方法,这个方法用于更新子弹的位置。
  3. move方法:

    • self.y -= 5:这行代码将子弹的y坐标减少5,使其向上移动。由于y坐标是垂直方向的,这表示子弹从英雄战机的位置向上发射,并逐渐消失在屏幕上方。

总的来说,这个HeroBullet类定义了一个简单的子弹对象,它具有初始位置、屏幕显示和移动能力。通过这个类,我们可以创建多个子弹对象,并在游戏过程中发射它们。

class HeroBullet:
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        self.pic = pygame.image.load("../飞机大战/img/bullet1.png")
    # 画子弹
    def draw(self):
        self.show.blit(self.pic,(self.x,self.y))
        self.move()
    # 子弹移动
    def move(self):
        self.y -= 5

敌机子弹类

这段代码定义了一个名为EnemyBullet的类,用于表示敌机发射的子弹。在这个类中,__init__方法用于初始化子弹的属性,而drawmove方法分别用于在屏幕上绘制子弹和更新子弹的位置。

让我们详细解释这段代码:

  1. __init__方法:

    • self.x = x:这行代码将传入的x值赋给子弹对象的x属性,表示子弹的初始水平位置。
    • self.y = y:这行代码将传入的y值赋给子弹对象的y属性,表示子弹的初始垂直位置。
    • self.show = screen:这行代码将传入的screen对象赋给子弹对象的show属性,这个属性是用于在游戏窗口上绘制图像的屏幕对象。
    • self.pic = pygame.image.load("../飞机大战/img/bullet2.png"):这行代码使用Pygame的image.load函数加载了一张图片,这张图片是敌机子弹的图像,并将其存储在子弹对象的pic属性中。
  2. draw方法:

    • self.show.blit(self.pic,(self.x,self.y)):这行代码使用blit方法将子弹的图像绘制到游戏窗口上,其中self.pic是子弹的图像,而(self.x, self.y)是子弹的当前位置。
    • self.move():这行代码调用move方法,这个方法用于更新子弹的位置。
  3. move方法:

    • self.y += 5:这行代码将子弹的y坐标增加5,使其向下移动。由于y坐标是垂直方向的,这表示子弹从敌机的位置向下发射,并逐渐消失在屏幕下方。

总的来说,这个EnemyBullet类定义了一个简单的子弹对象,它具有初始位置、屏幕显示和移动能力。通过这个类,我们可以创建多个子弹对象,并在游戏过程中由敌机发射它们。

class EnemyBullet:
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        self.pic = pygame.image.load("../飞机大战/img/bullet2.png")
    # 画子弹
    def draw(self):
        self.show.blit(self.pic,(self.x,self.y))
        self.move()
    # 子弹移动
    def move(self):
        self.y += 5

按键设置

飞机按键设置

这里我们实现飞机跟随你的按键移动和攻击。

  1. 检测pygame.QUIT事件,这是当用户关闭游戏窗口时触发的事件。如果检测到这个事件,游戏会打印出“游戏结束了”,然后调用pygame.quit()卸载Pygame模块,并使用exit(0)退出游戏。

  2. 检测pygame.KEYDOWN事件,这是当用户按下键盘按键时触发的事件。在这个事件中,我们通过event.key来检查按下的具体键,并做出相应的动作:

    • 如果按下的是左箭头键(pygame.K_LEFT),战机向左移动10个像素,但前提是战机的x坐标大于或等于5,以防止战机移出屏幕左侧。
    • 如果按下的是右箭头键(pygame.K_RIGHT),战机向右移动10个像素,但前提是战机的x坐标小于或等于370,以防止战机移出屏幕右侧。
    • 如果按下的是上箭头键(pygame.K_UP),战机向上移动10个像素,但前提是战机的y坐标大于或等于5,以防止战机移出屏幕上方。
    • 如果按下的是下箭头键(pygame.K_DOWN),战机向下移动20个像素,但前提是战机的y坐标小于或等于521,以防止战机移出屏幕下方。
    • 如果按下的是空格键(pygame.K_SPACE),战机发射子弹。这里创建了一个新的HeroBullet对象,其x坐标是战机x坐标加上40和10(调整子弹发射位置),y坐标是战机y坐标减去11(调整子弹发射位置),并将新子弹添加到战机子弹列表self.bullet_list中。

通过这些代码,我们实现了战机的基本移动和射击功能,这些是飞机大战游戏的核心交互部分

        for event in event_list:
            if event.type == pygame.QUIT:
                print("游戏结束了")
                # 卸载模块
                pygame.quit()
                exit(0)
            # 战机移动
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    self.x = self.x - 10 if self.x >= 5 else 0
                elif event.key == pygame.K_RIGHT:
                    self.x = self.x + 10 if self.x <= 370 else 380
                elif event.key == pygame.K_UP:
                    self.y = self.y - 10 if self.y >= 5 else 0
                elif event.key == pygame.K_DOWN:
                    self.y = self.y + 20 if self.y <= 521 else 526
                elif event.key == pygame.K_SPACE:
                    hero_bullet = HeroBullet(self.x + 40 + 10, self.y - 11, screen)
                    self.bullet_list.append(hero_bullet)

敌机的移动

我们只需要敌机在屏幕上方左右移动即可

  1. 首先,它检查敌机的当前移动方向self.b是否为"left"。

  2. 如果self.b为"left",那么它将敌机的x坐标减少3个像素,使其向左移动。同时,它检查敌机的x坐标是否小于或等于0,即是否已经到达屏幕左侧。如果已经到达,它将敌机的移动方向更新为"right",以便在下一次移动时向右移动。

  3. 如果self.b不为"left",那么它将敌机的x坐标增加3个像素,使其向右移动。同时,它检查敌机的x坐标是否大于或等于480 - 60,即是否已经到达屏幕右侧。如果已经到达,它将敌机的移动方向更新为"left",以便在下一次移动时向左移动。

通过这种方式,敌机会在屏幕的左右两侧之间来回移动,从而增加游戏的挑战性和趣味性。这种移动模式的实现使得敌机在游戏窗口上的位置不断变化,增加了玩家的射击难度。

    def move(self):
        if self.b == 'left':
            self.x = self.x - 3
            if self.x <= 0:
                self.b = 'right'
        elif self.b == 'right':
            self.x = self.x + 3
            if self.x >= 480 - 60:
                self.b = 'left'

敌机子弹

敌机子弹我们设置其随机发射

  1. 首先,它使用random.randint(1, 100)生成一个1到100之间的随机数x。这个随机数用来决定敌机是否发射子弹。

  2. 然后,它检查x是否等于5或者78。如果x等于这两个数中的任何一个,敌机就会发射子弹。这里设置了一个非常低的概率,使得敌机不会频繁发射子弹,从而增加游戏的难度和挑战性。

  3. 如果x等于5或者78,敌机创建一个新的EnemyBullet对象。这个新对象的x坐标是敌机x坐标加上69和5(69是敌机图片的宽度,5是调整子弹发射位置),y坐标是敌机y坐标加上99(99是敌机图片的高度,调整子弹发射位置)。

  4. 最后,它将新创建的子弹对象添加到敌机的子弹列表self.bullet_list中。这样,敌机发射的子弹就会被存储在这个列表中,并且可以在游戏窗口上绘制。

通过这种方式,敌机会在游戏过程中随机发射子弹,增加了游戏的挑战性和趣味性。这种发射模式的实现使得敌机在游戏窗口上的行为更加多样化和不可预测。

    def fire(self):
        x = random.randint(1, 100)
        if x == 5 or x == 78:
            enemybullet = EnemyBullet(self.x + (69 + 5) / 2, self.y + 99, screen)
            self.bullet_list.append(enemybullet)
        for bullet1 in self.bullet_list:
            bullet1.draw()

碰撞事件

用来实现子弹碰撞到飞机显示击毁的效果并加载击毁效果的图片

加载飞机击毁图片

self.hero_bomb_list = ["img/me_destroy_1.png",
                                              "img/me_destroy_2.png",
                                              "img/me_destroy_3.png",
                                              "img/me_destroy_4.png"]

self.enemy_bomb_list = ["img/enemy2_down1.png",
                        "img/enemy2_down2.png",
                        "img/enemy2_down3.png",
                        "img/enemy2_down4.png"]

碰撞实现

  1. 首先,它使用pygame.rect.Rect创建了一个英雄战机的矩形对象hero_rect。这个矩形对象的xy坐标分别是英雄战机的xy坐标,而宽度和高度分别是英雄战机的宽度和高度。

  2. 然后,它遍历敌机子弹列表bullet_list中的每个子弹。对于每个子弹,它使用pygame.rect.Rect创建了一个子弹的矩形对象enemy_bullet_rect。这个矩形对象的xy坐标分别是子弹的xy坐标,而宽度和高度分别是子弹的宽度和高度。

  3. 接着,它使用colliderect方法检查hero_rectenemy_bullet_rect是否发生了碰撞。如果发生了碰撞,flag变量将被设置为True

  4. 如果发生了碰撞,游戏会打印出“被对面打爆了”,并将英雄战机的hero_bomb属性设置为True,表示英雄战机被击中。同时,它从子弹列表bullet_list中移除击中英雄战机的子弹。

通过这种方式,英雄战机能够检测到是否被敌机子弹击中,并在被击中时结束游戏。这种碰撞检测机制增加了游戏的挑战性和趣味性,使得玩家必须时刻注意敌机子弹的威胁。

    def check_collision(self,bullet_list):
        hero_rect = pygame.rect.Rect(self.x,self.y,102,126)
        for bullet in bullet_list:
            enemy_bullet_rect = pygame.rect.Rect(bullet.x,bullet.y,5,12)
            flag = enemy_bullet_rect.colliderect(hero_rect)
            if flag:
                print("被对面打爆了")
                self.hero_bomb = True
                bullet_list.remove(bullet)

需要创建两个,一个飞机一个敌机

    def check_collision(self, bullet_list):
        enemy_rect = pygame.rect.Rect(self.x, self.y, 50, 56)
        for bullet in bullet_list:
            hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 5, 12)
            falg = hero_bullet_rect.colliderect(enemy_rect)
            if falg:
                print("把对面打爆了")
                self.enemy_bomb = True
                bullet_list.remove(bullet)

封装

封装代码的意义在于提高代码的可读性、可维护性和可重用性。它是一种面向对象编程(OOP)的实践,通过将相关的数据和函数组合在一起,形成一个具有明确功能的模块或类,从而实现代码的模块化。以下是封装代码的一些主要优点

  1. 模块化:封装允许将代码组织成更小的、可管理的部分,每个部分负责一个特定的功能。这使得代码更容易理解和维护。

  2. 隐藏内部细节:通过封装,类的内部实现细节对外部代码是隐藏的,这有助于减少外部代码对内部代码的依赖,从而提高代码的独立性和灵活性。

  3. 提高可重用性:封装后的代码可以被多次使用,只需将它们作为独立的模块或类导入到其他项目中。

  4. 提高安全性:封装可以防止外部代码直接访问或修改类的内部状态,从而提高了代码的安全性。

  5. 简化编程:通过封装,开发者可以专注于解决特定问题,而不需要关心其他部分如何实现。这有助于简化编程过程,提高开发效率。

  6. 促进协作:封装允许不同开发者专注于不同的模块或类,然后将它们组合在一起,形成一个完整的系统。这有助于促进团队合作和代码共享。

  7. 提高代码的扩展性:当需要添加新功能或修改现有功能时,封装可以帮助开发者在不影响其他部分的情况下进行操作。

封装后的代码展示

# 导包
import time
import pygame
import random
# 定义英雄子弹
class HeroBullet:
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        self.pic = pygame.image.load("../飞机大战/img/bullet1.png")
    # 画子弹
    def draw(self):
        self.show.blit(self.pic,(self.x,self.y))
        self.move()
    # 子弹移动
    def move(self):
        self.y -= 5
# 敌机子弹
class EnemyBullet:
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        self.pic = pygame.image.load("../飞机大战/img/bullet2.png")
    # 画子弹
    def draw(self):
        self.show.blit(self.pic,(self.x,self.y))
        self.move()
    # 子弹移动
    def move(self):
        self.y += 5
# 英雄战机类
class HeroPlane():
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        # 战机切换
        self.a = "小喷"
        # 战机图片
        self.hero_img1 = pygame.image.load("../飞机大战/img/me1.png")
        self.hero_img2 = pygame.image.load("../飞机大战/img/me2.png")
        # 战机爆炸
        self.hero_bomb_index = 0
        # 战机爆炸图片
        self.hero_bomb_list = ["img/me_destroy_1.png",
                                              "img/me_destroy_2.png",
                                              "img/me_destroy_3.png",
                                              "img/me_destroy_4.png"]
        # 战机爆炸条件
        self.hero_bomb = False
        # 子弹列表
        self.bullet_list = []
# 显示
    def draw(self):
        if self.hero_bomb == False:
            # 显示战机
            if self.a == "小喷":
                screen.blit(self.hero_img1, (self.x,self.y))
                self.a = "大喷"
            else:
                screen.blit(self.hero_img2, (self.x,self.y))
                self.a = "小喷"
        else:
            if self.hero_bomb_index == len(self.hero_bomb_list):
                time.sleep(0.3)
                exit()
            hero_bomb_img = pygame.image.load(self.hero_bomb_list[self.hero_bomb_index])
            screen.blit(hero_bomb_img, (self.x,self.y))
            self.hero_bomb_index += 1
            time.sleep(0.2)
# 战机移动
    def deal_event(self,event_list):
        for event in event_list:
            if event.type == pygame.QUIT:
                print("游戏结束了")
                # 卸载模块
                pygame.quit()
                exit(0)
            # 战机移动
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    self.x = self.x - 10 if self.x >= 5 else 0
                elif event.key == pygame.K_RIGHT:
                    self.x = self.x + 10 if self.x <= 370 else 380
                elif event.key == pygame.K_UP:
                    self.y = self.y - 10 if self.y >= 5 else 0
                elif event.key == pygame.K_DOWN:
                    self.y = self.y + 20 if self.y <= 521 else 526
                elif event.key == pygame.K_SPACE:
                    hero_bullet = HeroBullet(self.x + 40 + 10, self.y - 11, screen)
                    self.bullet_list.append(hero_bullet)
            # 调用函数画出战机子弹
        for bullet in self.bullet_list:
            bullet.draw()
# 碰撞事件
    def check_collision(self,bullet_list):
        hero_rect = pygame.rect.Rect(self.x,self.y,102,126)
        for bullet in bullet_list:
            enemy_bullet_rect = pygame.rect.Rect(bullet.x,bullet.y,5,12)
            flag = enemy_bullet_rect.colliderect(hero_rect)
            if flag:
                print("被对面打爆了")
                self.hero_bomb = True
                bullet_list.remove(bullet)
# 敌机类
class EnemyPlane():
    def __init__(self,x,y,screen):
        self.x = x
        self.y = y
        self.show = screen
        self.enemy_img = pygame.image.load("../飞机大战/img/enemy2.png")
        self.enemy1_img = pygame.image.load("../飞机大战/img/enemy2_hit.png")
        self.hit = 0
        self.enemy_bomb_list = ["img/enemy2_down1.png",
                        "img/enemy2_down2.png",
                        "img/enemy2_down3.png",
                        "img/enemy2_down4.png"]
        self.enemy_bomb_index = 0
        self.enemy_bomb = False
        self.bullet_list = []
        self.b = 'left'
# 画敌机
    def draw(self):
        if self.enemy_bomb == False:
            if self.hit == 0:
                screen.blit(self.enemy_img, (self.x,self.y))
                self.hit = 1
            else:
                screen.blit(self.enemy1_img, (self.x,self.y))
                self.hit = 0
        else:
            if self.enemy_bomb_index == len(self.enemy_bomb_list):
                time.sleep(0.2)
                exit(0)
            enemy_bomb_img = pygame.image.load(self.enemy_bomb_list[self.enemy_bomb_index])
            screen.blit(enemy_bomb_img,(self.x,self.y))
            self.enemy_bomb_index += 1
            time.sleep(0.2)
        self.move()
        self.fire()
    def move(self):
        if self.b == 'left':
            self.x = self.x - 3
            if self.x <= 0:
                self.b = 'right'
        elif self.b == 'right':
            self.x = self.x + 3
            if self.x >= 480 - 60:
                self.b = 'left'
    def fire(self):
        x = random.randint(1, 100)
        if x == 5 or x == 78:
            enemybullet = EnemyBullet(self.x + (69 + 5) / 2, self.y + 99, screen)
            self.bullet_list.append(enemybullet)
        for bullet1 in self.bullet_list:
            bullet1.draw()
    def check_collision(self, bullet_list):
        enemy_rect = pygame.rect.Rect(self.x, self.y, 50, 56)
        for bullet in bullet_list:
            hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 5, 12)
            falg = hero_bullet_rect.colliderect(enemy_rect)
            if falg:
                print("把对面打爆了")
                self.enemy_bomb = True
                bullet_list.remove(bullet)
# 初始化游戏
pygame.init()
# 显示窗口
screen = pygame.display.set_mode((480,650))
# 修改游戏图标
icon = pygame.image.load("../飞机大战/img/icon.png")
pygame.display.set_icon(icon)
# 加载背景
bg_img = pygame.image.load("../飞机大战/img/background.png")
# 加载战机
hero_plane = HeroPlane(480 // 2 - 102 // 2, 650 - 126,screen)
# 加载敌机
enemy_plane = EnemyPlane(480 // 2 - 69 // 2, 0,screen)
# 按键灵敏度
pygame.key.set_repeat(20, 30)
# 时钟
clock = pygame.time.Clock()
while True:
    # 设置时钟
    clock.tick(60)
    # 显示背景
    screen.blit(bg_img, (0, 0))
    # 敌机调用方法
    enemy_plane.check_collision(hero_plane.bullet_list)
    enemy_plane.draw()
    # 战机调用方法
    hero_plane.check_collision(enemy_plane.bullet_list)
    hero_plane.draw()
    hero_plane.deal_event(pygame.event.get())
    # 刷新窗口
    pygame.display.update()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值