python游戏开发实战:行走系统之地图编辑器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39687901/article/details/84879383

一、运行效果

操作说明:

方向键控制地图移动

w键保存地图

r键读取地图

鼠标左键设置障碍

鼠标右键删除障碍

二、前言

之前呢,写过一个python的A星算法类(A星算法),运行结果只能在控制台查看,太不爽了。A星算法可是游戏里常用的寻路算法,当然是要结合游戏使用才过瘾。

所以,我打算写几篇关于2drpg行走系统开发的文章。

写行走系统之前,我们得有个地图编辑器。将地图行走层编辑保存为文件,然后在游戏里读取这个行走层文件。

三、开发思路

游戏中的地图其实就是一个二维数组,我们的地图编辑器只需要将这个二维数组相应位置的值改变就行了。我们可以人为规定map[x][y]==0的时候是可行走的,map[x][y]==1的时候是障碍。

所以,地图编辑器就是用来编辑这个二维数组,并且将它可视化。

在我写的这个简易的地图编辑器中,规定16*16个像素为一个格子,当然你完全可以改成其他尺寸。

四、核心算法

鼠标点下去的位置是如何与二维数组下标对应的呢?这就是本文的重点。

在解决一个问题之前,我们得理一理已知条件是什么,需要求什么。

已知:

map_x,map_y  地图绘图坐标,也就是地图图片的左上角相对于窗口的坐标。

mouse_x,mouse_y 鼠标在窗口中的坐标

求:

indexX,indexY 鼠标点击位置所对应的地图二维数组中的下标

如图所示:

绿色的是游戏地图,黑色的是游戏窗口,红色点是鼠标点击的位置。

那么,鼠标相对于地图的坐标是多少呢?

设mouse_map_x,mouse_map_y为鼠标相对于地图的坐标,如图:

显然mouse_map_x=mouse_x+(-map_x),但是为什么是加(-map_x)呢?因为map_x是相对于游戏窗口的坐标,所以它总是一个负数,所以加一个负号让它变成正数。

同理mouse_map_y=mouse_y+(-map_y)

那么我们所求的indexX,indexY就很容易计算出来了,上面说过了一个格子占16*16个像素。

所以:

indexX=int(mouse_map_x/16)

indexY=int(mouse_map_y/16)

ok啦,下面放上代码(源码里的命名和上述命名有所不同,还请大家注意啦)。

五、源码

"""
    为演示A星算法的实际用途,而专门开发的地图编辑器
"""
import pygame


class Array2D:
    """
        说明:
            1.构造方法需要两个参数,即二维数组的宽和高
            2.成员变量w和h是二维数组的宽和高
            3.使用:‘对象[x][y]’可以直接取到相应的值
            4.数组的默认值都是0
    """

    def __init__(self, w, h):
        self.w = w
        self.h = h
        self.data = [[0 for y in range(h)] for x in range(w)]

    def showArray2D(self):
        for y in range(self.h):
            for x in range(self.w):
                print(self.data[x][y], end=' ')
            print("")

    def __getitem__(self, item):
        return self.data[item]


winSur = None  # 窗口的surface
map2d = None  # 地图的二维数组
mapImg = None  # 地图的图片
x, y = [0, 0]  # 地图当前绘图坐标
dirKeyState = [0, 0, 0, 0]  # 下,上,右,左方向键状态,0没按下 1按下


def init():
    global winSur, map2d, mapImg
    pygame.init()
    pygame.display.set_caption("地图行走层编辑器")
    winSur = pygame.display.set_mode((640, 480))
    mapImg = pygame.image.load('./images/btm_1_0.jpg')
    # 以16*16像素为一个可行走的格子
    map2d = Array2D(int(mapImg.get_width() / 16), int(mapImg.get_height() / 16))


def writeMap():
    with open('./map01.map', mode='w', encoding='utf8') as file:
        file.write(str(map2d.data))
    print("保存地图成功!")


def readMap():
    global map2d
    with open('./map01.map', mode='r', encoding='utf8') as file:
        data = file.read()
    map2d.data = eval(data)
    map2d.w = len(map2d.data)
    map2d.h = len(map2d.data[0])
    print("读取地图成功!")


def moveMap():
    """
    移动地图
    :return:
    """
    global x, y
    step = 8
    if dirKeyState[0] == 1:
        y += step
        if y + step > 0:
            y = 0

    if dirKeyState[1] == 1:
        y -= step
        if y - step < -(mapImg.get_height() - 480):
            y = -(mapImg.get_height() - 480)

    if dirKeyState[2] == 1:
        x += step
        if x + step > 0:
            x = 0

    if dirKeyState[3] == 1:
        x -= step
        if x - step < -(mapImg.get_width() - 640):
            x = -(mapImg.get_width() - 640)


def drawMap():
    """
    绘制不可行走区域
    :return:
    """
    for ty in range(map2d.h):
        for tx in range(map2d.w):
            if map2d[tx][ty] == 1:
                pygame.draw.rect(winSur, (255, 255, 255), (x + tx * 16 + 1, y + ty * 16 + 1, 14, 14), 1)


def mainLoop():
    global dirKeyState, map2d
    # 相关参数
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    dirKeyState[0] = 1
                elif event.key == pygame.K_DOWN:
                    dirKeyState[1] = 1
                elif event.key == pygame.K_LEFT:
                    dirKeyState[2] = 1
                elif event.key == pygame.K_RIGHT:
                    dirKeyState[3] = 1
                elif event.key == pygame.K_r:
                    readMap()  # 读取地图
                elif event.key == pygame.K_w:
                    writeMap()  # 保存地图
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    dirKeyState[0] = 0
                elif event.key == pygame.K_DOWN:
                    dirKeyState[1] = 0
                elif event.key == pygame.K_LEFT:
                    dirKeyState[2] = 0
                elif event.key == pygame.K_RIGHT:
                    dirKeyState[3] = 0
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_x, mouse_y = pygame.mouse.get_pos()  # 获得当前鼠标坐标
                map_x = mouse_x + (-x)
                map_y = mouse_y + (-y)
                cell_x = int(map_x / 16)
                cell_y = int(map_y / 16)
                if pygame.mouse.get_pressed() == (1, 0, 0):  # 鼠标左键按下
                    map2d[cell_x][cell_y] = 1
                if pygame.mouse.get_pressed() == (0, 0, 1):  # 鼠标左键按下
                    map2d[cell_x][cell_y] = 0
        pygame.time.delay(32)
        # 逻辑更新
        moveMap()
        # 绘图更新
        winSur.blit(mapImg, (x, y))
        drawMap()
        pygame.display.flip()


if __name__ == '__main__':
    init()
    mainLoop()

猜你喜欢

转载自blog.csdn.net/qq_39687901/article/details/84879383