Ga naar inhoud

Beurt systeem

Doelstelling

Er moest een beurtensysteem worden geimplementeerd.

Toegepaste oplossing

Mijn oplossing was om eerst een sequence diagram te maken om te weten hoe de berichten van en naar de server en client gaan.(C# Documentation, z.d.).

Sequence Diagram

sequenceDiagram Server->>Client: Het is jouw beurt, (Naam) Client->>Server: (Naam) speelt beurt. Client->>Server: (Naam) eindigt beurt. Server-->Client: Herhaal voor elke speler

Daarna heb ik in de file GameInfo een stuk code toegevoegd die een speler selecteerd als de huidige speler, en ervoor zorgt dat hij daarna de volgende speler pakt.

public class GameInfo
{
    ...
    private int playerIndex;
    ...
        public Player GetNextPlayer()
        {
            playerIndex++;

Het volgende stukje code zorgt ervoor dat er na de laatste speler in de room weer de eerste speler word gepakt.

            if (playerIndex >= room.players.Count) 
                playerIndex = 0;

            return room.players [playerIndex];
        }

        public Player GetCurrentPlayer()
            => room.players[playerIndex];
}

In Rooms.cs in de server wordt dan de eerste speler gepakt wanneer de room word gestart. Daarna word die speler de StartTurnPacket toegestuurd.

    public Task StartRoom(StartRoomPacket start)
    {
        ...
        room.game = new(room, 4);
        var currentPlayer = room.game.GetCurrentPlayer();

        var roomUpdate = new RoomListUpdatePacket()
        {
            room = room.ToPublicRoom(),
            change = RoomListUpdateType.Removed
        };

        var gameData = new GameDataPacket()
        {
            gameInfo = room.game.ToPublicGameInfo()
        };

        logger.LogInformation("{currentPlayer}", currentPlayer);

        return Task.WhenAll([
            Clients.Group(LOBBY_GROUP).SendPacketAsync(roomUpdate),
            Clients.Group(room.id).SendPacketAsync(gameData),
            Clients.Client(currentPlayer.id).SendPacketAsync(new StartTurnPacket())
        ]);
    }

Daarna maken we in Game.cs in de client de Gamestate aan, waar we de eerste speler notificeren dat het zijn beurt is met behulp van de yourTurn knop, die verdwijnt als je er op klikt. Daarnaast maken we een eindig beurt knop, die een StartTurnPacket naar de volgende speler stuurt.

public class GameState : BaseState
{
    protected Button endTurn;
    protected Button yourTurn;
    ...

    public GameState() : base()
    {
        SocketClient.Instance.SubscribeToPacket<GameDataPacket>(OnGameStarted);
        SocketClient.Instance.SubscribeToPacket<StartTurnPacket>(OnTurnStarted);

        // Initialize the button
        Vector2 buttonPosition = new Vector2(470, 525); 
        float buttonScale = 0.2f; 
        string buttonImageName = "Button@1x4";
        endTurn = new Button(buttonPosition, buttonScale, buttonImageName){
            Text = "End Turn",
            Visible = false

        };

        endTurn.Clicked += EndTurn;

        // Initialize the button
        Vector2 button2Position = new Vector2(300, 255); 
        float button2Scale = 0.2f; 
        string button2ImageName = "Button@1x4";
        yourTurn = new Button(button2Position, button2Scale, button2ImageName){
            Text = "Your Turn",
            Visible = false
        };

        yourTurn.Clicked += YourTurnClicked;
    }

    public void EndTurn(UIElement element)
    {
        SocketClient.Instance.SendDataPacket(new EndTurnPacket());
        endTurn.Visible = false;
    }
    ...
    private void OnTurnStarted(StartTurnPacket data)
    {
        Add(endTurn);
        endTurn.Visible = true;
        Add(yourTurn);
        yourTurn.Visible = true;
    }

    public void YourTurnClicked(UIElement element)
    {
        Console.WriteLine ("Your Turn");
        yourTurn.Visible = false;
    }
}

Als laatste maken we een stukje code aan in de Game.cs file in de server die ervoor zorgt dat de acties niet doorgaan wanneer er errors zijn.

public partial class HubHandler
{
    public Task EndTurn(EndTurnPacket end)
    {
        var player = players.GetPlayer(Context.ConnectionId);
        if (player == null)
        {
            Clients.Caller.SendPacketAsync(new ErrorPacket()
            {
                origin = "EndTurn",
                title = "Failed to end turn",
                message = "Your connection is not connected to a player, thus cannot end your turn."
            });

            throw new ArgumentNullException("End turn request didn't come from player");
        }

        var room = player.room;
        if (room == null)
        {
            Clients.Caller.SendPacketAsync(new ErrorPacket()
            {
                origin = "EndTurn",
                title = "Failed to end turn",
                message = "You are not in a room, so you cannot end your turn."
            });

            throw new ArgumentException($"Player {player.name}({player.id}) tried ending a turn without being in a room");
        }

        var currentPlayer = room.game.GetNextPlayer();

        return Clients.Client(currentPlayer.id).SendPacketAsync(new StartTurnPacket());
    }
}

Klassendiagram

classDiagram class GameInfo { - int playerIndex + Player GetNextPlayer() + Player GetCurrentPlayer() } class Room { - List players - Game game + PublicRoom ToPublicRoom() } class GameState { - Button endTurn - Button yourTurn + void EndTurn(UIElement element) + void YourTurnClicked(UIElement element) } class Game { + static Game() + Room room + Player GetCurrentPlayer() + Player GetNextPlayer() + PublicGameInfo ToPublicGameInfo() + void Add(object cell) + bool Remove(Vector2 pos) + object Get(Vector2 pos) } class PublicRoom { PublicRoom properties } class PublicGameInfo { PublicGameInfo properties } Connections GameInfo --> Room Player -- Room RoomListUpdatePacket --> Room Game o-- Room Game *-- Player Game --> PublicGameInfo PublicRoom *-- PublicGameInfo

Bronnen


Laatst geüpdatet: March 14, 2024
Gecreëerd: February 28, 2024