牧师与魔鬼游戏
游戏所使用的是MVC模式开发。
首先确定游戏界面组成部分:
由游戏界面组成部分可以设计模式开发结构的视图部分:
可以看到,游戏界面由五个部分组成:船、岸、角色、河流、功能提示框,所以首先可以创建船视图BoatView
、岸视图ShoreView
、角色视图RoleView
、河流视图RiverView
和功能视图FunctionView
五个视图类,因为移动也需要在界面中展现,所以还可以创建一个移动视图MoveView
,从而很简单地确定了MVC结构的视图部分:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace PriestsAndDevils { /* 船视图 */ public class BoatView { private GameObject boat; // 创建船视图需要的游戏对象 /* 创建船视图 */ public BoatView() { boat = Object.Instantiate(Resources.Load ("Perfabs/Boat", typeof(GameObject)), new Vector3(2.5F, -1, 0), Quaternion.identity, null) as GameObject; boat.name = "Boat"; } public GameObject GetGameObj() { return boat; } /* 为游戏对象添加移动控制器 */ public MoveController AddMoveScript() { MoveController moveScript = boat.AddComponent(typeof(MoveController)) as MoveController; return moveScript; } /* 为游戏对象添加点击控制器 */ public void AddClickScript() { boat.AddComponent(typeof(ClickController)); } } /* 岸视图 */ public class ShoreView { private GameObject shore; // 创建岸视图需要的游戏对象 /* 根据岸的边侧创建游戏对象和视图 */ public ShoreView(int side, string sideName) { shore = Object.Instantiate(Resources.Load("Perfabs/Shore", typeof(GameObject)), new Vector3(7 * side, -1, 0), Quaternion.identity, null) as GameObject; shore.name = sideName; } } /* 角色视图 */ public class RoleView { private GameObject role; // 创建角色视图需要的游戏对象 /* 根据角色类型和序号创建游戏对象和视图 */ public RoleView(string roleName, int number) { role = Object.Instantiate(Resources.Load ("Perfabs/" + roleName, typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject; role.name = roleName + number; } /* 为游戏对象添加移动控制器 */ public MoveController AddMoveScript() { MoveController moveScript = role.AddComponent(typeof(MoveController)) as MoveController; return moveScript; } /* 为游戏对象添加点击控制器 */ public ClickController AddClickScript() { return role.AddComponent(typeof(ClickController)) as ClickController; } /* 获取对象名字 */ public string GetName() { return role.name; } /* 设置角色父对象 */ public void SetRoleParentTrans(Transform trans) { role.transform.parent = trans; } /* 设置角色位置 */ public void SetPos(Vector3 pos) { role.transform.position = pos; } } /* 移动视图 */ public class MoveView : MonoBehaviour { /* 在界面上根据移动位置和速度呈现物体移动效果 */ public void MoveTo(Vector3 pos, int speed) { transform.position = Vector3.MoveTowards(transform.position, pos, speed * Time.deltaTime); } } /* 河流视图 */ public class RiverView { private GameObject river; // 创建河流视图需要的游戏对象 /* 创建河流视图 */ public RiverView() { river = Object.Instantiate(Resources.Load ("Perfabs/River", typeof(GameObject)), new Vector3(0, -1.5F, 0), Quaternion.identity, null) as GameObject; river.name = "River"; } } /* 功能视图 */ public class FunctionView : MonoBehaviour { private string tipContent; // 提示框显示内容 public FunctionView() { tipContent = "Click and Play the Game"; } public void SetTipContent(string tip) { tipContent = tip; } /* 初始化提示框 */ public void InitFunctionView() { tipContent = "Click and Play the Game"; } void ShowResetButton() { GUIStyle resetStyle = new GUIStyle("button"); resetStyle.fontSize = 20; // 按下重置按钮,游戏被初始化 if (GUI.Button(new Rect(30, 20, 70, 30), "Reset", resetStyle)) { SingleObject.getInstance().GetMainController().InitGame(); } } void ShowTip(string tipContent) { GUIStyle tipStyle = new GUIStyle(); tipStyle.fontSize = 20; GUI.Label(new Rect(Screen.width - 140, 20, 100, 50), "Priest: Yellow\nDevil: Red", tipStyle); tipStyle.fontSize = 30; tipStyle.alignment = TextAnchor.MiddleCenter; // 展示提示内容 GUI.Label(new Rect(Screen.width / 2 - 50, 70, 100, 50), tipContent, tipStyle); } void OnGUI() { ShowTip(tipContent); // 展现提示框 ShowResetButton(); // 展现重置按钮 } } }
由视图部分可以接着设计模型部分和控制器部分:
对于模型部分,因为河流基本没有相关逻辑,功能提示框的逻辑与整个游戏有关,所以首先想到,只为船Boat、岸Shore、角色Role创建三个模型,另外两个部分可以直接创建视图,移动视图也可以创建一个模型,从而使具体的游戏对象可以挂载一个移动控制部分进行移动,所以MVC的模型部分,一共可以创建BoatModel
、ShoreModel
、RoleModel
、MoveModel
四个模型类:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace PriestsAndDevils { /* 船模型 */ public class BoatModel { private int side; // 岸边方向,-1表示船在左岸即终点岸,1表示船在右岸即出发岸 private string [] roleOnBoat = new string [2]{"", ""}; // 船上的角色,要不为牧师或魔鬼,要不为空 public BoatModel(int side) { this.side = side; } public void SetSide(int side) { this.side = side; } public int GetSide() { return side; } public void SetRoleOnBoat(string [] roles) { roleOnBoat = roles; } public string [] GetRoleOnBoat() { return roleOnBoat; } } /* 岸模型 */ public class ShoreModel { private int side; // 岸边方向,-1表示左岸即终点岸,1表示右岸即出发岸 private string [] roleOnShore = new string [6]{"", "", "", "", "", ""}; // 岸上的角色,要不为牧师或魔鬼,要不为空 public ShoreModel(int side) { this.side = side; } public void SetSide(int side) { this.side = side; } public int GetSide() { return side; } public void SetRoleOnShore(string [] roles) { roleOnShore = roles; } public string [] GetRoleOnShore() { return roleOnShore; } } /* 角色模型 */ public class RoleModel { private int roleType; // 角色类型,0表示牧师,1表示魔鬼 private bool isOnBoat; // 角色是否在船上 public RoleModel(int type) { roleType = type; } public void SetRoleType(int type) { roleType = type; } public int GetRoleType() { return roleType; } public void SetIsOnBoat(bool isOnBoat) { this.isOnBoat = isOnBoat; } public bool GetIsOnBoat() { return isOnBoat; } } /* 移动模型 */ public class MoveModel { private static int speed = 25; // 移动速度 private Vector3 middlePos; // 移动的中间位置,因为角色以折线形式运动,所以会有一个先移动到的中间位置 private Vector3 endPos; // 移动的最后位置,角色或船最后移动到的位置 private int state; // 移动状态,0表示没有移动,1表示正在移动到中间位置,2表示正在从中间位置移动到最后位置 public int GetSpeed() { return speed; } public void SetMiddlePos(Vector3 pos) { middlePos = pos; } public Vector3 GetMiddlePos() { return middlePos; } public void SetEndPos(Vector3 pos) { endPos = pos; } public Vector3 GetEndPos() { return endPos; } public void SetState(int state) { this.state = state; } public int GetState() { return state; } } }
对应的控制类也要创建,所以首先创建BoatController
、ShoreController
、RoleController
、MoveController
这四个控制类,和模型部分以及视图部分相对应,由于游戏对象需要点击才能移动,所以也创建一个ClickController
类,处理点击事件,整个游戏可以创建一个主控制类MainController
,其中包含所有具体的游戏角色对应的控制器,比如船控制器、左岸控制器、右岸控制器、以及所有角色的6个控制器,最后创建一个单例对象类SingleObject
,里面有唯一一个主控制类,用来使其它类能获取主控制类的唯一实例从而向主控制类传递信息,完成相应逻辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace PriestsAndDevils { /* 河岸岸边,左岸终点岸为-1,右岸出发岸为1 */ enum ShoreSide { Left = -1, Right = 1 }; /* 移动状态,0表示没有移动,1表示正在移动到中间位置,2表示正在从中间位置移动到最后位置 */ enum MoveState { Not_Moving = 0, Moving_To_Middle = 1, Moving_To_End = 2 }; /* 角色类型,0为牧师,1为魔鬼 */ enum RoleType { NoRole = -1, Priest = 0, Devil = 1 }; /* 游戏状态,0为正在进行,1为游戏失败,2为游戏成功 */ enum GameState { Playing = 0, Lose = 1, Win = 2 }; /* 移动控制器,一般会挂载到某个具体的游戏对象上 */ public class MoveController : MonoBehaviour { private MoveModel moveModel; private MoveView moveView; void Start() { moveModel = new MoveModel(); moveView = gameObject.AddComponent<MoveView>() as MoveView; } void Update() { int state = moveModel.GetState(); Vector3 middlePos = moveModel.GetMiddlePos(); Vector3 endPos = moveModel.GetEndPos(); int speed = moveModel.GetSpeed(); // 根据速度、中间位置、终点位置、移动状态来移动物体 Move(state, middlePos, endPos, speed); } /* 初始化控制器,设置物体不移动 */ public void InitMoveController() { moveModel.SetState((int)MoveState.Not_Moving); } /* 根据速度、中间位置、终点位置、移动状态来移动物体 */ public void Move(int state, Vector3 middlePos, Vector3 endPos, int speed) { switch (state) { case (int)MoveState.Not_Moving: break; case (int)MoveState.Moving_To_Middle: // 移动物体到中间位置,移动到后,设置物体的下一个状态为移动到终点 moveView.MoveTo(middlePos, speed); if (transform.position == middlePos) { moveModel.SetState((int)MoveState.Moving_To_End); } break; case (int)MoveState.Moving_To_End: // 移动物体到终点位置,移动到后,设置物体的下一个状态为不移动 moveView.MoveTo(endPos, speed); if (transform.position == endPos) { moveModel.SetState((int)MoveState.Not_Moving); } break; } } /* 设置物体要移动到的位置 */ public void SetMovePos(Vector3 pos) { // 设置物体开始往中间位置移动 moveModel.SetState((int)MoveState.Moving_To_Middle); // 设置最终移动位置为pos moveModel.SetEndPos(pos); // 如果要移动到的位置的y坐标等于物体所在位置的y坐标,说明是船在移动 if (pos.y == transform.position.y) { // 船沿直线运动,所以中间位置也可设为最终位置 moveModel.SetMiddlePos(pos); // 移动状态可以直接设为往终点移动 moveModel.SetState((int)MoveState.Moving_To_End); } // 如果要移动到的位置的y坐标小于物体所在位置的y坐标,说明是物体从岸上移动到船上 else if (pos.y < transform.position.y) { moveModel.SetMiddlePos(new Vector3(pos.x, transform.position.y, pos.z)); } // 如果要移动到的位置的y坐标小于物体所在位置的y坐标,说明是物体从船上移动到岸上 else { moveModel.SetMiddlePos(new Vector3(transform.position.x, pos.y, pos.z)); } } } /* 点击控制器,一般会挂载在某个游戏对象上 */ public class ClickController : MonoBehaviour { RoleController clickRole; // 如果点击的是角色,那么记录点击的对象的控制器 public void SetClickRole(RoleController role) { clickRole = role; } void onm ouseDown() { // 如果鼠标点击的对象是船,那么移动船只 if (gameObject.name == "Boat") { SingleObject.getInstance().GetMainController().MoveBoat(); } else { // 如果鼠标点击的对象是角色,那么移动对象 SingleObject.getInstance().GetMainController().MoveRole(clickRole); } } } public class BoatController { // 船在左岸时装载角色的位置 private static Vector3 [] leftLoadPos = new Vector3 [] {new Vector3(-3, -0.5F, 0), new Vector3(-2, -0.5F, 0)}; // 船在右岸时装载角色的位置 private static Vector3 [] rightLoadPos = new Vector3 [] {new Vector3(2, -0.5F, 0), new Vector3(3, -0.5F, 0)}; private BoatModel boatModel; // 船模型 private BoatView boatView; // 船视图 private MoveController moveController; // 移动控制器 public BoatController() { // 船开始在右岸 boatModel = new BoatModel((int)ShoreSide.Right); boatView = new BoatView(); // 添加移动控制器 moveController = boatView.AddMoveScript(); // 添加点击控制器 boatView.AddClickScript(); } /* 初始化船控制器 */ public void InitBoatController() { // 先初始化移动控制器 moveController.InitMoveController(); // 获取船在哪边 int side = boatModel.GetSide(); // 在左边的话,船会回到右边去 if (side == (int)ShoreSide.Left) { MoveToOtherSide(); } // 初始化船模型没有乘客 boatModel.SetRoleOnBoat(new string [2]{"", ""}); } // 获取船所在的岸边 public int GetBoatSide() { return boatModel.GetSide(); } // 获取船的游戏对象 public GameObject GetBoat() { return boatView.GetGameObj(); } /* 将船移动到岸的另一侧 */ public void MoveToOtherSide() { // 先获取船在哪边 int side = boatModel.GetSide(); // 移动船到另一边 if (side == (int)ShoreSide.Left) { moveController.SetMovePos(new Vector3(2.5F, -1, 0)); boatModel.SetSide((int)ShoreSide.Right); } else { moveController.SetMovePos(new Vector3(-2.5F, -1, 0)); boatModel.SetSide((int)ShoreSide.Left); } } /* 获取船上空闲的位置 */ public int GetFreeIndex() { string [] roleOnBoat = boatModel.GetRoleOnBoat(); // 按照顺序获取船上空闲的位置 if (roleOnBoat[0] == "") { return 0; } else if (roleOnBoat[1] == "") { return 1; } else { // 如果没有空闲位置返回-1 return -1; } } /* 判断船上是否没有角色 */ public bool IsNoRole() { string [] roleOnBoat = boatModel.GetRoleOnBoat(); if (roleOnBoat[0] != "" || roleOnBoat[1] != "") { return false; } else { return true; } } /* 根据船靠岸的方向获取对应方向里船上空闲位置 */ public Vector3 GetFreePosition() { string [] roleOnBoat = boatModel.GetRoleOnBoat(); int freeIndex = GetFreeIndex(); // 如果没有空闲位置,直接返回 if (freeIndex < 0) { return new Vector3(-1, -1, -1); } int side = boatModel.GetSide(); if (side == (int)ShoreSide.Left) { return leftLoadPos[freeIndex]; } else { return rightLoadPos[freeIndex]; } } /* 将角色放到船上 */ public void PutRoleOnBoat(string roleName) { // 获取船上空闲位置 int freeIndex = GetFreeIndex(); // 如果没有空闲位置,直接返回 if (freeIndex < 0) { return; } // 利用角色名字将角色放入船 string [] roleOnBoat = boatModel.GetRoleOnBoat(); roleOnBoat[freeIndex] = roleName; } /* 将角色离开船上 */ public void PutRoleOffBoat(string roleName) { string [] roleOnBoat = boatModel.GetRoleOnBoat(); // 如果船的相应位置有角色名字,将其置为空 for (int i = 0; i < roleOnBoat.Length; i++) { if (roleOnBoat[i] == roleName) { roleOnBoat [i] = ""; break; } } } /* 获取船上的各个角色的数目 */ public int[] GetRoleCountOnBoat() { int [] count = {0, 0}; string [] roleOnBoat = boatModel.GetRoleOnBoat(); for (int i = 0; i < roleOnBoat.Length; i++) { string roleName = roleOnBoat[i]; if (roleName == "") continue; if (roleName.Remove(roleName.Length - 1, 1) == "Priest") { count[0]++; } else { count[1]++; } } return count; } } /* 岸控制器 */ public class ShoreController { private ShoreModel shoreModel; // 岸模型 private ShoreView shoreView; // 岸视图 // 右岸上可以放角色的位置,左岸的位置只需将坐标的x数值乘-1即可 private static Vector3 [] positions = new Vector3[] {new Vector3(4.5F, 0.25F, 0), new Vector3(5.5F, 0.25F, 0), new Vector3(6.5F, 0.25F, 0), new Vector3(7.5F, 0.25F, 0), new Vector3(8.5F, 0.25F, 0), new Vector3(9.5F, 0.25F, 0)}; public ShoreController(int side, string sideName) { shoreModel = new ShoreModel(side); shoreView = new ShoreView(side, sideName); } public void InitShoreController() { shoreModel.SetRoleOnShore(new string [6]{"", "", "", "", "", ""}); } /* 获取岸边 */ public int GetShoreSide() { return shoreModel.GetSide(); } /* 获取岸上空闲的位置 */ public int GetFreeIndex() { string [] roleOnShore = shoreModel.GetRoleOnShore(); for (int i = 0; i < roleOnShore.Length; i++) { if (roleOnShore[i] == "") { return i; } } // 如果没有空闲位置返回-1 return -1; } /* 根据船靠岸的方向获取对应方向里岸上空闲位置 */ public Vector3 GetFreePosition() { int freeIndex = GetFreeIndex(); // 如果没有空闲位置,直接返回 if (freeIndex < 0) { return new Vector3(-1, -1, -1); } Vector3 pos = positions[freeIndex]; // 坐标的x数值乘1是右边岸上的位置,乘-1即可得到左边岸上的位置 pos.x *= shoreModel.GetSide(); return pos; } /* 将角色放到岸上 */ public void PutRoleOnShore(string roleName) { // 获取岸上空闲位置 int freeIndex = GetFreeIndex(); // 如果没有空闲位置,直接返回 if (freeIndex < 0) { return; } // 利用角色名字将角色放上岸 string [] roleOnShore = shoreModel.GetRoleOnShore(); roleOnShore[freeIndex] = roleName; } /* 将角色离开岸上 */ public void PutRoleOffShore(string roleName) { // 0->priest, 1->devil string [] roleOnShore = shoreModel.GetRoleOnShore(); // 如果岸的相应位置有角色名字,将其置为空 for (int i = 0; i < roleOnShore.Length; i++) { if (roleOnShore[i] == roleName) { roleOnShore [i] = ""; break; } } } /* 获取岸上的各个角色的数目 */ public int [] GetRoleCountOnShore() { int [] count = {0, 0}; string [] roleOnShore = shoreModel.GetRoleOnShore(); for (int i = 0; i < roleOnShore.Length; i++) { string roleName = roleOnShore[i]; if (roleName == "") continue; if (roleName.Remove(roleName.Length - 1, 1) == "Priest") { count[0]++; } else { count[1]++; } } return count; } } /* 角色控制器 */ public class RoleController { private RoleModel roleModel; // 角色模型 private RoleView roleView; // 角色视图 private MoveController moveController; // 移动控制器 private ClickController clickController; // 点击控制器 ShoreController shoreController; // 角色所在相应岸上的岸控制器 public RoleController(int roleType, string roleName, int number) { roleModel = new RoleModel(roleType); roleView = new RoleView(roleName, number); // 添加移动控制器 moveController = roleView.AddMoveScript(); // 添加点击控制器,并记录点击对象的控制器 clickController = roleView.AddClickScript(); clickController.SetClickRole(this); } public void InitRoleController() { // 初始化移动控制器 moveController.InitMoveController(); // 获取主控制器中的右岸控制器 shoreController = (SingleObject.getInstance().GetMainController() as MainController).GetRightShore(); // 将角色放到右岸上 PutRoleOnShore(shoreController); SetRolePos(shoreController.GetFreePosition()); // 右岸控制器中关于角色的信息也被初始化 shoreController.PutRoleOnShore(this.GetRoleViewName()); } public ShoreController GetShoreController() { return shoreController; } /* 设置角色游戏对象位置 */ public void SetRolePos(Vector3 pos) { roleView.SetPos(pos); } /* 将角色移动到指定位置 */ public void MoveToPosition(Vector3 endPosination) { moveController.SetMovePos(endPosination); } /* 获取角色类型 */ public int GetRoleModelType() { return roleModel.GetRoleType(); } /* 获取角色游戏对象名字 */ public string GetRoleViewName() { return roleView.GetName(); } /* 获取游戏对象是否在船上 */ public bool IsOnBoat() { return roleModel.GetIsOnBoat(); } /* 将角色放到船上 */ public void PutRoleOnBoat(BoatController boatController) { // 设置角色不在岸上,所以也没有岸控制器 shoreController = null; // 设置角色在船上 roleModel.SetIsOnBoat(true); // 设置角色游戏对象的父对象是船只 roleView.SetRoleParentTrans(boatController.GetBoat().transform); } /* 将角色放到岸上 */ public void PutRoleOnShore(ShoreController shoreController) { // 设置角色在相应岸上的岸控制器 this.shoreController = shoreController; // 设置角色不在船上 roleModel.SetIsOnBoat(false); // 设置角色游戏对象的父对象为没有 roleView.SetRoleParentTrans(null); } } /* 主控制器 */ public class MainController : MonoBehaviour { private BoatController boat; // 船控制器 private ShoreController leftShore; // 左岸控制器 private ShoreController rightShore; // 右岸控制器 private RoleController [] roles; // 所有角色的控制器 private RiverView riverView; // 河流视图 private FunctionView functionView; // 功能视图,包括提示框,游戏信息等 private int gameState = (int)GameState.Playing; // 游戏状态,0表示游戏正在进行,1表示游戏失败,2表示游戏成功 void Awake() { // 设置单例对象中只有唯一一个主控制器 SingleObject instance = SingleObject.getInstance(); instance.SetMainController(this); // 展现游戏视图 ShowView(); } /* 通过创建控制器的方式初始化游戏视图 */ public void ShowView() { boat = new BoatController(); leftShore = new ShoreController((int)ShoreSide.Left, "LeftShore"); rightShore = new ShoreController((int)ShoreSide.Right, "RightShore"); roles = new RoleController[6]; CreateRolesController(); riverView = new RiverView(); functionView = gameObject.AddComponent<FunctionView>() as FunctionView; } /* 为每个角色创建控制器并初始化视图 */ private void CreateRolesController() { for (int i = 0; i < 3; i++) { roles[i] = new RoleController(0, "Priest", i + 1); roles[i].SetRolePos(rightShore.GetFreePosition()); roles[i].PutRoleOnShore(rightShore); rightShore.PutRoleOnShore(roles[i].GetRoleViewName()); } for (int i = 0; i < 3; i++) { roles[i + 3] = new RoleController(1, "Devil", i + 1); roles[i + 3].SetRolePos(rightShore.GetFreePosition()); roles[i + 3].PutRoleOnShore(rightShore); rightShore.PutRoleOnShore(roles[i + 3].GetRoleViewName()); } } /* 通过初始化控制器和视图的方式初始化游戏 */ public void InitGame() { boat.InitBoatController(); leftShore.InitShoreController(); rightShore.InitShoreController(); for (int i = 0; i < roles.Length; i++) { roles[i].InitRoleController(); } functionView.InitFunctionView(); gameState = (int)GameState.Playing; } public ShoreController GetRightShore() { return rightShore; } /* 根据不同的游戏状态返回不同的提示框内容 */ public string StateToTip(int gameState) { switch (gameState) { case (int)GameState.Playing: return "Click and Play the Game"; case (int)GameState.Lose: return "You lose! Click \"Reset\" to play again!"; case (int)GameState.Win: return "You win! Click \"Reset\" to play again!"; default: return ""; } } /* 通过船控制器来移动船只 */ public void MoveBoat() { // 如果游戏状态不是正在进行,那么不移动 if (gameState != (int)GameState.Playing) { return; } // 如果船上没有角色,不能开船 if (boat.IsNoRole()) { return; } else { // 否则直接将船开到另一边 boat.MoveToOtherSide(); } // 检查游戏状态 gameState = CheckGameState(); // 显示相应提示 functionView.SetTipContent(StateToTip(gameState)); } /* 通过角色控制器移动角色 */ public void MoveRole(RoleController role) { // 如果游戏状态不是正在进行,那么不移动 if (gameState != (int)GameState.Playing) { return; } // 如果角色在船上,那么要将角色放上相应岸边 if (role.IsOnBoat()) { // 获取船所在的岸边 ShoreController boatShore; if (boat.GetBoatSide() == (int)ShoreSide.Left) { boatShore = leftShore; } else { boatShore = rightShore; } /* 设置船和岸以及角色控制器以将角色放到岸上 */ role.MoveToPosition(boatShore.GetFreePosition()); boat.PutRoleOffBoat(role.GetRoleViewName()); role.PutRoleOnShore(boatShore); boatShore.PutRoleOnShore(role.GetRoleViewName()); } else { // 否则角色在岸上,要将角色放到船上,首先获取角色所在岸边的控制器 ShoreController boatShore = role.GetShoreController(); // 如果船上没有位置,或者船和物体所在的岸不是一边,直接返回 if (boat.GetFreeIndex() == -1 || boatShore.GetShoreSide() != boat.GetBoatSide()) { return; } /* 设置船和岸以及角色控制器以将角色放到船上 */ role.MoveToPosition(boat.GetFreePosition()); boat.PutRoleOnBoat(role.GetRoleViewName()); role.PutRoleOnBoat(boat); boatShore.PutRoleOffShore(role.GetRoleViewName()); } // 检查游戏状态 gameState = CheckGameState(); // 显示相应提示 functionView.SetTipContent(StateToTip(gameState)); } /* 检查游戏状态 */ public int CheckGameState() { // 初始化左边和右边的牧师和魔鬼数量都为0 int leftPriest = 0, rightPriest = 0; int leftDevil = 0, rightDevil = 0; // 获取左岸和右岸以及船上的牧师和魔鬼的数量数组 int [] leftShoreCount = leftShore.GetRoleCountOnShore(); int [] rightShoreCount = rightShore.GetRoleCountOnShore(); int [] boatCount = boat.GetRoleCountOnBoat(); // 如果船在左边,那么左边的牧师和魔鬼的数量为左岸数量加上船里的数量 if (boat.GetBoatSide() == (int)ShoreSide.Left) { leftPriest = leftShoreCount[0] + boatCount[0]; leftDevil = leftShoreCount[1] + boatCount[1]; rightPriest = rightShoreCount[0]; rightDevil = rightShoreCount[1]; } else { // 如果船在右边,那么右边的牧师和魔鬼的数量为右岸数量加上船里的数量 leftPriest = leftShoreCount[0]; leftDevil = leftShoreCount[1]; rightPriest = rightShoreCount[0] + boatCount[0]; rightDevil = rightShoreCount[1] + boatCount[1]; } // 如果左边牧师加魔鬼的数量等于6且魔鬼全部上岸,那么游戏成功 if (leftPriest + leftDevil == 6 && leftShoreCount[1] == 3) { return (int)GameState.Win; } else if (leftPriest < leftDevil && leftPriest > 0) { // 如果任意一边牧师的数量小于魔鬼的数量且有牧师,那么游戏失败 return (int)GameState.Lose; } else if (rightPriest < rightDevil && rightPriest > 0) { return (int)GameState.Lose; } else { // 否则游戏正在进行中 return (int)GameState.Playing; } } } /* 单例对象,里面有唯一一个主控制类 */ public class SingleObject { private static SingleObject instance = new SingleObject(); private MainController mainController; public static SingleObject getInstance() { return instance; } public void SetMainController(MainController controller) { mainController = controller; } public MainController GetMainController() { return mainController; } } }
最后在主文件中,调用主控制器,进行游戏,就实现了一个基本的MVC模式:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace PriestsAndDevils { public class Main : MonoBehaviour { void Start() { // 创建主控制器 MainController mainController = gameObject.AddComponent<MainController>() as MainController; } } }
总结: 所以在实现MVC模式时,可以先将最后的效果图画出来,创建相应的视图类,由视图类进行分析,设计相应的模型类和控制器类,基本没有逻辑的可以不创建模型,直接在主控制类中实现相应视图或逻辑控制,最后实现MVC模式的开发。
正在进行游戏:
游戏失败:
游戏成功: