diff --git a/.vs/ShadoowCrest_Gameengine/v17/.suo b/.vs/ShadoowCrest_Gameengine/v17/.suo new file mode 100644 index 0000000..5724ff4 Binary files /dev/null and b/.vs/ShadoowCrest_Gameengine/v17/.suo differ diff --git a/.vs/ShadoowCrest_Gameengine/v17/Browse.VC.db b/.vs/ShadoowCrest_Gameengine/v17/Browse.VC.db new file mode 100644 index 0000000..9a7f769 Binary files /dev/null and b/.vs/ShadoowCrest_Gameengine/v17/Browse.VC.db differ diff --git a/.vs/ShadoowCrest_Gameengine/v17/DocumentLayout.json b/.vs/ShadoowCrest_Gameengine/v17/DocumentLayout.json new file mode 100644 index 0000000..fd29503 --- /dev/null +++ b/.vs/ShadoowCrest_Gameengine/v17/DocumentLayout.json @@ -0,0 +1,23 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\steev\\Desktop\\shadowcrest\\ShadoowCrest_Gameengine\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": -1, + "Children": [ + { + "$type": "Bookmark", + "Name": "ST:0:0:{cce594b6-0c39-4442-ba28-10c64ac7e89f}" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/Classes/System/App.py b/Classes/System/App.py deleted file mode 100644 index f0f4c8d..0000000 --- a/Classes/System/App.py +++ /dev/null @@ -1,62 +0,0 @@ -import pygame -from pygame.locals import * - -from Classes.System.Components.Window import Window -from Classes.System.Components.InputHandler import InputHandler -from Classes.System.Network.TCPClient import TCPClient -from Classes.System.Utils.Path import PathUtil - -class App: - - __window:Window - __running:bool = True - __FPS = 60 - __clock = pygame.time.Clock() - __myFont:pygame.font - __inputHandler: InputHandler - __tcpClient: TCPClient - - def __init__(self, width:int=1920, height:int=1080, title:str="default title"): - pygame.font.init() - self.__myFont = pygame.font.SysFont('Comic Sans MS', 30) - self.__window = Window(width=width, height=height, title=title) - self.__inputHandler = InputHandler() - self.selectedCard = None - - self.startGameLoop() - self.onCleanup() - - def startGameLoop(self): - - while self.__running: - self.__clock.tick(self.__FPS) - - self.__window.getScreen().fill((0,0,0)) - - # render world - self.__window.drawWorld(self.__world) - - # event handler - self.handleEvent(pygame.event.get()) - - # emits update to the game - pygame.display.update() - - # handles incoming event queue - def handleEvent(self, events): - # TODO: fix bug that stacks cards when dragging them around - try: - for event in events: - if event.type == pygame.QUIT: - self.onCleanup() - except: - pass - - # sets the running state for the gameloop - def setRunning(self, running:bool): - self.__running = running - - # ensures the gameloop stops running and the pygame instance is stopped properly - def onCleanup(self): - self.__running = False - pygame.quit() \ No newline at end of file diff --git a/Classes/System/Components/InputHandler.py b/Classes/System/Components/InputHandler.py deleted file mode 100644 index df21df4..0000000 --- a/Classes/System/Components/InputHandler.py +++ /dev/null @@ -1,53 +0,0 @@ -import pygame - -from Classes.Game.BoardField import BoardField - -class InputHandler: - # returns pressed key - @staticmethod - def getPressed(): - return pygame.key.get_pressed() - - # returns pressed key - @staticmethod - def getMousePressed(): - return pygame.mouse.get_pressed() - - # takes in movement inputs and maps them to x and y axis - @staticmethod - def getInputAxis() -> tuple: - xvel = 0 - yvel = 0 - - # construct x and y velocity input axis - if InputHandler.getPressed()[pygame.K_a] or InputHandler.getPressed()[pygame.K_LEFT]: - xvel = -1 - if InputHandler.getPressed()[pygame.K_d] or InputHandler.getPressed()[pygame.K_RIGHT]: - xvel = 1 - if InputHandler.getPressed()[pygame.K_w] or InputHandler.getPressed()[pygame.K_UP]: - yvel = -1 - if InputHandler.getPressed()[pygame.K_s] or InputHandler.getPressed()[pygame.K_DOWN]: - yvel = 1 - - return tuple((xvel, yvel)) - - @staticmethod - def getMousePos() -> pygame.Vector2: - return pygame.Vector2(pygame.mouse.get_pos()) - - # get field under mousbutton - @staticmethod - def getMouseHover(mouse_pos: pygame.Vector2, world_card_width: int, world_card_height: int, board_fields: list) -> BoardField: - x_pos = mouse_pos.x / world_card_width - y_pos = mouse_pos.y / world_card_height - - for field in board_fields: - field_x = field.getPos().x - field_y = field.getPos().y - field_width = world_card_width # Annahme: Jedes Feld hat eine Breite von 1 Einheit - field_height = world_card_height # Annahme: Jedes Feld hat eine Höhe von 1 Einheit - - if field_x <= x_pos < field_x + field_width and field_y <= y_pos < field_y + field_height: - return field - - return None diff --git a/Classes/System/Components/Label.py b/Classes/System/Components/Label.py deleted file mode 100644 index ed04c54..0000000 --- a/Classes/System/Components/Label.py +++ /dev/null @@ -1,47 +0,0 @@ -import pygame - -class Label: - rect:pygame.rect - image:pygame.image - __screen:pygame.surface - __text:str - __pos:pygame.Vector2 - __font:pygame.font - font:pygame.font - __name:str - - def __init__(self, name:str, screen:pygame.surface, text:str, pos:pygame.Vector2, size:float=20, color:str="white"): - self.__font = pygame.font.SysFont("Arial", size) - self.font = pygame.font.SysFont("Arial", size) - self.image = self.font.render(text, 1, color) - _, _, w, h = self.image.get_rect() - self.__pos = pos - self.rect = pygame.Rect(self.__pos.x, self.__pos.y, w, h) - self.__screen = screen - self.__text = text - self.__name = name - - def getText(self) -> str: - return self.__text - - def getFont(self) -> pygame.font: - return self.__font - - def getPos(self) -> pygame.Vector2: - return self.__pos - - def getName(self) -> str: - return self.__name - - def setText(self, newtext:str, color:str="white"): - self.image = self.font.render(newtext, 1, color) - - def setFont(self, font:pygame.font, size:float, color:str="white"): - self.__font = pygame.font.SysFont(font, size) - self.change_text(self.text, color) - - def setPos(self, pos:pygame.Vector2): - self.__pos = pos - - def draw(self): - self.__screen.blit(self.image, (self.rect)) \ No newline at end of file diff --git a/Classes/System/Components/Window.py b/Classes/System/Components/Window.py deleted file mode 100644 index b4c3439..0000000 --- a/Classes/System/Components/Window.py +++ /dev/null @@ -1,54 +0,0 @@ -import pygame -from pygame.locals import * - -from Classes.Game.BoardField import BoardField -from Classes.Game.World import World - -class Window: - __width:int = 800 - __height:int = 600 # takes 80% of width which tranlates to 640 - __title:str = "python game engine" - __screen:pygame.Surface - __clock:pygame.time.Clock - - def __init__(self, width:int=800, height:int=600, title:str="python game engine"): - self.__width = width - self.__height = height - self.__title = title - - pygame.init() - - self.__screen = pygame.display.set_mode((self.__width, self.__height)) - self.__screen.fill((236, 240, 241)) # Hier liegt der Fehler, es muss eine Tuple übergeben werden - pygame.display.set_caption(self.__title) - - self.__clock = pygame.time.Clock() - self.__framerate = 60 # Framerate auf 60 FPS festlegen - - # set framerate (where the fuck is it?) - def Render(self): - # dear future me figure out what past me did! - pass - - def setWidth(self, width:int): - self.__width = width - - def setHeight(self, height:int): - self.__height = height - - def setTitle(self, title:str): - self.__title = title - - def getScreen(self) -> pygame.surface: - return self.__screen - - # draws a passed sprite group to the screen - def drawSpriteGroup(self, group:pygame.sprite.Group): - group.draw(self.__screen) - - # draws a given group of rectangles onto the screen - def drawWorld(self, world:World): - for field in world.getBoardFields(): - pygame.draw.rect(self.__screen, field.getColor(), field.getRect()) - for label in world.getLabels(): - label.draw() \ No newline at end of file diff --git a/Classes/System/GameManager.py b/Classes/System/GameManager.py deleted file mode 100644 index ea25200..0000000 --- a/Classes/System/GameManager.py +++ /dev/null @@ -1,23 +0,0 @@ -from Classes.Game.Player import Player -from Classes.Game.World import World - - -class GameManager: - player:Player - enemy:Player - world:World - - def __init__(self, world): - self.world = world - - def getPlayer(self) -> Player: - return self.player - - def getEnemy(self) -> Player: - return self.enemy - - def setPlayer(self, player:Player): - self.player = player - - def setEnemy(self, enemy:Player): - self.enemy = enemy \ No newline at end of file diff --git a/Classes/System/Network/EventHandler.py b/Classes/System/Network/EventHandler.py deleted file mode 100644 index e1ba80e..0000000 --- a/Classes/System/Network/EventHandler.py +++ /dev/null @@ -1,11 +0,0 @@ -import socket - -import pygame - -from Classes.System.Components.InputHandler import InputHandler -class TCPEventHandler: - def __init__(self, socket:socket): - self.tcp_socket = socket - - def handleEvents(self, message, inputHandler:InputHandler): - pass \ No newline at end of file diff --git a/Classes/System/Network/TCPClient.py b/Classes/System/Network/TCPClient.py deleted file mode 100644 index dcaf1b0..0000000 --- a/Classes/System/Network/TCPClient.py +++ /dev/null @@ -1,69 +0,0 @@ -import json -import socket -import threading - -import pygame - -from Classes.Game.World import World -from Classes.System.Components.InputHandler import InputHandler -from Classes.Game.Events.GameStart import GameStart -from Classes.Game.Events.Login import LoginResponse -from Classes.Game.Events.PlaceCard import CardPlaced -from Classes.Game.Player import Player - -class TCPClient: - def __init__(self, addr: str, port: str, world:World, inputHandler:InputHandler): - self.addr = addr - self.port = int(port) - self.tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.world = world - self.inputHandler = inputHandler - - try: - self.tcpSocket.connect((self.addr, self.port)) - except Exception as e: - print(f"Error connecting TCP socket: {e}") - - # Starten des Listener-Threads - self.listen() - - def send(self, message: dict): - try: - self.tcpSocket.sendall(json.dumps(message).encode()) - except Exception as e: - print(f"Error sending TCP data: {e}") - - def receive(self): - while True: - try: - data = self.tcpSocket.recv(1024) - if data: - decoded_data = json.loads(data.decode()) - self.handleEvents(decoded_data) - except Exception as e: - print(f"Error receiving TCP data: {e}") - break - - def handleEvents(self, message): - print(message) - if message["event"] == "loginresponse": - if message["status"] != "success": - print("login failed") - else: - print("receiving login confirmation from server") - self.world.setPlayer(Player(0,0,message["name"], message["id"])) - elif message["event"] == "startgame": - print(self.world.player) - # world.player.setMana(message["player"]["mana"]) - # world.player.setHp(message["player"]["hp"]) - self.world.setEnemy(Player(message["enemy"]["hp"],0,message["enemy"]["name"], message["enemy"]["id"])) - GameStart(self.world, message["player"]["hand"], self.inputHandler, self.world.getPlayer()) - pass - elif message["event"] == "PlacedCard": - CardPlaced(self.world, message["card"], message["owner"], pygame.Vector2(message["x"], message["y"]), self.inputHandler) - pass - - def listen(self): - tcpThread = threading.Thread(target=self.receive) - tcpThread.daemon = True - tcpThread.start() \ No newline at end of file diff --git a/Classes/System/Utils/Path.py b/Classes/System/Utils/Path.py deleted file mode 100644 index 9b01eb9..0000000 --- a/Classes/System/Utils/Path.py +++ /dev/null @@ -1,6 +0,0 @@ -import os - - -class PathUtil: - def getAbsolutePathTo(notAbsolutPath:str) -> str: - return os.path.abspath("Client/" + notAbsolutPath) \ No newline at end of file diff --git a/Classes/System/Utils/StringUtils.py b/Classes/System/Utils/StringUtils.py deleted file mode 100644 index e4d02a1..0000000 --- a/Classes/System/Utils/StringUtils.py +++ /dev/null @@ -1,11 +0,0 @@ -import random -import string - - -class StringUtils: - def get_random_string(length) -> str: - # choose from all lowercase letter - letters = string.ascii_lowercase - result_str = ''.join(random.choice(letters) for i in range(length)) - print("Random string of length", length, "is:", result_str) - return result_str diff --git a/README.md b/README.md index f13aa8e..8a887f6 100644 --- a/README.md +++ b/README.md @@ -3,44 +3,20 @@ # Shadowcrest -My own Gameengine used in games i make forward +My own Gameengine made in c++ which is used in games i make forward ## why do i want my own engine? -simply said because i want to know how games run in their backend -another strong reason would be i want to have full controll over what works how and when its added +Simply put i want to learn c++ and how the more lower level Systems on a computer work as i only have worked in languages that help out with things like memory management e.g. Javascript, PHP, C#, Go. In Addition to that i want to improve my skills on how to optimize code and how to properly work with memory. +and since that isn't enough i want to know how the System that are required to make games work eventually improving my engine on my way while working on projects. ## big things are to happen right now this repo only is a placeholder not planed to be worked on for a long while as i need to figure out what i want and how i want it -depending on what of the below i chose (i already think i will decide between 2 or 3 but am interessted in 3 due to more tech) i will start designing an engine architecture and also decide if i keep this project opensource or not +depending on what of the below i chose (i already think i will decide between 2 or 3 but am interested in 3 due to more tech) i will start designing an engine architecture and also decide if i keep this project oversource or not ### what does it aim todo -bulding my games to keep it simple +building my games to keep it simple - supporting 2D games - supporting 3D games - supporting networking networking solutions i develop in placeholder - a user interface for me to organize my project with -## multiple options emerge -### option 1 using pygame -as i am working on a project in pygame and have constructed a small engine arround pygame for the sake of getting the project to where i want it -a option would be clearing the present gamelogic out from it and constructing a more easy to use api and a user interface -#### downsides: -- python is compared to its dotnet competitors not very good in memory management -- python is simple but due to the lack of typesafety can be painfull to debug - -### option 2 using dotnet gameframeworks -dotnet is used very widely in game development and is used in the biggest known game engines currently available: -- godot (C#) -- unity (C#) -- cryengine (C#, LUA) -- unreal (c++) -i could use a game framework like [monogame](https://monogame.net/) - -### option 3 the hard way implementing public tech on my own -besides the option to use a framework that does the hard game technology part for me i can go all the way on my own and implement things like Vulcan or DirectX, a opensource physics engine like [project chrono](https://projectchrono.org/) or [react physics 3d](https://www.reactphysics3d.com/) or even a more widely used physics engine like nvidia physx or havok engine and fmod as audio engine - -this would be the by far hardest option out of all available but also the by a lot most custom experience -this approach would also teach me a very much more then all the other options above - -### downsides -a very very very very painfull development process diff --git a/ShadoowCrest_Gameengine.sln b/ShadoowCrest_Gameengine.sln new file mode 100644 index 0000000..264b588 --- /dev/null +++ b/ShadoowCrest_Gameengine.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36301.6 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShadoowCrest_Gameengine", "ShadoowCrest_Gameengine.vcxproj", "{EDD323AC-3212-4BD6-877E-1A0155781415}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EDD323AC-3212-4BD6-877E-1A0155781415}.Debug|x64.ActiveCfg = Debug|x64 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Debug|x64.Build.0 = Debug|x64 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Debug|x86.ActiveCfg = Debug|Win32 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Debug|x86.Build.0 = Debug|Win32 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Release|x64.ActiveCfg = Release|x64 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Release|x64.Build.0 = Release|x64 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Release|x86.ActiveCfg = Release|Win32 + {EDD323AC-3212-4BD6-877E-1A0155781415}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E38B3869-3F4D-47BE-9C10-30182BCFAEA1} + EndGlobalSection +EndGlobal diff --git a/ShadoowCrest_Gameengine.vcxproj b/ShadoowCrest_Gameengine.vcxproj new file mode 100644 index 0000000..4935a93 --- /dev/null +++ b/ShadoowCrest_Gameengine.vcxproj @@ -0,0 +1,134 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + 17.0 + Win32Proj + {edd323ac-3212-4bd6-877e-1a0155781415} + ShadoowCrestGameengine + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + + diff --git a/ShadoowCrest_Gameengine.vcxproj.filters b/ShadoowCrest_Gameengine.vcxproj.filters new file mode 100644 index 0000000..50aca57 --- /dev/null +++ b/ShadoowCrest_Gameengine.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/ShadoowCrest_Gameengine.vcxproj.user b/ShadoowCrest_Gameengine.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/ShadoowCrest_Gameengine.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sc_logo_3_4-removebg-preview.png b/ShadowCrest_Logo.png similarity index 100% rename from sc_logo_3_4-removebg-preview.png rename to ShadowCrest_Logo.png diff --git a/main.py b/main.py deleted file mode 100644 index d243f0c..0000000 --- a/main.py +++ /dev/null @@ -1,7 +0,0 @@ -import pygame -from Classes.System.App import App - -if __name__ == "__main__": - pygame.init() - game = App() - game.onExecute() \ No newline at end of file diff --git a/server logic notes.md b/server logic notes.md deleted file mode 100644 index 7370d4a..0000000 --- a/server logic notes.md +++ /dev/null @@ -1,42 +0,0 @@ -# validation for placing cards: -- is the game still running -- is it the players turn -- does the card exist -- does the player have that card in his deck -- does the player have this card in his hand -- is the type of card allowed in that type of field -- is the field already blocked by another card - -# validation for attacking another player -- is the game still running -- is it the players turn -- does the card exist -- does the player have that card in his deck -- is that card played -- does the enemy have remaining monster cards on his side - - if yes a direct attack would only be possible if a effect allows it -- can this card attack - - is the card of correct type - - is it blocked by effects (will be implemented after card effects are implemented) - -# player death management (win condition) -- does a players hp go to 0? - - make the other player the winner - - if an effect affects the playing player card priority comes first - -# handle a player leaving -- check if game still runs - - make remaining player win if yes - -# turn management -- server keeps track of each turn - - whos turn is it - - what turn state is currently active - - draw state - - place state - - is the player trying to do actions not allowed in the given state - -# drawing cards: -- ensure the player only can have 7 cards - - if limit exceeds the player payes lifepoints and drops a card -- ensure the drawn card for sure still can be in the players deck \ No newline at end of file