1. 程式人生 > >坦克大戰小遊戲 版本號v1.10

坦克大戰小遊戲 版本號v1.10

python 初階

'''
v1.10 實現子彈的移動與消失
'''
import pygame,time,random
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 550
VERSION = 'V1.10'
# v1.07新增 記錄敵方坦克的數量
ENEMY_TANK_COUNT = 5
# 主邏輯類
class MainGame():
    # 遊戲主視窗
    window = None
    # 我方坦克(唯一性)設定成類屬性
    tank1 = None
    # v1.07新增儲存敵方坦克的列表
    enemy_tanklist = []
    # v1.09 新增儲存我方子彈的列表
    mybullet_list = []
    def startGame(self):
        # 呼叫視窗初始化方法
        pygame.display.init()
        # 在視窗左上角設定遊戲標題
        pygame.display.set_caption('坦克大戰'+VERSION)
        # 建立一個視窗螢幕顯示錶面
        MainGame.window = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
        # 呼叫建立我方坦克的方法
        self.createMytank()
        # 呼叫建立敵方坦克的方法
        self.createEnemytank()
        while True:
            # 填充視窗背景色
            MainGame.window.fill((100,100,200))
            # 將獲取的事件型別在填充完視窗背景色後時刻處於迴圈中
            self.getEvents()
            # 展示我方坦克
            self.showMytank()
            # 呼叫展示敵方坦克的方法
            self.showEnemyTank()
            # v1.09 新增呼叫展示我方子彈的方法
            self.showMyBullet()
            # 更新
            pygame.display.update()
            # v1.06 新增程式休眠,優化坦克的移動速度
            time.sleep(0.025)
    # 獲取所有事件處理的方法
    def getEvents(self):
        # 獲取佇列中的所有事件,遍歷事件,對type為QUIT和KEYDOWN的兩種事件型別進行處理
        eventList = pygame.event.get()
        # 遍歷所有事件
        for e in eventList:
            # 當事件型別是QUIT時,退出遊戲
            if e.type == pygame.QUIT:
                self.showMytank()
                # 退出遊戲
                self.gameOver()
            #  當事件型別是KEYDOWN時,進行細化處理
            elif e.type == pygame.KEYDOWN:
                # 按下鍵盤上的向上按鍵時的處理
                if e.key == pygame.K_UP:
                    print('向上移動')
                    MainGame.tank1.direction = 'U'
                    # v1.06修改坦克的移動狀態
                    MainGame.tank1.stop = False
                # 按下鍵盤上的向下按鍵時的處理
                elif e.key == pygame.K_DOWN:
                    print('向下移動')
                    MainGame.tank1.direction = 'D'
                    # v1.06修改坦克的移動狀態
                    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~')
                    # v1.09 新增呼叫發射方法,並將子彈裝進列表
                    b = MainGame.tank1.shoot()
                    MainGame.mybullet_list.append(b)
                    print('子彈的數量%d'%len(MainGame.mybullet_list))
            #v1.06新增按鍵鬆開的事件處理
            elif e.type == pygame.KEYUP:
                if e.key == pygame.K_UP or e.key == pygame.K_DOWN or\
                    e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT:
                    # 將坦克的移動狀態改為停止
                    MainGame.tank1.stop = True
    # 建立我方坦克
    def createMytank(self):
        # 建立我方坦克並賦予其位置屬性座標
        MainGame.tank1 = MyTank(SCREEN_WIDTH/2,SCREEN_HEIGHT/3*2)
    #展示我方坦克
    def showMytank(self):
        MainGame.tank1.displayTank()
        # v1.08 新增將 我方坦克移動程式碼 移動位置
        if not MainGame.tank1.stop:
            # 我方坦克移動
            MainGame.tank1.move()
    # v1.07建立敵方坦克
    def createEnemytank(self):
        # 迴圈建立敵方坦克
        for i in range(ENEMY_TANK_COUNT):
            num = random.randint(1,7)
            # v1.08新增 隨機速度
            randomspeed = random.randint(3,10)
            # 建立第一個敵方坦克,出現位置為y=150,x隨機出現在(100-700),坦克移動的隨機速度是randomspeed
            # v1.08新增呼叫修改後的init方法
            etank = EnemyTank(100*num,150,randomspeed)
            # 建立敵方坦克列表,存入所有的敵方坦克
            MainGame.enemy_tanklist.append(etank)
    # v1.07展示敵方坦克
    def showEnemyTank(self):
        # 遍歷展示敵方坦克
        for etank in MainGame.enemy_tanklist:
            etank.displayTank()
            # v1.08 新增敵方坦克的移動
            etank.move()

    # v1.09 展示我方子彈的方法
    def showMyBullet(self):
        for b in MainGame.mybullet_list:
            # 如果子彈活著,展示並移動子彈
            if b.live == True:
                b.displayBullet()
                # v1.10 新增呼叫子彈的移動方法
                b.move()
            #   如果子彈死亡,移除子彈,給子彈列表騰空間,保證打到牆上的子彈消失
            else:
                MainGame.mybullet_list.remove(b)
    def gameOver(self):
        exit()
# 基本坦克類
class BaseTank():
    # 基本坦克屬性 位置 方向 速度 圖片
    def __init__(self):
        self.direction = None
        self.rect = None
        self.images = None
        self.image = None
        self.speed = 0
        #v1.06新增屬性,用來控制坦克是否移動
        self.stop = True
    # v1.08 優化移動
    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
     # v1.09 新增射擊方法
    def shoot(self):
        bullet = Bullet(self)
        return bullet
# 我方坦克類
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 返回的是一個surface)
        self.image = self.images[self.direction]
        # 先基於影象獲取坦克的位置和大小
        self.rect = self.image.get_rect()
        # 修改坦克座標,改成自定義位置
        self.rect.centerx = x
        self.rect.centery = y
        # 設定坦克速度
        self.speed = 5
    #將我方坦克加入到視窗中
    def displayTank(self):
        self.image = self.images[self.direction]
        # 把坦克的影象(即表面)和位置放到另一個影象或表面視窗
        MainGame.window.blit(self.image,self.rect)

# 敵方坦克類
class EnemyTank(BaseTank):
    # v1.08新增隨機速度引數
    def __init__(self,x,y,randSpeed):
        # v1.08新增呼叫父類的初始化
        super(EnemyTank, self).__init__()
        # 設定具體的圖片集
        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')
                       }
        # v1.07敵方坦克的初始方向為隨機方向
        self.direction = self.randomDirection()
        # 設定坦克的圖片(self.image 返回的是一個surface)
        self.image = self.images[self.direction]
        # 先基於影象獲取坦克的位置和大小
        self.rect = self.image.get_rect()
        # 修改坦克座標,改成自定義位置
        self.rect.centerx = x
        self.rect.centery = y
        # v1.08新增速度為引數傳進來的速度
        self.speed = randSpeed
        # v1.08新增記錄敵方坦克移動的步數
        self.step = 25
        # 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.08新增重寫父類中的移動move方法,方法中新增隨機方向的處理
    def move(self):
        if self.step == 0:
            # 變換方向
            self.direction = self.randomDirection()
            # 將步數重新歸置成25
            self.step = 25
        else:
            super(EnemyTank, self).move()
            self.step -= 1
    # 將敵方坦克加入到視窗中
    def displayTank(self):
        self.image = self.images[self.direction]
        # 把坦克的影象(即表面)和位置放到另一個影象或表面視窗
        MainGame.window.blit(self.image, self.rect)


#v1.09 新增實現子彈類
class Bullet():
    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.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.centerx = tank.rect.centerx - tank.rect.height/2 - self.rect.height/2
            self.rect.centery = tank.rect.centery
        elif self.direction == 'R':
            self.rect.centerx = tank.rect.centerx + tank.rect.height / 2 + self.rect.height / 2
            self.rect.centery = tank.rect.centery
        #v1.10 新增子彈移動速度
        self.speed = 11
        # v1.10 新增子彈的存活狀態,用來記錄子彈是否活著
        self.live = True
    # v1.10 新增子彈的移動方法
    def move(self):
        if self.direction == 'U':
            if self.rect.centery > self.rect.height/2:
                self.rect.centery -= self.speed
            else:
                self.live = False
        elif self.direction == 'D':
            if self.rect.centery < SCREEN_HEIGHT - self.rect.height/2:
                self.rect.centery += self.speed
            else:
                self.live = False
        elif self.direction == 'L':
            if self.rect.centerx > self.rect.height / 2:
                self.rect.centerx -= self.speed
            else:
                self.live = False
        elif self.direction == 'R':
            if self.rect.centerx < SCREEN_WIDTH - self.rect.height / 2:
                self.rect.centerx += self.speed
            else:
                self.live = False

    #將子彈的影象展示到遊戲主視窗
    def displayBullet(self):
        MainGame.window.blit(self.image,self.rect)
# 爆炸類
class Explode():
    pass
# 牆壁類
class Wall():
    pass
# 音效類
class Audio():
    pass
#建立一個主邏輯類的物件
game = MainGame()
# 開始遊戲
game.startGame()