merged broken branches client with master branch and added first statehandling for card placement

This commit is contained in:
steev 2024-01-08 20:07:29 +01:00
parent 8f90633b16
commit 677552a617
53 changed files with 344 additions and 224 deletions

View File

@ -7,13 +7,21 @@ class Player:
__mana:int __mana:int
__name:str __name:str
__handCards:list __handCards:list
__deck:list
def __init__(self, name:str, hp:int=1000, mana:int=0):
def __init__(self, name:str, deck:list, hp:int=1000, mana:int=0):
self.__hp = hp self.__hp = hp
self.__name = name self.__name = name
self.__handCards = [] self.__handCards = []
self.__deck = deck
self.__id = random.randint(3, 99999) 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: def getName(self) -> str:
return self.__name return self.__name
@ -40,6 +48,9 @@ class Player:
self.__handCards.append(card) self.__handCards.append(card)
return self.__handCards return self.__handCards
def setHand(self, hand:list):
self.__handCards = hand
def removeFromHand(self, pos:int) -> list: def removeFromHand(self, pos:int) -> list:
self.__handCards.remove(pos) self.__handCards.remove(pos)
return self.__handCards return self.__handCards

View File

@ -1,3 +1,4 @@
import json
import socket import socket
from Classes.Game.Player import Player from Classes.Game.Player import Player
@ -38,23 +39,28 @@ class GameManager:
# this section mostly only used by the networking and event handling classes # this section mostly only used by the networking and event handling classes
# other parts should never need to interface with this unless really required # other parts should never need to interface with this unless really required
# ============================================================================= # =============================================================================
def startGame(self): def startGame(self, tcpSocket:socket):
self.__state = "running" self.__state = "running"
print("game starts") print("game starts")
for userAddr in self.__users.keys(): for userAddr in self.__users.keys():
try: try:
user = self.__serverWorld.getPlayers[userAddr] user = self.__serverWorld.getPlayers[userAddr]["player"]
user.addMana(1000) user.addMana(1000)
user.adjustHP(1000) user.adjustHP(1000)
user.shuffleDeck()
cards = user.getDeck()
user.setHand(cards[:5])
payload = { payload = {
"event":"startgame", "event":"startgame",
"mana": user.getMana(), "playermana": user.getMana(),
"hp": user.getHP() "playerhp": user.getHP(),
"playername": user.getName(),
"hand": user.getHand()
} }
self.send(payload, userAddr) tcpSocket.send(json.dumps(payload).encode())
except Exception as e: except Exception as e:
print(f"failed to start game due to error: {e}") print(f"failed to start game due to error: {e}")
break break
@ -84,6 +90,6 @@ class GameManager:
# counts participating players and starts the game if enough have joined # counts participating players and starts the game if enough have joined
if len(self.__players) == 2: if len(self.__players) == 2:
self.startGame() self.startGame(socket)
return self.__players return self.__players

View File

@ -1,5 +1,6 @@
import json import json
import socket import socket
import sys
import threading import threading
from Classes.Game.Player import Player from Classes.Game.Player import Player
from Classes.System.GameManager import GameManager from Classes.System.GameManager import GameManager
@ -9,82 +10,84 @@ from Classes.System.World import World
class NetworkManager: class NetworkManager:
class UDP: #class UDP:
__Addr:str # __Addr:str
__Port:str # __Port:str
__BufferSize:int = 1024 # __BufferSize:int = 1024
__udpSocket:socket # __udpSocket:socket
__users:dict # __users:dict
__eventHandler: UDPEventHandler # __eventHandler: UDPEventHandler
__UDPClientThread:threading.Thread # __UDPClientThread:threading.Thread
__gameManager:GameManager # __gameManager:GameManager
#
def __init__(self, Addr:str, Port:str, gameManager:GameManager): # def __init__(self, Addr:str, Port:str, gameManager:GameManager):
self.__Addr = Addr # self.__Addr = Addr
self.__Port = int(Port) # self.__Port = int(Port)
self.__gameManager = gameManager # self.__gameManager = gameManager
self.__users = {} # self.__users = {}
self.__eventHandler = {} # self.__eventHandler = {}
self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # self.__udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#
try: # try:
self.__udpSocket.bind((self.__Addr, self.__Port)) # self.__udpSocket.bind((self.__Addr, self.__Port))
except OSError as e: # except OSError as e:
print(f"Error binding UDP socket: {e}") # print(f"Error binding UDP socket: {e}")
#
self.__UDPClientThread = threading.Thread(target=self.receive) # self.__UDPClientThread = threading.Thread(target=self.receive)
self.__UDPClientThread.start() # self.__UDPClientThread.start()
#
# handles incoming udp data # # handles incoming udp data
def receive(self): # def receive(self):
while True: # while True:
data, address = self.__udpSocket.recvfrom(self.__BufferSize) # data, address = self.__udpSocket.recvfrom(self.__BufferSize)
message = data.decode() # message = data.decode()
messageJson = json.loads(message) # messageJson = json.loads(message)
user = messageJson.get("user") # user = messageJson.get("user")
#
if user not in self.__users: # if user not in self.__users:
self.__users[user] = address # Storing new user in dictionary # self.__users[user] = address # Storing new user in dictionary
#
# Process the message and handle accordingly # # Process the message and handle accordingly
self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld) # self.__eventHandler.handleUDPEvents(messageJson, self.__serverWorld)
print(f"Received message from {address}: {message}") # print(f"Received message from {address}: {message}")
#
def broadcast(self, payload:dict): # def broadcast(self, payload:dict):
for user_address in self.__users.values(): # for user_address in self.__users.values():
self.__udpSocket.sendto(json.dumps(payload).encode(), user_address) # self.__udpSocket.sendto(json.dumps(payload).encode(), user_address)
#
def send(self, payload:dict, user:str): # def send(self, payload:dict, user:str):
if user in self.__users: # if user in self.__users:
self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user]) # self.__udpSocket.sendto(json.dumps(payload).encode(), self.__users[user])
#
class TCP: class TCP:
__Addr:str __Addr:str
__Port:str __Port:str
__BufferSize:int = 1024 __BufferSize:int = 1024
__tcpSocket:socket __tcpSocket:socket
__eventHandler: dict __eventHandler: dict
__users: dict
__TCPClientThread:threading.Thread __TCPClientThread:threading.Thread
__gameManager:GameManager __gameManager:GameManager
def __init__(self, Addr:str, Port:str, gameManager:GameManager): def __init__(self, Addr:str, Port:str, gameManager:GameManager):
self.running = True
self.__Addr = Addr self.__Addr = Addr
self.__Port = int(Port) self.__Port = int(Port)
self.__gameManager = gameManager self.__gameManager = gameManager
self.__eventHandler = {} self.__eventHandler = {}
self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__tcpSocket.bind((self.__Addr, self.__Port)) self.__tcpSocket.bind((self.__Addr, self.__Port))
self.__tcpSocket.listen(2) self.__tcpSocket.listen()
self.__TCPClientThread = threading.Thread(target=self.accept_connections) self.__TCPClientThread = threading.Thread(target=self.accept_connections)
self.__TCPClientThread.start() self.__TCPClientThread.start()
def accept_connections(self): def accept_connections(self):
while True: while self.running:
try: try:
client_tcp_socket, client_address = self.__tcpSocket.accept() client_tcp_socket, client_address = self.__tcpSocket.accept()
print(f"Connected with {client_address}") 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) self.__eventHandler[client_address] = TCPEventHandler(client_tcp_socket)
client_handler_thread = threading.Thread( client_handler_thread = threading.Thread(
target=self.receive, target=self.receive,
@ -96,7 +99,7 @@ class NetworkManager:
pass pass
def receive(self, client_socket, client_address): def receive(self, client_socket, client_address):
while True: while self.running:
try: try:
data = client_socket.recv(self.__BufferSize) data = client_socket.recv(self.__BufferSize)
if not data: if not data:
@ -109,10 +112,10 @@ class NetworkManager:
# creates a user and counts how many currently are connected to the server # 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 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": if messageJson["event"] == "login":
self.__gameManager.addPlayers(Player(messageJson["username"]), self.__tcpSocket, client_address) self.__gameManager.addPlayers(Player(messageJson["username"], messageJson["deck"]), client_socket, client_address)
print(f"connected users {len(self.__users)}") print(f"connected users {len(self.__gameManager.getPlayers())}")
self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address) self.__eventHandler[client_address].handleTCPEvents(messageJson, self.__gameManager, client_address)
print(f"Received message from {client_address}: {message}") print(f"Received message from {client_address}: {message}")
@ -138,10 +141,10 @@ class NetworkManager:
players[user]["socket"].send(json.dumps(payload).encode()) players[user]["socket"].send(json.dumps(payload).encode())
else: else:
print(f"user '{user}' or socket was not found 'socket' failed to send data.") print(f"user '{user}' or socket was not found 'socket' failed to send data.")
tcp: TCP tcp: TCP
udp: UDP # udp: UDP
def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager): def __init__(self, Addr:str, TCPPort:str, UDPPort:str, gameManager:GameManager):
self.tcp = self.TCP(Addr, TCPPort, gameManager) self.tcp = self.TCP(Addr, TCPPort, gameManager)
self.udp = self.UDP(Addr, UDPPort, gameManager) # self.udp = self.UDP(Addr, UDPPort, gameManager)

View File

@ -1,4 +1,5 @@
import os import os
import sys
from Classes.System.Server import Server from Classes.System.Server import Server
@ -9,6 +10,7 @@ def main():
UDPPORT = "54323" UDPPORT = "54323"
Server(HOST, TCPPORT, UDPPORT) Server(HOST, TCPPORT, UDPPORT)
sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,5 +1,6 @@
{ {
"id": 1, "id": 1,
"type":"MonsterCard",
"name": "Test Monster", "name": "Test Monster",
"image": "Assets/Cards/1/cards.png", "image": "Assets/Cards/1/cards.png",
"description": "can attack other monsters", "description": "can attack other monsters",

View File

@ -1,6 +1,9 @@
{ {
"name": "testspell", "name": "testspell",
"type":"EffectCard",
"image":"Assets/Cards/2/artwork.png", "image":"Assets/Cards/2/artwork.png",
"costs": 30, "costs": 30,
"description":"this is a test spell card" "defense": 0,
"description":"this is a test spell card",
"attacks": []
} }

View File

@ -1,6 +1,9 @@
{ {
"name": "testtrap", "name": "testtrap",
"type":"EffectCard",
"image":"Assets/Cards/3/artwork.png", "image":"Assets/Cards/3/artwork.png",
"costs": 30, "costs": 30,
"description":"this is a test trap card" "defense": 0,
"description":"this is a test trap card",
"attacks": []
} }

View File

@ -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

View File

@ -1,8 +1,16 @@
import pygame
from Classes.Game.World import World 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 # send from the server to tell the player the game starts
# gives the client its and the opponents stats (not cards!!) # gives the client its and the opponents stats (not cards!!)
def GameStart(world: World): def GameStart(world: World, handCards:list, inputHandler:InputHandler, owner:Player, opponent:Player):
print("game starts") index:int = 0
pass world.setEnemy(opponent)
for card in handCards:
world.AddToPlayerHand(Card(pygame.Vector2(500 + (index + 100), 1050), f"Assets/Cards/{card}/", inputHandler, owner))

View File

@ -1,20 +1,22 @@
import json
import pygame 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.World import World
from Classes.Game.Player import Player
# event the client sends to let the server know it logged in # event the client sends to let the server know it logged in
def Login(networkManager:NetworkManager): def Login(tcpClient:TCPClient):
payload = { payload = {
"event":"login", "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 # server response for login event
def LoginResponse(networkManager:NetworkManager, gameWorld: World): def LoginResponse(message:json):
# todo: get labels from world # checks if the response on the login request is successfull
# todo: get name for enemy if message["status"] != "success":
# todo: adjust enemy name label print("login failed")
pass

View File

@ -1,9 +1,9 @@
import pygame import pygame
from Classes.Game.World import World 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 # 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: send card information to the server
# todo: required info is: # todo: required info is:
# - position # - position
@ -12,12 +12,24 @@ def PlaceCard(networkManager: NetworkManager, card):
payload = { payload = {
"event":"placecard", "event":"placecard",
"card": card.getID(), "card": card.getID(),
"type": card.getType(),
"pos": card.getPos(), "pos": card.getPos(),
} }
networkManager.udp.send(payload) tcpClient.send(payload)
# the event send from the server to display a card on the field # 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 pass

View File

@ -6,6 +6,7 @@ from Classes.Game.Cards.SpellCard import SpellCard
from Classes.Game.Cards.TrapCard import TrapCard from Classes.Game.Cards.TrapCard import TrapCard
from Classes.System.Components.InputHandler import InputHandler from Classes.System.Components.InputHandler import InputHandler
from Classes.Game.Player import Player from Classes.Game.Player import Player
from Classes.Game.Cards.Card import Card
class World(): class World():
__boardFields:list __boardFields:list
@ -113,18 +114,8 @@ class World():
label.setText(player.getName()) label.setText(player.getName())
self.__enemy = player self.__enemy = player
def spawnMonsterCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> MonsterCard: def spawnCard(self, asset:str, pos:pygame.Vector2, inputHandler:InputHandler, owner:Player) -> Card:
card = MonsterCard(pos, asset, inputHandler, owner) card = Card(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)
self.__cards.add(card) self.__cards.add(card)
return card return card
@ -132,5 +123,5 @@ class World():
for card in cards: for card in cards:
self.__cards.add(card) self.__cards.add(card)
def AddToPlayerHand(self, Card): def AddToPlayerHand(self, Card:Card):
self.__PlayerHandCards.add(Card) self.__PlayerHandCards.add(Card)

View File

@ -5,10 +5,11 @@ from Classes.Game.Cards.MonsterCard import MonsterCard
from Classes.System.Components.Window import Window from Classes.System.Components.Window import Window
from Classes.System.Components.InputHandler import InputHandler from Classes.System.Components.InputHandler import InputHandler
from Classes.Game.World import World 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.Login import Login
from Classes.Game.Events.PlaceCard import PlaceCard from Classes.Game.Events.PlaceCard import PlaceCard
from Classes.Game.Player import Player from Classes.Game.Player import Player
from Classes.Game.Cards.Card import Card
class App: class App:
@ -19,7 +20,7 @@ class App:
__myFont:pygame.font __myFont:pygame.font
__world:World __world:World
__inputHandler: InputHandler __inputHandler: InputHandler
__networkManager: NetworkManager __tcpClient: TCPClient
def __init__(self, width:int=1920, height:int=1080, title:str="default title"): def __init__(self, width:int=1920, height:int=1080, title:str="default title"):
pygame.font.init() pygame.font.init()
@ -27,17 +28,17 @@ class App:
self.__window = Window(width=width, height=height, title=title) self.__window = Window(width=width, height=height, title=title)
self.__inputHandler = InputHandler() self.__inputHandler = InputHandler()
# game word
self.__world = World(self.__window.getScreen())
try: try:
self.__networkManager = NetworkManager("127.0.0.1", "54322", "54323") self.__tcpClient = TCPClient("127.0.0.1", "54322", self.__world, self.__inputHandler)
Login(self.__networkManager) # will login to the server Login(self.__tcpClient) # will login to the server
except Exception as e: except Exception as e:
print(f"failed to login due to error {e}") print(f"failed to login due to error {e}")
print("server connection failed or got refused") print("server connection failed or got refused")
pass pass
# game word
self.__world = World(self.__window.getScreen())
self.startGameLoop() self.startGameLoop()
self.onCleanup() self.onCleanup()
@ -46,12 +47,12 @@ class App:
# create sprite groups # create sprite groups
# todo: remove these and let server handle card creation instead # todo: remove these and let server handle card creation instead
# blocker: server - client communication [WIP] # blocker: server - client communication [WIP]
self.__world.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(500, 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.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(600, 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.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(700, 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.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(800, 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.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(900, 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.spawnMonsterCard("Assets/Cards/1/", pygame.Vector2(1000, 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: while self.__running:
self.__clock.tick(self.__FPS) self.__clock.tick(self.__FPS)
@ -63,6 +64,7 @@ class App:
# updates all cards inside the cards Spritegroup at each step the gameloops does # updates all cards inside the cards Spritegroup at each step the gameloops does
self.__world.getCards().update() self.__world.getCards().update()
self.__world.getHandCards().update()
# draw groups # draw groups
self.__window.drawSpriteGroup(self.__world.getCards()) self.__window.drawSpriteGroup(self.__world.getCards())
@ -88,22 +90,24 @@ class App:
for card in self.__world.getCards(): for card in self.__world.getCards():
if card.rect.collidepoint(mouse_pos) and selectedCard == None: if card.rect.collidepoint(mouse_pos) and selectedCard == None:
card.setDragging(True) if card.getState() == "onHand":
selectedCard = card 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]: elif self.__inputHandler.getPressed()[pygame.K_SPACE]:
print("card spawned") print("card spawned")
self.__world.spawnMonsterCard("Assets/Cards/MonsterCards/testmonstercard/", self.__inputHandler.getMousePos(), self.__inputHandler) 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 if event.button == 1: # Wenn linke Maustaste losgelassen wird
for card in self.__world.getCards(): for card in self.__world.getCards():
card.setDragging(False) card.setDragging(False)
card.setState("placed")
# TODO: send place card event to server # TODO: send place card event to server
# resets the currently selected card in order to prevent it getting moved # 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: if not card == None:
card = None card = None

View File

@ -1,27 +1,37 @@
import socket 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: class TCPEventHandler:
def __init__(self, socket:socket): def __init__(self, socket:socket):
self.tcp_socket = socket self.tcp_socket = socket
def handleEvents(self, message): def handleEvents(self, message, inputHandler:InputHandler, world:World):
if message["event"] == "login": if message["event"] == "login":
# todo: handle login response here # todo: handle login response here
pass pass
elif message["event"] == "startgame": elif message["event"] == "startgame":
# todo: handle starting the game here print("gamestart")
print("game starts") GameStart(world, message["hand"], inputHandler, world.getPlayer())
pass pass
elif message["event"] == "PlaceCard":
class UDPEventHandler: CardPlaced(world, message["card"], message["type"], message["owner"], pygame.Vector2(int(message["x"]), int(message["y"]), inputHandler))
def __init__(self, socket:socket):
self.udp_socket = socket
def handleEvents(self, message):
if message["event"] == "PlaceCard":
pass pass
elif message["event"] == "MoveCard": 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 pass
elif message["event"] == "RemoveCard": elif message["event"] == "RemoveCard":
pass pass

View File

@ -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)

View File

@ -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()