]> Skullheadx's Git Forge - Pygame-Jam.git/commitdiff
Revert "Revert "Merge branch 'main' into other-computer"" other-computer
authorSkullheadx <704277@pdsb.net>
Sun, 10 Jul 2022 01:40:28 +0000 (21:40 -0400)
committerSkullheadx <704277@pdsb.net>
Sun, 10 Jul 2022 01:40:28 +0000 (21:40 -0400)
This reverts commit 48a0136a464c672409a9a3132d085cd592039815.

56 files changed:
.gitignore
.idea/.gitignore [deleted file]
Assets/ARROW.png [new file with mode: 0644]
Assets/BOW.png [new file with mode: 0644]
Assets/BOW_PULLED.png [new file with mode: 0644]
Assets/FLINTLOCK_PISTOL.png [new file with mode: 0644]
Assets/GrassBlock.png [deleted file]
Assets/player/idle/Idle_Animation1.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation10.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation11.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation12.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation13.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation14.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation15.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation16.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation17.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation18.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation19.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation2.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation20.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation3.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation4.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation5.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation6.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation7.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation8.png [new file with mode: 0644]
Assets/player/idle/Idle_Animation9.png [new file with mode: 0644]
Assets/world/blocks/DIRT.png [new file with mode: 0644]
Assets/world/blocks/ENEMY.png [new file with mode: 0644]
Assets/world/blocks/GRASS.png [new file with mode: 0644]
Assets/world/blocks/LEAF.png [moved from Assets/LEAFS1.png with 100% similarity]
Assets/world/blocks/LEAFS.png [moved from Assets/LEAFS.png with 100% similarity]
Assets/world/blocks/NONE.png [new file with mode: 0644]
Assets/world/blocks/PLACEHOLDER.png [new file with mode: 0644]
Assets/world/blocks/PLAYER.png [new file with mode: 0644]
Assets/world/blocks/SAND.png [new file with mode: 0644]
Assets/world/blocks/STONE.png [moved from Assets/StoneBlock.png with 100% similarity]
Assets/world/blocks/STONEDIRT.png [new file with mode: 0644]
Assets/world/blocks/TREEBARK.png [moved from Assets/TREEBARK.png with 100% similarity]
Assets/world/blocks/WATER.png [moved from Assets/Water.png with 100% similarity]
Assets/world/decor/BLUE_CRYSTAL.png [new file with mode: 0644]
Assets/world/decor/PURPLE_CRYSTAL.png [new file with mode: 0644]
Block.py
DevLevelSelect.py [new file with mode: 0644]
EndScreen.py [new file with mode: 0644]
LevelCreator.py [new file with mode: 0644]
Potion.py [new file with mode: 0644]
SWORD.png [deleted file]
Save/SaveGame.py [new file with mode: 0644]
TODO [new file with mode: 0644]
Test.py
UI/DashMeter.py [new file with mode: 0644]
UI/HealthBar.py [new file with mode: 0644]
Weapon.py
World.py [new file with mode: 0644]
main.py

index 3f26c87d0b43879eb24a9c27d5977b2c87e5fea8..68aac717c0935cc69300bd2262e2398ff72df894 100644 (file)
@@ -11,4 +11,6 @@
 ignore_*
 /ignore
 */__pycache__
+Save/SaveData.txt
+/.idea
 .idea/Pygame-Jam-main.iml
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644 (file)
index 26d3352..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/Assets/ARROW.png b/Assets/ARROW.png
new file mode 100644 (file)
index 0000000..d79c4e0
Binary files /dev/null and b/Assets/ARROW.png differ
diff --git a/Assets/BOW.png b/Assets/BOW.png
new file mode 100644 (file)
index 0000000..74435e7
Binary files /dev/null and b/Assets/BOW.png differ
diff --git a/Assets/BOW_PULLED.png b/Assets/BOW_PULLED.png
new file mode 100644 (file)
index 0000000..0bfe625
Binary files /dev/null and b/Assets/BOW_PULLED.png differ
diff --git a/Assets/FLINTLOCK_PISTOL.png b/Assets/FLINTLOCK_PISTOL.png
new file mode 100644 (file)
index 0000000..4f6dafa
Binary files /dev/null and b/Assets/FLINTLOCK_PISTOL.png differ
diff --git a/Assets/GrassBlock.png b/Assets/GrassBlock.png
deleted file mode 100644 (file)
index b4a37fc..0000000
Binary files a/Assets/GrassBlock.png and /dev/null differ
diff --git a/Assets/player/idle/Idle_Animation1.png b/Assets/player/idle/Idle_Animation1.png
new file mode 100644 (file)
index 0000000..1bae45a
Binary files /dev/null and b/Assets/player/idle/Idle_Animation1.png differ
diff --git a/Assets/player/idle/Idle_Animation10.png b/Assets/player/idle/Idle_Animation10.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation10.png differ
diff --git a/Assets/player/idle/Idle_Animation11.png b/Assets/player/idle/Idle_Animation11.png
new file mode 100644 (file)
index 0000000..cae952a
Binary files /dev/null and b/Assets/player/idle/Idle_Animation11.png differ
diff --git a/Assets/player/idle/Idle_Animation12.png b/Assets/player/idle/Idle_Animation12.png
new file mode 100644 (file)
index 0000000..ee56a60
Binary files /dev/null and b/Assets/player/idle/Idle_Animation12.png differ
diff --git a/Assets/player/idle/Idle_Animation13.png b/Assets/player/idle/Idle_Animation13.png
new file mode 100644 (file)
index 0000000..b2e1016
Binary files /dev/null and b/Assets/player/idle/Idle_Animation13.png differ
diff --git a/Assets/player/idle/Idle_Animation14.png b/Assets/player/idle/Idle_Animation14.png
new file mode 100644 (file)
index 0000000..b2e1016
Binary files /dev/null and b/Assets/player/idle/Idle_Animation14.png differ
diff --git a/Assets/player/idle/Idle_Animation15.png b/Assets/player/idle/Idle_Animation15.png
new file mode 100644 (file)
index 0000000..b378f5e
Binary files /dev/null and b/Assets/player/idle/Idle_Animation15.png differ
diff --git a/Assets/player/idle/Idle_Animation16.png b/Assets/player/idle/Idle_Animation16.png
new file mode 100644 (file)
index 0000000..e36b0cb
Binary files /dev/null and b/Assets/player/idle/Idle_Animation16.png differ
diff --git a/Assets/player/idle/Idle_Animation17.png b/Assets/player/idle/Idle_Animation17.png
new file mode 100644 (file)
index 0000000..24026d8
Binary files /dev/null and b/Assets/player/idle/Idle_Animation17.png differ
diff --git a/Assets/player/idle/Idle_Animation18.png b/Assets/player/idle/Idle_Animation18.png
new file mode 100644 (file)
index 0000000..4fa5a85
Binary files /dev/null and b/Assets/player/idle/Idle_Animation18.png differ
diff --git a/Assets/player/idle/Idle_Animation19.png b/Assets/player/idle/Idle_Animation19.png
new file mode 100644 (file)
index 0000000..cae952a
Binary files /dev/null and b/Assets/player/idle/Idle_Animation19.png differ
diff --git a/Assets/player/idle/Idle_Animation2.png b/Assets/player/idle/Idle_Animation2.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation2.png differ
diff --git a/Assets/player/idle/Idle_Animation20.png b/Assets/player/idle/Idle_Animation20.png
new file mode 100644 (file)
index 0000000..cae952a
Binary files /dev/null and b/Assets/player/idle/Idle_Animation20.png differ
diff --git a/Assets/player/idle/Idle_Animation3.png b/Assets/player/idle/Idle_Animation3.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation3.png differ
diff --git a/Assets/player/idle/Idle_Animation4.png b/Assets/player/idle/Idle_Animation4.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation4.png differ
diff --git a/Assets/player/idle/Idle_Animation5.png b/Assets/player/idle/Idle_Animation5.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation5.png differ
diff --git a/Assets/player/idle/Idle_Animation6.png b/Assets/player/idle/Idle_Animation6.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation6.png differ
diff --git a/Assets/player/idle/Idle_Animation7.png b/Assets/player/idle/Idle_Animation7.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation7.png differ
diff --git a/Assets/player/idle/Idle_Animation8.png b/Assets/player/idle/Idle_Animation8.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation8.png differ
diff --git a/Assets/player/idle/Idle_Animation9.png b/Assets/player/idle/Idle_Animation9.png
new file mode 100644 (file)
index 0000000..428c4e0
Binary files /dev/null and b/Assets/player/idle/Idle_Animation9.png differ
diff --git a/Assets/world/blocks/DIRT.png b/Assets/world/blocks/DIRT.png
new file mode 100644 (file)
index 0000000..4998792
Binary files /dev/null and b/Assets/world/blocks/DIRT.png differ
diff --git a/Assets/world/blocks/ENEMY.png b/Assets/world/blocks/ENEMY.png
new file mode 100644 (file)
index 0000000..7ab0889
Binary files /dev/null and b/Assets/world/blocks/ENEMY.png differ
diff --git a/Assets/world/blocks/GRASS.png b/Assets/world/blocks/GRASS.png
new file mode 100644 (file)
index 0000000..4ec4647
Binary files /dev/null and b/Assets/world/blocks/GRASS.png differ
diff --git a/Assets/world/blocks/NONE.png b/Assets/world/blocks/NONE.png
new file mode 100644 (file)
index 0000000..835725e
Binary files /dev/null and b/Assets/world/blocks/NONE.png differ
diff --git a/Assets/world/blocks/PLACEHOLDER.png b/Assets/world/blocks/PLACEHOLDER.png
new file mode 100644 (file)
index 0000000..a5379e2
Binary files /dev/null and b/Assets/world/blocks/PLACEHOLDER.png differ
diff --git a/Assets/world/blocks/PLAYER.png b/Assets/world/blocks/PLAYER.png
new file mode 100644 (file)
index 0000000..59817c8
Binary files /dev/null and b/Assets/world/blocks/PLAYER.png differ
diff --git a/Assets/world/blocks/SAND.png b/Assets/world/blocks/SAND.png
new file mode 100644 (file)
index 0000000..22da885
Binary files /dev/null and b/Assets/world/blocks/SAND.png differ
diff --git a/Assets/world/blocks/STONEDIRT.png b/Assets/world/blocks/STONEDIRT.png
new file mode 100644 (file)
index 0000000..8d253bd
Binary files /dev/null and b/Assets/world/blocks/STONEDIRT.png differ
diff --git a/Assets/world/decor/BLUE_CRYSTAL.png b/Assets/world/decor/BLUE_CRYSTAL.png
new file mode 100644 (file)
index 0000000..3911548
Binary files /dev/null and b/Assets/world/decor/BLUE_CRYSTAL.png differ
diff --git a/Assets/world/decor/PURPLE_CRYSTAL.png b/Assets/world/decor/PURPLE_CRYSTAL.png
new file mode 100644 (file)
index 0000000..cb927a1
Binary files /dev/null and b/Assets/world/decor/PURPLE_CRYSTAL.png differ
index 6e77b193da44001cc1dec20c6227a9f82a43f593..89bcf037c54a043d0bc1d671f375823edc1279f2 100644 (file)
--- a/Block.py
+++ b/Block.py
@@ -2,20 +2,27 @@ from Setup import *
 
 
 class Block:
-    width, height = SCREEN_WIDTH, 50
+    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()
     colour = (71, 77, 97)
 
-    def __init__(self, pos, collision_layer):
+    def __init__(self, pos, collision_layer, texture="PLACEHOLDER"):
         self.position = pg.Vector2(pos)
         self.velocity = pg.Vector2(0,0) # So that we may have moving blocks
         collision_layer.add(self)
 
+        self.texture = self.textures[texture]
+
         self.movable = False
 
     def update(self, delta):
-        pass # when player "moves", it's actually the blocks
+        pass
 
     def get_collision_rect(self):
         return pg.Rect(self.position, (self.width, self.height))
+
     def draw(self, surf):
-        pg.draw.rect(surf, self.colour, get_display_rect(self.get_collision_rect()), border_radius=5)
+        pg.draw.rect(surf, self.colour, get_display_rect(self.get_collision_rect()), border_radius=3)
+        surf.blit(self.texture, get_display_rect(self.get_collision_rect()))
diff --git a/DevLevelSelect.py b/DevLevelSelect.py
new file mode 100644 (file)
index 0000000..0aa19ae
--- /dev/null
@@ -0,0 +1,80 @@
+from Setup import *
+from CommonImports.colours import black
+from Function.createText import createText
+
+from Game import Game
+from Test import Test
+from LevelCreator import LevelCreator
+from MainMenu import Menu
+
+class DevLevelSelect:
+
+    def __init__(self):
+        self.texts = []
+        X = 250
+        self.texts.append(createText(X, 100, 32, black, "Bold", "DEVELOPER LEVEL SELECT",))
+        self.texts.append(createText(X, 250, 24, black, "Regular", "MainMenu"))
+        self.texts.append(createText(X, 350, 24, black, "Regular", "Game"))
+        self.texts.append(createText(X, 450, 24, black, "Regular", "LevelCreator"))
+        self.texts.append(createText(X, 550, 24, black, "Regular", "AutoLoad [-]"))
+
+        self.autoload = False
+
+        try:
+            f = open("./Save/ignore_DevAutoload.txt", "x")
+        except:
+            f = open("./Save/ignore_DevAutoload.txt", "w")
+            try:
+                lines = f.readlines()
+            except:
+                pass;
+        f.close()
+        try:
+            self.level = int(lines[0])
+        except:
+            self.level = -3
+
+        
+    def update(self, delta):
+        for ev in pg.event.get():
+            if ev.type == pg.MOUSEBUTTONDOWN:
+                mouseX, mouseY = pg.mouse.get_pos()
+                for i in range(len(self.texts)):
+                    x1 = self.texts[i][1][0]
+                    y1 = self.texts[i][1][1]
+                    x2 = x1 + self.texts[i][0].get_rect()[2]
+                    y2 = y1 + self.texts[i][0].get_rect()[3]
+
+                    if (x1 <= mouseX <= x2 and y1 <= mouseY <= y2):
+                        self.menuFunctions(i)
+            return
+
+    def draw(self, surf):
+        screen.fill((255, 255, 255))
+        for i in self.texts:
+            screen.blit(i[0], i[1])
+
+    def menuFunctions(self, num):
+        match num:
+            case 1:
+                self.level = 0
+            case 2:
+                self.level = 1
+            case 3:
+                self.level = -2
+            case 4:
+                if(self.autoload == False):
+                    self.texts[4] = createText(250, 550, 24, black, "Regular", "AutoLoad [x]")
+                    self.autoload = True
+                else:
+                    self.texts[4] = createText(250, 550, 24, black, "Regular", "AutoLoad [-]")
+                    self.autoload = False
+                return;
+
+        if(self.autoload == True):
+            try:
+                f = open("./Save/ignore_DevAutoload.txt", "x")
+            except:
+                f = open("./Save/ignore_DevAutoload.txt", "w")
+            f.write(str(self.level))
+            f.close()
diff --git a/EndScreen.py b/EndScreen.py
new file mode 100644 (file)
index 0000000..aaecb36
--- /dev/null
@@ -0,0 +1,44 @@
+from Setup import *
+from CommonImports.colours import black
+from Function.createText import createText
+
+class EndScreen:
+
+    def __init__(self):
+        self.texts = []
+        X = 250
+        self.texts.append(createText(X, 100, 32, black, "Bold", "You Died",))
+        self.texts.append(createText(X, 250, 24, black, "Regular", "Respawn"))
+        self.texts.append(createText(X, 350, 24, black, "Regular", "Options"))
+        self.texts.append(createText(X, 450, 24, black, "Regular", "Quit"))
+
+        self.level = -1
+
+        
+    def update(self):
+        for ev in pg.event.get():
+            if ev.type == pg.MOUSEBUTTONDOWN:
+                mouseX, mouseY = pg.mouse.get_pos()
+                for i in range(len(self.texts)):
+                    x1 = self.texts[i][1][0]
+                    y1 = self.texts[i][1][1]
+                    x2 = x1 + self.texts[i][0].get_rect()[2]
+                    y2 = y1 + self.texts[i][0].get_rect()[3]
+
+                    if (x1 <= mouseX <= x2 and y1 <= mouseY <= y2):
+                        self.menuFunctions(i)
+            return
+
+    def draw(self):
+        screen.fill((255, 255, 255))
+        for i in self.texts:
+            screen.blit(i[0], i[1])
+
+    def menuFunctions(self, num):
+        match num:
+            case 1:
+                self.level = -1
+            case 2:
+                print("Options")
+            case 3:
+                pg.quit();
diff --git a/LevelCreator.py b/LevelCreator.py
new file mode 100644 (file)
index 0000000..920f9ed
--- /dev/null
@@ -0,0 +1,404 @@
+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)
diff --git a/Potion.py b/Potion.py
new file mode 100644 (file)
index 0000000..3bd81ad
--- /dev/null
+++ b/Potion.py
@@ -0,0 +1,21 @@
+from Setup import *
+
+class Potion:
+    
+    def __init__(self, player, heal_amount = 25):
+        self.heal = heal_amount
+        self.player = player
+
+    def get_input(self, player):
+        pressed_key = pg.key.get_pressed()
+        if pressed_key[pg.K_1] and player.potion_cooldown == 0:
+            self.consume_potion(player)
+    
+    def consume_potion(self, player):
+        player.health += self.heal
+        del player.potion_bag[0]
+        player.potion_cooldown = 5
+
+    #def cooldown(self, player):
+        
+
diff --git a/SWORD.png b/SWORD.png
deleted file mode 100644 (file)
index e1c4104..0000000
Binary files a/SWORD.png and /dev/null differ
diff --git a/Save/SaveGame.py b/Save/SaveGame.py
new file mode 100644 (file)
index 0000000..aa08c58
--- /dev/null
@@ -0,0 +1,13 @@
+def SaveGame(level):
+    try:
+        f = open("./Save/SaveData.txt", "x")
+    except:
+        f = open("./Save/SaveData.txt", "w")
+    f.write(str(level)+"\n")
+    f.close()
+
+def LoadGame():
+    f = open("./Save/SaveData.txt", "r")
+    lines = f.readlines()
+    f.close()
+    return int(lines[0])
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..8daea4d
--- /dev/null
+++ b/TODO
@@ -0,0 +1,33 @@
+Gameplay:
+- Make levels
+- Add save game functionality
+
+Movement:
+- Custom Dash movement function for dashing
+
+Combat:
+- Health potion items to collect
+- bow
+- gun
+- sword
+- buffs?
+
+- Level Creator
+    - to facilitate level creation
+- Dialogue display
+    - characters appear one at a time so more readable
+
+- Story elements
+
+- dimension travel effect
+    - I'm thinking like we go on the ship and
+    the ship travels into a portal that opens
+    in front and inside that portal is some
+    purple space with ??? particles flying
+    around. After a few seconds, go to next
+    dimension.
+
+
+Art:
+- Finish assets
+- add assets to game
\ No newline at end of file
diff --git a/Test.py b/Test.py
index ba64cc433e2251dde30351f6422bc870ab9f8661..09d366cf3921f504d63345cac2c7a15585dc7486 100644 (file)
--- a/Test.py
+++ b/Test.py
@@ -8,7 +8,7 @@ class Test:
 
         self.angle = 0
         self.pivot = pg.Vector2(SCREEN_WIDTH / 2 + 50, SCREEN_HEIGHT / 2 + 50)
-        self.img = pg.transform.scale(pygame.image.load("SWORD.png"), (100, 100))
+        self.img = pg.transform.scale(pygame.image.load("Assets/SWORD.png"), (100, 100))
         self.display = self.img.copy()
         self.img_rect = self.display.get_rect()
 
diff --git a/UI/DashMeter.py b/UI/DashMeter.py
new file mode 100644 (file)
index 0000000..e1da4c9
--- /dev/null
@@ -0,0 +1,33 @@
+from Setup import *
+from CommonImports.colours import white
+from Function.createText import createText
+from datetime import datetime
+
+class DashMeter:
+
+    def __init__(self, cooldown):
+        self.texts = ['a']
+        self.timeSinceLastDash = datetime.utcnow()
+        self.timer = self.timeSinceLastDash.second + self.timeSinceLastDash.microsecond / 100000
+        self.cooldown = cooldown.seconds + cooldown.microseconds/1000000
+
+        
+    def update(self, dash):
+        self.timeSinceLastDash = datetime.utcnow() - dash
+        self.timer = self.timeSinceLastDash.seconds + self.timeSinceLastDash.microseconds / 1000000
+        if(self.timer > self.cooldown):
+            self.timer = self.cooldown
+
+    def draw(self, surf):
+        background_rect = pg.Rect(844, 20, 1080 * 0.2, 640 * 0.08)
+        foreground_rect = pg.Rect(0, 0, 1080 * 0.185 * (self.timer/self.cooldown), 640 * 0.06)
+        self.texts[0] = createText(0, 0, 30, white, "Regular", str(round(self.timer/(self.cooldown/100))) + "%")[0]
+
+        foreground_rect.center = (
+            background_rect.centerx - 1080 * 0.185 * ((1 - self.timer/self.cooldown) / 2), background_rect.centery)
+
+        pg.draw.rect(surf, (54, 54, 54), background_rect)
+        pg.draw.rect(surf, (175, 175, 175), foreground_rect)
+
+        text_rect = self.texts[0].get_rect(center=background_rect.center)
+        surf.blit(self.texts[0], text_rect)
diff --git a/UI/HealthBar.py b/UI/HealthBar.py
new file mode 100644 (file)
index 0000000..8021781
--- /dev/null
@@ -0,0 +1,31 @@
+from Setup import *
+from CommonImports.colours import white, red
+from Function.createText import createText
+from datetime import datetime
+
+class HealthBar:
+
+    def __init__(self):
+        return;
+        
+    def update(self):
+        return;
+
+    def draw(self, surf, health):
+        # Healthbar Stuff
+        # bar is made of 2 rectanges, background which is just a simple rectange and foreground which goes on top and has a bit of math involved
+        background_rect = pg.Rect(20, 20, 1080 * 0.2, 640 * 0.08)
+
+        # idea is that 1080*0.185 = size of bar at 100% hp, at lower hp you want to get a fraction of that which is why we multiply by (health*0.01) example: 70 hp * 0.01 = 0.7
+        foreground_rect = pg.Rect(0, 0, 1080 * 0.185 * (health * 0.01), 640 * 0.06)
+        # make sure the red part health bar always sits on the left
+        # sets bar to center of background bar, then subtracts 1/2 of blank space to put it on the left
+        foreground_rect.center = (
+            background_rect.centerx - 1080 * 0.185 * ((1 - health * 0.01) / 2), background_rect.centery)
+        pg.draw.rect(surf, (54, 54, 54), background_rect)
+        pg.draw.rect(surf, red, foreground_rect)
+
+        # text
+        current_health_display = createText(0, 0, 30, white, "Regular", str(health) + "/100")[0]
+        text_rect = current_health_display.get_rect(center=background_rect.center)
+        surf.blit(current_health_display, text_rect)
index 3d424e30a261815403da4515bcd8cb792340a5af..a36395fdcfb3c63aad3848f9b4f2c47b9774c7eb 100644 (file)
--- a/Weapon.py
+++ b/Weapon.py
@@ -4,11 +4,11 @@ from Setup import *
 
 
 class Melee:
-    img = pg.transform.scale(pg.image.load("SWORD.png"), (40,40))
+    img = pg.transform.scale(pg.image.load("Assets/SWORD.png"), (40, 40))
     flipped_img = pg.transform.flip(img,True,False)
     width,height = img.get_size()
 
-    def __init__(self, pos, offset, pivot, width,direction):
+    def __init__(self, pos, offset, pivot, width,direction, damage):
         self.position = pg.Vector2(pos)
         self.offset = pg.Vector2(offset)
         self.pivot = self.position + pg.Vector2(pivot)
@@ -19,12 +19,15 @@ class Melee:
         self.display = self.img
         self.display_rect = self.display.get_rect()
         self.swing_timer = 0
+        self.attacking = False
 
+        self.damage = damage
 
     def update(self, delta, pos, direction):
         self.position = pg.Vector2(pos)
         self.pivot = self.position + self.offset + pg.Vector2(self.width/2, self.height/2)
-        self.direction = direction
+        if direction != 0:
+            self.direction = direction
 
         if self.direction == -1:
             angle = 25 * (math.sin(math.radians(self.swing_timer)))
@@ -35,6 +38,10 @@ class Melee:
 
         self.swing_timer -= delta
         self.swing_timer = max(self.swing_timer, 0)
+        if self.swing_timer == 0:
+            self.attacking = False
+        else:
+            self.attacking = True
 
     def get_collision_rect(self):
         if self.direction == -1:
@@ -47,7 +54,7 @@ class Melee:
             if self.swing_timer == 0:
                 self.swing_timer = 360
 
-    def draw(self, surf):
-        surf.blit(self.display, get_display_rect(self.get_collision_rect()).topleft)
-        # pygame.draw.circle(surf,(255,0,255),self.pivot,3)
-        # pygame.draw.circle(surf,(0,255,0),self.position,3)
+    def draw(self, surf, display_offset = pg.Vector2(0,0)):
+        surf.blit(self.display, get_display_rect(self.get_collision_rect()).topleft + display_offset)
+        # pg.draw.circle(surf,(255,0,255),get_display_point(self.pivot),3)
+        # pg.draw.circle(surf,(0,255,0),get_display_point(self.position),3)
diff --git a/World.py b/World.py
new file mode 100644 (file)
index 0000000..e82f2fe
--- /dev/null
+++ b/World.py
@@ -0,0 +1,42 @@
+from Setup import *
+from Block import Block
+from os import path
+
+
+class World:
+
+    def __init__(self, collision_layer):
+        self.collision_layer = collision_layer
+        self.blocks = []
+
+    def load_world(self, level):
+        with open(path.join("Levels", f'Level{level}.txt'), 'r') as f:
+            file_contents = f.read().split("\n")
+
+        out = [[], center]
+        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(',')
+                x = float(x)
+                y = float(y)
+                if t == "PLAYER":
+                    out[1] = (x, y)
+                elif t == "ENEMY":
+                    out[0].append((x, y))
+                else:
+                    self.blocks.append(Block((x, y), self.collision_layer[l], t))
+        return out
+
+    def update(self, delta):
+        for block in self.blocks:
+            block.update(delta)
+
+    def draw(self, surf):
+        for block in self.blocks:
+            block.draw(surf)
diff --git a/main.py b/main.py
index 507912d5d123b62168b3c34b7af8d2a8a71ba701..e3ccf8bb7bbc86730f4991f40351f42bcb297b54 100644 (file)
--- a/main.py
+++ b/main.py
@@ -1,31 +1,39 @@
 from Setup import *
 from Game import Game
 from Test import Test
+from LevelCreator import LevelCreator
 from MainMenu import Menu
 
+from DevLevelSelect import DevLevelSelect
+
 delta = 1000//fps
 is_running = True
 
-level = 1
-old_level = level
 # scene = Menu()
-
-scene = Game()
+scene = DevLevelSelect()
+old_level = 0
+level = 1
 
 while is_running:
     if pg.event.peek(pg.QUIT):
         is_running = False
 
-    if level == 0:
+    if level <= 1:
         level = scene.level
 
+    if level == -1:
+        level = old_level
+        old_level = 0
+    
     if old_level != level:
-        old_level = level
         match level:
+            case -2:
+                scene = LevelCreator()
             case 0:
                 scene = Menu()
             case 1:
-                scene = Game()
+                scene = Game(1)
+        old_level = level
 
     scene.update(delta)
     scene.draw(screen)