+++ /dev/null
-import os
-import numpy as np
-
-from Function.createText import createText
-from Setup import *
-
-import tkinter as tk
-from tkinter import filedialog
-
-
-class LevelCreator:
- canvas_layers = 5
- textures = [file[:file.index(".")] for file in listdir("Assets/world/blocks")]
- textures.append("NONE")
-
- def __init__(self):
- self.blocks = {"none": [[] for _ in range(self.canvas_layers)],
- "world": [[] for _ in range(self.canvas_layers)]}
-
- self.grid = Grid()
-
- self.zoom = 1
- self.total_offset = pg.Vector2(0, 0)
- self.world_transform = np.identity(3)
- self.inv_world_transform = np.linalg.inv(self.world_transform)
-
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
- self.translation_back_matrix = np.array([[1, 0, -self.total_offset.x],
- [0, 1, -self.total_offset.y],
- [0, 0, 1]])
-
- self.current_texture = self.textures.index("PLACEHOLDER")
- self.current_layer = 0
- self.show_grid = True
- self.show_hitboxes = False
- self.collision_layer = "world"
-
- self.buttons = [Button((0, 0), "Toggle Grid", self.toggle_grid),
- Button((0, 0), "-Layer", self.decrease_layer),
- Button((0, 0), f"{self.current_layer=}", self.upd_layer),
- Button((0, 0), "+Layer", self.increase_layer),
- Button((0, 0), f"{self.collision_layer=}", self.toggle_collidable),
- Button((0, 0), "Toggle Hitboxes", self.toggle_show_hitboxes),
- Button((0, 0), "Import", self.import_level),
- Button((0, 0), "Export", self.export),
- ]
-
- self.level = -2
-
- def export(self):
- # for layer in out:
- # for i,block in enumerate(layer):
- # layer[i] = Block(block.position,block.collision_layer,block.texture_name)
-
- counter = 1
-
- def get_key(mask):
- for key, value in self.blocks.items():
- if mask == value:
- return key
-
- while True:
- try:
- with open(os.path.join("Levels", f'Level{counter}.txt'), 'x') as f:
- out = ""
- for layer in self.get_canvas_layers():
- t = ""
- pos = ""
- texture = ""
- for block in layer:
- t += f"{get_key(block.collision_layer)}|"
- pos += f"{block.position.x},{block.position.y}|"
- texture += f"{block.texture_name}|"
- out += f"{t[:-1]}\n{pos[:-1]}\n{texture[:-1]}\n"
- f.write(out)
-
- print(f"File saved as Level{counter} in folder Levels")
- break
- except FileExistsError:
- counter += 1
-
- def import_level(self):
- root = tk.Tk()
- root.withdraw()
-
- filename = filedialog.askopenfilename(initialdir="./Levels", title="Select A File",
- filetypes=((".txt", "*.txt"), ("all files", "*.*")))
- if filename == '':
- return
- with open(filename, 'r', encoding='utf-8') as f:
- file_contents = f.read().split("\n")
-
- # with open(path.join("Levels", f'Level{1}.txt'), 'r') as f:
- # file_contents = f.read().split("\n")
-
- for i in range(0, len(file_contents) - 1, 3):
- layer = file_contents[i].split("|")
- pos = file_contents[i + 1].split("|")
- texture = file_contents[i + 2].split("|")
-
- for l, p, t in zip(layer, pos, texture):
- if p == "":
- break
- x, y = p.split(',')
- self.add_block(self.apply_transformations((float(x), float(y))), self.blocks[l], t, i)
-
- def toggle_collidable(self):
- if self.collision_layer == "none":
- self.collision_layer = "world"
- else:
- self.collision_layer = "none"
- button = self.buttons[4]
- button.upd_text(button.position, f"{self.collision_layer=}")
-
- def toggle_show_hitboxes(self):
- self.show_hitboxes = not self.show_hitboxes
-
- def toggle_grid(self):
- self.show_grid = not self.show_grid
-
- def decrease_layer(self):
- self.current_layer = max(self.current_layer - 1, 0)
- self.upd_layer()
-
- def increase_layer(self):
- self.current_layer = min(self.current_layer + 1, self.canvas_layers - 1)
- self.upd_layer()
-
- def upd_layer(self):
- button = self.buttons[2]
- button.__init__(button.position, f"{self.current_layer=}", self.upd_layer)
-
- def fit_to_grid(self, pt, use_floor=True):
- pos = self.reverse_transformations(pg.Vector2(pt))
- if use_floor:
- return pg.Vector2((pos.x // EditorBlock.width) * EditorBlock.width,
- (pos.y // EditorBlock.height) * EditorBlock.height)
- else:
- return pg.Vector2(round(pos.x / EditorBlock.width) * EditorBlock.width,
- round(pos.y / EditorBlock.height) * EditorBlock.height)
-
- def apply_rect_transformations(self, rect):
- top_left = np.array([rect.left, rect.top, 1])
- bottom_right = np.array([rect.right, rect.bottom, 1])
-
- top_left = pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ top_left)[0:2]))
- bottom_right = pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ bottom_right)[0:2]))
-
- return pg.Rect(top_left, bottom_right - top_left)
-
- def add_block(self, pos, mask, texture, canvas_layer):
- pos = self.fit_to_grid(pos)
- for m in self.blocks.values():
- for i, block in enumerate(m[canvas_layer]):
- if block.position == pos:
- del m[canvas_layer][i]
- break
- if texture != "NONE":
- mask[canvas_layer].append(EditorBlock(pos, mask, texture))
-
- def calculate_transformations(self, current_frame_zoom):
- mouse_pos = pg.Vector2(pg.mouse.get_pos())
-
- translation_matrix = np.array([[1, 0, mouse_pos.x],
- [0, 1, mouse_pos.y],
- [0, 0, 1]])
- translation_back_matrix = np.array([[1, 0, -mouse_pos.x],
- [0, 1, -mouse_pos.y],
- [0, 0, 1]])
- scale_matrix = np.array([[current_frame_zoom, 0, 0],
- [0, current_frame_zoom, 0],
- [0, 0, 1]])
- self.world_transform = translation_matrix @ scale_matrix @ translation_back_matrix @ self.world_transform
- self.inv_world_transform = np.linalg.inv(self.world_transform)
-
- def apply_transformations(self, pt):
- point = pg.Vector2(pt)
- point = np.array([point.x, point.y, 1])
- return pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ point)[0:2]))
-
- def reverse_transformations(self, pt):
- point = pg.Vector2(pt)
- point = np.array([point.x, point.y, 1])
- return pg.Vector2(tuple((self.translation_back_matrix @ self.inv_world_transform @ point)[0:2]))
-
- def update(self, delta):
- current_frame_zoom = 1
- for event in pg.event.get((pg.MOUSEBUTTONDOWN, pg.MOUSEWHEEL, pg.KEYUP)):
- if event.type == pg.MOUSEBUTTONDOWN:
- if event.button == 1:
- pg.mouse.get_rel()
- if event.type == pg.MOUSEWHEEL:
- if event.y < 0:
- current_frame_zoom *= 0.75
- self.zoom *= 0.75
- elif event.y > 0:
- current_frame_zoom *= 1.25
- self.zoom *= 1.25
- if event.type == pg.KEYUP:
- if event.key in [pg.K_a, pg.K_s, pg.K_LEFT, pg.K_DOWN]:
- self.current_texture = (self.current_texture - 1) % len(self.textures)
- elif event.key in [pg.K_d, pg.K_w, pg.K_RIGHT, pg.K_UP]:
- self.current_texture = (self.current_texture + 1) % len(self.textures)
-
- mouse_pressed = pg.mouse.get_pressed(3)
- if mouse_pressed[0]:
- mouse_rel = pg.mouse.get_rel()
- self.total_offset += pg.Vector2(mouse_rel[0] / self.zoom, mouse_rel[1] / self.zoom)
- if mouse_pressed[2]:
- self.add_block(pg.mouse.get_pos(), self.blocks[self.collision_layer], self.textures[self.current_texture],
- self.current_layer)
-
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
- self.translation_back_matrix = np.array([[1, 0, -self.total_offset.x],
- [0, 1, -self.total_offset.y],
- [0, 0, 1]])
-
- self.calculate_transformations(current_frame_zoom)
-
- self.grid.update(delta, self.world_transform, self.inv_world_transform, self.total_offset, self.zoom)
-
- for mask in self.blocks.values():
- for layer in mask:
- for block in layer:
- block.update(delta, self.world_transform, self.total_offset)
-
- prev_x = 0
- for button in self.buttons:
- button.update(delta, dx=prev_x)
- prev_x += button.width + 10
-
- def get_canvas_layers(self):
- out = [[] for _ in range(self.canvas_layers)]
- for mask in self.blocks.values():
- for i, layer in enumerate(mask):
- out[i] += layer
- return out
-
- def draw(self, surf):
- surf.fill((0, 0, 0))
- if self.show_grid:
- self.grid.draw(surf)
-
- for i, layer in enumerate(self.get_canvas_layers()):
- if i <= self.current_layer:
- for block in layer:
- block.draw(surf)
- if self.show_hitboxes:
- block.show_hitbox(surf, self.blocks["world"])
-
- pg.draw.line(surf, (255, 0, 0), self.apply_transformations((self.reverse_transformations((0, 0)).x, 0)),
- self.apply_transformations((self.reverse_transformations((SCREEN_WIDTH, 0)).x, 0)),
- math.ceil(self.zoom * 5))
- pg.draw.line(surf, (255, 0, 0), self.apply_transformations((0, self.reverse_transformations((0, 0)).y)),
- self.apply_transformations((0, self.reverse_transformations((0, SCREEN_HEIGHT)).y)),
- math.ceil(self.zoom * 5))
-
- display_img = EditorBlock.textures[self.textures[self.current_texture]].copy()
- display_img.set_alpha(100)
- surf.blit(pg.transform.scale(display_img, self.apply_rect_transformations(display_img.get_rect()).size),
- self.apply_transformations(self.fit_to_grid(pg.mouse.get_pos(), use_floor=True)))
- for button in self.buttons:
- button.draw(surf)
-
-
-class Grid:
- thickness = 2
- colour = (100, 100, 100)
-
- def __init__(self):
- self.zoom = 1
- self.world_transform = np.identity(3)
- self.inv_world_transform = np.linalg.inv(self.world_transform)
- self.total_offset = pg.Vector2(0, 0)
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
- self.translation_back_matrix = np.array([[1, 0, -self.total_offset.x],
- [0, 1, -self.total_offset.y],
- [0, 0, 1]])
-
- def update(self, delta, world_transform, inv_world_transform, total_offset, zoom):
- self.zoom = zoom
- self.world_transform = world_transform
- self.inv_world_transform = inv_world_transform
- self.total_offset = total_offset
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
- self.translation_back_matrix = np.array([[1, 0, -self.total_offset.x],
- [0, 1, -self.total_offset.y],
- [0, 0, 1]])
-
- def apply_transformations(self, pt):
- point = pg.Vector2(pt)
- point = np.array([point.x, point.y, 1])
- return pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ point)[0:2]))
-
- def reverse_transformations(self, pt):
- point = pg.Vector2(pt)
- point = np.array([point.x, point.y, 1])
- return pg.Vector2(tuple((self.translation_back_matrix @ self.inv_world_transform @ point)[0:2]))
-
- def draw(self, surf):
- start = self.reverse_transformations((0, 0))
- end = self.reverse_transformations(dimensions)
-
- start = pg.Vector2(start.x // EditorBlock.width, start.y // EditorBlock.width)
- end = pg.Vector2(end.x // EditorBlock.height, end.y // EditorBlock.height)
-
- for i in range(math.floor(start.x), math.floor(end.x) + 1):
- pg.draw.line(surf, self.colour,
- self.apply_transformations((i * EditorBlock.width, start.y * EditorBlock.height)),
- self.apply_transformations((i * EditorBlock.width, (end.y + 1) * EditorBlock.height)),
- math.ceil(self.thickness * self.zoom))
- for i in range(math.floor(start.y), math.floor(end.y) + 1):
- pg.draw.line(surf, self.colour,
- self.apply_transformations((start.x * EditorBlock.width, i * EditorBlock.height)),
- self.apply_transformations(((end.x + 1) * EditorBlock.width, i * EditorBlock.height)),
- math.ceil(self.thickness * self.zoom))
-
-
-class EditorBlock:
- textures = {file[:file.index(".")]: pg.transform.scale(
- pg.image.load(path.join("Assets/world/blocks", file)), (50, 50)) for
- file in listdir("Assets/world/blocks")}
- width, height = textures["PLACEHOLDER"].get_size()
-
- def __init__(self, pos, collision_layer, texture="PLACEHOLDER"):
- self.position = pg.Vector2(pos)
- self.texture = self.textures[texture]
- self.texture_name = texture
-
- self.collision_layer = collision_layer
-
- self.world_transform = np.identity(3)
- self.total_offset = pg.Vector2(0, 0)
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
-
- def update(self, delta, world_transform, total_offset):
- self.world_transform = world_transform
- self.total_offset = total_offset
- self.translation_matrix = np.array([[1, 0, self.total_offset.x],
- [0, 1, self.total_offset.y],
- [0, 0, 1]])
-
- def apply_transformations(self, rect):
- top_left = np.array([rect.left, rect.top, 1])
- bottom_right = np.array([rect.right, rect.bottom, 1])
-
- top_left = pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ top_left)[0:2]))
- bottom_right = pg.Vector2(tuple((self.world_transform @ self.translation_matrix @ bottom_right)[0:2]))
-
- return pg.Rect(top_left, bottom_right - top_left)
-
- def get_display_rect(self):
- return self.apply_transformations(pg.Rect(self.position, (self.width, self.height)))
-
- def draw(self, surf):
- display_rect = self.get_display_rect()
- surf.blit(pg.transform.scale(self.texture, display_rect.size), display_rect)
-
- def show_hitbox(self, surf, collision_layer):
- if collision_layer == self.collision_layer:
- pg.draw.rect(surf, (255, 0, 0), self.get_display_rect(), 3)
-
-
-class Button:
-
- def __init__(self, pos, msg, func):
- self.position = pg.Vector2(pos)
- self.text, self.rect = createText(self.position.x * 2, self.position.y, 20, (200, 200, 200), "Regular", msg)
- self.width, self.height = self.text.get_size()
- self.func = func
- self.msg = msg
- self.cooldown = 500
-
- def upd_text(self, pos, msg):
- self.position = pg.Vector2(pos)
- self.text, self.rect = createText(self.position.x * 2, self.position.y, 20, (200, 200, 200), "Regular", msg)
- self.width, self.height = self.text.get_size()
- self.msg = msg
-
- def update(self, delta, dx):
- self.upd_text((dx, self.position.y), self.msg)
- mouse_pos = pg.mouse.get_pos()
- if self.cooldown == 0:
- if pg.mouse.get_pressed(3)[0]:
- if (self.position.x <= mouse_pos[0] <= self.position.x + self.width and
- self.position.y <= mouse_pos[1] <= self.position.y + self.height):
- self.func()
- self.cooldown = 500
- self.cooldown = max(self.cooldown - delta, 0)
-
- def draw(self, surf):
- pg.draw.rect(surf, (80, 80, 80), pg.Rect(self.position, self.text.get_size()), border_radius=3)
- pg.draw.rect(surf, (120, 120, 120), pg.Rect(self.position, self.text.get_size()), 1, border_radius=3)
- surf.blit(self.text, self.rect)