前言
本来有好多篇博文想写的,但是目前在做的是这款战棋游戏的开发,所以其他版块只能先咕咕咕了。或者有关注的小伙伴们可以留言希望下一个更新的版块是啥子?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)]
主要有四步:
- 设置地图大小
- 设置格子大小(这步可以在格子类中设置)
- 设置二维数组的下标(用地图宽高/格子宽高)
- 初始化二维数组
在第四步初始化二维数组的时候,我一开始是使用下面这种方式初始化的
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)
修改后运行效果如下:
总结
目前完成了基本的地图制作,但是正常来说一个战棋游戏的地图最少要包含各式各样的棋子,但是考虑到功能的分类,就划分到下一篇推文的内容中。
对于地图的制作其实还有很多问题,每次循环都需要重新刷新地图,这样对电脑的消耗会不会很大?如果地图的大小超过屏幕的大小,应该怎么处理?每次刷新地图,其实都是在原有地图的基础上重新铺满一层,等程序运行时间增长,地图就会越铺越多,最后可能会造成内存溢出问题。
但是目前暂时还没有的解决这些问题,打算先把基本的功能都做出来,然后再回头补充。感兴趣的小伙伴可以私聊或者评论我,我们一起交流一下呀。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)