【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码

文章目录

      • 一、游戏运行效果
      • 二、代码实现
        • 2.1 项目搭建
        • 2.2 加载我方坦克
        • 2.3 加载敌方坦克
        • 2.4 添加爆炸效果
        • 2.5 坦克大战之音效处理
      • 三、完整代码

一、游戏运行效果

二、代码实现

坦克大战游戏

2.1 项目搭建

本游戏主要分为两个对象,分别是我方坦克和敌方坦克。用户可以通过控制我方的坦克来摧毁敌方的坦克保护自己的“家”,把所有的敌方坦克消灭完达到胜利。敌方的坦克在初始的时候是默认 5 个的(这可以自己设置),当然,如果我方坦克被敌方坦克的子弹打中,游戏结束。从面向对象分析该项目有以下类组成:
在这里插入图片描述

  • 主类:主要包括开始游戏、结束游戏的功能。
class MainGame():
    def __init__(self):
        pass
    # 开始游戏
    def startGame(self):
        pass
    # 结束游戏
    def endGame(self):
        pass
  • 坦克类:主要包括坦克的创建、显示、移动及射击的功能。
class Tank():
    def __init__(self):
        pass
    # 移动
    def move(self):
        pass
    # 射击
    def shot(self):
        pass
    # 展示坦克的方法
    def displayTank(self):
        pass
  • 我方坦克类继承坦克类,主要包括创建、与敌方坦克的碰撞方法。
# 我方坦克
class MyTank(Tank):
    def __init__(self):
        pass
  • 敌方坦克类继承坦克类,主要包括创建、与我方坦克碰撞方法。
# 敌方坦克
class EnemyTank(Tank):
    def __init__(self):
        pass
  • 子弹类:主要包括子弹的创建、显示及移动的功能。
# 子弹类
class Bullet():
    def __init__(self):
        pass
    # 移动
    def move(self):
        pass
    # 展示子弹的方法
    def displayBullet(self):
        pass
  • 墙壁类:主要包括墙壁的创建、显示的功能。
class Wall():
    def __init__(self):
        pass
    # 展示墙壁的方法
    def displayWall(self):
        pass
  • 爆炸效果类:主要展示爆炸效果。
class Explode():
    def __init__(self):
        pass
    # 展示爆炸效果的方法
    def displayExplode(self):
        pass
  • 音效类:主要播放音乐。
class Music():
    def __init__(self):
        pass
    # 播放音乐
    def play(self):
        pass

显示游戏窗口

在游戏设计的前期,要先创建游戏的界面,也就是要为所设计的游戏创建一个窗口。
【示例】:显示游戏窗口

def startGame(self):
    # 加载主窗口
    # 初始化窗口
    pygame.display.init()
    # 设置窗口的大小及显示
    MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
    # 设置窗口的标题
    pygame.display.set_caption('坦克大战1.03')
    while True:
        # 给窗口设置填充色
        MainGame.window.fill(BG_COLOR)
        pygame.display.update()
MainGame().startGame()

运行效果:
在这里插入图片描述

添加提示文字
在运行代码时会发现,创建的窗口没有任何提示。然而在实际中希望窗口提示敌方坦克的数量,因此,需要在现有窗口进行必须的改进,添加敌方坦克数量提示。

# 文字显示
def getTextSuface(self, text):
    pygame.font.init()  # 字体初始化
    font = pygame.font.SysFont('kaiti', 16)
    # 绘制文字信息
    textSurface = font.render(text, True, TEXT_COLOR)
    return textSurface

在这里插入图片描述

2.2 加载我方坦克

通过加载一张图片来表示游戏中的坦克,此坦克代表我方坦克,完善坦克类。

class Tank():
    # 添加距离左边left 距离上边top
    def __init__(self, left, top):
        # 保存加载的图片
        self.images = {
            'U': pygame.image.load('img/p1tankU.gif'),
            'D': pygame.image.load('img/p1tankD.gif'),
            'L': pygame.image.load('img/p1tankL.gif'),
            'R': pygame.image.load('img/p1tankR.gif'),
        }
        # 方向
        self.direction = 'L'
        # 根据当前图片的方向获取图片 surface
        self.image = self.images[self.direction]
        # 根据图片获取区域
        self.rect = self.image.get_rect()
        # 设置区域的left 和top
        self.rect.left = left
        self.rect.top = top

在这里插入图片描述
添加事件监听

上面创建的坦克还不能动,显示不是创建游戏的目的,因此,要给创建的坦克赋予“生命”。添加事件监听,控制上、下、左、右四个方向键,实现针对不同的键改变坦克的方向及移动功能,点击关闭退出游戏。

实现退出方法:

# 结束游戏
    def endGame(self):
        print('游戏结束')
        exit()  # 退出游戏

坦克类中添加移动开关属性,按下上、下、左、右四个方向键修改坦克的方向及开关状态,按下关闭键,调用关闭方法退出游戏。

# 获取程序期间所有事件(鼠标事件,键盘事件)
    def getEvent(self):
        # 获取所有事件
        eventList = pygame.event.get()
        # 遍历事件
        for event in eventList:
            # 判断按下的键是关闭还是键盘按下
            # 如果按的是退出,关闭窗口
            if event.type == pygame.QUIT:
                self.endGame()
            # 如果是键盘的按下
            if event.type == pygame.KEYDOWN:
                # 判断按下的是上、下、左、右
                if event.key == pygame.K_LEFT:
                    print('按下左键,坦克向左移动')
                elif event.key == pygame.K_RIGHT:
                    print('按下右键,坦克向右移动')
                elif event.key == pygame.K_UP:
                    print('按下上键,坦克向上移动')
                elif event.key == pygame.K_DOWN:
                    print('按下左键,坦克向下移动')

在这里插入图片描述
按下上、下、左、右之后控制台上会打印对应的信息。

随机生成敌方坦克

初始化敌方坦克,随机在不同坐标生成敌方坦克。

# 敌方坦克
class EnemyTank(Tank):
    def __init__(self, left, top, speed):
        super(EnemyTank, self).__init__(left, top)
        # 加载图片集
        self.images = {
            'U': pygame.image.load('img/enemy1U.gif'),
            'D': pygame.image.load('img/enemy1D.gif'),
            'L': pygame.image.load('img/enemy1L.gif'),
            'R': pygame.image.load('img/enemy1R.gif'),
        }
        # 随机生成方向
        self.direction = self.randDirection()
        self.image = self.images[self.direction]  # 根据方向获取图片
        self.rect = self.image.get_rect()  # 获取区域
        self.rect.left, self.rect.top = left, top  # 对left和top赋值
        self.speed = speed  # 速度
        self.flag = True  # 坦克移动开关
        self.step = 50  # 敌方坦克步数
2.3 加载敌方坦克

MainGame类中创建敌方坦克:

    def createEnemyTank(self):  # 初始化敌方坦克, 将敌方坦克添加到列表中
        top = 100
        for i in range(self.enemyTankCount):  # 生成指定敌方坦克数量
            left = random.randint(0, 600)
            speed = random.randint(1, 4)
            enemy = EnemyTank(left, top, speed)
            MainGame.enemyTankList.append(enemy)

在敌方坦克类中实现敌方坦克的随机移动

    def randMove(self):  # 坦克的随机方向移动
        if self.step < 0:  # 步数小于0, 随机改变方向
            self.direction = self.randDirection()
            self.step = 50  # 步数复位
        else:
            self.move()
            self.step -= 1

在开始游戏方法,加载敌方坦克

self.creatEnemyTank()

在这里插入图片描述
我方坦克发射子弹
在子弹类中初始化子弹,每个子弹在不同的方向发射会有不同的运动轨迹,每个子弹在坦克方向上的不同子弹发射的坐标也会有所不同。需要计算四个不同方向上的子弹发射坐标。

    def __init__(self, tank):
        self.image = pygame.image.load('img/enemymissile.gif')  # 图片加载
        self.direction = tank.direction  # 子弹的方向
        self.rect = self.image.get_rect()  # 获取区域
        if self.direction == 'U':  # 子弹的left和top与方向有关
            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top - self.rect.height
        elif self.direction == 'D':
            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top + tank.rect.height
        elif self.direction == 'L':
            self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
        elif self.direction == 'R':
            self.rect.left = tank.rect.left + tank.rect.width
            self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
        self.speed = 5   # 子弹的速度
        self.live = True  # 子弹的状态

敌方坦克随机发射子弹

def shot(self):
	num = random.randint(1,1000)
	if num <= 20:
		return Bullet(self)

我方法子弹与敌方坦克的碰撞检测
在游戏开发中,通常把显示图像的对象叫做精灵 Spire,精灵需要有两个属性 image 要
显示的图像,rect 图像要显示在屏幕的位置。
在 Pygame 框架中,使用 pygame. sprite 模块中的内置函数可以实现碰撞检测。代码如
下:

pygame.sprite.collide_rect(first, second) #返回布尔值

pygame.sprite.Sprite 是 pygame 精灵的基类,一般来说,总是需要写一个自己的精灵类继承 pygame.sprite.Sprite。让坦克类、子弹类都继承编写的精灵类。
在子弹类中增加我方子弹碰撞敌方坦克的方法,如果发生碰撞,修改我方子弹及敌方坦克 live 属性的状态值。

#新增我方子弹碰撞敌方坦克的方法
def hitEnemyTank(self):
	for eTank in MainGame.EnemyTank_list:
		if pygame.sprite.collide_rect(eTank,self):
			self.live = False
			eTank.live = False
2.4 添加爆炸效果

在我方子弹碰撞敌方坦克的方法中,如果检测到碰撞,产生爆炸类,并将爆炸效果添加到爆炸列表。

#新增我方子弹碰撞敌方坦克的方法
def hitEnemyTank(self):
	for eTank in MainGame.EnemyTank_list:
		if pygame.sprite.collide_rect(eTank,self):
			#产生一个爆炸效果
			explode = Explode(eTank)
			#将爆炸效果加入到爆炸效果列表
			MainGame.Explode_list.append(explode)
			self.live = False
			eTank.live = False

我方坦克的消亡
子弹类中,新增敌方子弹与我方坦克的碰撞。如果发生碰撞,修改敌方子弹、我方坦克的状态及产生爆炸效果。
添加敌方子弹到窗口中时候,如果子弹还活着,显示子弹、调用子弹移动并判断敌方子弹是否与我方坦克发生碰撞。

    def blitEnemyBullet(self):  # 循环敌方子弹列表, 并展示
        for enemyBullet in MainGame.enemyBulletList:
            if enemyBullet.live:
                enemyBullet.displayBullet()
                enemyBullet.move()
                enemyBullet.enemyBullet_hit_myTank()
                enemyBullet.hitWall()  # 检测敌方坦克子弹是否碰撞
            else:
                MainGame.enemyBulletList.remove(enemyBullet)

子弹不能穿墙
子弹类中新增方法,子弹与墙壁的碰撞,如果子弹与墙壁碰撞,修改子弹的状态,墙壁的生命值减少,如果墙壁的生命值小于等于零时候修改墙壁的状态。

坦克不能穿墙
如果坦克与墙壁碰撞,则坦克不能继续移动,需要修改坦克的坐标为移动之前的。因此在坦克类中新增属性 oldLeft、oldTop 记录移动之前的坐标,新增 stay()、hitWalls()方法。

    def hitWall(self):
        for wall in MainGame.WallList:  # 循环遍历墙壁列表
            if pygame.sprite.collide_rect(self, wall):  # 检测子弹是否碰撞墙壁
                self.live = False  # 修改子弹状态
                wall.hp -= 1  # 碰撞后墙壁生命值减少
                if wall.hp <= 0:
                    wall.live = False

双方坦克之间的碰撞检测
如果我方坦克碰撞到敌方坦克,则我方坦克再不能继续移动。同理如果敌方坦克碰撞到
我方坦克也不能继续移动。
在我方坦克类中新增我方坦克与敌方坦克碰撞的方法。

class MyTank(Tank):
    def __init__(self, left, top):
        super(MyTank, self).__init__(left, top)

    def myTank_hit_enemyTank(self):
        for enemyTank in MainGame.enemyTankList:
            if pygame.sprite.collide_rect(self, enemyTank):
                self.stay()

我方坦克移动后,调用是否与敌方坦克发生碰撞。在敌方坦克类中,新增敌方坦克碰撞我方坦克的方法。敌方坦克添加到窗口时候,调用是否与我方坦克碰撞。

    def blitEnemyBullet(self):  # 循环敌方子弹列表, 并展示
        for enemyBullet in MainGame.enemyBulletList:
            if enemyBullet.live:
                enemyBullet.displayBullet()
                enemyBullet.move()
                enemyBullet.enemyBullet_hit_myTank()
                enemyBullet.hitWall()  # 检测敌方坦克子弹是否碰撞
            else:
                MainGame.enemyBulletList.remove(enemyBullet)
2.5 坦克大战之音效处理

music 是 pygame 中控制流音频的 pygame 模块,音乐模块与 pygame.mixer 紧密相连,pygame.mixer 是一个用来处理声音的模块,其含义为“混音器”。游戏中对声音的处理一般包括制造声音和播放声音两部分。使用 pygame.mixer.music.load()加载一个播放音乐的文件,pygame.mixer.music.play() 开始播放音乐流。

初始化音效类

class Music():
    def __init__(self, filename):
        self.filename = filename
        pygame.mixer.init()
        pygame.mixer.music.load(self.filename)  # 加载音乐
    # 音乐播放
    def play(self):
        pygame.mixer.music.play()
music.play()

创建坦克时,添加音效和在我方坦克发射子弹时,添加音效。

三、完整代码

注意因为代码过长,且含音频和图片,不方便复制,可使用下方码云链接直接下载就好啦
https://gitee.com/bow-elongation/tank-battle.git
在这里插入图片描述
在这里插入图片描述

# 导入模块
import pygame, time, random
from pygame.sprite import Sprite
SCREEN_WIDTH = 800  # 宽度
SCREEN_HEIGHT = 500  # 高度
BG_COLOR = pygame.Color(0, 0, 0)  # 颜色
TEXT_COLOR = pygame.Color(255, 0, 0)  # 字体颜色


class Baseitem(Sprite):
    def __init__(self, color, width, height):
        pygame.sprite.Sprite.__init__(self)

# 坦克类
class MainGame():
    window = None
    my_tank = None
    enemyTankList = []  # 敌方坦克列表
    enemyTankCount = 5  # 敌方坦克数量
    myBulletList = []  # 我方坦克子弹列表
    enemyBulletList = []  # 敌方坦克子弹列表
    explodeList = []  # 爆炸效果列表
    WallList = []  # 墙壁列表

    def __init__(self):
        pass

    # 开始游戏
    def startGame(self):
        pygame.display.init()  # 加载主窗口
        MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])  # 设置窗口大小并显示
        self.createMytank()
        self.createEnemyTank()  # 初始化敌方坦克
        self.createWall()  # 初始化墙壁
        # 窗口标题设置
        pygame.display.set_caption('坦克大战')
        while True:
            time.sleep(0.02)
            # 颜色填充
            MainGame.window.fill(BG_COLOR)
            # 获取事件
            self.getEvent()
            # 绘制文字
            MainGame.window.blit(self.getTextSuface('敌方坦克剩余数量%d' % len(MainGame.enemyTankList)), (10, 10))
            if MainGame.my_tank and MainGame.my_tank.live:
                MainGame.my_tank.displayTank()  # 展示我方坦克
            else:
                del MainGame.my_tank  # 删除我方坦克
                MainGame.my_tank = None
            self.blitEnemyTank()  # 展示敌方坦克
            self.blitMyBullet()  # 我方坦克子弹
            self.blitEnemyBullet()  # 展示敌方子弹
            self.blitExplode()  # 爆炸效果展示
            self.blitWall()  # 展示墙壁
            if MainGame.my_tank and MainGame.my_tank.live:
                if not MainGame.my_tank.stop:
                    MainGame.my_tank.move()  # 调用坦克移动方法
                    MainGame.my_tank.hitWall()
                    MainGame.my_tank.myTank_hit_enemyTank()
            pygame.display.update()

    def blitWall(self):
        for wall in MainGame.WallList:
            if wall.live:
                wall.displayWall()
            else:
                MainGame.WallList.remove(wall)

    def createWall(self):  # 初始化墙壁
        for i in range(6):
            wall = Wall(i * 145, 220)
            MainGame.WallList.append(wall)

    def createMytank(self):  # 初始化我方坦克
        MainGame.my_tank = MyTank(350, 300)
        music = Music('img/start.wav')  # 创建音乐对象
        music.play()  # 播放音乐

    def createEnemyTank(self):  # 初始化敌方坦克, 将敌方坦克添加到列表中
        top = 100
        for i in range(self.enemyTankCount):  # 生成指定敌方坦克数量
            left = random.randint(0, 600)
            speed = random.randint(1, 4)
            enemy = EnemyTank(left, top, speed)
            MainGame.enemyTankList.append(enemy)

    def blitEnemyTank(self):
        for enemyTank in MainGame.enemyTankList:
            if enemyTank.live:  # 判断敌方坦克状态
                enemyTank.displayTank()
                enemyTank.randMove()  # 调用子弹移动
                enemyTank.hitWall()
                if MainGame.my_tank and MainGame.my_tank.live:
                    enemyTank.enemyTank_hit_myTank()
                enemyBullet = enemyTank.shot()  # 敌方坦克射击
                if enemyBullet:  # 判断敌方坦克子弹是否为None
                    MainGame.enemyBulletList.append(enemyBullet)  # 存储敌方坦克子弹
            else:
                MainGame.enemyTankList.remove(enemyTank)

    def blitExplode(self):
        for expolde in MainGame.explodeList:
            if expolde.live:
                expolde.displayExplode()
            else:
                MainGame.explodeList.remove(expolde)

    def blitMyBullet(self):  # 循环我方子弹列表, 并展示
        for myBullet in MainGame.myBulletList:
            if myBullet.live:  # 判断子弹的状态
                myBullet.displayBullet()
                myBullet.move()
                myBullet.myBullet_hit_enemyTank()
                myBullet.hitWall()  # 检测我方坦克子弹是否碰撞
            else:
                MainGame.myBulletList.remove(myBullet)

    def blitEnemyBullet(self):  # 循环敌方子弹列表, 并展示
        for enemyBullet in MainGame.enemyBulletList:
            if enemyBullet.live:
                enemyBullet.displayBullet()
                enemyBullet.move()
                enemyBullet.enemyBullet_hit_myTank()
                enemyBullet.hitWall()  # 检测敌方坦克子弹是否碰撞
            else:
                MainGame.enemyBulletList.remove(enemyBullet)

    # 结束游戏
    def endGame(self):
        print('游戏结束')
        exit()  # 退出游戏

    # 文字显示
    def getTextSuface(self, text):
        pygame.font.init()  # 字体初始化
        font = pygame.font.SysFont('kaiti', 16)
        # 绘制文字信息
        textSurface = font.render(text, True, TEXT_COLOR)
        return textSurface

    # 事件获取
    def getEvent(self):
        # 获取所有事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                # 退出游戏
                self.endGame()
            # 键盘按键
            if event.type == pygame.KEYDOWN:
                if not MainGame.my_tank:  # 当我方坦克不存在时, 按下Esc键重生
                    if event.key == pygame.K_ESCAPE:
                        self.createMytank()
                if MainGame.my_tank and MainGame.my_tank.live:
                    # 上、下、左、右键的判断
                    if event.key == pygame.K_LEFT:
                        MainGame.my_tank.direction = 'L'
                        MainGame.my_tank.stop = False
                        print('左键, 坦克向左移动')
                    elif event.key == pygame.K_RIGHT:
                        MainGame.my_tank.direction = 'R'
                        MainGame.my_tank.stop = False
                        print('右键, 坦克向右移动')
                    elif event.key == pygame.K_UP:
                        MainGame.my_tank.direction = 'U'
                        MainGame.my_tank.stop = False
                        print('上键, 坦克向上移动')
                    elif event.key == pygame.K_DOWN:
                        MainGame.my_tank.direction = 'D'
                        MainGame.my_tank.stop = False
                        print('下键, 坦克向下移动')
                    elif event.key == pygame.K_SPACE:
                        print('发射子弹')
                        if len(MainGame.myBulletList) < 3:  # 可以同时发射子弹数量的上限
                            myBullet = Bullet(MainGame.my_tank)
                            MainGame.myBulletList.append(myBullet)
                            music = Music('img/fire.wav')
                            music.play()
            # 松开键盘, 坦克停止移动
            if event.type == pygame.KEYUP:
                # 只有松开上、下、左、右键时坦克才停止, 松开空格键坦克不停止
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    if MainGame.my_tank and MainGame.my_tank.live:
                        MainGame.my_tank.stop = True


# 坦克类
class Tank(Baseitem):
    def __init__(self, left, top):
        # 保存加载的图片
        self.images = {
            'U': pygame.image.load('img/p1tankU.gif'),
            'D': pygame.image.load('img/p1tankD.gif'),
            'L': pygame.image.load('img/p1tankL.gif'),
            'R': pygame.image.load('img/p1tankR.gif'),
        }
        self.direction = 'L'  # 方向
        self.image = self.images[self.direction]  # 根据图片方向获取图片
        self.rect = self.image.get_rect()  # 根据图片获取区域
        self.rect.left, self.rect.top = left, top
        self.speed = 5  # 移动速度
        self.stop = True  # 坦克移动开关
        self.live = True
        self.OldLeft = self.rect.left
        self.OldTop = self.rect.top

    # 移动
    def move(self):
        self.OldLeft = self.rect.left
        self.OldTop = self.rect.top
        # 判断坦克方向进行移动
        if self.direction == 'L':
            if self.rect.left > 0:
                self.rect.left -= self.speed
        elif self.direction == 'U':
            if self.rect.top > 0:
                self.rect.top -= self.speed
        elif self.direction == 'D':
            if self.rect.top + self.rect.height < SCREEN_HEIGHT:
                self.rect.top += self.speed
        elif self.direction == 'R':
            if self.rect.left + self.rect.height < SCREEN_WIDTH:
                self.rect.left += self.speed

    # 射击
    def shot(self):
        return Bullet(self)

    def stay(self):
        self.rect.left = self.OldLeft
        self.rect.top = self.OldTop

    def hitWall(self):
        for wall in MainGame.WallList:
            if pygame.sprite.collide_rect(self, wall):
                self.stay()

    # 展示坦克的方法
    def displayTank(self):
        # 获取展示对象
        self.image = self.images[self.direction]
        # 调用blit展示
        MainGame.window.blit(self.image, self.rect)


# 我方坦克
class MyTank(Tank):
    def __init__(self, left, top):
        super(MyTank, self).__init__(left, top)

    def myTank_hit_enemyTank(self):
        for enemyTank in MainGame.enemyTankList:
            if pygame.sprite.collide_rect(self, enemyTank):
                self.stay()


# 敌方坦克
class EnemyTank(Tank):
    def __init__(self, left, top, speed):
        super(EnemyTank, self).__init__(left, top)
        # 加载图片集
        self.images = {
            'U': pygame.image.load('img/enemy1U.gif'),
            'D': pygame.image.load('img/enemy1D.gif'),
            'L': pygame.image.load('img/enemy1L.gif'),
            'R': pygame.image.load('img/enemy1R.gif'),
        }
        # 随机生成方向
        self.direction = self.randDirection()
        self.image = self.images[self.direction]  # 根据方向获取图片
        self.rect = self.image.get_rect()  # 获取区域
        self.rect.left, self.rect.top = left, top  # 对left和top赋值
        self.speed = speed  # 速度
        self.flag = True  # 坦克移动开关
        self.step = 50  # 敌方坦克步数

    def enemyTank_hit_myTank(self):
        if pygame.sprite.collide_rect(self, MainGame.my_tank):
            self.stay()

    def randDirection(self):
        nums = random.randint(1, 4)  # 生成1~4的随机整数
        if nums == 1:
            return "U"
        elif nums == 2:
            return "D"
        elif nums == 3:
            return "L"
        elif nums == 4:
            return "R"

    def randMove(self):  # 坦克的随机方向移动
        if self.step < 0:  # 步数小于0, 随机改变方向
            self.direction = self.randDirection()
            self.step = 50  # 步数复位
        else:
            self.move()
            self.step -= 1

    def shot(self):  # 重写shot方法
        num = random.randint(1, 100)
        if num < 10:
            return Bullet(self)


# 子弹类
class Bullet(Baseitem):
    def __init__(self, tank):
        self.image = pygame.image.load('img/enemymissile.gif')  # 图片加载
        self.direction = tank.direction  # 子弹的方向
        self.rect = self.image.get_rect()  # 获取区域
        if self.direction == 'U':  # 子弹的left和top与方向有关
            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top - self.rect.height
        elif self.direction == 'D':
            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top + tank.rect.height
        elif self.direction == 'L':
            self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2
            self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
        elif self.direction == 'R':
            self.rect.left = tank.rect.left + tank.rect.width
            self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
        self.speed = 5   # 子弹的速度
        self.live = True  # 子弹的状态

    # 移动
    def move(self):
        if self.direction == 'U':
            if self.rect.top > 0:
                self.rect.top -= self.speed
            else:
                self.live = False  # 修改子弹的状态
        elif self.direction == 'R':
            if self.rect.left + self.rect.width < SCREEN_WIDTH:
                self.rect.left += self.speed
            else:
                self.live = False  # 修改子弹的状态
        elif self.direction == 'D':
            if self.rect.top + self.rect.height < SCREEN_HEIGHT:
                self.rect.top += self.speed
            else:
                self.live = False  # 修改子弹的状态
        elif self.direction == 'L':
            if self.rect.left > 0:
                self.rect.left -= self.speed
            else:
                self.live = False  # 修改子弹的状态

    def hitWall(self):
        for wall in MainGame.WallList:  # 循环遍历墙壁列表
            if pygame.sprite.collide_rect(self, wall):  # 检测子弹是否碰撞墙壁
                self.live = False  # 修改子弹状态
                wall.hp -= 1  # 碰撞后墙壁生命值减少
                if wall.hp <= 0:
                    wall.live = False

    # 子弹展示
    def displayBullet(self):
        # 将图片加载到窗口
        MainGame.window.blit(self.image, self.rect)

    def myBullet_hit_enemyTank(self):
        for enemyTank in MainGame.enemyTankList:
            if pygame.sprite.collide_rect(enemyTank, self):
                enemyTank.live = False
                self.live = False
                explode = Explode(enemyTank)
                MainGame.explodeList.append(explode)

    def enemyBullet_hit_myTank(self):
        if MainGame.my_tank and MainGame.my_tank.live:
            if pygame.sprite.collide_rect(MainGame.my_tank, self):
                explode = Explode(MainGame.my_tank)  # 爆炸对象
                MainGame.explodeList.append(explode)  # 将爆炸对象添加到爆炸列表中
                self.live = False  # 修改敌方子弹的状态
                MainGame.my_tank.live = False  # 我方坦克的状态


# 墙壁类
class Wall():
    def __init__(self, left, top):
        self.image = pygame.image.load('img/steels.gif')  # 加载墙壁图片
        self.rect = self.image.get_rect()  # 获取区域
        self.rect.left, self.rect.top = left, top  # 设置left, top
        self.live = True  # 存活状态
        self.hp = 3  # 设置墙壁生命值

    # 展示墙壁
    def displayWall(self):
        MainGame.window.blit(self.image, self.rect)


# 爆炸类
class Explode():
    def __init__(self, tank):
        self.rect = tank.rect
        self.images = [
            pygame.image.load('img/blast0.gif'),
            pygame.image.load('img/blast1.gif'),
            pygame.image.load('img/blast2.gif'),
            pygame.image.load('img/blast3.gif'),
            pygame.image.load('img/blast4.gif'),
        ]
        self.step = 0
        self.image = self.images[self.step]
        self.live = True

    # 爆炸效果
    def displayExplode(self):
        if self.step < len(self.images):
            self.image = self.images[self.step]
            self.step += 1
            MainGame.window.blit(self.image, self.rect)  # 添加到主窗口
        else:
            self.live = False
            self.step = 0


# 音效类
class Music():
    def __init__(self, filename):
        self.filename = filename
        pygame.mixer.init()
        pygame.mixer.music.load(self.filename)  # 加载音乐

    # 音乐播放
    def play(self):
        pygame.mixer.music.play()


if __name__ == '__main__':
    MainGame().startGame()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/583013.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能技术在教育中的潜力有多大

原文&#xff1a;人工智能技术在教育中的潜力有多大&#xff1f; - 知乎 作者&#xff1a;大全Prompt 链接&#xff1a;https://www.zhihu.com/question/637034129/answer/3346272227 来源&#xff1a;知乎 谢邀&#xff1a;在技术快速发展的今天&#xff0c;人工智能&#x…

数据复制的艺术:深拷贝与浅拷贝在JavaScript中的实现方式

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 赋值和拷贝 浅拷贝与深拷贝区别 浅拷贝的实现方式 1.Object.assign() 2.…

变革 Perplexica:AI驱动的问答搜索引擎

Perplexica是一个开源的人工智能搜索工具&#xff0c;也可以说是一款人工智能搜索引擎&#xff0c;它深入互联网以找到答案。受Perplexity AI启发&#xff0c;它是一个开源选择&#xff0c;不仅可以搜索网络&#xff0c;还能理解您的问题。它使用先进的机器学习算法&#xff0c…

国产Sora诞生!清华团队发布Vidu大模型,可直接生成16秒视频

大模型之争已从单模态转向多模态。 4月27日&#xff0c;在2024中关村论坛年会未来人工智能先锋论坛上&#xff0c;清华大学联合北京生数科技有限公司正式发布了文生视频大模型——Vidu。 在会议上&#xff0c;清华大学人工智能研究院副院长、生数科技首席科学家朱军对外展示了…

windows11家庭版开启Hyper-v

前提&#xff1a;如果在控制面板中-->程序和功能-->启用和关闭windows功能-->没有Hyper-v 1.什么是Hyper-v&#xff1f; Hyper-v分为两个部分&#xff1a;底层的虚拟机平台、上层的虚拟机管理软件 2.Hyper-v安装 2.1新建hyper.cmd文件&#xff0c;写入下面的内容&…

C++初阶-----对运算符重载的进一步理解(2)

目录 1.对于加加&#xff0c;减减运算符的重载理解 2.const修饰的一些事情 3.日期对象之间的减法实现逻辑 1.对于加加&#xff0c;减减运算符的重载理解 &#xff08;1&#xff09;在C语言里面&#xff0c;我们已经知道并且了解加加&#xff0c;减减的一些基本的用法&#…

RepeatMasker 基因组重复区域文件

rmsk.txt 一般关注标红的几列, 各列含义: Schema for RepeatMasker - Repeating Elements by RepeatMasker "rmsk.txt" 是 UCSC Genome Browser 提供的一个文件,用于描述重复序列的注释信息。通常,它包含了以下列: 1. **bin**:UCSC Genome Browser 使用的染色…

笔记:编写程序,绘制一个展示 2013~2019 财年阿里巴 巴淘宝+天猫平台的 GMV 的柱形图,实现过程如下:

文章目录 前言一、GMV 的柱形图是什么&#xff1f;二、编写代码总结 前言 编写程序。根据实例 2 的要求&#xff0c;绘制一个展示 2013~2019 财年阿里巴 巴淘宝天猫平台的 GMV 的柱形图&#xff0c;实现过程如下&#xff1a; &#xff08;1&#xff09; 导入 matplotlib.pypl…

2024中国(江西)国际先进陶瓷材料及智能装备博览会

2024中国&#xff08;江西&#xff09;国际先进陶瓷材料及智能装备博览会 “中国&#xff08;江西&#xff09;国际先进陶瓷材料及智能装备博览会” 陶瓷三新展 &#xff08;新材料、新装备、新技术&#xff09; 绿色智能、引领未来 2024年11月1日-11月3日 中国江西 南昌…

生活服务推出品牌实惠团购,覆盖五一假期“吃喝玩乐”多场景

4月26日&#xff0c;抖音生活服务平台上线“跟着大牌过五一”活动会场&#xff0c;携手22家连锁品牌商家&#xff0c;于“五一”前推出优价团购和时令新品&#xff0c;覆盖“吃喝玩乐”多重购物需求&#xff0c;助力假期消费。同时&#xff0c;伴随各地涌现的文旅热潮&#xff…

项目:使用LNMP搭建私有云存储

目录 项目&#xff1a;使用LNMP搭建私有云存储 准备工作 回复快照&#xff0c;关闭安全软件 上传软件 设置nextcloud安装命令权限 设置数据库 重启数据库 配置nginx 安装 内网穿透 cpolar的域名信任 项目&#xff1a;使用LNMP搭建私有云存储 准备工作 回复快照&a…

C#上位机与S7-200Smart通信注意事项

S7-200SMART连接 问题描述 我们使用C#开发上位机和S7-200Smart系列PLC交互数据时&#xff0c;大多会用到Sharp7、Snap7之类的通信类库。有些通信类库默认的使用的是PG连接资源&#xff0c;而对于S7-200Smart来说&#xff0c;它的PG连接资源只有1个。 官网200smart提到的连接数…

解决idea不识别${pageContext.request.contextPath}的方法

文章目录 一、产生原因二、解决方法——直接修改web.xml文件三、修改模板——找到web.xml模板&#xff0c;修改替换 一、产生原因 由于web.xml 使用的web-app版本号过低。导致无法识别"{pageContext.request.contextPath}"。 IDEA在创建javaweb项目的时候&#xff0…

imx6ull配置交叉编译环境编译u-boot及linux所遇问题解决记录

文章目录 前言一、问题 1 及解决方法1、问题 1 描述2、问题 1 解决方法 二、问题 2 及解决方法1、问题 2 描述2、问题 2 解决方法 三、问题 3 及解决方法1、问题 3 描述2、问题 3 解决方法 四、问题 4 及解决方法1、问题 4 描述2、问题 4 解决方法 前言 CoM-iMX6UL(L) 是一款兼…

笔记:能量谱密度与功率谱密度(二)

目录 一、ESD与PSD的定义、单位、性质 二、对ESD与PSD的直观理解 三、总结&#xff1a; 某物理量的“分布”在离散系统中&#xff0c;各点(纵坐标含义&#xff09;的物理意义仍然是该物理量&#xff0c;而在连续系统中&#xff0c;各点&#xff08;纵坐标含义&#xff09;的物…

react报错:Warning: Each child in a list should have a unique “key“ prop.

我是万万没想到的&#xff0c;使用Popconfirm不添加key属性也会报错&#xff1a; react-refresh:160Warning: Each child in a list should have a unique "key" prop. Check the render method of Cell. Seehttps://reactjs.org/link/warning-keys for more informa…

STM32点灯大师(点了一颗LED灯,轮询法)

配置操作&#xff1a; 一、使用CubeMX配置到大致的操作 1.1 选择芯片 1.2 选择引脚&#xff08;根据电路图&#xff09; 1.3 配置gpio口 1.4 配置系统 1.5文件项目操作 最后就是点击 二、点击CubeMX生成的代码&#xff0c;并且修改代码 2.1 看看效果 2.2 写代码

Python 网络编程实践:从基础到进阶

目录 网络编程 一.IP地址简介 1. IP 地址的概念 1.1. IP 地址的表现形式 1.2. IP 地址的作用 2. 查看 IP 地址 3. 检查网络是否正常 4. 小技巧 二.端口和端口号 1. 什么是端口 2. 什么是端口号 3. 端口和端口号的关系 4. 端口号的分类 4.1. 知名端口号 4.2. 动…

【Unity学习笔记】第十四 Prefab 概念解惑

目录 1 prefab、prefab变体、prefab覆盖和prefab 嵌套2 connect 与unpack3 prefab到底是什么&#xff0c;它和gameobject又有什么区别&#xff1f;4 为什么要用prefab&#xff1f;5 代码动态加载prefab6 为什么我unity PrefabUtility.InstantiatePrefab() 得到的是null7 Prefab…

基于Springboot的租房网站

基于SpringbootVue的租房网站的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 房屋信息 交流论坛 房屋资讯 后台登录 用户管理 房屋类型管理 房屋信息管理 预…