当前位置: 首页 > news >正文

【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 距离上边topdef __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'# 根据当前图片的方向获取图片 surfaceself.image = self.images[self.direction]# 根据图片获取区域self.rect = self.image.get_rect()# 设置区域的left 和topself.rect.left = leftself.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 = 100for 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 / 2self.rect.top = tank.rect.top - self.rect.heightelif self.direction == 'D':self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top + tank.rect.heightelif self.direction == 'L':self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2elif self.direction == 'R':self.rect.left = tank.rect.left + tank.rect.widthself.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2self.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 = FalseeTank.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 = FalseeTank.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 = filenamepygame.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 = Nonemy_tank = NoneenemyTankList = []  # 敌方坦克列表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 = Noneself.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 = 100for 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:  # 判断敌方坦克子弹是否为NoneMainGame.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 = Falseprint('左键, 坦克向左移动')elif event.key == pygame.K_RIGHT:MainGame.my_tank.direction = 'R'MainGame.my_tank.stop = Falseprint('右键, 坦克向右移动')elif event.key == pygame.K_UP:MainGame.my_tank.direction = 'U'MainGame.my_tank.stop = Falseprint('上键, 坦克向上移动')elif event.key == pygame.K_DOWN:MainGame.my_tank.direction = 'D'MainGame.my_tank.stop = Falseprint('下键, 坦克向下移动')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, topself.speed = 5  # 移动速度self.stop = True  # 坦克移动开关self.live = Trueself.OldLeft = self.rect.leftself.OldTop = self.rect.top# 移动def move(self):self.OldLeft = self.rect.leftself.OldTop = self.rect.top# 判断坦克方向进行移动if self.direction == 'L':if self.rect.left > 0:self.rect.left -= self.speedelif self.direction == 'U':if self.rect.top > 0:self.rect.top -= self.speedelif self.direction == 'D':if self.rect.top + self.rect.height < SCREEN_HEIGHT:self.rect.top += self.speedelif 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.OldLeftself.rect.top = self.OldTopdef 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 -= 1def 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 / 2self.rect.top = tank.rect.top - self.rect.heightelif self.direction == 'D':self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top + tank.rect.heightelif self.direction == 'L':self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2elif self.direction == 'R':self.rect.left = tank.rect.left + tank.rect.widthself.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2self.speed = 5   # 子弹的速度self.live = True  # 子弹的状态# 移动def move(self):if self.direction == 'U':if self.rect.top > 0:self.rect.top -= self.speedelse:self.live = False  # 修改子弹的状态elif self.direction == 'R':if self.rect.left + self.rect.width < SCREEN_WIDTH:self.rect.left += self.speedelse:self.live = False  # 修改子弹的状态elif self.direction == 'D':if self.rect.top + self.rect.height < SCREEN_HEIGHT:self.rect.top += self.speedelse:self.live = False  # 修改子弹的状态elif self.direction == 'L':if self.rect.left > 0:self.rect.left -= self.speedelse: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 = Falseself.live = Falseexplode = 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, topself.live = True  # 存活状态self.hp = 3  # 设置墙壁生命值# 展示墙壁def displayWall(self):MainGame.window.blit(self.image, self.rect)# 爆炸类
class Explode():def __init__(self, tank):self.rect = tank.rectself.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 = 0self.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 += 1MainGame.window.blit(self.image, self.rect)  # 添加到主窗口else:self.live = Falseself.step = 0# 音效类
class Music():def __init__(self, filename):self.filename = filenamepygame.mixer.init()pygame.mixer.music.load(self.filename)  # 加载音乐# 音乐播放def play(self):pygame.mixer.music.play()if __name__ == '__main__':MainGame().startGame()

相关文章:

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

文章目录 一、游戏运行效果二、代码实现2.1 项目搭建2.2 加载我方坦克2.3 加载敌方坦克2.4 添加爆炸效果2.5 坦克大战之音效处理 三、完整代码 一、游戏运行效果 二、代码实现 坦克大战游戏 2.1 项目搭建 本游戏主要分为两个对象&#xff0c;分别是我方坦克和敌方坦克。用户可…...

【机器学习】经典CNN架构

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 经典CNN架构1. 引言2. LeNet3. AlexNet4. VGGNet5. GoogLeNet(Inception)6. Res…...

图像数据处理21

五、边缘检测 5.2基于二阶导数的边缘检测 一阶导数&#xff08;如Sobel、Prewitt算子&#xff09;能够捕捉到灰度值的快速变化&#xff0c;但有时会因检测到过多的边缘点而导致边缘线过粗。为了更加精确地定位边缘位置&#xff0c;可以利用二阶导数的零交叉点。零交叉点是是函…...

day37动态规划+三.Github链接本地仓库

一.动态规划 474.一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 思路:这道题更像是另一种的0-…...

设备运维故障排查与修复技巧

运维中最常见的40个故障问题及其解决方法: 1. 网络不通问题:无法访问网络资源。 解决方法:检查物理线路、交换机端口、网卡驱动和配置,使用ping、traceroute等工具定位问题。 2. 网络速度慢问题:访问网络资源速度慢。 解决方法:分析带宽使用情况,检查是否存在广播风…...

探索Python的自动化魔法:AutoIt库揭秘

文章目录 探索Python的自动化魔法&#xff1a;AutoIt库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;AutoIt是什么&#xff1f;第三部分&#xff1a;如何安装AutoIt库&#xff1f;第四部分&#xff1a;AutoIt的五个简单函数第五部分&#xff1a;场景应用第六部分&…...

【I/O多路复用】

基于I/O多路复用的并发编程 I/O实现I/O多路复用select优缺点 pollepoll优点 I/O I/O复用是基于一个单进程或单线程的一个执行流当中监控多个输入输出流的技术&#xff08;网络套接字或者文件描述符进行监控&#xff09;。单进程或单线程&#xff0c;允许多个用户对单进程发起连…...

【python报错已解决】“IndexError: list index out of range”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 你是否在处理Python列表时遇到了“IndexError: list index out of range”的错误&#xff1f;这个错误可能会让你的程序中…...

oracle和mysql查询某字段在哪个表中

oracle和mysql查询某字段在哪个表中 oracle的 select TABLE_NAME from user_tab_columns where COLUMN_NAME字段名mysql的&#xff1a; select table_schema ,table_name from information_schema.columns where column_name ‘字段名’ 查询结果table_schema为数据库名&a…...

TCP vs UDP:揭秘可靠性与效率之争

概述 今天我们开始主要讲解TCP的相关知识点。在之前讲解分层章节的时候&#xff0c;我们提到过一个重要观点。在网络层及以下几层&#xff0c;更多的是让主机与主机建立连接&#xff0c;也就是说你的电脑需要知道另一台电脑在哪里才能连接上它。然而&#xff0c;在网络中的通信…...

“树”的高度的计算——CSP-J1真题详解

如同树有高度一样&#xff0c;数据结构中的“树”也有高度&#xff0c;只不过这个高度指的是第几“层”。就像武功可以修炼到第几层一样&#xff0c;树也可以长到第几层。 需要指明的是&#xff0c;树的根节点属于第几层是没有严格的定义的&#xff0c;一般被认为是处于第0层或…...

Docker介绍、docker安装以及实现docker的远程管理

1.Docker介绍 1.Docker介绍 Docker 是⼀个开源的应用容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采用“沙盒”机制&#xff0c;容器之间不会存在任何接口。 Docker 通过 Linux Container&#xff08;容器&#xff09;技术将任意类型的应用进行包装&#xff0c;变成一…...

【UE5】基于摄像机距离逐渐剔除角色

效果 步骤 1. 新建一个工程&#xff0c;在内容浏览器中添加第三人称游戏内容包 2. 找到第三人称角色的材质实例“MI_Quinn_01”并打开 找到材质实例的父项材质“M_Mannequin” 打开材质“M_Mannequin” 在材质图表中添加如下节点 此时运行效果如文章开头所示。 参考视频&#…...

LabVIEW优化内存使用

在LabVIEW中&#xff0c;优化内存使用的关键在于理解LabVIEW的内存管理机制并采用一些最佳实践。以下是一些可能帮助减少内存占用的方法&#xff1a; 1. 减少数据副本的生成 避免不必要的数据复制&#xff1a;每当你在程序中传递数组或子数组时&#xff0c;LabVIEW可能会创建副…...

多进程和多线程基础概念LINUX

进程和程序的区别 程序是静态的&#xff0c;它是保存在磁盘上的指令的有序集合&#xff0c;没有任何执行的概念进程是一个动态的概念&#xff0c;它是程序执行的过程&#xff0c;包括了动态创建、调度和销毁的整个过程 并行&#xff1a;在 cpu 多核的支持下&#xff0c;实现物…...

React Native的Android端fetch的网络请求FormData请求错误:TypeError:Network request failed

// formdataconst formData new FormData();formData.append("code", appUserCode);formData.append("wallet", appName);// const formDataStr code appUserCode &wallet appName;// 参数形式//const _body code${appUserCode}&wallet${app…...

python之matplotlib (1 介绍及基本用法)

介绍 matplotlib是Python中的一个绘图库&#xff0c;它提供了一个类似于 MATLAB 的绘图系统。使用matplotlib你可以生成图表、直方图、功率谱、条形图、错误图、散点图等。matplotlib广泛用于数据可视化领域&#xff0c;是 Python 中最著名的绘图库之一。 同样matplotlib的安…...

ROS2常用指令

ROS2&#xff08;Robot Operating System 2&#xff09;是一个用于机器人软件开发的灵活框架&#xff0c;它提供了一套丰富的工具和库来支持机器人的开发、模拟、部署和测试。ROS2的常用指令可以大致分为几个类别&#xff0c;包括功能包管理、节点管理、话题管理、服务管理、动…...

SQL注入(原理、分类、union、POST注入)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 SQL注入简介 SQL注入原理 SQL注入类型 MySQL与SQL注入的相关知识 information_schema 数据库的结构 数据库查询语句 limit的用法 需要记住的几个函数 注释符号 SQL注入探测方法 SQL注入漏洞攻击流程…...

【勒索病毒应急响应流程】

概述 不同应急事件响应方式不同,建议大家阅读以下案例,解决自己当前的困扰,当然也可以根据自己的经验对文章进行补充和修正,欢迎在评论区留言。 案例1 事件概述 某安服团队接到某政府部门的远程应急响应求助,要求对被勒索服务器进行排查分析并溯源。 排查溯源 1、应…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...