记得以前有几款很经典的游戏(红色警戒,命令与征服,英雄无敌),不小心暴漏了自己的年龄(这几款游戏都有年头了),因为知道并玩过这几款游戏的人可能还记得,里面有一个功能,就是自己编辑地图,在自己编辑的地图上玩游戏。
当时觉得这个功能很炫酷,因为通常游戏场景都是游戏制作者给出的,玩家没得选。最近学习Python,觉得Pygame可以很轻松就实现这个功能,于是自己实现了一下。供感兴趣的朋友们参考,批评指正。
废话不多说,说正事。
既然是编辑地图,必须要有背景和地图上展示的元素,以及元素在地图上的位置等信息。
打码开始:
地图元素类:
class Elements(Sprite):
def __init__(self, image, position, layer, layerGroup, *groups):
self._layer = layer
self.groups = layerGroup, *groups
super().__init__(self.groups)
# image 包含了路径 "assets/images/"...
self.imageFile = image # 记录图像路径和文件名
self.image = pygame.image.load(image).convert_alpha()
self.rect = Rect(position, self.image.get_size())
def get_layer(self):
return self._layer
地图类如下。
class Map:
def __init__(self):
self.bg = None
self.elements = []
def re_init(self):
if self.bg:
self.bg.kill()
self.bg = None
for element in self.elements:
element.kill()
self.elements = []
def change_bg(self, newBg):
if self.bg:
self.bg.kill()
self.bg = newBg
def add_element_into_map(self, element):
self.elements.append(element)
实际上地图就是一个地图元素(包含背景地图和元素的容器)。因此非常简单。那么如何实现编辑地图呢?下面给出地图编辑类。
class MapMaker(Sprite):
def __init__(self, image, layer, layerGroup):
self._layer = layer
super().__init__(layerGroup)
self.layerGroup = layerGroup
self.image = pygame.image.load(image).convert()
self.rect = Rect((0, 0), SCREEN_SIZE)
# 保存从素材库获取的背景地图素材和地图元素素材
self.bgElements = []
self.elements = []
# 从素材库中读取素材
self.get_elements_from_files()
# 添加背景和地图元素后的地图 并给一个缺省的背景
self.map = Map()
self.map.bg = Elements(DEFAUT_MAP_BACKGROUP, (0, 0), BACKGROUND_LAYER, self.layerGroup)
# 处理事件时使用
self.elementSelected = None # 将要操作的地图元素
self.relPos = (0, 0) # 记录在选择区鼠标位置与被选择元素rect.topleft 的相对位置
self.selectedList = [] # 从地图区选择的地图元素
self.relPosList = [] # 修改地图去元素的位置时记录rect.topleft 和鼠标位置的相对值
# 是否加载过地图,保存加载地图的信息用于覆盖或者新建地图
self.currentOpenedMap = None
# 增加命令按钮
self.buttonList = Group()
self.init_button_list()
从 mapMaker类的初始化函数中可以看到定义了一些地图操作时需要的变量,另外定义了几个button。Button类在我的以前的文章中已经给出过,基本上没有什么修改,小小调整一下就可以直接拿过来用。这里就不重复了。
下面是button初始化和button的回调函数:
def init_button_list(self):
self.buttonList.append(Button(NEW_MAP_BUTTON, "New Map", FONT_NAME, FONT_SIZE, FONT_COLOR, MSG_LAYER,
(BOTTOM_COLOR, ON_HOVER_COLOR, ON_CLICK_COLOR),
self.layerGroup, None, None, None, self.new_map_callback))
self.buttonList.append(Button(LOAD_MAP_BUTTON, "Load Map", FONT_NAME, FONT_SIZE, FONT_COLOR, MSG_LAYER,
(BOTTOM_COLOR, ON_HOVER_COLOR