学习 Python 之 Pygame 开发坦克大战

Posted _DiMinisH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习 Python 之 Pygame 开发坦克大战相关的知识,希望对你有一定的参考价值。

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

坦克大战的需求

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

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

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

素材链接:百度网盘
链接:https://pan.baidu.com/s/19sCyH7rp37f6DzRj0iXDCA?pwd=tkdz
提取码:tkdz

开始编写坦克大战

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

1. 搭建主类框架

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

import pygame


SCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
class MainGame:

    # 窗口Surface对象
    window = None

    def __init__(self):
        pass

    def 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 = pygame.event.get()
    for event in eventList:

        if event.type == pygame.QUIT:
            sys.exit()

        if event.type == 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按下')

        if event.type == 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 sys


SCREEN_WIDTH = 1100
SCREEN_HEIGHT = 600
BACKGROUND_COLOR = pygame.Color(0, 0, 0)
FONT_COLOR = (255, 255, 255)
class MainGame:

    # 窗口Surface对象
    window = None

    def __init__(self):
        pass

    def 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)
            
            # 获取窗口事件
            self.getPlayingModeEvent()
            
            # 更新窗口
            pygame.display.update()
            
    def getPlayingModeEvent(self):
        # 获取所有事件
        eventList = pygame.event.get()
        for event in eventList:
            
            if event.type == pygame.QUIT:
                sys.exit()
                
            if event.type == 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按下')

            if event.type == 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.sprite


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

4. 初始化我方坦克类

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

import pygame as pg
import pygame.image
from ParentObject import ParentObject


class 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.direction]
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y

        # 速度
        self.accumulation: float = 0
        self.speed = 2
        # 移动开关
        self.stop = True
        

        # 等级
        self.level = 1
        # 伤害
        self.damage = 1

    def move(self):
        pass

    def shot(self):
        pass

    def draw(self):
       pass

5. 完善我方坦克的移动

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

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

def move(self):
    if self.accumulation >= 1:
        self.accumulation = 0
        if self.direction == 'LEFT':
            if self.rect.left > 0:
                self.rect.left -= self.speed
        elif self.direction == 'UP':
            if self.rect.top > 0:
                self.rect.top -= self.speed
        elif self.direction == 'DOWN':
            if self.rect.top < 555:
                self.rect.top += self.speed
        elif self.direction == 'RIGHT':
            if self.rect.left < 855:
                self.rect.left += self.speed
    else:
        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, self.rect)

我方坦克类完整代码

import pygame as pg
import pygame.image
from ParentObject import ParentObject


class 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.direction]
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y

        # 速度
        self.accumulation: float = 0
        self.speed = 2
        # 移动开关
        self.stop = True

        # 碰撞前的坐标
        self.prvX = self.rect.left
        self.prvY = self.rect.top

        # 等级
        self.level = 1
        # 伤害
        self.damage = 1

    def move(self):
        if self.accumulation >= 1:
            self.accumulation = 0
            if self.direction == 'LEFT':
                if self.rect.left > 0:
                    self.rect.left -= self.speed
            elif self.direction == 'UP':
                if self.rect.top > 0:
                    self.rect.top -= self.speed
            elif self.direction == 'DOWN':
                if self.rect.top < 555:
                    self.rect.top += self.speed
            elif self.direction == 'RIGHT':
                if self.rect.left < 855:
                    self.rect.left += self.speed
        else:
            self.accumulation += 0.20


    def shot(self):
        pass

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

以上是关于学习 Python 之 Pygame 开发坦克大战的主要内容,如果未能解决你的问题,请参考以下文章

学习 Python 之 Pygame 开发坦克大战

学习 Python 之 Pygame 开发坦克大战

学习 Python 之 Pygame 开发坦克大战

python之游戏开发-坦克大战

Python游戏开发,pygame模块,Python实现经典90坦克大战游戏

Python游戏开发,pygame模块,Python实现升级版坦克大战小游戏