python小游戏————坦克大战

命运对每个人都是一样的,不一样的是各自的努力和付出不同,付出的越多,努力的越多,得到的回报也越多,在你累的时候请看一下身边比你成功却还比你更努力的人,这样,你就会更有动力。

导读:本篇文章讲解 python小游戏————坦克大战,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

目录

一、需求分析

二、系统分析

主类:

坦克类(包含我方坦克,敌方坦克)

子弹类

爆炸类

三、代码功能实现

五、总代码:


  • 一、需求分析

坦克大战是儿时经常玩的一个游戏,没想起它,脑子里都是满满的童年回忆,如今初步掌握了python这一门语言,用它来编写一个坦克大战小游戏,以求深入理解python这一门语言,同时纪念一去不复返的童年时代。

  • 二、系统分析

本游戏由pygame游戏引擎实现。基于面向对象的思想,完成以下功能:

  1. 主类:

    1. 开始游戏
    2. 结束游戏
  2. 坦克类(包含我方坦克,敌方坦克)

    1. 移动
    2. 射击
  3. 子弹类

    1. 移动

     爆炸类

4.1.子弹打到敌法坦克时,显示爆炸

5. 障碍物类

6.音效类

6.1.播放bgm

  • 三、代码功能实现

  1. 开始游戏:首先得调用pygame的set_mode()方法加载游戏窗口,并且使用fill()类调制窗口的颜色(这里为黑      色)
  2. (1)设置停止游戏按钮,以及实现方向键的处理(L,R,D,U),当检测到以上四种方向键时,加载相应的坦克的图片
  3. 坦克的调头和移动:按想要的方向键,加载不同方向的坦克会实现调头效果,通过self.rect.+方向,来移动坦克的位置,在后台设置移动的速度
def move(self):       if self.direction == 'U':        if self.rect.top > 0:            self.rect.top -= self.speed    elif self.direction == 'D':        if self.rect.top < MainGame.SCREEN_HEIGHT-MainGame.PI_TANK.rect.height:            self.rect.top += self.speed    elif self.direction == 'L':        if self.rect.left > 0:            self.rect.left -= self.speed    elif self.direction == 'R':        if self.rect.left < MainGame.SCREEN_WIDTH-MainGame.PI_TANK.rect.width:            self.rect.left += self.speed
  1. 加载敌方坦克:使用一个list存储敌方坦克,并且使敌方坦克随机移动,使用random.randint()方法,随机生成一个left值和速度,使用self.randirection()(自创建,实际上还是random.randint())随机生成敌方坦克的方向。
class EnemyTank(Tank):    def __init__(self,left,top,speed):        super(EnemyTank, self).__init__(left,top)        # self.live = True        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 = left        self.rect.top = top        self.speed = speed        self.stop = True        self.step = 30
  1. 创建墙壁类:墙壁随机生成
class Wall():    def __init__(self,left,top):        self.image = pygame.image.load('img/steels.gif')        self.rect = self.image.get_rect()        self.rect.left = left        self.rect.top = top

        #用来判断墙壁是否应该在窗口中展示
        self.live = True
        #用来记录墙壁的生命值
        self.hp = 3
    #展示墙壁的方法
    def displayWall(self):
        MainGame.window.blit(self.image,self.rect)

  1. 创建子弹类
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':            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 = 7        #用来记录子弹是否活着        self.live = True    #子弹的移动方法    def bulletMove(self):        if self.direction == 'U':            if self.rect.top > 0:                self.rect.top -= self.speed            else:                #修改状态值                self.live = False        elif self.direction == 'D':            if self.rect.top < MainGame.SCREEN_HEIGHT - self.rect.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        elif self.direction == 'R':            if self.rect.left < MainGame.SCREEN_WIDTH - self.rect.width:                self.rect.left += self.speed            else:                # 修改状态值                self.live = False

  1. 我方坦克发射和敌方坦克的碰撞处理:我方坦克要是击中敌方坦克,敌方坦克会爆炸
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

  1. 实现子弹和墙壁的碰撞:子弹与墙壁碰撞三次之后,墙壁也会消失(被remove掉),并且会重新修改子弹的状态(子弹消失)
def hitWalls(self):    for wall in MainGame.Wall_list:        if pygame.sprite.collide_rect(wall,self):            #修改子弹的live属性            self.live = False            wall.hp -= 1            if wall.hp <= 0:                wall.live = False

  1. 音效类
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()MainGame().startGame()

上述代码展示:

1.

python小游戏————坦克大战

2.

python小游戏————坦克大战

python小游戏————坦克大战

3.

python小游戏————坦克大战

4.

python小游戏————坦克大战

5.

python小游戏————坦克大战

6.

python小游戏————坦克大战

五、总代码:

import pygame,time,random_display = pygame.displayCOLOR_BLACK = pygame.Color(0, 0, 0)COLOR_RED = pygame.Color(255, 0, 0)version = 'v1.25'class MainGame():    #游戏主窗口    window = None    SCREEN_HEIGHT = 500    SCREEN_WIDTH = 800    #创建我方坦克    TANK_P1 = None    #存储所有敌方坦克    EnemyTank_list = []    #要创建的敌方坦克的数量    EnemTank_count = 5    #存储我方子弹的列表    Bullet_list = []    #存储敌方子弹的列表    Enemy_bullet_list = []    #爆炸效果列表    Explode_list = []    #墙壁列表    Wall_list = []    #开始游戏方法    def startGame(self):        _display.init()        #创建窗口加载窗口(借鉴官方文档)        MainGame.window = _display.set_mode([MainGame.SCREEN_WIDTH,MainGame.SCREEN_HEIGHT])        self.creatMyTank()        self.creatEnemyTank()        self.creatWalls()        #设置一下游戏标题        _display.set_caption("坦克大战"+version)        #让窗口持续刷新操作        while True:            #给窗口完成一个填充颜色            MainGame.window.fill(COLOR_BLACK)            #在循环中持续完成事件的获取            self.getEvent()            #将绘制文字得到的小画布,粘贴到窗口中            MainGame.window.blit(self.getTextSurface("剩余敌方坦克%d辆"%len(MainGame.EnemyTank_list)),(5,5))            #调用展示墙壁的方法            self.blitWalls()            if MainGame.TANK_P1 and MainGame.TANK_P1.live:                # 将我方坦克加入到窗口中                MainGame.TANK_P1.displayTank()            else:                del MainGame.TANK_P1                MainGame.TANK_P1 = None            #循环展示敌方坦克            self.blitEnemyTank()            #根据坦克的开关状态调用坦克的移动方法            if MainGame.TANK_P1 and not MainGame.TANK_P1.stop:                MainGame.TANK_P1.move()                #调用碰撞墙壁的方法                MainGame.TANK_P1.hitWalls()                MainGame.TANK_P1.hitEnemyTank()            #调用渲染子弹列表的一个方法            self.blitBullet()            #调用渲染敌方子弹列表的一个方法            self.blitEnemyBullet()            #调用展示爆炸效果的方法            self.displayExplodes()            time.sleep(0.02)            #窗口的刷新            _display.update()    #创建我方坦克的方法    def creatMyTank(self):        # 创建我方坦克        MainGame.TANK_P1 = MyTank(400, 300)        #创建音乐对象        music = Music('img/start.wav')        #调用播放音乐方法        music.play()    #创建敌方坦克    def creatEnemyTank(self):        top = 100        for i in range(MainGame.EnemTank_count):            speed = random.randint(3,6)            #每次都随机生成一个left值            left = random.randint(1, 7)            eTank = EnemyTank(left*100,top,speed)            MainGame.EnemyTank_list.append(eTank)    #创建墙壁的方法    def creatWalls(self):        for i in range(6):            wall = Wall(130*i,240)            MainGame.Wall_list.append(wall)    def blitWalls(self):        for wall in MainGame.Wall_list:            if wall.live:                wall.displayWall()            else:                MainGame.Wall_list.remove(wall)    #将敌方坦克加入到窗口中    def blitEnemyTank(self):        for eTank in MainGame.EnemyTank_list:            if eTank.live:                eTank.displayTank()                # 坦克移动的方法                eTank.randMove()                #调用敌方坦克与墙壁的碰撞方法                eTank.hitWalls()                #敌方坦克是否撞到我方坦克                eTank.hitMyTank()                # 调用敌方坦克的射击                eBullet = eTank.shot()                # 如果子弹为None。不加入到列表                if eBullet:                    # 将子弹存储敌方子弹列表                    MainGame.Enemy_bullet_list.append(eBullet)            else:                MainGame.EnemyTank_list.remove(eTank)    #将我方子弹加入到窗口中    def blitBullet(self):        for bullet in MainGame.Bullet_list:            #如果子弹还活着,绘制出来,否则,直接从列表中移除该子弹            if bullet.live:                bullet.displayBullet()                # 让子弹移动                bullet.bulletMove()                # 调用我方子弹与敌方坦克的碰撞方法                bullet.hitEnemyTank()                # 调用判断我方子弹是否碰撞到墙壁的方法                bullet.hitWalls()            else:                MainGame.Bullet_list.remove(bullet)    #将敌方子弹加入到窗口中    def blitEnemyBullet(self):        for eBullet in MainGame.Enemy_bullet_list:            # 如果子弹还活着,绘制出来,否则,直接从列表中移除该子弹            if eBullet.live:                eBullet.displayBullet()                # 让子弹移动                eBullet.bulletMove()                #调用是否碰撞到墙壁的一个方法                eBullet.hitWalls()                if MainGame.TANK_P1 and MainGame.TANK_P1.live:                    eBullet.hitMyTank()            else:                MainGame.Enemy_bullet_list.remove(eBullet)    #新增方法: 展示爆炸效果列表    def displayExplodes(self):        for explode in MainGame.Explode_list:            if explode.live:                explode.displayExplode()            else:                MainGame.Explode_list.remove(explode)    #获取程序期间所有事件(鼠标事件,键盘事件)    def getEvent(self):        #1.获取所有事件        eventList = pygame.event.get()        #2.对事件进行判断处理(1、点击关闭按钮  2、按下键盘上的某个按键)        for event in eventList:            #判断event.type 是否QUIT,如果是退出的话,直接调用程序结束方法            if event.type == pygame.QUIT:                self.endGame()            #判断事件类型是否为按键按下,如果是,继续判断按键是哪一个按键,来进行对应的处理            if event.type == pygame.KEYDOWN:                #点击ESC按键让我方坦克重生                if event.key == pygame.K_ESCAPE and not MainGame.TANK_P1:                    #调用创建我方坦克的方法                    self.creatMyTank()                if MainGame.TANK_P1 and MainGame.TANK_P1.live:                    # 具体是哪一个按键的处理                    if event.key == pygame.K_LEFT:                        print("坦克向左调头,移动")                        # 修改坦克方向                        MainGame.TANK_P1.direction = 'L'                        MainGame.TANK_P1.stop = False                    elif event.key == pygame.K_RIGHT:                        print("坦克向右调头,移动")                        # 修改坦克方向                        MainGame.TANK_P1.direction = 'R'                        MainGame.TANK_P1.stop = False                    elif event.key == pygame.K_UP:                        print("坦克向上调头,移动")                        # 修改坦克方向                        MainGame.TANK_P1.direction = 'U'                        MainGame.TANK_P1.stop = False                    elif event.key == pygame.K_DOWN:                        print("坦克向下掉头,移动")                        # 修改坦克方向                        MainGame.TANK_P1.direction = 'D'                        MainGame.TANK_P1.stop = False                    elif event.key == pygame.K_SPACE:                        print("发射子弹")                        if len(MainGame.Bullet_list) < 3:                            # 产生一颗子弹                            m = Bullet(MainGame.TANK_P1)                            # 将子弹加入到子弹列表                            MainGame.Bullet_list.append(m)                            music = Music('img/fire.wav')                            music.play()                        else:                            print("子弹数量不足")                        print("当前屏幕中的子弹数量为:%d" % len(MainGame.Bullet_list))            #结束游戏方法            if event.type == pygame.KEYUP:                #松开的如果是方向键,才更改移动开关状态                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:                    if MainGame.TANK_P1 and MainGame.TANK_P1.live:                        # 修改坦克的移动状态                        MainGame.TANK_P1.stop = True    #左上角文字绘制的功能    def getTextSurface(self,text):        # 初始化字体模块        pygame.font.init()        #查看系统支持的所有字体        # fontList = pygame.font.get_fonts()        # print(fontList)        # 选中一个合适的字体        font = pygame.font.SysFont('kaiti',18)        # 使用对应的字符完成相关内容的绘制        textSurface = font.render(text,True,COLOR_RED)        return textSurface    def endGame(self):        print("谢谢使用")        #结束python解释器        exit()class BaseItem(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)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 = 'U'        self.image = self.images[self.direction]        #坦克所在的区域  Rect->        self.rect = self.image.get_rect()        #指定坦克初始化位置 分别距x,y轴的位置        self.rect.left = left        self.rect.top = top        #新增速度属性        self.speed = 5        #新增属性: 坦克的移动开关        self.stop = True        #新增属性  live 用来记录,坦克是否活着        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 == 'R':            if self.rect.left + self.rect.height < MainGame.SCREEN_WIDTH:                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 < MainGame.SCREEN_HEIGHT:                self.rect.top += self.speed    def stay(self):        self.rect.left = self.oldLeft        self.rect.top = self.oldTop    #新增碰撞墙壁的方法    def hitWalls(self):       for wall in MainGame.Wall_list:           if pygame.sprite.collide_rect(wall,self):               self.stay()    #射击方法    def shot(self):        return Bullet(self)    #展示坦克(将坦克这个surface绘制到窗口中  blit())    def displayTank(self):        #1.重新设置坦克的图片        self.image = self.images[self.direction]        #2.将坦克加入到窗口中        MainGame.window.blit(self.image,self.rect)class MyTank(Tank):    def __init__(self,left,top):        super(MyTank, self).__init__(left,top)    #新增主动碰撞到敌方坦克的方法    def hitEnemyTank(self):        for eTank in MainGame.EnemyTank_list:            if pygame.sprite.collide_rect(eTank,self):                self.stay()class EnemyTank(Tank):    def __init__(self,left,top,speed):        super(EnemyTank, self).__init__(left,top)        # self.live = True        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]        # 坦克所在的区域  Rect->        self.rect = self.image.get_rect()        # 指定坦克初始化位置 分别距x,y轴的位置        self.rect.left = left        self.rect.top = top        # 新增速度属性        self.speed = speed        self.stop = True        #新增步数属性,用来控制敌方坦克随机移动        self.step = 30    def randDirection(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'    # def displayEnemtTank(self):    #     super().displayTank()    #随机移动    def randMove(self):        if self.step <= 0:            self.direction = self.randDirection()            self.step = 50        else:            self.move()            self.step -= 1    def shot(self):        num = random.randint(1,1000)        if num  <= 20:            return Bullet(self)    def hitMyTank(self):        if MainGame.TANK_P1 and MainGame.TANK_P1.live:            if pygame.sprite.collide_rect(self, MainGame.TANK_P1):                # 让敌方坦克停下来  stay()                self.stay()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':            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 = 7        #用来记录子弹是否活着        self.live = True    #子弹的移动方法    def bulletMove(self):        if self.direction == 'U':            if self.rect.top > 0:                self.rect.top -= self.speed            else:                #修改状态值                self.live = False        elif self.direction == 'D':            if self.rect.top < MainGame.SCREEN_HEIGHT - self.rect.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        elif self.direction == 'R':            if self.rect.left < MainGame.SCREEN_WIDTH - self.rect.width:                self.rect.left += self.speed            else:                # 修改状态值                self.live = False    #展示子弹的方法    def displayBullet(self):        MainGame.window.blit(self.image,self.rect)    #新增我方子弹碰撞敌方坦克的方法    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 hitMyTank(self):        if pygame.sprite.collide_rect(self,MainGame.TANK_P1):            # 产生爆炸效果,并加入到爆炸效果列表中            explode = Explode(MainGame.TANK_P1)            MainGame.Explode_list.append(explode)            #修改子弹状态            self.live = False            #修改我方坦克状态            MainGame.TANK_P1.live = False    #新增子弹与墙壁的碰撞    def hitWalls(self):        for wall in MainGame.Wall_list:            if pygame.sprite.collide_rect(wall,self):                #修改子弹的live属性                self.live = False                wall.hp -= 1                if wall.hp <= 0:                    wall.live = Falseclass Explode():    def __init__(self,tank):        self.rect = tank.rect        self.step = 0        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.image = self.images[self.step]        self.live = True    #展示爆炸效果    def displayExplode(self):        if self.step < len(self.images):            MainGame.window.blit(self.image, self.rect)            self.image = self.images[self.step]            self.step += 1        else:            self.live = False            self.step = 0class Wall():    def __init__(self,left,top):        self.image = pygame.image.load('img/steels.gif')        self.rect = self.image.get_rect()        self.rect.left = left        self.rect.top = top        #用来判断墙壁是否应该在窗口中展示        self.live = True        #用来记录墙壁的生命值        self.hp = 3    #展示墙壁的方法    def displayWall(self):        MainGame.window.blit(self.image,self.rect)#我方坦克出生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()MainGame().startGame()

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143182.html

(1)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!