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

news2024/11/24 5:56:06

文章目录

      • 一、游戏运行效果
      • 二、代码实现
        • 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.coloradmin.cn/o/1633023.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构复习指导之数组和特殊矩阵

文章目录 数组和特殊矩阵 考纲内容 复习提示 前言 1.数组的定义 2.数组的存储结构 3.特殊矩阵的压缩存储 3.1对称矩阵 3.2三角矩阵 3.3三对角矩阵 4.稀疏矩阵 5.知识回顾 数组和特殊矩阵 考纲内容 &#xff08;一&#xff09;栈和队列的基本概念 &#xff08;二&a…

数据结构六:线性表之顺序栈的设计

目录 一、栈的应用场景 二、栈的基本概念和结构 2.1 栈的基本概念 2.2 栈的结构 2.3 栈的实现方式 三、顺序栈的接口函数实现 3.0 顺序栈的概念和结构 3.1 顺序栈的接口函数 3.2 顺序栈的设计&#xff08;结构体&#xff09; 3.3 顺序栈的初始化 3.4 入栈&#x…

Python转换文本文件为PDF文档,绘制文本到PDF文档页面

文本文件因其轻便、易编辑的优势&#xff0c;常用于日常文字记录与数据交换&#xff1b;而PDF文档则以高保真、格式稳定和良好的阅读体验&#xff0c;成为正式报告、文献发布等场景的首选。将文本文件转为PDF&#xff0c;在PDF内精准绘制文本&#xff0c;旨在兼顾内容的规范呈现…

云计算革新:以太网 Scale-UP 网络为 GPU 加速赋能

谈谈基于以太网的GPU Scale-UP网络 Intel Gaudi-3 采用 RoCE 互联技术&#xff0c;促进了 Scale-UP 解决方案。业界专家 Jim Keller 倡导以太网替代 NVLink。Tenstorrent 成功应用以太网实现片上网络互联。RoCE 和以太网已成为互联解决方案的新兴趋势&#xff0c;为高性能计算提…

区块链技术--编译BSV源码(v1.0.1)

编译好的可执行文件bitcoin-cli 和 bitcoind 下载: https://github.com/youngqqcn/QBlockChainNotes/blob/master/BTC%E7%B3%BB%E5%B1%B1%E5%AF%A8%E5%B8%81/my_bsv_v1.0.1.tar.gz 安装 libminiupnpc wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packa…

商店数据(六)

目录 41.短信发送记录表 42.职员登录记录表 43.会员登录记录表 ​44.后台菜单表 45.商城信息表 46.消息队列表 47.移动端首页按钮管理表 48.商城导航表 41.短信发送记录表 CREATE TABLE wst_log_sms (smsId int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,smsSrc t…

IOCP实现UDP Server

IOCP实现UDP Server 1、IOCP原理图 参考文献1&#xff1a;IOCP详解-阿里云开发者社区 (aliyun.com) 参考文献2&#xff1a;IOCP编程之基本原理 - 史D芬周 - 博客园 (cnblogs.com) 原理图 同步以及异步 2、UDP Server代码以及测试代码 // iocpudpdemo.cpp : 此文件包含 &qu…

再谈钓鱼邮件

再谈钓鱼邮件 概述 最近对邮件的防御策略进行了更新&#xff0c;结合威胁情报和安全沙箱对收到的钓鱼邮件进行了分析&#xff0c;期望这些案例能对大家有所帮助。 网关上拦截的钓鱼邮件基本可以分三个类别&#xff1a;链接钓鱼邮件、附件钓鱼邮件以及邮件头伪造钓鱼邮件&…

在谷歌浏览器访问特定的网站 提示此网站无法提供安全连接

1、问题描述&#xff1a; 最近通过谷歌浏览器访问某些网址提示此网站无法提供安全连接&#xff0c;换一个浏览器就能正确打开&#xff01; 例子如下&#xff1a; 访问 https://baijiahao.baidu.com/s?id1788533041823242656 2、查找原因 通过控制台发现请求未有响应码&#xf…

【数据分析面试】34.填充NaN值 (Python:groupby/sort_value/ffill)

题目&#xff1a;填充NaN值 &#xff08;Python) 给定一个包含三列的DataFrame&#xff1a;client_id、ranking、value 编写一个函数&#xff0c;将value列中的NaN值用相同client_id的前一个非NaN值填充&#xff0c;按升序排列。 如果不存在前一个client_id&#xff0c;则返…

小红书从记忆机制解读信息检索,提出新范式获得 EACL Oral

近日&#xff0c;来自小红书搜索算法团队的论文《Generative Dense Retrieval: Memory Can Be a Burden》被自然语言处理领域国际会议 EACL 2024 接收为 Oral&#xff0c;接受率为 11.32%&#xff08;144/1271&#xff09;。 他们在论文中提出了一种新颖的信息检索范式——生成…

python环境安装jupyter

安装完毕之后下一步可以参考&#xff1a;配置jupyter的启动路径-CSDN博客 1 前提条件&#xff1a;python环境 系统&#xff1a;win10 python&#xff1a;本地已经有python&#xff0c;可以查看本地的python版本&#xff1a; C:\Users\PC>python --version Python 3.8.10 …

为什么本国货币的贬值会导致本国物价的上涨

本国货币贬值意味着其对外国货币的汇率下降&#xff0c;也就是说&#xff0c;同样数量的本国货币现在能兑换的外国货币减少了。这种情况下&#xff0c;本国货币的购买力相对于外国货币减弱了。本国货币贬值可能导致本国物价上涨的几个原因&#xff1a; 进口成本上升&#xff1a…

38.WEB渗透测试-信息收集-信息收集-企业信息收集(5)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;37.WEB渗透测试-信息收集-企业信息收集&#xff08;4&#xff09; 上个内容用到了cdn&am…

Windows Server 评估版转换(升级)为完整版

临时方法 获取 Windows Server 的剩余宽限期 Slmgr /dliWindows Server免费试用期可以使用以下命令合法延长5次&#xff0c;共180天&#xff1a; slmgr /rearm这意味着所评估的 Windows Server 的最长可用时间为 3 年 ( 180 days * 6)。 试用期到期后&#xff0c;Windows S…

Python对Excel两列数据进行运算

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python对Excel两列数据进行运算 在日常工作中&#xff0c;经常会遇到需要对Excel表格中的数…

win中python中OpenCV使用cv2.imshow()报错的解决办法

1. 问题 cv2.error: OpenCV(4.9.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:1272: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK 2.x or Cocoa support. If you are on Ubuntu o…

STM32读写备份寄存器BKP

今天学习的读写STM32的备份寄存器BKP的步骤&#xff0c;这节知识是比较简单的&#xff0c;一共也就两大部&#xff1a; 这个BKP寄存器的意思就是在芯片的VB引脚上接个电池&#xff0c;就能保存其寄存器中的数据掉电不丢失。先来看看电池的接法&#xff1a; 好&#xff0c;下面…

3分钟了解拍摄VR全景需要哪些硬件

VR全景图片是一张水平方向360度&#xff0c;垂直方向180度&#xff0c; 图片尺寸宽高比为2:1的图片。 通过720yun APP或720yun官网上传生成全景H5页面&#xff0c;即可360度全方位观看画面中的景象。 拍摄VR全景有很多方法&#xff0c;下面介绍用单反相机、全景相机、智能手机…

【Paddle】PCA线性代数基础 + 领域应用:人脸识别算法(1.1w字超详细:附公式、代码)

【Paddle】PCA线性代数基础及领域应用 写在最前面一、PCA线性代数基础1. PCA的算法原理2. PCA的线性代数基础2.1 标准差 Standard Deviation2.2 方差 Variance2.3 协方差 Covariance2.4 协方差矩阵 The Covariance Matrix2.5 paddle代码demo①&#xff1a;计算协方差矩阵2.6 特…