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

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

View File

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

View File

@ -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": []
}

View File

@ -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": []
}

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

View File

@ -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
def LoginResponse(message:json):
# checks if the response on the login request is successfull
if message["status"] != "success":
print("login failed")

View File

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

View File

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

View File

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

View File

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

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