pygame战棋游戏制作之战棋地图绘制(一)

pygame战棋游戏制作之战棋地图绘制(一),第1张

pygame战棋游戏制作之战棋地图绘制(一)
前言

本来有好多篇博文想写的,但是目前在做的是这款战棋游戏的开发,所以其他版块只能先咕咕咕了。或者有关注的小伙伴们可以留言希望下一个更新的版块是啥子?postgresql数据库底层原理?网络编程?计算机网络?redis底层原理?Nginx底层原理?Django的各种模块运用?

写这篇博文的原因还有一个是因为百度了一下,全网居然只有一个战棋开发的博文,这让想要学习的我很是苦恼,为了以后广大兴趣战棋开发爱好者有更多的资料可以借鉴,就萌生了这个版块的想法。

正文

战棋游戏首先第一件事就是要有个地图。

第一个想法很简单,就是一个二维的数组。但是制作起来才发现比想象中困难。

遇到的第一个困难就是,如何将二维数组铺在屏幕上。肯定会有小伙伴说很简单呀,遍历数组就好了。

实际上,pygame一次只能布置一个图片在屏幕上,如果只是单纯遍历数组,以数组下标作为布置图片的x,y坐标的话,你会发现,所有的格子都会叠在一起。因为格子的像素远大于1(我是使用宽高32像素的格子图案)

因此每次布置格子的时候,需要用数组下标*像素大小才能铺满整个屏幕。做出来的地图类会像是这样

class Map:
    def __init__(self):
        self.map_width,self.map_height = 960, 640
        self.block = 32
        self.real_width,self.real_height = self.map_width//self.block, self.map_height//self.block
        self.empty_map = [[0 for i in range(self.real_width)] for j in range(self.real_height)]

    def create(self,screen,b):
        for i in range(self.real_height):
            for j in range(self.real_width):
                screen.blit(b.block, (j*self.block, i*self.block))

这个地图类目前包含两个方法:一个是地图初始化方法,另一个是地图铺满屏幕方法。


我们先来看看初始化方法:

self.map_width,self.map_height = 960, 640
self.block = 32
self.real_width,self.real_height = self.map_width//self.block, self.map_height//self.block
self.empty_map = [[0 for i in range(self.real_width)] for j in range(self.real_height)]

主要有四步:

  1. 设置地图大小
  2. 设置格子大小(这步可以在格子类中设置)
  3. 设置二维数组的下标(用地图宽高/格子宽高)
  4. 初始化二维数组

在第四步初始化二维数组的时候,我一开始是使用下面这种方式初始化的

self.empty_map = [[0]*self.real_width]*self.real_height

 一开始没有什么问题,直到改变二维数组某一个下标(x,y)值的时候,整列([:][y])都变成了那个值,推测用这种[0]*num方法创建的数组,每次修改任意下标的值,都会重新生成整个数组。


接着是地图铺满屏幕方法:

首先传入两个参数,一个是screen,另一个是b

screen是pygames的场景类,布置精灵都需要它

b是格子类,下面我们看一下格子类

class Block:
    def __init__(self):
        self.block = pygame.image.load('images/green.png')

这是最初始的格子类,只有一个加载图片的功能,后面我们会逐步开发格子类的其他功能。

 接着就是循环遍历地图数组,为每个下标渲染格子。因为一开始数组都为0,所以只需要加载背景格子就可以了。


场景布置好之后我们就要开始渲染场景了,渲染函数如下:

def main():
    pygame.init()
    clock = pygame.time.Clock()             # 设置时钟
    clock.tick(10)                      # 每秒执行60次
    m = Map()
    b = Block()
    screen = pygame.display.set_mode((m.width,m.height))  # 显示窗口
    color = (255,255,0)
    screen.fill(color)
    while True:
        # 轮询事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:   # 如果检测到事件是关闭窗口
                sys.exit()
            else:
                m.create(screen,b)
                pygame.display.update()
    pygame.quit()

渲染函数主要有以下几个要点

  • pygame初始化,必须的
pygame.init()
  • 时钟设置,一秒钟刷新60次地图
clock = pygame.time.Clock()             # 设置时钟
clock.tick(10)                      # 每秒执行60次
  • 死循环渲染地图
m.create(screen,b)
pygame.display.update()

运行之后效果如下:

说好的格子呢???黑人问号,一脸懵逼。

遇到的第二个问题就是边框问题

原来是因为选择了纯色的格子,无缝铺满之后,看起来就像是设置了背景色一般。这明显不满足我们想要的风格呀。怎么办呢?加边框。


加边框有两种方法,一种直接找一张带边框的图片或者找一种给图片加边框的方法(可惜找了好久没找到),另一种就是用程式加边框。

现在我们修改地图类的地图铺满屏幕方法,添加边框。同时我们添加一个函数用来返回地图大小,这样就不需要每次手动设置窗口大小了

class Map:
    def __init__(self):
        self.map_width,self.map_height = 960, 640
        self.block = 32
        self.real_width,self.real_height = self.map_width//self.block, self.map_height//self.block
        self.empty_map = [[0 for i in range(self.real_width)] for j in range(self.real_height)]
        
    @property
    def map_size(self):
        return (self.map_width,self.map_height)

    def create(self,screen,b):
        for i in range(self.real_height):
                screen.blit(b.block, (j*self.block, i*self.block))
                pygame.draw.line(screen, (0,0,0), (j*self.block,0), (j*self.block,self.map_height), 1)
            pygame.draw.line(screen, (0,0,0), (0,i*self.block), (self.map_width,i*self.block), 1)

修改后运行效果如下:


总结

目前完成了基本的地图制作,但是正常来说一个战棋游戏的地图最少要包含各式各样的棋子,但是考虑到功能的分类,就划分到下一篇推文的内容中。

对于地图的制作其实还有很多问题,每次循环都需要重新刷新地图,这样对电脑的消耗会不会很大?如果地图的大小超过屏幕的大小,应该怎么处理?每次刷新地图,其实都是在原有地图的基础上重新铺满一层,等程序运行时间增长,地图就会越铺越多,最后可能会造成内存溢出问题。

但是目前暂时还没有的解决这些问题,打算先把基本的功能都做出来,然后再回头补充。感兴趣的小伙伴可以私聊或者评论我,我们一起交流一下呀。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5595084.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存