python/pygame坦克游戏边学边写笔记(一)

准备挑战一下坦克大战的游戏,感觉要比飞机游戏复杂一些,坦克移动时候需要考虑图片跟随方向改变,地图是游戏元素的一部分,需要增加这部分的载入和碰撞检测。

参考网上的教程,按照自己的理解和思路来尝试实现。一步步来吧,遇到问题再说,基本还是按以前的思维方式来写。

一、先写出坦克游戏主循环框架:

import pygame
import sys

pygame.init()

WIDTH = 900
HEIGHT = 600
FPS = 60

running = True

game_window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()


def control():
    global running
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False


def main():
    while running:
        control()

        clock.tick(FPS)
        pygame.display.set_caption('Tank  ' + '{0:0.2f}'.format(clock.get_fps()))
        pygame.display.update()

    pygame.quit()
    sys.exit()


if __name__ == '__main__':
    main()

二、玩家坦克类

从网上找到的资料,玩家坦克每个方向都有6个图片,代表坦克的装甲,不同装甲坦克图片不同,这里先每个方向复制出1个,搞明白怎么让坦克跟随按键改变方向再说。

开始写玩家坦克类,还是按照以前飞机的思路来,利用sprite精灵组调用draw和update来进行绘制和移动:

导入四个方向的图片:

player_tank_up = pygame.image.load(os.path.join('image', 'player_tank', 'up1.png'))
player_tank_down = pygame.image.load(os.path.join('image', 'player_tank', 'down1.png'))
player_tank_left = pygame.image.load(os.path.join('image', 'player_tank', 'left1.png'))
player_tank_right = pygame.image.load(os.path.join('image', 'player_tank', 'right1.png'))
class PlayerTank(pygame.sprite.Sprite):
    player_tank_list = {
        'up': [player_tank_up],
        'down': [player_tank_down],
        'left': [player_tank_left],
        'right': [player_tank_right]
    }

    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.direction = 'up'
        self.life = 3
        self.image = self.player_tank_list[self.direction][0]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speed = 2

    def update(self):
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_UP] and self.rect.top >= 0:
            self.direction = 'up'
            self.rect.y -= self.speed
        if key_pressed[pygame.K_DOWN] and self.rect.bottom <= HEIGHT:
            self.direction = 'down'
            self.rect.y += self.speed
        if key_pressed[pygame.K_LEFT] and self.rect.x >= 0:
            self.direction = 'left'
            self.rect.x -= self.speed
        if key_pressed[pygame.K_RIGHT] and self.rect.right <= WIDTH:
            self.direction = 'right'
            self.rect.x += self.speed

三、玩家坦克移动及图片载入

主函数中实例化玩家坦克类后,坦克实现了移动,但方向没有跟随改变。检查发现,在按键响应里面写了跟随按键来改变direction的值,在控制台打印direction,direction值跟随按键方向实现了改变,但是坦克却没有跟随方向键改变图片方向。

后来又想采用图片翻转旋转的方式,需要写在update方法里面,这才想到,是不是应该在upate里面重新载入图片呢?哈哈,居然实现了。原来问题出在改变direction值后需要在主循环中重新刷新载入,可以进行下一步了。

    def update(self):
        self.image = self.player_tank_list[self.direction][0]
        key_pressed = pygame.key.get_pressed()

现在解决一个方向多个图片的导入问题,多个图片是为了实现不同坦克装甲值有不同的图片显示,可以在游戏过程中看到坦克被击中后图片产生变化。

先建立玩家坦克字典,键是4个方向,值是各自方向中的6个图片列表,总不能写24个图片导入代码吧!改好图片名称,删掉原来的图片导入,采用for循环逐步将图片导入到各自方向的列表中,然后给玩家坦克属性中增加一个装甲属性amour,后期可以根据不同装甲值变化绘制不同坦克图片,amour在这里类似生命值。

class PlayerTank(pygame.sprite.Sprite):
    player_tank_dict = {
        'up': [],
        'down': [],
        'left': [],
        'right': []
    }

    for i in range(6):
        player_tank_dict['up'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'up' + str(i + 1) + '.png')))
        player_tank_dict['down'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'down' + str(i + 1) + '.png')))
        player_tank_dict['left'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'left' + str(i + 1) + '.png')))
        player_tank_dict['right'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'right' + str(i + 1) + '.png')))

移动的时候还有点问题,坦克游戏的移动方式和飞机游戏的移动方式不太一样,比如同时按下左键和上键,坦克会斜45度移动,这不符合坦克类游戏体验。

增加横向和纵向方向移动开关,限定移动方向唯一。最后的update方法如下:

    def update(self):
        self.image = self.player_tank_dict[self.direction][self.amour]
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_UP] and self.rect.top >= 0:
            self.direction = 'up'
            if self.direction_y:
                self.rect.y -= self.speed
        if key_pressed[pygame.K_DOWN] and self.rect.bottom <= HEIGHT:
            self.direction = 'down'
            if self.direction_y:
                self.rect.y += self.speed
        if key_pressed[pygame.K_LEFT] and self.rect.x >= 0:
            self.direction = 'left'
            if self.direction_x:
                self.rect.x -= self.speed
        if key_pressed[pygame.K_RIGHT] and self.rect.right <= WIDTH:
            self.direction = 'right'
            if self.direction_x:
                self.rect.x += self.speed

        if self.direction == 'up' or self.direction == 'down':
            self.direction_x = False
            self.direction_y = True
        if self.direction == 'left' or self.direction == 'right':
            self.direction_x = True
            self.direction_y = False

四、现阶段的完整代码:

# 导入使用到的库
import os.path
import pygame
import sys
# 初始化pygame
pygame.init()
# 定义常量
WIDTH = 900
HEIGHT = 600
BLACK = (0, 0, 0)
FPS = 60
# 定义变量,running用来控制主循环
running = True
level = 0
# 确定游戏窗口,设定游戏时钟
game_window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
# 建立精灵组,all_sprites用来存放全部的精灵组,通过调用draw函数和update函数实现图片绘制及更新移动
all_sprites = pygame.sprite.Group()


# 玩家坦克类,继承精灵属性,图片存放于字典中,并按照方向归类
class PlayerTank(pygame.sprite.Sprite):
    player_tank_dict = {
        'up': [],
        'down': [],
        'left': [],
        'right': []
    }
    # 通过for循环,将图片分别加入字典中个方向值的列表
    for i in range(6):
        player_tank_dict['up'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'up' + str(i + 1) + '.png')))
        player_tank_dict['down'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'down' + str(i + 1) + '.png')))
        player_tank_dict['left'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'left' + str(i + 1) + '.png')))
        player_tank_dict['right'].append(
            pygame.image.load(os.path.join('image', 'player_tank', 'right' + str(i + 1) + '.png')))

    # 初始化函数,定义方向、装甲、移动开关、速度
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.direction = 'up'
        self.amour = 5
        self.life = 3
        self.image = self.player_tank_dict[self.direction][self.amour]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.direction_x = None
        self.direction_y = None
        self.speed = 2

    # 重写update函数,重新加载图片,实现图片跟随direction值改变方向,实现玩家坦克移动
    def update(self):
        self.image = self.player_tank_dict[self.direction][self.amour]
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_UP] and self.rect.top >= 0:
            self.direction = 'up'
            if self.direction_y:
                self.rect.y -= self.speed
        if key_pressed[pygame.K_DOWN] and self.rect.bottom <= HEIGHT:
            self.direction = 'down'
            if self.direction_y:
                self.rect.y += self.speed
        if key_pressed[pygame.K_LEFT] and self.rect.x >= 0:
            self.direction = 'left'
            if self.direction_x:
                self.rect.x -= self.speed
        if key_pressed[pygame.K_RIGHT] and self.rect.right <= WIDTH:
            self.direction = 'right'
            if self.direction_x:
                self.rect.x += self.speed
        # 设定移动方向开关,控制坦克只能在横向或纵向移动
        if self.direction == 'up' or self.direction == 'down':
            self.direction_x = False
            self.direction_y = True
        if self.direction == 'left' or self.direction == 'right':
            self.direction_x = True
            self.direction_y = False


# 事件响应函数,接受键盘控制响应
def control():
    global running
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            pass


# 开始界面函数
def start_interface():
    pass


# 结束界面函数
def end_interface():
    pass


# 游戏主循环
def main():
    # 实例化玩家坦克,初始位置为家的左侧
    player = PlayerTank(325, 550)
    # 主循环
    while running:
        # 接受键盘控制并响应
        control()
        # 游戏窗口背景,暂时填充为黑色
        game_window.fill(BLACK)
        # 如果玩家生命数量大于0,游戏开始,小于0则游戏结束
        if player.life > 0:
            # 设定level为0是为开始界面,游戏选择及玩法说明
            if level == 0:
                start_interface()
            # 第一关游戏,更换地图等
            elif level == 1:
                all_sprites.add(player)
                all_sprites.draw(game_window)
                all_sprites.update()
            # 第二关游戏,更换地图等
            elif level == 2:
                pass
        # 玩家生命数量为0时,结束游戏,显示得分及重新开始
        else:
            end_interface()
        # 设定游戏帧率
        clock.tick(FPS)
        # 设定游戏窗口名称,并显示实时帧率
        pygame.display.set_caption('Tank  ' + '{0:0.2f}'.format(clock.get_fps()))
        # 刷新游戏窗口
        pygame.display.update()
    # 退出pygame/python
    pygame.quit()
    sys.exit()


if __name__ == '__main__':
    main()

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值