Example Board Game Movement System

Very rough example of how I would approach the task.
 avatar
user_8400650
csharp
2 years ago
5.2 kB
51
Indexable
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using Random = UnityEngine.Random;

namespace _Scripts.Examples
{

    public struct PlayerInfo
    {
        public int id;
    }

    public class PlayerInputHandler
    {
        public Action<MoveDirection> OnDirectionInput;
        
        // allows for creating input handlers for both input systems
        // I'd likely make this an interface or abstract class -- would have to test a bit
        
    }

    public class PlayerTurnManager
    {
        public Action<PlayerInfo> OnNewTurn;

        static PlayerTurnManager() { }
        private PlayerTurnManager(){ }

        public static PlayerTurnManager instance { get; } = new PlayerTurnManager();

        private Dictionary<int, PlayerInfo> _players = new Dictionary<int, PlayerInfo>();
        private int _currPlayerIndex;
        
        
        public void RegisterPlayer(PlayerInfo playerInfo)
        {
            _players.TryAdd(playerInfo.id, playerInfo);
        }

        public void OnTurnFinished()
        {
            // do stuff like check for end of game with game manager, etc
            // if game is still valid:
            NotifyNextTurn();
        }

        private void NotifyNextTurn()
        {
            OnNewTurn?.Invoke(NextPlayer());
        }

        private PlayerInfo NextPlayer()
        {
            _currPlayerIndex = _currPlayerIndex >= _players.Count - 1 ? 0 : _currPlayerIndex + 1;
            return _players[_currPlayerIndex];
        }
    }

    public static class DataGenerator
    {
        public static int GetDiceRoll(int low = 1, int high = 6)
        {
            return Random.Range(low, high);
        }
    }

    public enum MoveDirection
    {
        Up,
        Right,
        Down,
        Left
    }

    public struct BoardPosition
    {
        public int id;
        public List<BoardPosition> nextBoardPositions;
    }

    public class PlayerMoveHandler
    {
        public Action<BoardPosition> OnMoveComplete;

        public bool InitMovement(MoveDirection moveDirection)
        {
            // check for valid move
            // if valid
                MovePlayer(moveDirection);
                // return true
            
            // else
            return false;
        }
        
        private void MovePlayer(MoveDirection moveDirection)
        {
            // ... do movement stuff
            // ... get ending position node and send in action (instead of new placeholder)
            OnMoveComplete?.Invoke(new BoardPosition());
        }
    }
    
    public class PlayerControllerExample : MonoBehaviour
    {
        private PlayerInfo _playerInfo;
        private PlayerInputHandler _playerInputHandler;
        private PlayerMoveHandler _playerMoveHandler;

        [SerializeField]
        private GameObject inputPrompt;
        
        private int _movesRemaining;
        private bool _isMoving;

        public PlayerInfo playerInfo
        {
            get => _playerInfo;
            set => _playerInfo = value;
        }

        private void Awake()
        {
            PlayerTurnManager.instance.RegisterPlayer(_playerInfo);
        }

        private void OnEnable()
        {
            PlayerTurnManager.instance.OnNewTurn += OnNewTurn;
            _playerInputHandler.OnDirectionInput += OnDirectionInput;
            _playerMoveHandler.OnMoveComplete += OnMoveComplete;
        }
        
        private void OnDisable()
        {
            PlayerTurnManager.instance.OnNewTurn -= OnNewTurn;
            _playerInputHandler.OnDirectionInput -= OnDirectionInput;
            _playerMoveHandler.OnMoveComplete -= OnMoveComplete;
        }
        
        private void OnMoveComplete(BoardPosition obj)
        {
            // perhaps notify game manager or UI of relevant info
            _isMoving = false;
        }
        
        private void OnDirectionInput(MoveDirection obj)
        {
            _isMoving = _playerMoveHandler.InitMovement(obj);
        }

        private void OnNewTurn(PlayerInfo turnPlayerInfo)
        {
            if (turnPlayerInfo.id != _playerInfo.id) return;
            
            SetRemainingMoves();
            InitMoveProcess();
        }

        private void InitMoveProcess()
        {
            Move();
        }

        private async Task Move()
        {
            
            while (_movesRemaining > 0)
            {
                if (!_isMoving)
                {
                    // probably would do this a bit more elegantly
                    // but this gets the point across
                    inputPrompt.SetActive(true);
                }
                
                await Task.Yield();
            }
            
            // perhaps notify game manager or UI of relevant info
            PlayerTurnManager.instance.OnTurnFinished();
        }

        private void SetRemainingMoves()
        {
            _movesRemaining = DataGenerator.GetDiceRoll();
        }
    }
}
Editor is loading...