Unity+Photon实现五子棋功能,可多人联机

一共设有3个类,分别管理网络、棋子、角色。

  1. 网络类里主要是关于Photon的通信和ui上的处理
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
using DG.Tweening;

public enum PlayerType
{
    none=-1,
    black,
    white,
}

public class NetWorkManager : MonoBehaviourPunCallbacks
{
    public GameObject mPlayer;
    public PlayerType playerTurn = PlayerType.black;
    public List<Vector2> piecePos = new List<Vector2>();
    private PhotonView photonView;
    public GameObject mGoGameOver;
    public AudioSource audio;

    [Header("Room")]
    public InputField mInputRoom;
    public Button mBtnEnter;
    private string mRoom;
    private List<string> mRoomList = new List<string>();
    public int mRoomMaxCount = 2;
    public GameObject mGoHintCount;
    public GameObject mGoRoom;
    public GameObject mGoCheckerboard;
    public Text mTxtRoomName;
    [Header("界面")]
    public GameObject mGoInterface;
    public GameObject mBtnStart;
    public GameObject mGoStartHint;
    public GameObject mGoStart;
    public Text mTxtThis;
    public Text mTxtOther;
    public Text mTxtChess;
    private void Awake()
    {
        Screen.SetResolution(480, 800, false);

        photonView = GetComponent<PhotonView>();
    }
    void Start()
    {
        PhotonNetwork.ConnectUsingSettings();

        mBtnEnter.onClick.AddListener(() => {
            mRoom = mInputRoom.text;
            if (!string.IsNullOrEmpty(mRoom) && PhotonNetwork.IsConnected)
            {
                if (GetRoomCount() > mRoomMaxCount)
                {
                    photonView.RPC("HintCount", RpcTarget.All);
                }
                else
                {
                    RoomOptions room = new RoomOptions();
                    room.MaxPlayers = 2;
                    PhotonNetwork.JoinOrCreateRoom(mRoom, room, TypedLobby.Default);
                }
            }
        });

        mBtnStart.GetComponent<Button>().onClick.AddListener(() => {
            if (GetRoomCount() == mRoomMaxCount)
            {
                photonView.RPC("OnStart", RpcTarget.All);
            }
            else
            {
                mGoStartHint.SetActive(true);
            }
        });
    }

    public override void OnConnectedToMaster()
    {
        base.OnConnectedToMaster();
    }

    public override void OnJoinedRoom()
    {
        base.OnJoinedRoom();
        photonView.RPC("CreateRoom", RpcTarget.All);
        if (mPlayer != null)
        {
            GameObject go = PhotonNetwork.Instantiate(mPlayer.name, Vector3.zero, mPlayer.transform.rotation);
            if (PhotonNetwork.IsMasterClient)
            {
                go.GetComponent<Player>().Init(PlayerType.black, this);
            }
            else
            {
                go.GetComponent<Player>().Init(PlayerType.white, this);
            }
        }
    }

    /// <summary>
    /// 是否可以下棋
    /// </summary>
    /// <param name="_pos"></param>
    /// <returns></returns>
    public bool IsChess(int[] _pos)
    {
        if (_pos.Length != 2) return false;
        if (_pos[0] < 0 || _pos[0] > 14 || _pos[1] < 0 || _pos[1] > 14) return false;
        foreach (var item in piecePos)
        {
            if (item.x == _pos[0] && item.y == _pos[1]) return false;
        }

        return true;
    }

    #region PunRPC

    [PunRPC]
    private void OnPunRPC(int[] _pos)
    {
        playerTurn = playerTurn == PlayerType.black ? PlayerType.white : PlayerType.black;
        if (_pos.Length != 2) return;
        piecePos.Add(new Vector2(_pos[0], _pos[1]));
    }

    [PunRPC]
    private void OnOver()
    {
        mGoGameOver.SetActive(true);
    }

    [PunRPC]
    private void CreateRoom()
    {
        photonView.RPC("AppendRoom", RpcTarget.All);

        mGoCheckerboard.SetActive(true);
        mGoRoom.SetActive(false);
        mGoInterface.SetActive(true);
        mTxtRoomName.text = mRoom;

        if (PhotonNetwork.IsMasterClient)
        {
            mTxtThis.text = "白棋";
            mTxtOther.text = "黑棋";
        }
        else
        {
            mTxtThis.text = "黑棋";
            mTxtOther.text = "白棋";
        }

        switch (playerTurn)
        {
            case PlayerType.black:
                mTxtChess.text = "请持黑色玩家下棋";
                break;
            case PlayerType.white:
                mTxtChess.text = "请持白色玩家下棋";
                break;
        }
    }

    [PunRPC]
    private void HintCount()
    {
        mGoHintCount.SetActive(true);
        //DOVirtual.DelayedCall(1.5f, () => {
        //    mGoHintCount.SetActive(false);
        //});
    }

    [PunRPC]
    public void OnStart()
    {
        mGoStart.SetActive(true);
        mBtnStart.SetActive(false);
        mGoStartHint.SetActive(false);
    }

    [PunRPC]
    public void AppendRoom()
    {
        mRoomList.Add(mRoom);
    }

    [PunRPC]
    public void PlayChess()
    {
        switch (playerTurn)
        {
            case PlayerType.black:
                mTxtChess.text = "请持黑色玩家下棋";
                break;
            case PlayerType.white:
                mTxtChess.text = "请持白色玩家下棋";
                break;
        }
    }

    public void RPC(int[] _pos)
    {
        photonView.RPC("OnPunRPC", RpcTarget.All, _pos);
        photonView.RPC("PlayChess", RpcTarget.All);
    }

    public void GameOver()
    {
        photonView.RPC("OnOver", RpcTarget.All);
    }

    private int GetRoomCount()
    {
        int _count = 0;
        foreach (var item in mRoomList)
        {
            if (item == mRoom)
            {
                _count++;
            }
        }

        return _count;
    }

    #endregion

    public void Audio()
    {
        audio.Play();
    }
}
  1. 角色类是棋子的控制对象,棋子生成、落子位置、可落子范围,当前位置可落子等
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Photon.Pun;
using UnityEngine;

public enum Dir
{
    Up,
    Down,
    left,
    Right,
    leftUp,
    RightDown,
    leftDown,
    RightUp,
}

public class Player : MonoBehaviour
{
    public Vector3 zeroPointPosition;
    public float cellWidth;
    public int row, column;
    public PlayerType playerType = PlayerType.none;
    public GameObject mGoBlack, mGoWhite;
    private PhotonView photonView;
    private Vector3 mousePos, offsetPos,piecePos;
    public List<Piece> pieces = new List<Piece>();
    private NetWorkManager netWorkManager;
    private void Awake()
    {
        photonView = GetComponent<PhotonView>();
    }

    void Update()
    {
        if (!photonView.IsMine) return;
        if (netWorkManager.playerTurn != playerType) return;

        if (Input.GetMouseButtonDown(0))
        {
            //计算位置
            mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            offsetPos = mousePos - zeroPointPosition;
            row = (int)Mathf.Round(offsetPos.y / cellWidth);
            column = (int)Mathf.Round(offsetPos.x / cellWidth);

            //判断该位置能不能下
            int[] rowColumnValue = { row, column };
            if (!netWorkManager.IsChess(rowColumnValue)) return;

            //创建棋子
            piecePos = new Vector3(column * cellWidth, row * cellWidth, zeroPointPosition.z) + zeroPointPosition;
            GameObject goPiece = null;
            switch (playerType)
            {
                case PlayerType.black:
                    goPiece = PhotonNetwork.Instantiate(mGoBlack.name, piecePos, mGoBlack.transform.rotation);
                    break;
                case PlayerType.white:
                    goPiece = PhotonNetwork.Instantiate(mGoWhite.name, piecePos, mGoWhite.transform.rotation);
                    break;
            }

            //播放音频
            netWorkManager.Audio();

            //设置棋子位置并保存
            Piece _piece = goPiece.GetComponent<Piece>();
            pieces.Add(_piece);
            _piece.SetRowColumnValue(rowColumnValue);

            //切换下棋角色且记录所有棋子位置
            netWorkManager.RPC(rowColumnValue);

            //判断是否5连
            bool result = _piece.IsFive(pieces);
            if (result)
            {
                netWorkManager.GameOver();
            }
        }
    }

    public void Init(PlayerType _type, NetWorkManager _manager)
    {
        playerType = _type;
        netWorkManager = _manager;
    }
}

  1. 棋子类主要是5连完成判断
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;

public class Piece : MonoBehaviour
{
    public int row;
    public int column;
    public PlayerType playerType = PlayerType.none;
    private PhotonView photonView;
    void Awake()
    {
        photonView = GetComponent<PhotonView>();
    }

    [PunRPC]
    private void RowColumn(int[] _rowColumnValue)
    {
        if (_rowColumnValue.Length != 2) return;
        row = _rowColumnValue[0];
        column = _rowColumnValue[1];
    }

    public void SetRowColumnValue(int[] _rowColumnValue)
    {
        photonView.RPC("RowColumn", RpcTarget.All, _rowColumnValue);
    }

    /// <summary>
    /// 是否5连
    /// </summary>
    /// <returns></returns>
    public bool IsFive(List<Piece> _pieces)
    {
        if((PieceCount(_pieces, Dir.Up) + PieceCount(_pieces, Dir.Down) + 1)==5
            || (PieceCount(_pieces, Dir.left) + PieceCount(_pieces, Dir.Right) + 1) == 5
            || (PieceCount(_pieces, Dir.leftUp) + PieceCount(_pieces, Dir.RightDown) + 1) == 5
            || (PieceCount(_pieces, Dir.leftDown) + PieceCount(_pieces, Dir.RightUp) + 1) == 5
        )
        {
            return true;
        }
        return false;
    }

    public int PieceCount(List<Piece> _pieces, Dir _dir)
    {
        int count = 0;
        switch (_dir)
        {
            case Dir.Up:
                foreach (var item in _pieces)
                {
                    if (row + 1 == item.row && column == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.Up);
                    }
                }
                break;
            case Dir.Down:
                foreach (var item in _pieces)
                {
                    if (row - 1 == item.row && column == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.Down);
                    }
                }
                break;
            case Dir.left:
                foreach (var item in _pieces)
                {
                    if (row == item.row && column - 1 == item.column) 
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.left);
                    }
                }
                break;
            case Dir.Right:
                foreach (var item in _pieces)
                {
                    if (row == item.row && column + 1 == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.Right);
                    }
                }
                break;
            case Dir.leftUp:
                foreach (var item in _pieces)
                {
                    if (row - 1 == item.row && column + 1 == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.leftUp);
                    }
                }
                break;
            case Dir.RightDown:
                foreach (var item in _pieces)
                {
                    if (row + 1 == item.row && column - 1 == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.RightDown);
                    }
                }
                break;
            case Dir.leftDown:
                foreach (var item in _pieces)
                {
                    if (row - 1 == item.row && column - 1 == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.leftDown);
                    }
                }
                break;
            case Dir.RightUp:
                foreach (var item in _pieces)
                {
                    if (row + 1 == item.row && column + 1 == item.column)
                    {
                        count++;
                        count += item.PieceCount(_pieces, Dir.RightUp);
                    }
                }
                break;
        }

        return count;
    }
}

猜你喜欢

转载自blog.csdn.net/D_kkkk/article/details/131093321