用pygame寫像素遊戲地圖編輯器

用pygame寫像素遊戲地圖編輯器

像素遊戲的地圖

我使用一個矩陣來存儲地圖,像下面這樣:
[[1,0,0],[0,1,0],[1,2,0]]
不同的數字代表不同的物體,比如1代表一個房子,0代表路面。
不同區間之間的物體的類型不同,比如

區間 類型
<1 代表路面、草坪等可以通過的地方
≥1且<2 代表牆面、等
≥2 代表可以交互的地方

功能

創建後是這樣的,按動按鍵可以改變下面的圖片,點擊上面的矩陣將上面的圖片改變成下面的圖片地圖編輯器

建立地圖類

初始化地圖類
我用一個字典self.dic 來保存地圖的矩陣中的數對應儲存地圖圖片,鍵是是儲存的數,值是儲存的文件名,self.dic_l則是用於字典的鍵的值便於後續對它操作,self.un_maps則是儲存地圖的矩陣。同時我還初始化了一個表面self.s_map用於繪製地圖。

class MapMaker:

    def __init__(self):
        """
        用字典來保存圖片位置
        <1 代表路面、草坪等可以通過的地方
        ≥1且<2 代表牆面、等
        ≥2 代表可以交互的地方
        """
        self.dic = {0: "road", 0.1: "roadv", 0.11: "roadc1", 0.12: "roadc2", 0.13: "roadc3", 0.14: "roadc4",
                    0.15: "hospital_road2", 0.16: "hospital_road3",
                    0.2: "glass", 0.21: "hospital_f1", 0.22: "hospital_f2",
                    1: "wall", 1.1: "wallv", 1.11: "wallc", 1.12: "wallc1", 1.13: "wallc2", 1.14: "wallc3",
                    1.2: "hospital_wall1", 1.21: "hospital_wall2", 1.22: "hospital_wall3", 1.23: "hospital_wall4",
                    1.24: "hospital_wall5", 1.25: "hospital_wall6"}
        self.s_map = pygame.Surface(screen.get_size())
        self.s_map.fill([255, 255, 255])
        self.dic_l = list(self.dic)

        # 遊戲地圖 un_maps
        self.un_maps = [[1,0,0],[0,1,0],[1,2,0]]

更新表面

這個函數用於將表面更新到屏幕上。

    def r_show(self):
        # 再現地圖
        screen.blit(self.s_map, (0, 0))

繪製地圖

這個函數用於根據行列拆分地圖,然後根據矩陣中每個元素的位置確定要繪製的地圖的位置並更新表面。最後調用self.r_show()來更新顯示。

    def get_map(self):
        # 放置下方的橫條
        img_b = pygame.image.load(r"s\bang.png")
        self.s_map.blit(img_b, [0, -1])
        # 讀取數組中位置的圖片並更新
        ci, ri = 0, 0
        for c in self.un_maps:
            for r in c:
                # 按行繪製
                image = pygame.image.load(r"s\{}.png".format(self.dic[r]))
                px, py = image.get_size()
                self.s_map.blit(image, (ri * px, ci * py))
                ri = ri + 1
            ci = ci + 1
            ri = 0  # 初始化行標識
            self.r_show()

實現的效果是地圖

更新地圖中的元素

這個函數用於更新地圖中的元素,需要元素的行索引、列索引和改變後的值

    def c_map(self, inx, iny, change):
        self.un_maps[iny][inx] = change
        self.get_map()

顯示當前的圖像

這個函數根據在字典中的順序來顯示當前值對應的文件名。

    def show_now(self, r):
        image = pygame.image.load(r"s\{}.png".format(self.dic[self.dic_l[r]]))
        self.s_map.blit(image, (100, 600))
        self.r_show()

實現的效果
下一個替換的圖片

儲存地圖文件

保存在map.txt上

    def write_map(self):
        fo = open("map.txt", "w")
        fo.write(str(self.un_maps))

初始化

初始化地圖類,並繪製地圖
設置一個變量now_talent用來保存當前位置的值。

# 遊戲初始化
pygame.init()
# 創建窗口
screen = pygame.display.set_mode([1080, 720])
screen.fill([255, 255, 255])
pygame.display.set_caption("Map Maker")

mp = MapMaker()
mp.get_map()

now_talent = 0

處理事件

下面用於獲取鼠標的位置,並且如果鼠標按鍵動了,就更新鼠標所在位置元素塊的圖片。

if event.type == pygame.MOUSEBUTTONDOWN:
            print(pygame.mouse.get_pos())
            x, y = pygame.mouse.get_pos()
            if x < 1080 and y < 540:
                x, y = int(x / 36), int(y / 36)
                mp.c_map(x, y, mp.dic_l[now_talent])
                mp.show_now(now_talent)

如果按動鍵盤按鍵,就更新索引值。

if event.type == pygame.KEYDOWN:
            if now_talent < len(mp.dic_l) - 1:
                now_talent = now_talent + 1
                mp.show_now(now_talent)
            else:
                now_talent = 0
                mp.show_now(now_talent)
    pygame.display.update()

完整代碼

import pygame


# 本例用於完成二維像素地圖的編輯


class MapMaker:

    def __init__(self):
        """
        用字典來保存圖片位置
        <1 代表路面、草坪等可以通過的地方
        ≥1且<2 代表牆面、等
        ≥2 代表可以交互的地方
        """
        self.dic = {0: "road", 0.1: "roadv", 0.11: "roadc1", 0.12: "roadc2", 0.13: "roadc3", 0.14: "roadc4",
                    0.15: "hospital_road2", 0.16: "hospital_road3",
                    0.2: "glass", 0.21: "hospital_f1", 0.22: "hospital_f2",
                    1: "wall", 1.1: "wallv", 1.11: "wallc", 1.12: "wallc1", 1.13: "wallc2", 1.14: "wallc3",
                    1.2: "hospital_wall1", 1.21: "hospital_wall2", 1.22: "hospital_wall3", 1.23: "hospital_wall4",
                    1.24: "hospital_wall5", 1.25: "hospital_wall6",
                    2: "hospital_home1", 2.1: "hospital_home2", 2.11: "hospital_home3", 2.12: "hospital_road1",
                    3: "SCUT"}
        self.s_map = pygame.Surface(screen.get_size())
        self.s_map.fill([255, 255, 255])
        self.dic_l = list(self.dic)

        # 遊戲地圖 un_maps
        self.un_maps = [[0.15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.25, 1, 0.21, 0.13, 1.22], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0.15, 2, 0.15, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 2, 2.1, 2.11, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0.12, 2.12, 0.16, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.24, 1.2, 0.16, 1.2, 1.23], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

    def get_map(self):
        # 放置下方的橫條
        img_b = pygame.image.load(r"s\bang.png")
        self.s_map.blit(img_b, [0, -1])
        # 讀取數組中位置的圖片並更新
        ci, ri = 0, 0
        for c in self.un_maps:
            for r in c:
                # 按行繪製
                image = pygame.image.load(r"s\{}.png".format(self.dic[r]))
                px, py = image.get_size()
                self.s_map.blit(image, (ri * px, ci * py))
                ri = ri + 1
            ci = ci + 1
            ri = 0  # 初始化行標識
            self.r_show()

    def r_show(self):
        # 再現地圖
        screen.blit(self.s_map, (0, 0))

    def c_map(self, inx, iny, change):
        self.un_maps[iny][inx] = change
        self.get_map()

    def write_map(self):
        fo = open("map.txt", "w")
        fo.write(str(self.un_maps))

    def show_now(self, r):
        image = pygame.image.load(r"s\{}.png".format(self.dic[self.dic_l[r]]))
        self.s_map.blit(image, (100, 600))
        self.r_show()



# 遊戲初始化
pygame.init()
# 創建窗口
screen = pygame.display.set_mode([1080, 720])
screen.fill([255, 255, 255])
pygame.display.set_caption("Map Maker")

mp = MapMaker()
mp.get_map()

now_talent = 0
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            mp.write_map()
            # 退出遊戲
            pygame.quit()
            break
        elif event.type == pygame.MOUSEBUTTONDOWN:
            print(pygame.mouse.get_pos())
            x, y = pygame.mouse.get_pos()
            if x < 1080 and y < 540:
                x, y = int(x / 36), int(y / 36)
                mp.c_map(x, y, mp.dic_l[now_talent])
                mp.show_now(now_talent)
        elif event.type == pygame.KEYDOWN:
            if now_talent < len(mp.dic_l) - 1:
                now_talent = now_talent + 1
                mp.show_now(now_talent)
            else:
                now_talent = 0
                mp.show_now(now_talent)
    pygame.display.update()

發佈了5 篇原創文章 · 獲贊 0 · 訪問量 1666
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章