学习 Python 之 Pygame 开发坦克大战(二)

阅读: 评论:0

学习 Python 之 Pygame 开发坦克大战(二)

学习 Python 之 Pygame 开发坦克大战(二)

学习 Python 之 Pygame 开发坦克大战(二)

    • 坦克大战的需求
    • 开始编写坦克大战
      • 1. 搭建主类框架
      • 2. 获取窗口中的事件
      • 3. 创建基类
      • 4. 初始化我方坦克类
      • 5. 完善我方坦克的移动
      • 5. 完善我方坦克的显示
      • 6. 在主类中加入我方坦克并完成坦克移动
      • 7. 初始化子弹类
      • 8. 完善子弹的移动
      • 9. 完善坦克开火
      • 10. 实现敌方坦克类
      • 11. 在主类中加入敌方坦克并完成坦克移动和开火

坦克大战的需求

坦克大战游戏包含很多个物体,现在要对这些物体进行总结

类名包含的操作包含的属性
敌方坦克类射击,移动,显示生命,速度,伤害,方向,类型
我方坦克类射击,移动,显示生命,速度,伤害,方向,装甲,等级
子弹类移动,显示方向,伤害,发射源,速度
墙壁类、草类、石砖类、河类显示是否可以摧毁
音效类播放,停止,设置音乐-
爆炸效果类显示是否可以摧毁
主类

物体总结完毕后,规划一下窗口的大小,下面是我设置的窗口大小

素材链接:百度网盘
链接:=tkdz
提取码:tkdz

开始编写坦克大战

一切都准备就绪啦,现在开始编写坦克大战的代码吧

1. 搭建主类框架

主类是整个游戏运作的类,当然你也可以不用使用类,直接创建一个函数也可以,这里使用了面向对象的思想

import pygameSCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
class MainGame:# 窗口Surface对象window = Nonedef __init__(self):passdef startGame(self):# 初始化展示模块pygame.display.init()# 设置窗口大小size = (SCREEN_WIDTH, SCREEN_HEIGHT)# 初始化窗口MainGame.window = pygame.display.set_mode(size)# 设置窗口标题pygame.display.set_caption('Tank Battle')while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 更新窗口pygame.display.update()if __name__ == '__main__':MainGame().startGame()

运行结果

主类中运用到的知识,都是学习 Python 之 Pygame 开发坦克大战(一)中所包含的

2. 获取窗口中的事件

坦克大战关键是对玩家自己的坦克进行操控,消灭敌人的坦克,所以键盘事件响应是必不可少的

def getPlayingModeEvent(self):# 获取所有事件eventList = ()for event in eventList:pe == pygame.it()pe == pygame.KEYDOWN:print('键盘按键按下')if event.key == pygame.K_w:print('w按下')elif event.key == pygame.K_s:print('s按下')elif event.key == pygame.K_a:print('a按下')elif event.key == pygame.K_d:print('d按下')elif event.key == pygame.K_j:print('j按下')pe == pygame.KEYUP:print('键盘按键抬起')if event.key == pygame.K_w:print('w抬起')elif event.key == pygame.K_s:print('s抬起')elif event.key == pygame.K_a:print('a抬起')elif event.key == pygame.K_d:print('d抬起')

获取窗口中的事件,用于玩家操控坦克、发射坦克子弹等操作

游戏中,我规定aswd操控坦克,j攻击,当然你也可以上下左右键移动,空格攻击,如果你想设置双人游戏,这也是可以的

import pygame
import sysSCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
class MainGame:# 窗口Surface对象window = Nonedef __init__(self):passdef startGame(self):# 初始化展示模块pygame.display.init()# 设置窗口大小size = (SCREEN_WIDTH, SCREEN_HEIGHT)# 初始化窗口MainGame.window = pygame.display.set_mode(size)# 设置窗口标题pygame.display.set_caption('Tank Battle')while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 更新窗口pygame.display.update()def getPlayingModeEvent(self):# 获取所有事件eventList = ()for event in eventList:pe == pygame.it()pe == pygame.KEYDOWN:print('键盘按键按下')if event.key == pygame.K_w:print('w按下')elif event.key == pygame.K_s:print('s按下')elif event.key == pygame.K_a:print('a按下')elif event.key == pygame.K_d:print('d按下')elif event.key == pygame.K_j:print('j按下')pe == pygame.KEYUP:print('键盘按键抬起')if event.key == pygame.K_w:print('w抬起')elif event.key == pygame.K_s:print('s抬起')elif event.key == pygame.K_a:print('a抬起')elif event.key == pygame.K_d:print('d抬起')if __name__ == '__main__':MainGame().startGame()

3. 创建基类

坦克操控事件完成后,现在就是实现坦克啦,首先场景中的物体都需要发生物体间的碰撞,简单来说就是检测两个屏幕上的图片是否发生了重叠,如果发生了,就要触发一些事件,这里创建ParentObject类,用于继承pygame.sprite.Sprite类

pygame.sprite.Sprite类可以用来检测物体碰撞,是pygame提供的一个类,非常的方便

import pygame.spriteclass ParentObject(pygame.sprite.Sprite):def __init__(self):super().__init__()

4. 初始化我方坦克类

创建我方坦克类,并且继承基类

import pygame as pg
import pygame.image
from ParentObject import ParentObjectclass PlayerTank(ParentObject):def __init__(self, x, y, order, amour):""":param x: 坦克横坐标:param y: 坦克纵坐标:param order: 玩家坦克序号,1表示一号玩家,2表示二号玩家:param amour: 坦克初始护甲"""super().__init__()self.images = []if order == 1:self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP1.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN1.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT1.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT1.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP2.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN2.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT2.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT2.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP3.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN3.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT3.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT3.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP4.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN4.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT4.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT4.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP5.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN5.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT5.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT5.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP6.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN6.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT6.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT6.png')})# 生命self.life = 3# 装甲self.armor = amour# 方向self.direction = 'UP'# 根据护甲选择坦克的样子self.image: pg.Surface = self.images[max(self.armor - 1, 0)][self. = _rect()left = p = y# 速度self.accumulation: float = 0self.speed = 2# 移动开关self.stop = True# 等级self.level = 1# 伤害self.damage = 1def move(self):passdef shot(self):passdef draw(self):pass

5. 完善我方坦克的移动

accumulation 可以更细的控制坦克的移动速度

当 accumulation 累加到 1 时,坦克移动一次,如果不设置这个属性,即使是速度每次 +1,坦克移动的也速度很快,所以增加这个属性,可以减慢坦克的移动速度

def move(self):if self.accumulation >= 1:self.accumulation = 0if self.direction == 'LEFT':left > left -= self.speedelif self.direction == 'UP':op > op -= self.speedelif self.direction == 'DOWN':op < op += self.speedelif self.direction == 'RIGHT':left < left += self.speedelse:self.accumulation += 0.20

这里需要设置坦克的边界范围
防止坦克跑出窗口

坦克的图片是45x45

5. 完善我方坦克的显示

坦克的显示就是把坦克的图片显示在窗口中

def draw(self, window):# window传入主窗口# 坦克生命中为0,表示已经死亡,不再展示坦克if self.life <= 0:return# 获取展示的对象self.image = self.images[max(self.armor - 1, 0)][self.direction]window.blit(self.image, )

我方坦克类完整代码

import pygame as pg
import pygame.image
from ParentObject import ParentObjectclass PlayerTank(ParentObject):def __init__(self, x, y, order, amour):""":param x: 坦克横坐标:param y: 坦克纵坐标:param order: 玩家坦克序号,1表示一号玩家,2表示二号玩家:param amour: 坦克初始护甲"""super().__init__()self.images = []if order == 1:self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP1.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN1.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT1.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT1.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP2.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN2.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT2.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT2.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP3.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN3.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT3.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT3.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP4.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN4.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT4.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT4.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP5.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN5.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT5.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT5.png')})self.images.append({'UP': pygame.image.load('../Image/Player1/45x45/UP6.png'),'DOWN': pygame.image.load('../Image/Player1/45x45/DOWN6.png'),'LEFT': pygame.image.load('../Image/Player1/45x45/LEFT6.png'),'RIGHT': pygame.image.load('../Image/Player1/45x45/RIGHT6.png')})# 生命self.life = 3# 装甲self.armor = amour# 方向self.direction = 'UP'# 根据护甲选择坦克的样子self.image: pg.Surface = self.images[max(self.armor - 1, 0)][self. = _rect()left = p = y# 速度self.accumulation: float = 0self.speed = 2# 移动开关self.stop = True# 碰撞前的坐标self.prvX = leftself.prvY = p# 等级self.level = 1# 伤害self.damage = 1def move(self):if self.accumulation >= 1:self.accumulation = 0if self.direction == 'LEFT':left > left -= self.speedelif self.direction == 'UP':op > op -= self.speedelif self.direction == 'DOWN':op < op += self.speedelif self.direction == 'RIGHT':left < left += self.speedelse:self.accumulation += 0.20def shot(self):passdef draw(self, window):# 坦克生命中为0,表示已经死亡,不再展示坦克if self.life <= 0:return# 获取展示的对象self.image = self.images[max(self.armor - 1, 0)][self.direction]# 画出图片window.blit(self.image, )

6. 在主类中加入我方坦克并完成坦克移动

我方坦克类中移动和显示函数实现后,就要让它们在主类中调用

添加类变量playerTank,用于存放我方坦克的对象

修改循环中的代码

while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 显示我方坦克MainGame.playerTank.draw(MainGame.window)# 我方坦克移动if not MainGame.playerTank.stop:ve()# 更新窗口pygame.display.update()

完整我方坦克类代码

import pygame
import sysfrom PlayerTank import PlayerTankSCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
PLAYER_TANK_POSITION = (325, 550)class MainGame:# 窗口Surface对象window = None# 玩家坦克playerTank = Nonedef __init__(self):passdef startGame(self):# 初始化展示模块pygame.display.init()# 设置窗口大小size = (SCREEN_WIDTH, SCREEN_HEIGHT)# 初始化窗口MainGame.window = pygame.display.set_mode(size)# 设置窗口标题pygame.display.set_caption('Tank Battle')# 初始化我方坦克MainGame.playerTank = PlayerTank(PLAYER_TANK_POSITION[0], PLAYER_TANK_POSITION[1], 1, 1)while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 显示我方坦克MainGame.playerTank.draw(MainGame.window)# 我方坦克移动if not MainGame.playerTank.stop:ve()# 更新窗口pygame.display.update()def getPlayingModeEvent(self):# 获取所有事件eventList = ()for event in eventList:pe == pygame.it()"""stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动"""pe == pygame.KEYDOWN:print('键盘按键按下')if event.key == pygame.K_w:MainGame.playerTank.direction = 'UP'MainGame.playerTank.stop = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_j:print('j按下')pe == pygame.KEYUP:print('键盘按键抬起')if event.key == pygame.K_w:MainGame.playerTank.stop = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = Trueif __name__ == '__main__':MainGame().startGame()

运行结果

7. 初始化子弹类

现在已经实现了坦克的移动啦,下面就要实现坦克的发射子弹

实际上,子弹也是一幅图片,当我们按下开火按键后,就在坦克的正前方画出子弹,随着时间的流逝,要让子弹按照当前方向一直运动下去

import pygame
from ParentObject import ParentObjectclass Bullet(ParentObject):def __init__(self, tank):super().__init__()self.images = {'UP': pygame.image.load('../Image/Bullet/Bullet(UP).png'),'DOWN': pygame.image.load('../Image/Bullet/Bullet(DOWN).png'),'LEFT': pygame.image.load('../Image/Bullet/Bullet(LEFT).png'),'RIGHT': pygame.image.load('../Image/Bullet/Bullet(RIGHT).png')}# 方向self.direction = tank.directionself.image: pygame.Surface = self.images[self. = _rect()# 坦克发射子弹的位置if self.direction == 'UP':left = left + op = p - 25elif self.direction == 'DOWN':left = left + op = p + 25elif self.direction == 'LEFT':left = left - p = p + 17.5elif self.direction == 'RIGHT':left = left + p = p + 17.5# 速度self.accumulationMax: float = 0self.accumulation = 0.25self.speed = 10# 销毁开关self.isDestroy = False# 发射源self.source = tank# 伤害self.damage = tank.damagedef move(self, explodeList):passdef draw(self, window):window.blit(self.image, )

下面是确定子弹的位置:

子弹图片是25x10,坦克发射子弹是在坦克中间位置发射

8. 完善子弹的移动

子弹的初始位置确定后,一旦创建出来,就要一直移动下去,实际上就是刷新屏幕,然后把原来位置上的子弹图片去掉,在新的位置上再画出子弹图片,坦克移动的原理也是这样

修改move函数,添加检查子弹出界函数

    def move(self):if self.accumulation >= 1:self.accumulation = 0if self.direction == 'LEFT':left -= self.speedelif self.direction == 'UP':p -= self.speedelif self.direction == 'DOWN':p += self.speedelif self.direction == 'RIGHT':left += self.speed# 检查子弹是否出界self.checkBullet()else:self.accumulation += 0.20def checkBullet(self):toDestroy = False# 如果出界,就设置为销毁op < 0 op > 600:toDestroy = left < 0 ight > 900:toDestroy = Trueif toDestroy:self.isDestroy = True

子弹类完整代码

import pygame
from ParentObject import ParentObjectclass Bullet(ParentObject):def __init__(self, tank):super().__init__()self.images = {'UP': pygame.image.load('../Image/Bullet/Bullet(UP).png'),'DOWN': pygame.image.load('../Image/Bullet/Bullet(DOWN).png'),'LEFT': pygame.image.load('../Image/Bullet/Bullet(LEFT).png'),'RIGHT': pygame.image.load('../Image/Bullet/Bullet(RIGHT).png')}# 方向self.direction = tank.directionself.image: pygame.Surface = self.images[self. = _rect()# 坦克发射子弹的位置if self.direction == 'UP':left = left + op = p - 25elif self.direction == 'DOWN':left = left + op = p + 25elif self.direction == 'LEFT':left = left - p = p + 17.5elif self.direction == 'RIGHT':left = left + p = p + 17.5# 速度self.accumulationMax: float = 0self.accumulation = 0.25self.speed = 10# 销毁开关self.isDestroy = False# 发射源self.source = tank# 伤害self.damage = tank.damagedef move(self):if self.accumulation >= 1:self.accumulation = 0if self.direction == 'LEFT':left -= self.speedelif self.direction == 'UP':p -= self.speedelif self.direction == 'DOWN':p += self.speedelif self.direction == 'RIGHT':left += self.speed# 检查子弹是否出界self.checkBullet()else:self.accumulation += 0.20def checkBullet(self):toDestroy = False# 如果出界,就设置为销毁op < 0 op > 600:toDestroy = left < 0 ight > 900:toDestroy = Trueif toDestroy:self.isDestroy = Truedef draw(self, window):window.blit(self.image, )

9. 完善坦克开火

有了子弹类,就可以让坦克发射子弹了

在主类中设置玩家子弹数量的最大值

... ...class MainGame:# 窗口Surface对象window = None# 指定的子弹个数,这里设置玩家的子弹最多只有3颗子弹可以同时在场playerBulletNumber = 3# 玩家坦克playerTank =  ...

修改坦克的 shot() 函数

def shot(self):return Bullet(self)

修改 getPlayingModeEvent() 函数
当 j键按下,发射子弹

    def getPlayingModeEvent(self):# 获取所有事件eventList = ()for event in eventList:pe == pygame.it()"""stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动"""pe == pygame.KEYDOWN:print('键盘按键按下')if event.key == pygame.K_w:MainGame.playerTank.direction = 'UP'MainGame.playerTank.stop = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_j:# 判断子弹数量是否超过指定的个数if len(MainGame.playerBulletList) < MainGame.playerBulletNumber:bullet = MainGame.playerTank.shot()MainGame.playerBulletList.append(bullet)pe == pygame.KEYUP:print('键盘按键抬起')if event.key == pygame.K_w:MainGame.playerTank.stop = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = True

子弹有了,但是没有显示在窗口,此时写一个函数让子弹在窗口显示出来

def drawPlayerBullet(self, playerBulletList):# 遍历整个子弹列表,如果是没有被销毁的状态,就把子弹显示出来,否则从列表中删除for bullet in playerBulletList:if not bullet.isDestroy:bullet.draw(MainGame.ve()ve(bullet)

有了函数还需要调用,在while循环中加入该函数

while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 显示我方坦克MainGame.playerTank.draw(MainGame.window)# 我方坦克移动if not MainGame.playerTank.stop:ve()# 显示我方坦克子弹self.drawPlayerBullet(MainGame.playerBulletList)# 更新窗口pygame.display.update()

运行游戏看看结果

当我们按下开火键时,子弹就发射了


注意:MainGame.playerBulletList 需要定义出来,否则程序运行会报错

添加位置如下:

... ...class MainGame:# 窗口Surface对象window = NoneplayerBulletList = []playerBulletNumber = 3# 玩家坦克playerTank =  ...

10. 实现敌方坦克类

现在我的坦克可以移动和开火,那么就要有点靶子给我们练习了,是时候实现敌方坦克类了

敌方坦克类的大部分代码跟我方坦克类一样,这里可以用继承,即父类是坦克类,实现两个类的一样的代码,然后我方坦克类和敌方坦克类继承这个类,不过我没有使用继承

import random
import pygame
import pygame.imagefrom ParentObject import ParentObject
from Bullet import Bulletclass EnemyTank(ParentObject):def __init__(self, x, y):super().__init__()types = [(1, 3), (2, 1), (3, 2), (4, 10)]# 随机产生一种坦克pe = types[random.randint(0, len(types) - 1)]up = []down = []left = []right = []for i in range(1, pe[1] + 1):up.append(pygame.image.load('../Image/Enemy/EnemyTank' + pe[0]) + '/EnemyTank'+ pe[0]) + 'Lv' + str(i) + '(UP).png'))down.append(pygame.image.load('../Image/Enemy/EnemyTank' + pe[0]) + '/EnemyTank'+ pe[0]) + 'Lv' + str(i) + '(DOWN).png'))left.append(pygame.image.load('../Image/Enemy/EnemyTank' + pe[0]) + '/EnemyTank' + pe[0]) + 'Lv' + str(i) + '(LEFT).png'))right.append(pygame.image.load('../Image/Enemy/EnemyTank' + pe[0]) + '/EnemyTank' + pe[0]) + 'Lv' + str(i) + '(RIGHT).png'))self.images = {'UP': up,'DOWN': down,'LEFT': left,'RIGHT': right}# 生命self.life = pe[1]# 方向self.direction = 'DOWN'self.image: pygame.Surface = self.images[self.direction][self.life -  = _rect()left = p = y# 速度self.accumulationMax: float = 0self.accumulation = 0.1speed = 0maxBulletCount = 0damage = pe[0] == 1:speed = 3self.level = 1maxBulletCount = pe[0] == 2:speed = 5self.level = 2maxBulletCount = 1damage = pe[0] == 3:speed = 7self.level = 1maxBulletCount = 3damage = pe[0] == 4:speed = 6self.level = 2maxBulletCount = 3damage = 1self.speed = speed# 移动开关self.stop = True# 开火开关self.fire = True# 步数self.step = 30# 伤害self.damage = damage# 子弹个数self.bulletCount = 0self.maxBulletCount = maxBulletCountdef move(self):"""新增步数变量, 当坦克移动时, 步数进行减少, 当步数小于等于0的时候, 修改地方坦克的方向:return: None"""if self.stop:if self.step <= 0:self.direction = self.randDirection()self.step = 30else:if self.accumulationMax >= 1:self.accumulationMax = 0if self.direction == 'LEFT':left > left -= self.speedelif self.direction == 'UP':op > op -= self.speedelif self.direction == 'DOWN':op < op += self.speedelif self.direction == 'RIGHT':left < left += self.speedself.step -= 1else:self.accumulationMax += self.accumulationdef shot(self):if self.fire:if self.bulletCount < self.maxBulletCount:num = random.randint(0, 100)if num == 5 or num == 6:self.bulletCount += 1return Bullet(self)return Nonedef draw(self, window):# 获取展示的对象self.image = self.images[self.direction][self.life - 1]window.blit(self.image, )def randDirection(self):directions = ['UP', 'DOWN', 'LEFT', 'RIGHT']index = random.randint(0, 3)return directions[index]

我实际上设置了四种坦克的种类,下面types变量中记录着四种种类的序号和生命值,我规定,生命中不同坦克的样子也不同

types = [(1, 3), (2, 1), (3, 2), (4, 10)]
# 随机产生一种坦克
pe = types[random.randint(0, len(types) - 1)]

元组中的第二个元素表示生命值, 直接获取

# 生命
self.life = pe[1]

根据方向和生命值获取对应的图片

self.image: pygame.Surface = self.images[self.direction][self.life - 1]

坦克的属性

根据坦克种类的不同,伤害、等级、生命值也不同

等级是子弹的穿透性,1级只能打烂砖墙,2级可以打烂石墙,3级以上可以打烂黑曜石墙,这个黑曜石墙是我自己新加入的,我们以前玩的坦克大战是没有的,而且规则和我这个不太一样,当然你也可以修改,比如给坦克加入能量,当坦克在一定时间内连续击杀多个敌人,可以获得怒气,短时间伤害提升,这些都可以实现

speed = 0
maxBulletCount = 0
damage = 1
# 每种坦克都有不同的属性
pe[0] == 1:speed = 3self.level = 1maxBulletCount = 1
pe[0] == 2:speed = 5self.level = 2maxBulletCount = 1damage = 3
pe[0] == 3:speed = 7self.level = 1maxBulletCount = 3damage = 2
pe[0] == 4:speed = 6self.level = 2maxBulletCount = 3damage = 1

坦克的移动

step是步数,每次按照30次循环作为一次坦克的操作

 if self.stop:if self.step <= 0:# 随机产生一个方向,接下来朝这个方向移动self.direction = self.randDirection()self.step = 30else:if self.accumulationMax >= 1:self.accumulationMax = 0if self.direction == 'LEFT':left > left -= self.speedelif self.direction == 'UP':op > op -= self.speedelif self.direction == 'DOWN':op < op += self.speedelif self.direction == 'RIGHT':left < left += self.speedself.step -= 1else:self.accumulationMax += self.accumulation

坦克开火

随机产生一个0到100的数字,当为5或者6时,坦克就开火

def shot(self):if self.fire:if self.bulletCount < self.maxBulletCount:num = random.randint(0, 100)if num == 5 or num == 6:self.bulletCount += 1return Bullet(self)return None

在上面的代码中,下面的变量用来设置敌方坦克是否移动,是否开火

# 移动开关
self.stop = True
# 开火开关
self.fire = True

11. 在主类中加入敌方坦克并完成坦克移动和开火

在主类中创建类变量

class MainGame:# 窗口Surface对象window = None# 玩家坦克playerTank = None# 玩家子弹playerBulletList = []playerBulletNumber = 3# 敌人坦克enemyTankList = []enemyTankTotalCount = 5# 用来给玩家展示坦克的数量enemyTankCurrentCount = 5# 敌人坦克子弹enemyTankListBulletList = []

创建展示敌方坦克函数

这里我规定一次展示三辆敌方坦克,当全部被消灭后,再展示3辆,直到全部被消灭

def drawEnemyTank(self):# 如果当前坦克为0,那么就该重新生成坦克if TankList) == 0:# 一次性产生三个,如果剩余坦克数量超过三,那只能产生三个n = min(3, TankTotalCount)# 如果最小是0,就说明敌人坦克没有了,那么就赢了if n == 0:print('赢了')return# 没有赢的话,就产生n个坦克self.initEnemyTank(n)# 总个数减去产生的个数TankTotalCount -= n# 遍历坦克列表,展示坦克并且移动for tank TankList:# 坦克还有生命值if tank.life > 0:tank.draw(MainGame.ve()bullet = tank.shot()if bullet is not TankBulletList.append(bullet)# 坦克生命值为0,就从列表中剔除TankCurrentCount -= ve(tank)

坦克开火之后子弹加入敌方坦克子弹列表,把里面的子弹画出来,然后在while中调用它

def drawEnemyBullet(self):for bullet TankBulletList:if not bullet.isDestroy:bullet.draw(MainGame.ve()else:bullet.source.bulletCount -= ve(bullet)
while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 显示我方坦克MainGame.playerTank.draw(MainGame.window)# 我方坦克移动if not MainGame.playerTank.stop:ve()# 显示我方坦克子弹self.drawPlayerBullet(MainGame.playerBulletList)# 展示敌方坦克self.drawEnemyTank()# 展示敌方坦克子弹self.drawEnemyBullet()# 更新窗口pygame.display.update()

完整的主类代码

import pygame
import sysfrom PlayerTank import PlayerTank
from EnemyTank import EnemyTankSCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
PLAYER_TANK_POSITION = (325, 550)class MainGame:# 窗口Surface对象window = None# 玩家坦克playerTank = None# 玩家子弹playerBulletList = []playerBulletNumber = 3# 敌人坦克enemyTankList = []enemyTankTotalCount = 5# 用来给玩家展示坦克的数量enemyTankCurrentCount = 5# 敌人坦克子弹enemyTankBulletList = []def __init__(self):passdef startGame(self):# 初始化展示模块pygame.display.init()# 设置窗口大小size = (SCREEN_WIDTH, SCREEN_HEIGHT)# 初始化窗口MainGame.window = pygame.display.set_mode(size)# 设置窗口标题pygame.display.set_caption('Tank Battle')# 初始化我方坦克MainGame.playerTank = PlayerTank(PLAYER_TANK_POSITION[0], PLAYER_TANK_POSITION[1], 1, 1)while 1:# 设置背景颜色MainGame.window.fill(BACKGROUND_COLOR)# 获取窗口事件PlayingModeEvent()# 显示我方坦克MainGame.playerTank.draw(MainGame.window)# 我方坦克移动if not MainGame.playerTank.stop:ve()# 显示我方坦克子弹self.drawPlayerBullet(MainGame.playerBulletList)# 展示敌方坦克self.drawEnemyTank()# 展示敌方坦克子弹self.drawEnemyBullet()# 更新窗口pygame.display.update()def getPlayingModeEvent(self):# 获取所有事件eventList = ()for event in eventList:pe == pygame.it()"""stop属性用来控制坦克移动,当键盘按键按下时,坦克可以移动,一直按住一直移动,当按键抬起时,停止移动如果没有该属性,按一下按键移动一次,按一下移动一下,不能一直按住一直移动"""pe == pygame.KEYDOWN:if event.key == pygame.K_w:MainGame.playerTank.direction = 'UP'MainGame.playerTank.stop = Falseelif event.key == pygame.K_s:MainGame.playerTank.direction = 'DOWN'MainGame.playerTank.stop = Falseelif event.key == pygame.K_a:MainGame.playerTank.direction = 'LEFT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_d:MainGame.playerTank.direction = 'RIGHT'MainGame.playerTank.stop = Falseelif event.key == pygame.K_j:# 判断子弹数量是否超过指定的个数if len(MainGame.playerBulletList) < MainGame.playerBulletNumber:bullet = MainGame.playerTank.shot()MainGame.playerBulletList.append(bullet)pe == pygame.KEYUP:if event.key == pygame.K_w:MainGame.playerTank.stop = Trueelif event.key == pygame.K_s:MainGame.playerTank.stop = Trueelif event.key == pygame.K_a:MainGame.playerTank.stop = Trueelif event.key == pygame.K_d:MainGame.playerTank.stop = Truedef drawPlayerBullet(self, playerBulletList):# 遍历整个子弹列表,如果是没有被销毁的状态,就把子弹显示出来,否则从列表中删除for bullet in playerBulletList:if not bullet.isDestroy:bullet.draw(MainGame.ve()ve(bullet)def drawEnemyTank(self):# 如果当前坦克为0,那么就该重新生成坦克if TankList) == 0:# 一次性产生三个,如果剩余坦克数量超过三,那只能产生三个n = min(3, TankTotalCount)# 如果最小是0,就说明敌人坦克没有了,那么就赢了if n == 0:print('赢了')return# 没有赢的话,就产生n个坦克self.initEnemyTank(n)# 总个数减去产生的个数TankTotalCount -= n# 遍历坦克列表,展示坦克并且移动for tank TankList:# 坦克还有生命值if tank.life > 0:tank.draw(MainGame.ve()bullet = tank.shot()if bullet is not TankBulletList.append(bullet)# 坦克生命值为0,就从列表中剔除TankCurrentCount -= ve(tank)def initEnemyTank(self, number):y = 0position = [0, 425, 850]index = 0for i in range(number):x = position[index]enemyTank = EnemyTank(x, TankList.append(enemyTank)index += 1def drawEnemyBullet(self):for bullet TankBulletList:if not bullet.isDestroy:bullet.draw(MainGame.ve()else:bullet.source.bulletCount -= ve(bullet)if __name__ == '__main__':MainGame().startGame()

运行一下,看看结果

哈哈,终于实现发射子弹啦

本文发布于:2024-02-02 00:12:24,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170680966840093.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:坦克   大战   Python   Pygame
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23