Skip to content

Latest commit

 

History

History

PriestsAndDevils-ActionSeparate

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

lab06-创建游戏世界2

以下内容与原版无异,详情可查看牧师与魔鬼 原版

  • 游戏中提及的事物

  • 玩家动作表

  • 预制

牧师与魔鬼 动作分离版

设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束

游戏展示

点击观看视频👇

牧师与魔鬼 动作分离版

添加裁判类

原本由FirstController检查游戏状态的函数继承到裁判类JudgeController.UpdateGameState()中。

public class JudgeController
{
    ...

    //判断游戏状态
    public int UpdateGameState()
    {
        if (firstCtrl.gameState != FirstController.PLAYING)
        {
            return firstCtrl.gameState;
        }
        //判断是否失败
        int[,] rolePos = new int[2, 3] { { 0, 0, 0 }, { 0, 0, 0 } };
        foreach (RoleController r in firstCtrl.RoleCtrl)
        {
            rolePos[r.roleType, r.roleState]++;
        }
        if ((rolePos[0, 0] > 0 && rolePos[0, 0] < rolePos[1, 0]) ||
           (rolePos[0, 1] > 0 && rolePos[0, 1] < rolePos[1, 1]) ||
           (rolePos[0, 2] > 0 && rolePos[0, 2] < rolePos[1, 2]))
        {
            return FirstController.FAILED;
        }
        //判断是否成功
        foreach (RoleController r in firstCtrl.RoleCtrl)
        {
            if (r.roleType == 0 && r.roleState != FirstController.RIGHTLAND)
            {
                return FirstController.PLAYING;
            }
        }
        return FirstController.WIN;
    }
}

通过变量gameState通知场景控制器是否结束游戏。

集成动作管理类

Models.Move迁移到Action.Move,不再需要Controllers.MoveController

添加移动序列desseq,解决了lab05中游戏对象穿模的问题。

public class Move : MonoBehaviour
{
    ...

    void Update()
    {
        if (moveMode == -1)
        {
            return;
        } 
        if (!initialized)
        {
            /*如果moveMode为single,则desseq数组长度为1,将目标位置destination赋值给desseq[0];如果moveMode为sequence,则desseq数组长度为3,分别将当前位置(transform.localPosition)和目标位置(destination)在Y轴上升高1个单位后赋值给desseq[0]和desseq[1],并将目标位置destination赋值给desseq[2]。*/
            if (moveMode == single)
            {
                desseq = new Vector3[1];
                desseq[0] = destination;
            }
            else if (moveMode == sequence)
            {
                desseq = new Vector3[3];
                desseq[0] = transform.localPosition + new Vector3(0, 1, 0);
                desseq[1] = destination + new Vector3(0, 1, 0);
                desseq[2] = destination;
            }
            else
            {
                Debug.Log("ERROR");
            }
            initialized = true;
        }
        isMoving = true;
        /*如果n_seq大于等于desseq数组的长度,表示已经完成了所有的移动序列,将一些变量重置为默认值,并将isMoving设置为false,然后返回。*/
        if (n_seq >= desseq.Length)
        {
            n_seq = 0;
            moveMode = -1;
            initialized = false;
            isMoving = false;
            return;
        }
        /*如果当前位置(transform.localPosition)与desseq[n_seq]相等,则表示已经到达当前目标位置,将n_seq加1,表示切换到下一个目标位置。*/
        if (transform.localPosition == desseq[n_seq])
        {
            n_seq++;
            return;
        }
        transform.localPosition = Vector3.MoveTowards(transform.localPosition, desseq[n_seq], speed * Time.deltaTime);
    }
}

Action.CCMoveAction中的MoveTo()MoveSequence()分别封装了对象的单次移动和序列移动。

public class CCMoveAction
{
    ...

    public void MoveTo(GameObject moveObject, Vector3 destination)
    {
        Move test;
        this.moveObject = moveObject;
        if (!moveObject.TryGetComponent<Move>(out test))
        {
            moveObject.AddComponent<Move>();
        }
        this.moveObject.GetComponent<Move>().moveAction = this;
        this.moveObject.GetComponent<Move>().destination = destination;
        this.moveObject.GetComponent<Move>().moveMode = Move.single;
    }

    public void MoveSequence(GameObject moveObject, Vector3 destination)
    {
        Move test;
        this.moveObject = moveObject;
        if (!moveObject.TryGetComponent<Move>(out test))
        {
            moveObject.AddComponent<Move>();
        }
        this.moveObject.GetComponent<Move>().moveAction = this;
        this.moveObject.GetComponent<Move>().destination = destination;
        this.moveObject.GetComponent<Move>().moveMode = Move.sequence;
    }
}

FirstController.MoveRoleFirstController.MoveBoat的具体实现迁移到CCActionManager

public class CCActionManager
{
    ...

    //点击角色时执行
    public void MoveRole(BoatController BoatCtrl, RoleController RoleCtrl, int destination, int seat)
    {
        Vector3 finalPos;
        if (destination == FirstController.RIGHTLAND)
        {
            finalPos = Position.roleRightPos[seat];
        }
        else if (destination == FirstController.LEFTLAND)
        {
            finalPos = Position.roleLeftPos[seat];
        }
        else
        {
            if (BoatCtrl.onLeftside)
            {
                finalPos = Position.seatLeftPos[seat];
            }
            else
            {
                finalPos = Position.seatRightPos[seat];
            }
        }
        moveRoleAction.MoveSequence(RoleCtrl.GetModelGameObject(), finalPos);
    }

    //点击船时执行
    public void MoveBoat(BoatController BoatCtrl, int destination)
    {
        if (destination == FirstController.RIGHTLAND)
        {
            moveBoatAction.MoveTo(BoatCtrl.GetModelGameObject(), Position.boatRightPos);
            for (int i = 0; i < BoatCtrl.seat.Length; i++)
            {
                if (BoatCtrl.seat[i] != -1)
                {
                    RoleController r = controller.RoleCtrl[controller.IDToNumber(BoatCtrl.seat[i])];
                    moveRoleAction.MoveTo(r.GetModelGameObject(), Position.seatRightPos[i]);
                }
            }
        }
        else
        {
            moveBoatAction.MoveTo(BoatCtrl.GetModelGameObject(), Position.boatLeftPos);
            for (int i = 0; i < BoatCtrl.seat.Length; i++)
            {
                if (BoatCtrl.seat[i] != -1)
                {
                    RoleController r = controller.RoleCtrl[controller.IDToNumber(BoatCtrl.seat[i])];
                    moveRoleAction.MoveTo(r.GetModelGameObject(), Position.seatLeftPos[i]);
                }
            }
        }
    }
}

FirstController.MoveRoleFirstController.MoveBoat直接调用到CCActionManager.MoveRole和到CCActionManager.MoveBoat

public class FirstController : MonoBehaviour, ISceneController, IUserAction
{
    ...

    // 点击船时执行
    public void MoveBoat()
    {
        ...

        if (BoatCtrl.onLeftside)
        {
            actionManager.MoveBoat(BoatCtrl, RIGHTLAND);
        }
        else
        {
            actionManager.MoveBoat(BoatCtrl, LEFTLAND);
        }
        BoatCtrl.onLeftside = !BoatCtrl.onLeftside;
    }

    // 点击角色时执行
    public void MoveRole(int id)
    {
        ...

        switch (RoleCtrl[num].roleState)
        {
            case 0: // LEFTLAND
                if (!BoatCtrl.onLeftside) return;
                seat = BoatCtrl.embark(id);
                if (seat == -1) return;
                LandCtrl[0].LeaveLand(id);
                RoleCtrl[num].GoTo(BOAT);
                actionManager.MoveRole(BoatCtrl, RoleCtrl[num], BOAT, seat);
                break;

            ...

            default: break;
        }
    }

    ...
}

FirstController.MoveController替换成FirstController.CCActionManager,由动作管理类负责管理动作。

项目结构

MVC模式

├─Action
│      CCActionManager.cs
│      CCMoveAction.cs
│      Move.cs
│      
├─Controllers
│      BoatController.cs
│      FirstController.cs
│      IObjectController.cs
│      ISceneController.cs
│      IUserAction.cs
│      JudgeController.cs
│      LandController.cs
│      RoleController.cs
│      SSDirector.cs
│      
├─Models
│      Boat.cs
│      Click.cs
│      Land.cs
│      Position.cs
│      Role.cs
│      
└─Views
        UserGUI.cs 

UML图

文章引用

Unity3D小游戏——牧师与魔鬼(动作分离版) - LoongChan - 博客园