以下内容与原版无异,详情可查看牧师与魔鬼 原版
-
游戏中提及的事物
-
玩家动作表
-
预制
设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束
点击观看视频👇
原本由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.MoveRole
和FirstController.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.MoveRole
和FirstController.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