基于python实现坦克大战游戏
作者:严肃温柔 发布时间:2023-01-29 01:48:30
标签:python,坦克大战
本文实例为大家分享了python实现坦克大战游戏的具体代码,供大家参考,具体内容如下
游戏界面
pygame游戏引擎的安装
pip安装
windows + R --> cmd --> 命令行输入 pip install 模块名==版本号
pycharm中安装
File --> setting --> Project --> Project Interpreter --> 右侧 + install --> 搜索框输入pygame --> 下方
installPackage
面向对象分析
分析组成类
实现框架的搭建(类的设计)
主逻辑类
坦克类
我方坦克
敌方坦克 * 类
* 类
墙壁类
音效类
框架搭建
import pygame
#主逻辑类
class MainGame():
def startGame(self):
pass
def gameOver(self):
pass
#基本坦克类
class BaseTank():
pass
#我方坦克类
class MyTank():
pass
#敌方坦克类
class EnemyTank():
pass
# * 类
class Bullet():
pass
# * 类
class Explode():
pass
#墙壁类
class Wall():
pass
#音效类
class Audio():
pass
game = MainGame()
game.startGame()
展示主窗口
import pygame
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 550
#主逻辑类
class MainGame():
#游戏主窗口
window = None
def startGame(self):
#调用窗口初始化方法
pygame.display.init()
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
pygame.display.set_caption('坦克大战v1.02')
while True:
#填充窗口背景色
MainGame.window.fill((0,0,0))
#刷新
pygame.display.update()
def gameOver(self):
pass
事件监听
class MainGame():
#游戏主窗口
window = None
def startGame(self):
#调用窗口初始化方法
pygame.display.init()
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
pygame.display.set_caption('坦克大战'+VERSION)
while True:
#填充窗口背景色
MainGame.window.fill((0,0,0))
#调用事件处理方法
self.getEvents()
#刷新
pygame.display.update()
#所有事件处理的方法
def getEvents(self):
#获取队列中所有事件,遍历事件,对type为QUIT以及KEYDOWN两种事件类型处理
eventList = pygame.event.get()
#遍历所有事件
for e in eventList:
if e.type == pygame.QUIT:
#调用游戏结束的方法
self.gameOver()
#如果事件类型为按下键盘按键
elif e.type == pygame.KEYDOWN:
#根据具体按键做对应处理
if e.key == pygame.K_UP:
print("向上移动")
elif e.key == pygame.K_DOWN:
print("向下移动")
elif e.key == pygame.K_LEFT:
print("向左移动")
elif e.key == pygame.K_RIGHT:
print("向右移动")
elif e.key == pygame.K_SPACE:
print("biubiu~~~")
# elif e.type == pygame.MOUSEMOTION:
# print(e.pos)
def gameOver(self):
#结束程序
exit()
显示我方坦克
#我方坦克类
class MyTank(BaseTank):
def __init__(self,x,y):
super(MyTank, self).__init__()
#设置具体的图片集
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 = 'U'
#设置坦克的图片
self.image = self.images[self.direction]
#先基于图像获取坦克的位置以及大小
self.rect = self.image.get_rect()
#修改坦克坐标,改成自定义位置
self.rect.centerx = x
self.rect.centery = y
def displayTank(self):
self.image = self.images[self.direction]
MainGame.window.blit(self.image,self.rect)
实现我方坦克的移动
坦克类中,实现移动方法
def move(self):
#移动,基于速度在指定的方向进行移动
if self.direction == 'U':
if self.rect.centery > self.rect.height/2:
self.rect.centery ‐= self.speed
elif self.direction == 'D':
if self.rect.centery < SCREEN_HEIGHT ‐ self.rect.height/2:
self.rect.centery += self.speed
elif self.direction == 'L':
if self.rect.centerx > self.rect.height/2:
self.rect.centerx ‐= self.speed
elif self.direction == 'R':
if self.rect.centerx < SCREEN_WIDTH ‐ self.rect.height/2:
self.rect.centerx += self.speed
事件处理方法中新增移动处理
#所有事件处理的方法
def getEvents(self):
#获取队列中所有事件,遍历事件,对type为QUIT以及KEYDOWN两种事件类型处理
eventList = pygame.event.get()
#遍历所有事件
for e in eventList:
if e.type == pygame.QUIT:
#调用游戏结束的方法
self.gameOver()
#如果事件类型为按下键盘按键
elif e.type == pygame.KEYDOWN:
#根据具体按键做对应处理
if e.key == pygame.K_UP:
print("向上移动")
MainGame.tank1.direction = 'U'
MainGame.tank1.move()
elif e.key == pygame.K_DOWN:
print("向下移动")
MainGame.tank1.direction = 'D'
MainGame.tank1.move()
elif e.key == pygame.K_LEFT:
print("向左移动")
MainGame.tank1.direction = 'L'
MainGame.tank1.move()
elif e.key == pygame.K_RIGHT:
print("向右移动")
MainGame.tank1.direction = 'R'
MainGame.tank1.move()
elif e.key == pygame.K_SPACE:
print("biubiu~~~")
优化移动方式
事件中新增坦克移动开关控制
#所有事件处理的方法
def getEvents(self):
#获取队列中所有事件,遍历事件,对type为QUIT以及KEYDOWN两种事件类型处理
eventList = pygame.event.get()
#遍历所有事件
for e in eventList:
if e.type == pygame.QUIT:
#调用游戏结束的方法
self.gameOver()
#如果事件类型为按下键盘按键
elif e.type == pygame.KEYDOWN:
#根据具体按键做对应处理
if e.key == pygame.K_UP:
print("向上移动")
MainGame.tank1.direction = 'U'
#修改坦克运动状态
MainGame.tank1.stop = False
elif e.key == pygame.K_DOWN:
print("向下移动")
MainGame.tank1.direction = 'D'
MainGame.tank1.stop = False
elif e.key == pygame.K_LEFT:
print("向左移动")
MainGame.tank1.direction = 'L'
MainGame.tank1.stop = False
elif e.key == pygame.K_RIGHT:
print("向右移动")
MainGame.tank1.direction = 'R'
MainGame.tank1.stop = False
elif e.key == pygame.K_SPACE:
print("biubiu~~~")
主逻辑的循环中优化移动
def startGame(self):
#调用窗口初始化方法
pygame.display.init()
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
pygame.display.set_caption('坦克大战'+VERSION)
#调用创建我方坦克的方法
self.creatMyTank()
while True:
#填充窗口背景色
MainGame.window.fill((0,0,0))
#调用事件处理方法
self.getEvents()
#展示我方坦克
self.showMyTank()
if not MainGame.tank1.stop:
# 我方坦克移动
MainGame.tank1.move()
#刷新
pygame.display.update()
#新增,程序休眠,优化坦克移动速度
time.sleep(0.020)
实现敌方坦克的加载
完善敌方坦克类
#敌方坦克类
class EnemyTank(BaseException):
#v1.07
def __init__(self,x,y):
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.randomDirection()
# 设置坦克的图片
self.image = self.images[self.direction]
# 先基于图像获取坦克的位置以及大小
self.rect = self.image.get_rect()
# 修改坦克坐标,改成自定义位置
self.rect.centerx = x
self.rect.centery = y
#v1.07生成坦克的随机方向
def randomDirection(self):
num = random.randint(1,4)
if num == 1:
return 'U'
elif num == 2:
return 'D'
elif num == 3:
return 'L'
elif num == 4:
return 'R'
#v1.07将敌方坦克加入到窗口中
def displayTank(self):
self.image = self.images[self.direction]
MainGame.window.blit(self.image, self.rect)
主逻辑中实现敌方坦克的加载
class MainGame():
#游戏主窗口
window = None
tank1 = None
#v1.07 新增存储敌方坦克的列表
enemy_tanklist = []
def startGame(self):
#调用窗口初始化方法
pygame.display.init()
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
pygame.display.set_caption('坦克大战'+VERSION)
#调用创建我方坦克的方法
self.creatMyTank()
#v1.07调用创建敌方坦克的方法
self.creatEnemyTank()
while True:
#填充窗口背景色
MainGame.window.fill((0,0,0))
#调用事件处理方法
self.getEvents()
#展示我方坦克
self.showMyTank()
#v1.07调用展示敌方坦克的方法
self.showEnemyTank()
if not MainGame.tank1.stop:
# 我方坦克移动
MainGame.tank1.move()
#刷新
pygame.display.update()
#v1.06新增,程序休眠,优化坦克移动速度
time.sleep(0.020)
#创建我方坦克
def creatMyTank(self):
MainGame.tank1 = MyTank(SCREEN_WIDTH/2,SCREEN_HEIGHT/3*2)
#展示我方坦克
def showMyTank(self):
MainGame.tank1.displayTank()
#v1.07创建敌方坦克
def creatEnemyTank(self):
for i in range(ENEMM_TANK_COUNT):
num = random.randint(1,7)
etank = EnemyTank(100*num,150)
MainGame.enemy_tanklist.append(etank)
#v1.07展示敌方坦克
def showEnemyTank(self):
for etank in MainGame.enemy_tanklist:
etank.displayTank()
运行效果
完整代码
# from pygame import *
import pygame,time,random
SCREEN_WIDTH = 900
SCRREN_HEIGHT = 600
COLOR_BLACK = pygame.Color(0,0,0)
VERSION = 'v2.5'
class MainGame():
#游戏窗口
window = None
P1 = None
#敌方坦克列表
enemyTankList = []
#我方 * 列表
myBulletList = []
#存储敌方 *
enemyBulletList = []
#存储 * 效果的列表
bombList = []
#存储墙壁的列表
wallList = []
def __init__(self):
self.version = VERSION
def startGame(self):
print('游戏开始')
#初始化展示模块
pygame.display.init()
#调用自定义的创建窗口的方法
self.creatWindow()
#设置游戏标题
pygame.display.set_caption('坦克大战'+self.version)
#调用创建墙壁的方法
self.creatWalls()
#调用创建坦克方法
self.creatMyTank()
#调用创建敌方坦克
self.creatEnemyTank()
while True:
#设置游戏背景的填充色
MainGame.window.fill(COLOR_BLACK)
#调用展示墙壁的方法
self.showAllWalls()
# 调用展示我方坦克的方法
self.showMyTank()
#调用展示我方 * 的方法
self.showAllMyBullet()
#调用展示所有 * 效果的方法
self.showAllBombs()
#调用展示敌方坦克的方法
self.showEnemyTank()
#调用展示敌方 * 的方法
self.showAllEnemyBullet()
#调用获取事件,处理事件的方法
self.getAllEvents()
#窗口持续刷新以即时显示
pygame.display.update()
time.sleep(0.02)
def creatWindow(self):
MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCRREN_HEIGHT))
def getAllEvents(self):
#获取所有的事件
event_list = pygame.event.get()
for e in event_list:
if e.type == pygame.QUIT:
#关闭窗口,结束游戏,调用gameOver方法
self.gameOver()
elif e.type == pygame.KEYDOWN:
print('点击键盘按键')
if e.key == pygame.K_SPACE:
bullet = MainGame.P1.shot()
#控制 * 发射的数量
if len(MainGame.myBulletList) < 4:
print('发射 * ')
MainGame.myBulletList.append(bullet)
print('当前我方 * 数量为:',len(MainGame.myBulletList))
#创建音效对象,播放音效文件
audio = Audio('tank-images/boom.wav')
audio.play()
#创建墙壁的方法
def creatWalls(self):
for i in range(1,8):
wall = Wall(i*120,380,'tank-images/steels.gif')
MainGame.wallList.append(wall)
#展示墙壁的方法
def showAllWalls(self):
for w in MainGame.wallList:
w.displayWall()
def creatMyTank(self):
MainGame.P1 = MyTank(SCREEN_WIDTH/2,SCRREN_HEIGHT/4*3)
def showMyTank(self):
MainGame.P1.displayTank()
MainGame.P1.move()
MainGame.P1.hitWalls()
#展示我方 *
def showAllMyBullet(self):
for b in MainGame.myBulletList:
if b.live:
b.displayBullet()
#调用 * 的移动方法
b.move()
#调用是否打中敌方坦克的方法
b.hitEnemyTank()
#调用是否打中墙壁的方法
b.hitWalls()
else:
MainGame.myBulletList.remove(b)
#展示敌方 *
def showAllEnemyBullet(self):
for b in MainGame.enemyBulletList:
if b.live:
b.displayBullet()
b.move()
#调用是否打中墙壁的方法
b.hitWalls()
else:
MainGame.enemyBulletList.remove(b)
def creatEnemyTank(self):
for i in range(5):
etank = EnemyTank(random.randint(1,8)*100,150)
MainGame.enemyTankList.append(etank)
def showEnemyTank(self):
for etank in MainGame.enemyTankList:
etank.displayTank()
etank.move()
etank.hitWalls()
#调用射击方法
etank.shot()
#展示所有 * 效果
def showAllBombs(self):
for bomb in MainGame.bombList:
if bomb.live:
bomb.displayBomb()
else:
MainGame.bombList.remove(bomb)
def gameOver(self):
print('游戏结束')
exit()
class Tank():
def __init__(self,x,y):
#图片集(存储4个方向的所有图片)
self.images = {
'U':pygame.image.load('tank-images/tankU.gif'),
'D':pygame.image.load('tank-images/tankD.gif'),
'L':pygame.image.load('tank-images/tankL.gif'),
'R':pygame.image.load('tank-images/tankR.gif'),
}
self.direction = 'U'
#从图片集中根据方向获取图片
self.image = self.images[self.direction]
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.speed = 3
self.isDead = False
#新增属性用来记录上一步的坐标
self.oldx = self.rect.centerx
self.oldy = self.rect.centery
def stay(self):
self.rect.centerx = self.oldx
self.rect.centery = self.oldy
def hitWalls(self):
index = self.rect.collidelist(MainGame.wallList)
if index != -1:
self.stay()
def move(self):
#记录移动之前的坐标
self.oldx = self.rect.centerx
self.oldy = self.rect.centery
if self.direction == 'U':
if self.rect.centery > self.rect.height/2:
self.rect.centery -= self.speed
elif self.direction == 'D':
if self.rect.centery < SCRREN_HEIGHT - self.rect.height/2:
self.rect.centery += self.speed
elif self.direction == 'L':
if self.rect.centerx > self.rect.height/2:
self.rect.centerx -= self.speed
elif self.direction == 'R':
if self.rect.centerx < SCREEN_WIDTH - self.rect.height/2:
self.rect.centerx += self.speed
def shot(self):
return Bullet(self)
def displayTank(self):
# 重新设置坦克图片
self.image = self.images[self.direction]
# 将坦克加载的到窗口
MainGame.window.blit(self.image, self.rect)
class MyTank(Tank):
def __init__(self,x,y):
super(MyTank, self).__init__(x,y)
def move(self):
#pygame.key
pressed_list = pygame.key.get_pressed()
#分别判断上下左右四个方向的按键,按下的状态
if pressed_list[pygame.K_LEFT]:
#修改坦克的方向
self.direction = 'L'
super(MyTank, self).move()
elif pressed_list[pygame.K_RIGHT]:
self.direction = 'R'
super(MyTank, self).move()
elif pressed_list[pygame.K_UP]:
self.direction = 'U'
super(MyTank, self).move()
elif pressed_list[pygame.K_DOWN]:
self.direction = 'D'
super(MyTank, self).move()
class EnemyTank(Tank):
def __init__(self,x,y):
super(EnemyTank, self).__init__(x,y)
#随机速度
self.speed = self.randSpeed(2,5)
#随机方向
self.direction = self.randDirection()
#图片
# self.image = self.images[self.direction]
#坐标位置
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#记录坦克移动步数的变量
self.step = random.randint(25,50)
#生成随机速度值
def randSpeed(self,from_,to_):
return random.randint(from_,to_)
def randDirection(self):
list1 = ['U','D','L','R']
return list1[random.randint(0,3)]
def move(self):
if self.step > 0:
super(EnemyTank, self).move()
self.step -= 1
else:
#1.生成新的方向
self.direction = self.randDirection()
#2.步数还原
self.step = random.randint(25,50)
def shot(self):
num = random.randint(1,40)
if num == 1:
b = Bullet(self)
MainGame.enemyBulletList.append(b)
class Bullet():
def __init__(self,tank):
#图片
if isinstance(tank,MyTank):
self.image = pygame.image.load('tank-images/tankmissile.gif')
else:
self.image = pygame.image.load('tank-images/enemymissile.gif')
#方向
self.direction = tank.direction
#坐标位置
self.rect = self.image.get_rect()
# * 的具体位置
if self.direction == 'U':
self.rect.centerx = tank.rect.centerx
self.rect.centery = tank.rect.centery - tank.rect.height/2 - self.rect.height/2
elif self.direction == 'D':
self.rect.centerx = tank.rect.centerx
self.rect.centery = tank.rect.centery + tank.rect.height / 2 + self.rect.height / 2
elif self.direction == 'L':
self.rect.centery = tank.rect.centery
self.rect.centerx = tank.rect.centerx - tank.rect.height/2 - self.rect.height/2
elif self.direction == 'R':
self.rect.centery = tank.rect.centery
self.rect.centerx = tank.rect.centerx + tank.rect.height / 2 + self.rect.height / 2
#移动速度
self.speed = 8
# * 的状态(live)
self.live = True
def move(self):
if self.direction == 'U':
#边界控制
if self.rect.centery > 0:
self.rect.centery -= self.speed
else:
self.live = False
elif self.direction == 'D':
if self.rect.centery < SCRREN_HEIGHT:
self.rect.centery += self.speed
else:
self.live = False
elif self.direction == 'L':
if self.rect.centerx > 0:
self.rect.centerx -= self.speed
else:
self.live = False
elif self.direction == 'R':
if self.rect.centerx < SCREEN_WIDTH:
self.rect.centerx += self.speed
else:
self.live = False
def displayBullet(self):
MainGame.window.blit(self.image, self.rect)
# * 与墙壁的碰撞
def hitWalls(self):
index = self.rect.collidelist(MainGame.wallList)
if index != -1:
self.live = False
# 我方 * 是否碰撞到敌方坦克
def hitEnemyTank(self):
index = self.rect.collidelist(MainGame.enemyTankList)
if index != -1:
# 打中敌方坦克后的业务逻辑
# 修改 * 的live属性
self.live = False
tank = MainGame.enemyTankList.pop(index)
# 打中敌方坦克之后产生一个 * 效果,装进 * 效果列表中
bomb = Bomb(tank)
MainGame.bombList.append(bomb)
class Bomb():
def __init__(self,tank):
#存储多张 * 效果的图片
self.images = [
pygame.image.load('tank-images/0.gif'),
pygame.image.load('tank-images/1.gif'),
pygame.image.load('tank-images/2.gif'),
pygame.image.load('tank-images/3.gif'),
pygame.image.load('tank-images/4.gif'),
pygame.image.load('tank-images/5.gif'),
pygame.image.load('tank-images/6.gif')
]
#用来记录图片为图片集中的第几张
self.index = 0
self.image = self.images[self.index]
self.live = True
self.rect = self.image.get_rect()
self.rect.centerx = tank.rect.centerx
self.rect.centery = tank.rect.centery
def displayBomb(self):
if self.index < len(self.images):
self.image = self.images[self.index]
self.index += 1
MainGame.window.blit(self.image, self.rect)
else:
self.index = 0
self.live = False
class Audio():
def __init__(self,musicpath):
pygame.mixer.init()
pygame.mixer.music.load(musicpath)
def play(self):
pygame.mixer.music.play()
class Wall():
def __init__(self,x,y,imagepath):
self.image = pygame.image.load(imagepath)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
def displayWall(self):
MainGame.window.blit(self.image,self.rect)
game = MainGame()
game.startGame()
python俄罗斯方块游戏集合
python经典小游戏汇总
python微信跳一跳游戏集合
更多有趣的经典小游戏实现专题,分享给大家:
C++经典小游戏汇总
python经典小游戏汇总
python俄罗斯方块游戏集合
JavaScript经典游戏 玩不停
javascript经典小游戏汇总
来源:https://blog.csdn.net/weixin_43301259/article/details/106960612


猜你喜欢
- 本文实例为大家分享了TensorFlow实现简单线性回归的具体代码,供大家参考,具体内容如下简单的一元线性回归一元线性回归公式:其中x是特征
- InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定。下面是已知的两者之间的差别,仅供参考。1.Inn
- 前言说到面向对象,大家都不陌生。关系型数据库也是后端日常用来存储数据的,但数据库是关系型的,因此,ORM通过对象模型和数据库的关系模型之间建
- 如果你会查询这些相关的问题,说明你是一个正在或者准备从事IT的程序猿,对于一个程序猿而言,不会使用linux系统的程序猿不是一好的程序猿哦!
- 前言前面我们已经将GO的环境安装好了,那么是否可以进行开发了呢?可以,但是为了能够更高效率的开发,我们还需要下载一个软件,该软件的作用就是方
- 前言其实就是Django RESTful Framework,RESTful一种API的命名风格,主要因为前后端分离开发出现,前后端分离:
- 同时在线访问量继续增大 对于1G内存的服务器明显感觉到吃力严重时甚至每天都会死机 或者时不时的服务器卡一下 这个问题曾经困扰了我半个多月My
- 函数的增益值torch.nn.init.calculate_gain(nonlinearity, param=None)提供了对非线性函数增
- 在日常工作中,PPT制作是常见的工作,如果制作创意类PPT,则无法通过自动化的形式生成,因为创意本身具有随机性,而自动化解决的是重复性工作,
- 0. 引言马上314情人节就要来了,是否需要一首歌来抚慰你,受伤或躁动的心灵。来吧,今天教你用15行代码搞定热门歌单。学起来并听起来吧。本文
- 我就废话不多说了,大家还是直接看代码吧~func ReadLine(fileName string) ([]string,error){f,
- 首先得有一个Scrapy项目,我在Desktop上新建一个Scrapy的项目叫test,在Desktop目录打开命令行,键入命令:scrap
- 俺比较笨,对太专业的书一直不感冒,看了就想睡觉。最近李明同学传了本“大话设计模式”电子版。偶然翻了翻,感觉还满通俗的,正适合我这样的懒人学习
- 案例一:运行下面的代码结果是什么?class Person: def run(self): &nbs
- SQLite 的 AUTOINCREMENT 是一个关键字,用于表中的字段值自动递增。我们可以在创建表时在特定的列名称上使用 AUTOINC
- 首先要挂代理,但是还不够,pycharm默认不使用代理,需要进行设置找到代理软件的HTTP代理地址,将地址和端口填入设置中即可来源:http
- 首先是不知道怎么忽然mysql用命令行,workbench都登录不了,都提示'Access denied for user '
- 每次查询分析器寻找路径时,并不会每一次都去统计索引中包含的行数,值的范围等,而是根据一定条件创建和更新这些信息后保存到数据库中,这也就是所谓
- 关于建立索引的几个准则:1、合理的建立索引能够加速数据读取效率,不合理的建立索引反而会拖慢数据库的响应速度。2、索引越多,更新数据的速度越慢
- 前言本文的github仓库地址为: 替换照片人物背景项目(模型文件过大,不在仓库中)由于模型文件过大,没放在仓库中,本文下面有模型下载地址。