diff --git a/Game Server/Classes/Game/Player.py b/Game Server/Classes/Game/Player.py index bb9044b..0b39b40 100644 --- a/Game Server/Classes/Game/Player.py +++ b/Game Server/Classes/Game/Player.py @@ -7,13 +7,21 @@ class Player: __mana:int __name:str __handCards:list - - def __init__(self, name:str, hp:int=1000, mana:int=0): + __deck:list + + def __init__(self, name:str, deck:list, hp:int=1000, mana:int=0): self.__hp = hp self.__name = name self.__handCards = [] + self.__deck = deck self.__id = random.randint(3, 99999) + def shuffleDeck(self): + self.__deck = random.shuffle(self.__deck) + + def getDeck(self) -> list: + return self.__deck + def getName(self) -> str: return self.__name @@ -40,6 +48,9 @@ class Player: self.__handCards.append(card) return self.__handCards + def setHand(self, hand:list): + self.__handCards = hand + def removeFromHand(self, pos:int) -> list: self.__handCards.remove(pos) return self.__handCards \ No newline at end of file diff --git a/Game Server/Classes/Game/__pycache__/Player.cpython-311.pyc b/Game Server/Classes/Game/__pycache__/Player.cpython-311.pyc index 83afbc8..7b50bcd 100644 Binary files a/Game Server/Classes/Game/__pycache__/Player.cpython-311.pyc and b/Game Server/Classes/Game/__pycache__/Player.cpython-311.pyc differ diff --git a/Game Server/Classes/System/GameManager.py b/Game Server/Classes/System/GameManager.py index 69dfe6b..db684b7 100644 --- a/Game Server/Classes/System/GameManager.py +++ b/Game Server/Classes/System/GameManager.py @@ -1,3 +1,4 @@ +import json import socket from Classes.Game.Player import Player @@ -38,23 +39,28 @@ class GameManager: # this section mostly only used by the networking and event handling classes # other parts should never need to interface with this unless really required # ============================================================================= - def startGame(self): + def startGame(self, tcpSocket:socket): self.__state = "running" print("game starts") for userAddr in self.__users.keys(): try: - user = self.__serverWorld.getPlayers[userAddr] + user = self.__serverWorld.getPlayers[userAddr]["player"] user.addMana(1000) user.adjustHP(1000) + user.shuffleDeck() + cards = user.getDeck() + user.setHand(cards[:5]) payload = { "event":"startgame", - "mana": user.getMana(), - "hp": user.getHP() + "playermana": user.getMana(), + "playerhp": user.getHP(), + "playername": user.getName(), + "hand": user.getHand() } - self.send(payload, userAddr) + tcpSocket.send(json.dumps(payload).encode()) except Exception as e: print(f"failed to start game due to error: {e}") break @@ -84,6 +90,6 @@ class GameManager: # counts participating players and starts the game if enough have joined if len(self.__players) == 2: - self.startGame() + self.startGame(socket) return self.__players \ No newline at end of file diff --git a/Game Server/Classes/System/Network/NetworkManger.py b/Game Server/Classes/System/Network/NetworkManger.py index 38df93a..abc7626 100644 --- a/Game Server/Classes/System/Network/NetworkManger.py +++ b/Game Server/Classes/System/Network/NetworkManger.py @@ -1,5 +1,6 @@ import json import socket +import sys import threading from Classes.Game.Player import Player from Classes.System.GameManager import GameManager @@ -9,82 +10,84 @@ from Classes.System.World import World class NetworkManager: - class UDP: - __Addr:str - __Port:str - __BufferSize:int = 1024 - __udpSocket:socket - __users:dict - __eventHandler: UDPEventHandler - __UDPClientThread:threading.Thread - __gameManager:GameManager - - def __init__(self, Addr:str, Port:str, gameManager:GameManager): - self.__Addr = Addr - self.__Port = int(Port) - self.__gameManager = gameManager - self.__users = {} - self.__eventHandler = {} - self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - try: - self.__udpSocket.bind((self.__Addr, self.__Port)) - except OSError as e: - print(f"Error binding UDP socket: {e}") - - self.__UDPClientThread = threading.Thread(target=self.receive) - self.__UDPClientThread.start() - - # handles incoming udp data - def receive(self): - while True: - data, address = self.__udpSocket.recvfrom(self.__BufferSize) - message = data.decode() - messageJson = json.loads(message) - user = messageJson.get("user") - - if user not in self.__users: - self.__users[user] = address # Storing new user in dictionary - - # Process the message and handle accordingly - self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld) - print(f"Received message from {address}: {message}") - - def broadcast(self, payload:dict): - for user_address in self.__users.values(): - self.__udpSocket.sendto(json.dumps(payload).encode(), user_address) - - def send(self, payload:dict, user:str): - if user in self.__users: - self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user]) - +#class UDP: +# __Addr:str +# __Port:str +# __BufferSize:int = 1024 +# __udpSocket:socket +# __users:dict +# __eventHandler: UDPEventHandler +# __UDPClientThread:threading.Thread +# __gameManager:GameManager +# +# def __init__(self, Addr:str, Port:str, gameManager:GameManager): +# self.__Addr = Addr +# self.__Port = int(Port) +# self.__gameManager = gameManager +# self.__users = {} +# self.__eventHandler = {} +# self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# +# try: +# self.__udpSocket.bind((self.__Addr, self.__Port)) +# except OSError as e: +# print(f"Error binding UDP socket: {e}") +# +# self.__UDPClientThread = threading.Thread(target=self.receive) +# self.__UDPClientThread.start() +# +# # handles incoming udp data +# def receive(self): +# while True: +# data, address = self.__udpSocket.recvfrom(self.__BufferSize) +# message = data.decode() +# messageJson = json.loads(message) +# user = messageJson.get("user") +# +# if user not in self.__users: +# self.__users[user] = address # Storing new user in dictionary +# +# # Process the message and handle accordingly +# self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld) +# print(f"Received message from {address}: {message}") +# +# def broadcast(self, payload:dict): +# for user_address in self.__users.values(): +# self.__udpSocket.sendto(json.dumps(payload).encode(), user_address) +# +# def send(self, payload:dict, user:str): +# if user in self.__users: +# self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user]) +# class TCP: __Addr:str __Port:str __BufferSize:int = 1024 __tcpSocket:socket - __eventHandler: dict + __eventHandler: dict + __users: dict __TCPClientThread:threading.Thread __gameManager:GameManager def __init__(self, Addr:str, Port:str, gameManager:GameManager): + self.running = True self.__Addr = Addr self.__Port = int(Port) self.__gameManager = gameManager self.__eventHandler = {} self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__tcpSocket.bind((self.__Addr, self.__Port)) - self.__tcpSocket.listen(2) + self.__tcpSocket.listen() self.__TCPClientThread = threading.Thread(target=self.accept_connections) self.__TCPClientThread.start() def accept_connections(self): - while True: + while self.running: try: client_tcp_socket, client_address = self.__tcpSocket.accept() print(f"Connected with {client_address}") - self.__users[client_address] = client_tcp_socket + self.__gameManager.getPlayers()[client_address] = client_tcp_socket self.__eventHandler[client_address] = TCPEventHandler(client_tcp_socket) client_handler_thread = threading.Thread( target=self.receive, @@ -96,7 +99,7 @@ class NetworkManager: pass def receive(self, client_socket, client_address): - while True: + while self.running: try: data = client_socket.recv(self.__BufferSize) if not data: @@ -109,10 +112,10 @@ class NetworkManager: # creates a user and counts how many currently are connected to the server # if enough users for a round are connected the server has to start the game - if user not in self.__users: + if user not in self.__gameManager.getPlayers(): if messageJson["event"] == "login": - self.__gameManager.addPlayers(Player(messageJson["username"]), self.__tcpSocket, client_address) - print(f"connected users {len(self.__users)}") + self.__gameManager.addPlayers(Player(messageJson["username"], messageJson["deck"]), client_socket, client_address) + print(f"connected users {len(self.__gameManager.getPlayers())}") self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address) print(f"Received message from {client_address}: {message}") @@ -138,10 +141,10 @@ class NetworkManager: players[user]["socket"].send(json.dumps(payload).encode()) else: print(f"user '{user}' or socket was not found 'socket' failed to send data.") - + tcp: TCP - udp: UDP + # udp: UDP def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager): self.tcp = self.TCP(Addr, TCPPort, gameManager) - self.udp = self.UDP(Addr, UDPPort, gameManager) + # self.udp = self.UDP(Addr, UDPPort, gameManager) \ No newline at end of file diff --git a/Game Server/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc b/Game Server/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc index 4f106e3..a715b7a 100644 Binary files a/Game Server/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc and b/Game Server/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc differ diff --git a/Game Server/Classes/System/Network/__pycache__/NetworkManger.cpython-311.pyc b/Game Server/Classes/System/Network/__pycache__/NetworkManger.cpython-311.pyc index 7bc686b..7d5188f 100644 Binary files a/Game Server/Classes/System/Network/__pycache__/NetworkManger.cpython-311.pyc and b/Game Server/Classes/System/Network/__pycache__/NetworkManger.cpython-311.pyc differ diff --git a/Game Server/Classes/System/__pycache__/GameManager.cpython-311.pyc b/Game Server/Classes/System/__pycache__/GameManager.cpython-311.pyc index 8fa01a3..1e24e1d 100644 Binary files a/Game Server/Classes/System/__pycache__/GameManager.cpython-311.pyc and b/Game Server/Classes/System/__pycache__/GameManager.cpython-311.pyc differ diff --git a/Game Server/Classes/System/__pycache__/Server.cpython-311.pyc b/Game Server/Classes/System/__pycache__/Server.cpython-311.pyc index c6001c4..f6841be 100644 Binary files a/Game Server/Classes/System/__pycache__/Server.cpython-311.pyc and b/Game Server/Classes/System/__pycache__/Server.cpython-311.pyc differ diff --git a/Game Server/index.py b/Game Server/index.py index 18c5a2a..d93b9d6 100644 --- a/Game Server/index.py +++ b/Game Server/index.py @@ -1,4 +1,5 @@ import os +import sys from Classes.System.Server import Server @@ -9,6 +10,7 @@ def main(): UDPPORT = "54323" Server(HOST, TCPPORT, UDPPORT) + sys.exit(0) if __name__ == "__main__": diff --git a/Game_Client/Assets/Cards/1/card.json b/Game_Client/Assets/Cards/1/card.json index b2b53c5..3ce8af5 100644 --- a/Game_Client/Assets/Cards/1/card.json +++ b/Game_Client/Assets/Cards/1/card.json @@ -1,5 +1,6 @@ { "id": 1, + "type":"MonsterCard", "name": "Test Monster", "image": "Assets/Cards/1/cards.png", "description": "can attack other monsters", diff --git a/Game_Client/Assets/Cards/2/testspellcard.json b/Game_Client/Assets/Cards/2/testspellcard.json index 7c1ebee..f812019 100644 --- a/Game_Client/Assets/Cards/2/testspellcard.json +++ b/Game_Client/Assets/Cards/2/testspellcard.json @@ -1,6 +1,9 @@ { "name": "testspell", + "type":"EffectCard", "image":"Assets/Cards/2/artwork.png", "costs": 30, - "description":"this is a test spell card" + "defense": 0, + "description":"this is a test spell card", + "attacks": [] } \ No newline at end of file diff --git a/Game_Client/Assets/Cards/3/testtrapcard.json b/Game_Client/Assets/Cards/3/testtrapcard.json index ef4ad97..13ed51a 100644 --- a/Game_Client/Assets/Cards/3/testtrapcard.json +++ b/Game_Client/Assets/Cards/3/testtrapcard.json @@ -1,6 +1,9 @@ { "name": "testtrap", + "type":"EffectCard", "image":"Assets/Cards/3/artwork.png", "costs": 30, - "description":"this is a test trap card" + "defense": 0, + "description":"this is a test trap card", + "attacks": [] } \ No newline at end of file diff --git a/Game_Client/Classes/Game/Cards/Card.py b/Game_Client/Classes/Game/Cards/Card.py new file mode 100644 index 0000000..748819e --- /dev/null +++ b/Game_Client/Classes/Game/Cards/Card.py @@ -0,0 +1,98 @@ +import json +import pygame + +from Classes.System.Components.InputHandler import InputHandler +from Classes.Game.Player import Player + +class Card(pygame.sprite.Sprite): + __name:str + __id:int + __description:str + __attacks = [] + __type:str = "MonsterCard" + __pos:pygame.Vector2 + __dragging:bool = False + __offset:pygame.Vector2 = pygame.Vector2(0,0) + __inputHandler: InputHandler + __owner:Player + __state:str + image:pygame.image + rect:pygame.rect + + def __init__(self, pos: pygame.Vector2, assetDir: str, inputHandler: InputHandler, owner: Player): + if assetDir == "": + raise ValueError("Card: imagePath cannot be empty") + + pygame.sprite.Sprite.__init__(self) + + with open(assetDir + "/card.json", 'r') as file: + data = json.load(file) + + self.__owner = owner + self.__id = int(data["id"]) + self.__pos = pos + self.__name = data["name"] + self.__type = data.get("type") + self.image = pygame.image.load(assetDir + "/card.png").convert_alpha() + self.rect = self.image.get_rect() + self.__inputHandler = inputHandler + self.rect.center = self.__pos + self.__description = data["description"] + self.original_size = self.image.get_size() + self.original_position = self.rect.center + self.__state = "onHand" + + self.__attacks = [] + for attack in data.get("attacks", []): + self.__attacks.append(attack) + + def update(self): + if self.__dragging: + mouse_pos = self.__inputHandler.getMousePos() + self.__pos = mouse_pos + self.rect.center = self.__pos + + def attacks(self): + return self.__attacks + + def getName(self) -> str: + return self.__name + + def getCardSprite(self) -> pygame.image: + return self.__cardSprite + + def getDescription(self): + return self.__description + + def getDragging(self): + return self.__dragging + + def getOffset(self): + return self.__offset + + def getPos(self): + return self.__pos + + def getType(self): + return self.__type + + def getID(self) -> int: + return self.__id + + def getOwner(self) -> Player: + return self.__owner + + def getState(self) -> str: + return self.__state + + def setDragging(self, dragging:bool): + self.__dragging = dragging + + def setOffset(self, offset:pygame.Vector2): + self.__offset = offset + + def setPos(self, pos:pygame.Vector2): + self.__pos = pos + + def setState(self, state:str): + self.__state = state \ No newline at end of file diff --git a/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-311.pyc b/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-311.pyc new file mode 100644 index 0000000..2613763 Binary files /dev/null and b/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-312.pyc b/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-312.pyc new file mode 100644 index 0000000..efc7f3b Binary files /dev/null and b/Game_Client/Classes/Game/Cards/__pycache__/Card.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-311.pyc b/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-311.pyc index 4e5d7a7..af7a820 100644 Binary files a/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-311.pyc and b/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-312.pyc b/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-312.pyc index 572cc0b..4f889b7 100644 Binary files a/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-312.pyc and b/Game_Client/Classes/Game/Cards/__pycache__/MonsterCard.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-311.pyc b/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-311.pyc index af192b3..5322c49 100644 Binary files a/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-311.pyc and b/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-312.pyc b/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-312.pyc new file mode 100644 index 0000000..e3fe757 Binary files /dev/null and b/Game_Client/Classes/Game/Cards/__pycache__/SpellCard.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-311.pyc b/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-311.pyc index 3cda490..8b137f5 100644 Binary files a/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-311.pyc and b/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-312.pyc b/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-312.pyc new file mode 100644 index 0000000..7a01791 Binary files /dev/null and b/Game_Client/Classes/Game/Cards/__pycache__/TrapCard.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Events/GameStart.py b/Game_Client/Classes/Game/Events/GameStart.py index 5faf41d..29b3bff 100644 --- a/Game_Client/Classes/Game/Events/GameStart.py +++ b/Game_Client/Classes/Game/Events/GameStart.py @@ -1,8 +1,16 @@ +import pygame from Classes.Game.World import World +from Classes.Game.Cards.Card import Card +from Classes.Game.Player import Player +from Classes.System.Components.InputHandler import InputHandler # send from the server to tell the player the game starts # gives the client its and the opponents stats (not cards!!) -def GameStart(world: World): - print("game starts") - pass \ No newline at end of file +def GameStart(world: World, handCards:list, inputHandler:InputHandler, owner:Player, opponent:Player): + index:int = 0 + world.setEnemy(opponent) + + for card in handCards: + world.AddToPlayerHand(Card(pygame.Vector2(500 + (index + 100), 1050), f"Assets/Cards/{card}/", inputHandler, owner)) + \ No newline at end of file diff --git a/Game_Client/Classes/Game/Events/Login.py b/Game_Client/Classes/Game/Events/Login.py index 244ca7c..1b809b2 100644 --- a/Game_Client/Classes/Game/Events/Login.py +++ b/Game_Client/Classes/Game/Events/Login.py @@ -1,20 +1,22 @@ +import json import pygame -from Classes.System.Network.NetworkManager import NetworkManager +from Classes.System.Network.TCPClient import TCPClient from Classes.Game.World import World +from Classes.Game.Player import Player # event the client sends to let the server know it logged in -def Login(networkManager:NetworkManager): +def Login(tcpClient:TCPClient): payload = { "event":"login", - "username": "player" + "username": "player", + "deck": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] } - networkManager.tcp.send(payload) + tcpClient.send(payload) # server response for login event -def LoginResponse(networkManager:NetworkManager, gameWorld: World): - # todo: get labels from world - # todo: get name for enemy - # todo: adjust enemy name label - pass \ No newline at end of file +def LoginResponse(message:json): + # checks if the response on the login request is successfull + if message["status"] != "success": + print("login failed") \ No newline at end of file diff --git a/Game_Client/Classes/Game/Events/PlaceCard.py b/Game_Client/Classes/Game/Events/PlaceCard.py index e78522b..1be3cc7 100644 --- a/Game_Client/Classes/Game/Events/PlaceCard.py +++ b/Game_Client/Classes/Game/Events/PlaceCard.py @@ -1,9 +1,9 @@ import pygame from Classes.Game.World import World -from Classes.System.Network.NetworkManager import NetworkManager +from Classes.System.Components.InputHandler import InputHandler # the event the client sends to the server when it places a card -def PlaceCard(networkManager: NetworkManager, card): +def PlaceCard(tcpClient, card): # todo: send card information to the server # todo: required info is: # - position @@ -12,12 +12,24 @@ def PlaceCard(networkManager: NetworkManager, card): payload = { "event":"placecard", "card": card.getID(), + "type": card.getType(), "pos": card.getPos(), } - networkManager.udp.send(payload) + tcpClient.send(payload) # the event send from the server to display a card on the field -def CardPlaced(world:World, card:int, pos:pygame.Vector2): - +def CardPlaced(world:World, card:int, type:str, owner:str, pos:pygame.Vector2, inputHandler:InputHandler): + if type == "MonsterCard": + world.spawnMonsterCard(f"Assets/Cards/{card}/", pos, inputHandler, owner) + pass + elif type == "SpellCard": + world.spawnSpellCard(f"Assets/Cards/{card}/", pos, inputHandler, owner) + pass + elif type == "TrapCard": + world.spawmTrapCard(f"Assets/Cards/{card}/", pos, inputHandler, owner) + pass + pass + +def MovedCard(world:World, card:int, type:str, owner:str, oldPos:pygame.Vector2, newPos:pygame.Vector2, inputHandler:InputHandler): pass \ No newline at end of file diff --git a/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-311.pyc b/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-311.pyc new file mode 100644 index 0000000..771d6ae Binary files /dev/null and b/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-312.pyc b/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-312.pyc new file mode 100644 index 0000000..dbd04b2 Binary files /dev/null and b/Game_Client/Classes/Game/Events/__pycache__/GameStart.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-311.pyc b/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-311.pyc index f47c334..c7fd9e6 100644 Binary files a/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-311.pyc and b/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-312.pyc b/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-312.pyc new file mode 100644 index 0000000..5fa9f20 Binary files /dev/null and b/Game_Client/Classes/Game/Events/__pycache__/Login.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-311.pyc b/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-311.pyc index c2793fb..25507b3 100644 Binary files a/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-311.pyc and b/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-312.pyc b/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-312.pyc new file mode 100644 index 0000000..6a1a142 Binary files /dev/null and b/Game_Client/Classes/Game/Events/__pycache__/PlaceCard.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/World.py b/Game_Client/Classes/Game/World.py index 06d51b3..56212a8 100644 --- a/Game_Client/Classes/Game/World.py +++ b/Game_Client/Classes/Game/World.py @@ -6,6 +6,7 @@ from Classes.Game.Cards.SpellCard import SpellCard from Classes.Game.Cards.TrapCard import TrapCard from Classes.System.Components.InputHandler import InputHandler from Classes.Game.Player import Player +from Classes.Game.Cards.Card import Card class World(): __boardFields:list @@ -113,18 +114,8 @@ class World(): label.setText(player.getName()) self.__enemy = player - def spawnMonsterCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> MonsterCard: - card = MonsterCard(pos, asset, inputHandler, owner) - self.__cards.add(card) - return card - - def spawnSpellCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> SpellCard: - card = SpellCard(pos, asset, inputHandler, owner) - self.__cards.add(card) - return card - - def spawnTrapCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> TrapCard: - card = TrapCard(pos, asset, inputHandler, owner) + def spawnCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> Card: + card = Card(pos, asset, inputHandler, owner) self.__cards.add(card) return card @@ -132,5 +123,5 @@ class World(): for card in cards: self.__cards.add(card) - def AddToPlayerHand(self, Card): + def AddToPlayerHand(self, Card:Card): self.__PlayerHandCards.add(Card) \ No newline at end of file diff --git a/Game_Client/Classes/Game/__pycache__/BoardField.cpython-311.pyc b/Game_Client/Classes/Game/__pycache__/BoardField.cpython-311.pyc index a5b09d1..ad4f1a0 100644 Binary files a/Game_Client/Classes/Game/__pycache__/BoardField.cpython-311.pyc and b/Game_Client/Classes/Game/__pycache__/BoardField.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/__pycache__/BoardField.cpython-312.pyc b/Game_Client/Classes/Game/__pycache__/BoardField.cpython-312.pyc index 6f6562b..403c685 100644 Binary files a/Game_Client/Classes/Game/__pycache__/BoardField.cpython-312.pyc and b/Game_Client/Classes/Game/__pycache__/BoardField.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/__pycache__/Player.cpython-311.pyc b/Game_Client/Classes/Game/__pycache__/Player.cpython-311.pyc index c97d217..2bebd25 100644 Binary files a/Game_Client/Classes/Game/__pycache__/Player.cpython-311.pyc and b/Game_Client/Classes/Game/__pycache__/Player.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/__pycache__/Player.cpython-312.pyc b/Game_Client/Classes/Game/__pycache__/Player.cpython-312.pyc new file mode 100644 index 0000000..f0510f8 Binary files /dev/null and b/Game_Client/Classes/Game/__pycache__/Player.cpython-312.pyc differ diff --git a/Game_Client/Classes/Game/__pycache__/World.cpython-311.pyc b/Game_Client/Classes/Game/__pycache__/World.cpython-311.pyc index 3f8ca3e..b598ff5 100644 Binary files a/Game_Client/Classes/Game/__pycache__/World.cpython-311.pyc and b/Game_Client/Classes/Game/__pycache__/World.cpython-311.pyc differ diff --git a/Game_Client/Classes/Game/__pycache__/World.cpython-312.pyc b/Game_Client/Classes/Game/__pycache__/World.cpython-312.pyc index 5abd067..455efe1 100644 Binary files a/Game_Client/Classes/Game/__pycache__/World.cpython-312.pyc and b/Game_Client/Classes/Game/__pycache__/World.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/App.py b/Game_Client/Classes/System/App.py index 215660b..969f758 100644 --- a/Game_Client/Classes/System/App.py +++ b/Game_Client/Classes/System/App.py @@ -5,10 +5,11 @@ from Classes.Game.Cards.MonsterCard import MonsterCard from Classes.System.Components.Window import Window from Classes.System.Components.InputHandler import InputHandler from Classes.Game.World import World -from Classes.System.Network.NetworkManager import NetworkManager +from Classes.System.Network.TCPClient import TCPClient from Classes.Game.Events.Login import Login from Classes.Game.Events.PlaceCard import PlaceCard from Classes.Game.Player import Player +from Classes.Game.Cards.Card import Card class App: @@ -19,7 +20,7 @@ class App: __myFont:pygame.font __world:World __inputHandler: InputHandler - __networkManager: NetworkManager + __tcpClient: TCPClient def __init__(self, width:int=1920, height:int=1080, title:str="default title"): pygame.font.init() @@ -27,17 +28,17 @@ class App: self.__window = Window(width=width, height=height, title=title) self.__inputHandler = InputHandler() + # game word + self.__world = World(self.__window.getScreen()) + try: - self.__networkManager = NetworkManager("127.0.0.1", "54322", "54323") - Login(self.__networkManager) # will login to the server + self.__tcpClient = TCPClient("127.0.0.1", "54322", self.__world, self.__inputHandler) + Login(self.__tcpClient) # will login to the server except Exception as e: print(f"failed to login due to error {e}") print("server connection failed or got refused") pass - # game word - self.__world = World(self.__window.getScreen()) - self.startGameLoop() self.onCleanup() @@ -46,12 +47,12 @@ class App: # create sprite groups # todo: remove these and let server handle card creation instead # blocker: server - client communication [WIP] - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(500, 1050), self.__inputHandler, Player(1000, 0, "test")) - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(600, 1050), self.__inputHandler, Player(1000, 0, "test")) - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(700, 1050), self.__inputHandler, Player(1000, 0, "test")) - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(800, 1050), self.__inputHandler, Player(1000, 0, "test")) - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(900, 1050), self.__inputHandler, Player(1000, 0, "test")) - self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(1000, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(500, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(600, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(700, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(800, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(900, 1050), self.__inputHandler, Player(1000, 0, "test")) + self.__world.spawnCard("Assets/Cards/1/", pygame.Vector2(1000, 1050), self.__inputHandler, Player(1000, 0, "test")) while self.__running: self.__clock.tick(self.__FPS) @@ -63,6 +64,7 @@ class App: # updates all cards inside the cards Spritegroup at each step the gameloops does self.__world.getCards().update() + self.__world.getHandCards().update() # draw groups self.__window.drawSpriteGroup(self.__world.getCards()) @@ -88,22 +90,24 @@ class App: for card in self.__world.getCards(): if card.rect.collidepoint(mouse_pos) and selectedCard == None: - card.setDragging(True) - selectedCard = card + if card.getState() == "onHand": + card.setDragging(True) + selectedCard = card + for field in self.__world.getBoardFields(): + if field.getRect().collidepoint(mouse_pos): + if field.getSide() == "Player": + if field.getType() == "MonsterField" and card.getType() == "MonsterCard": + # todo: resize card so that it fits into the card field + card.rect.center = field.rect.center + field.image = card.image.copy() + card.setDragging(False) + elif field.getType() == "EffectField" and card.getType() == "EffectCard" or field.getType() == "EffectField" and card.getType() == "EffectCard": + # todo: resize card so that it fits into the card field + card.rect.center = field.rect.center + field.image = card.image.copy() + card.setDragging(False) + - for field in self.__world.getBoardFields(): - if field.getRect().collidepoint(mouse_pos): - if field.getSide() == "Player": - if field.getType() == "MonsterField" and card.getType() == "MonsterCard": - # todo: resize card so that it fits into the card field - card.rect.center = field.rect.center - field.image = card.image.copy() - card.setDragging(False) - elif field.getType() == "EffectField" and card.getType() == "SpellCard" or field.getType() == "EffectField" and card.getType() == "TrapCard": - # todo: resize card so that it fits into the card field - card.rect.center = field.rect.center - field.image = card.image.copy() - card.setDragging(False) elif self.__inputHandler.getPressed()[pygame.K_SPACE]: print("card spawned") self.__world.spawnMonsterCard("Assets/Cards/MonsterCards/testmonstercard/", self.__inputHandler.getMousePos(), self.__inputHandler) @@ -113,9 +117,14 @@ class App: if event.button == 1: # Wenn linke Maustaste losgelassen wird for card in self.__world.getCards(): card.setDragging(False) + card.setState("placed") # TODO: send place card event to server # resets the currently selected card in order to prevent it getting moved - PlaceCard(self.__networkManager, card) # tells the server that the player placed this card + try: + PlaceCard(self.__tcpClient, card) # tells the server that the player placed this card + except Exception as e: + print(f"failed to place card on server due to error: {e}") + if not card == None: card = None diff --git a/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-311.pyc b/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-311.pyc index 4699ec5..706de1d 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-311.pyc and b/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-312.pyc b/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-312.pyc index 2e1a3c9..cb9e6ba 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-312.pyc and b/Game_Client/Classes/System/Components/__pycache__/InputHandler.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/Components/__pycache__/Label.cpython-311.pyc b/Game_Client/Classes/System/Components/__pycache__/Label.cpython-311.pyc index 4a6f27e..b8e8e31 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/Label.cpython-311.pyc and b/Game_Client/Classes/System/Components/__pycache__/Label.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/Components/__pycache__/Label.cpython-312.pyc b/Game_Client/Classes/System/Components/__pycache__/Label.cpython-312.pyc index 8593d32..4134b34 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/Label.cpython-312.pyc and b/Game_Client/Classes/System/Components/__pycache__/Label.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/Components/__pycache__/Window.cpython-311.pyc b/Game_Client/Classes/System/Components/__pycache__/Window.cpython-311.pyc index 7aca994..04c4b84 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/Window.cpython-311.pyc and b/Game_Client/Classes/System/Components/__pycache__/Window.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/Components/__pycache__/Window.cpython-312.pyc b/Game_Client/Classes/System/Components/__pycache__/Window.cpython-312.pyc index d96025d..75b44d3 100644 Binary files a/Game_Client/Classes/System/Components/__pycache__/Window.cpython-312.pyc and b/Game_Client/Classes/System/Components/__pycache__/Window.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/Network/EventHandler.py b/Game_Client/Classes/System/Network/EventHandler.py index b1ecd8a..6fc941e 100644 --- a/Game_Client/Classes/System/Network/EventHandler.py +++ b/Game_Client/Classes/System/Network/EventHandler.py @@ -1,27 +1,37 @@ import socket +import pygame + +from Classes.Game.Events.PlaceCard import CardPlaced +from Classes.System.Components.InputHandler import InputHandler +from Classes.Game.World import World +from Classes.Game.Events.GameStart import GameStart +from Classes.Game.Player import Player class TCPEventHandler: def __init__(self, socket:socket): self.tcp_socket = socket - def handleEvents(self, message): + def handleEvents(self, message, inputHandler:InputHandler, world:World): if message["event"] == "login": # todo: handle login response here pass elif message["event"] == "startgame": - # todo: handle starting the game here - print("game starts") + print("gamestart") + GameStart(world, message["hand"], inputHandler, world.getPlayer()) pass - -class UDPEventHandler: - def __init__(self, socket:socket): - self.udp_socket = socket - - def handleEvents(self, message): - if message["event"] == "PlaceCard": + elif message["event"] == "PlaceCard": + CardPlaced(world, message["card"], message["type"], message["owner"], pygame.Vector2(int(message["x"]), int(message["y"]), inputHandler)) pass elif message["event"] == "MoveCard": + CardMoved( + world, + message["card"], + message["type"], + message["owner"], + pygame.Vector2(int(message["old_x"]), int(message["old_y"])), + pygame.Vector2(int(message["new_x"]), int(message["new_y"])), + inputHandler) pass elif message["event"] == "RemoveCard": pass diff --git a/Game_Client/Classes/System/Network/NetworkManager.py b/Game_Client/Classes/System/Network/NetworkManager.py deleted file mode 100644 index 36d84f5..0000000 --- a/Game_Client/Classes/System/Network/NetworkManager.py +++ /dev/null @@ -1,85 +0,0 @@ -import json -import socket -import threading - -from Classes.System.Network.EventHandler import TCPEventHandler, UDPEventHandler - -class NetworkManager: - class UDP: - def __init__(self, addr: str, port: str): - self.addr = addr - self.port = int(port) - self.udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.eventHandler = UDPEventHandler(self.udpSocket) - - try: - self.udpSocket.bind((self.addr, self.port)) - except Exception as e: - print(f"Error binding UDP socket: {e}") - - # start listener thread - self.listen() - - def send(self, message: dict): - try: - self.udpSocket.sendto(json.dumps(message).encode(), (self.addr, self.port)) - except Exception as e: - print(f"Error sending UDP data: {e}") - - # starts a listener thread for udp data - def receive(self): - while True: - try: - data, addr = self.udpSocket.recvfrom(1024) - if data: - decoded_data = json.loads(data.decode()) - self.eventHandler.handleEvents(decoded_data) - except Exception as e: - print(f"Error receiving UDP data: {e}") - break - - def listen(self): - udpThread = threading.Thread(target=self.receive) - udpThread.daemon = True - udpThread.start() - - class TCP: - def __init__(self, addr: str, port: str): - self.addr = addr - self.port = int(port) - self.tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.eventHandler = TCPEventHandler(self.tcpSocket) - - 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.eventHandler.handleEvents(decoded_data) - except Exception as e: - print(f"Error receiving TCP data: {e}") - break - - def listen(self): - tcpThread = threading.Thread(target=self.receive) - tcpThread.daemon = True - tcpThread.start() - - def __init__(self, addr: str, tcpport: str, udpport: str): - self.tcp = self.TCP(addr, tcpport) - self.udp = self.UDP(addr, udpport) \ No newline at end of file diff --git a/Game_Client/Classes/System/Network/TCPClient.py b/Game_Client/Classes/System/Network/TCPClient.py new file mode 100644 index 0000000..c1d7354 --- /dev/null +++ b/Game_Client/Classes/System/Network/TCPClient.py @@ -0,0 +1,46 @@ +import json +import socket +import threading + +from Classes.System.Network.EventHandler import TCPEventHandler +from Classes.Game.World import World +from Classes.System.Components.InputHandler import InputHandler + +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.eventHandler = TCPEventHandler(self.tcpSocket) + 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.eventHandler.handleEvents(decoded_data, self.inputHandler, self.world) + except Exception as e: + print(f"Error receiving TCP data: {e}") + break + + def listen(self): + tcpThread = threading.Thread(target=self.receive) + tcpThread.daemon = True + tcpThread.start() \ No newline at end of file diff --git a/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc b/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc index 525d7ce..c5de520 100644 Binary files a/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc and b/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-312.pyc b/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-312.pyc new file mode 100644 index 0000000..9fc3b73 Binary files /dev/null and b/Game_Client/Classes/System/Network/__pycache__/EventHandler.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-311.pyc b/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-311.pyc new file mode 100644 index 0000000..29668c3 Binary files /dev/null and b/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-312.pyc b/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-312.pyc new file mode 100644 index 0000000..a22909a Binary files /dev/null and b/Game_Client/Classes/System/Network/__pycache__/TCPClient.cpython-312.pyc differ diff --git a/Game_Client/Classes/System/__pycache__/App.cpython-311.pyc b/Game_Client/Classes/System/__pycache__/App.cpython-311.pyc index a32120b..b40c2b1 100644 Binary files a/Game_Client/Classes/System/__pycache__/App.cpython-311.pyc and b/Game_Client/Classes/System/__pycache__/App.cpython-311.pyc differ diff --git a/Game_Client/Classes/System/__pycache__/App.cpython-312.pyc b/Game_Client/Classes/System/__pycache__/App.cpython-312.pyc index 5949f98..173a8ff 100644 Binary files a/Game_Client/Classes/System/__pycache__/App.cpython-312.pyc and b/Game_Client/Classes/System/__pycache__/App.cpython-312.pyc differ