Simple priest and devil games with Unity3D

Simple priest and devil games with Unity3D

Project Address

Priest and Devil Game

Finish Effects

Realization Experience

The game is developed in MVC mode.

First determine the game interface components:

Components of the game interface can design the view part of the pattern development structure:

You can see that the game interface consists of five parts: boat, shore, character, river, function prompt box, so you can first create five view classes: BoatView, ShoreView, RoleView, RiverView and FunctionView. Because movement also needs to be represented in the interface, you can also create a mobile view, MoveView, fromSimply determine the view part of the MVC structure:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PriestsAndDevils {
    /* Ship View */
    public class BoatView {
        private GameObject boat; // Game object needed to create ship view

        /* Create ship view */
        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;
        }

        /* Add a mobile controller to the game object */
        public MoveController AddMoveScript() {
            MoveController moveScript = boat.AddComponent(typeof(MoveController)) as MoveController;
            return moveScript;
        }

        /* Add a Click Controller to the Game Object */
        public void AddClickScript() {
            boat.AddComponent(typeof(ClickController));
        }
    }

    /* Shore view */
    public class ShoreView {
        private GameObject shore; // Game objects needed to create shore view

        /* Create game objects and views from the side of the 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;
        }
    }

    /* Role View */
    public class RoleView {
        private GameObject role; // Game Objects Required to Create Role Views

        /* Create game objects and views based on character types and serial numbers */
        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;
        }

        /* Add a mobile controller to the game object */
        public MoveController AddMoveScript() {
            MoveController moveScript = role.AddComponent(typeof(MoveController)) as MoveController;
            return moveScript;
        }

        /* Add a Click Controller to the Game Object */
        public ClickController AddClickScript() {
            return role.AddComponent(typeof(ClickController)) as ClickController;
        }

        /* Get Object Name */
        public string GetName() {
            return role.name;
        }

        /* Set Role Parent Object */
        public void SetRoleParentTrans(Transform trans) {
            role.transform.parent = trans;
        }

        /* Set Role Location */
        public void SetPos(Vector3 pos) {
            role.transform.position = pos;
        }
    }

    /* Move View */
    public class MoveView : MonoBehaviour {
        /* Presents the effect of moving an object based on its position and speed on the interface */
        public void MoveTo(Vector3 pos, int speed) {
            transform.position = Vector3.MoveTowards(transform.position, pos, speed * Time.deltaTime);
        }
    }

    /* River view */
    public class RiverView {
        private GameObject river; // Game object needed to create River View

        /* Create a view of the 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";
        }
    }

    /* Functional View */
    public class FunctionView : MonoBehaviour {
        private string tipContent; // Tip Box Display Content

        public FunctionView() {
            tipContent = "Click and Play the Game";
        }

        public void SetTipContent(string tip) {
            tipContent = tip;
        }

        /* Initialization prompt box */
        public void InitFunctionView() {
            tipContent = "Click and Play the Game";
        }

        void ShowResetButton() {
            GUIStyle resetStyle = new GUIStyle("button");
			resetStyle.fontSize = 20;

            // Press the reset button and the game is initialized
			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;

            // Show tips
			GUI.Label(new Rect(Screen.width / 2 - 50, 70, 100, 50), tipContent, tipStyle);
        }

        void OnGUI() {
            ShowTip(tipContent); // Show prompt box
            ShowResetButton(); // Show reset button
		}

    }
}

The View section connects the Design Model section and the Controller section:

For the model part, since there is little logic associated with the river and the logic of the function prompt box is related to the whole game, the first thought is that only three models are created for Boat, Shore and Role. The other two parts can create views directly, and the mobile view can also create a model so that a specific game object can mount a mobile control part to move it.So in the model section of MVC, four model classes can be created, BoatModel, ShoreModel, RoleModel, MoveModel:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PriestsAndDevils {
    /* Ship Model */
    public class BoatModel {
        private int side;  // Shore direction, -1 means that the ship is on the left shore, that is, the end shore, and 1 means that the ship is on the right shore, that is, the departure shore.
        private string [] roleOnBoat = new string [2]{"", ""};  // Characters on board, not clergy or demon, or empty

        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;
        }
    }

    /* Shore model */
    public class ShoreModel {
		private int side;  // Shore direction, -1 means left shore is end shore, 1 means right shore is start shore
        private string [] roleOnShore = new string [6]{"", "", "", "", "", ""};  // Characters on shore, not clergy or demon, not empty

        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;
        }
    }

    /* Role Model */
    public class RoleModel {
		private int roleType;  // Role type, 0 for priest, 1 for devil
        private bool isOnBoat;  // Is the role on board

        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;
        }
    }

    /* Move Model */
    public class MoveModel {
        private static int speed = 25;  // Moving speed
        private Vector3 middlePos;  // The middle of the move, because the character moves in a polyline, there is a middle position to move to first
        private Vector3 endPos;  // The last position to which a character or ship moves.
		private int state;	// Move status, 0 means no move, 1 means moving to middle position, 2 means moving from middle position to last position

        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;
        }
    }
}

Corresponding control classes are also created, so first create four control classes: BoatController, ShoreController, RoleController, MoveController, which correspond to the model part and the view part. Since the game object needs to click to move, a ClickController class is also created to handle click events, and the whole game can create a main control class, MainController.It contains the controllers corresponding to all the specific game roles, such as ship controller, left-bank controller, right-bank controller, and 6 controllers for all the roles. Finally, a single object class SingleObject is created, which has a unique master control class, so that other classes can get a unique instance of the master control class to pass information to the master control class and complete the corresponding logic.:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PriestsAndDevils {
	/* Riverbank, left end bank -1, right start Bank 1 */
	enum ShoreSide {
		Left = -1, Right = 1
	};

	/* Move status, 0 means no move, 1 means moving to middle position, 2 means moving from middle position to last position */
	enum MoveState {
		Not_Moving = 0, Moving_To_Middle = 1, Moving_To_End = 2
	};

	/* Role Type, 0 for Priest, 1 for Devil */
	enum RoleType {
		NoRole = -1, Priest = 0, Devil = 1
	};

	/* Game status, 0 in progress, 1 in failure, 2 in success */
	enum GameState {
		Playing = 0, Lose = 1, Win = 2
	};

	/* Mobile controllers, typically mounted on a specific game object */
	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 an object according to speed, middle position, end position, moving state
			Move(state, middlePos, endPos, speed);
		}

		/* Initialize controller to set object not to move */
		public void InitMoveController() {
			moveModel.SetState((int)MoveState.Not_Moving);
		}

		/* Move an object according to speed, middle position, end position, moving state */
		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:
					// Move the object to the middle position, after moving, set the next state of the object to move to the end point
					moveView.MoveTo(middlePos, speed);
					if (transform.position == middlePos) {
						moveModel.SetState((int)MoveState.Moving_To_End);
					}
					break;
				case (int)MoveState.Moving_To_End:
					// Move the object to the end position, after moving it, set the next state of the object to not move
					moveView.MoveTo(endPos, speed);
					if (transform.position == endPos) {
						moveModel.SetState((int)MoveState.Not_Moving);
					}
					break;
			}
		}

		/* Set the position to which the object is to be moved */
		public void SetMovePos(Vector3 pos) {
			// Set the object to start moving in the middle
			moveModel.SetState((int)MoveState.Moving_To_Middle);
			// Set final move position to pos
			moveModel.SetEndPos(pos);
			// If the y-coordinate of the position to be moved is equal to the y-coordinate of the object's position, the ship is moving
			if (pos.y == transform.position.y) {
				// The ship moves in a straight line, so the middle position can also be set as the final position
				moveModel.SetMiddlePos(pos);
				// Move status can be set to move directly to the end point
				moveModel.SetState((int)MoveState.Moving_To_End);
			}
			// If the y-coordinate of the location to be moved is less than the y-coordinate of the object's location, it means that the object moves from the shore to the ship.
			else if (pos.y < transform.position.y) {
				moveModel.SetMiddlePos(new Vector3(pos.x, transform.position.y, pos.z));
			}
			// If the y-coordinate of the position to be moved is less than the y-coordinate of the object's position, it means that the object moves from the ship to the shore.
			else {
				moveModel.SetMiddlePos(new Vector3(transform.position.x, pos.y, pos.z));
			}
		}
	}

	/* Click on the controller and it will normally be mounted on a game object */
	public class ClickController : MonoBehaviour {
		RoleController clickRole; // If you click on a role, the controller that records the object clicked on

		public void SetClickRole(RoleController role) {
			clickRole = role;
		}

		void OnMouseDown() {
			// If the mouse clicks on a ship, move the ship
			if (gameObject.name == "Boat") {
				SingleObject.getInstance().GetMainController().MoveBoat();
			} else {
				// If the object the mouse clicks on is a role, move the object
				SingleObject.getInstance().GetMainController().MoveRole(clickRole);
			}
		}
	}

	public class BoatController {
		// Position of the ship's loading role on the left bank
		private static Vector3 [] leftLoadPos = new Vector3 [] {new Vector3(-3, -0.5F, 0), new Vector3(-2, -0.5F, 0)};
		// Position of the ship's loading role on the right bank
		private static Vector3 [] rightLoadPos =  new Vector3 [] {new Vector3(2, -0.5F, 0), new Vector3(3, -0.5F, 0)};

		private BoatModel boatModel; // Ship Model
		private BoatView boatView; // Ship View
		private MoveController moveController; // Mobile Controller

		public BoatController() {
			// The ship started on the right bank
			boatModel = new BoatModel((int)ShoreSide.Right);
			boatView = new BoatView();
			// Add a mobile controller
			moveController = boatView.AddMoveScript();
			// Add Click Controller
			boatView.AddClickScript();
		}

		/* Initialize ship controller */
		public void InitBoatController() {
			// Initialize the mobile controller first
			moveController.InitMoveController();
			// Get where the ship is
			int side = boatModel.GetSide();
			// On the left, the ship will go back to the right
			if (side == (int)ShoreSide.Left) {
				MoveToOtherSide();
			}
			// Initialize ship model with no passengers
			boatModel.SetRoleOnBoat(new string [2]{"", ""});
		}

		// Get the shore where the ship is located
		public int GetBoatSide() {
			return boatModel.GetSide();
		}

		// Get the ship's game object
		public GameObject GetBoat() {
			return boatView.GetGameObj();
		}

		/* Move the ship to the other side of the shore */
		public void MoveToOtherSide() {
			// Get where the ship is first
			int side = boatModel.GetSide();
			// Move the boat to the other side
			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);
			}
		}

		/* Get the free position over the ship */
		public int GetFreeIndex() {
			string [] roleOnBoat = boatModel.GetRoleOnBoat();
			// Get the free position on the ship in sequence
			if (roleOnBoat[0] == "") {
				return 0;
			} else if (roleOnBoat[1] == "") {
				return 1;
			} else {
				// Return-1 if there is no idle location
				return -1;
			}
		}

		/* Judging if there are no roles on board */
		public bool IsNoRole() {
			string [] roleOnBoat = boatModel.GetRoleOnBoat();
			if (roleOnBoat[0] != "" || roleOnBoat[1] != "") {
				return false;
			} else {
				return true;
			}
		}

		/* Obtain the free position of the ship in the corresponding direction according to the direction of the ship docking */
		public Vector3 GetFreePosition() {
			string [] roleOnBoat = boatModel.GetRoleOnBoat();
			int freeIndex = GetFreeIndex();
			// If there is no free location, go back directly
			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];
			}
		}

		/* Put the character on the ship */
		public void PutRoleOnBoat(string roleName) {
			// Get free position over ship
			int freeIndex = GetFreeIndex();
			// If there is no free location, go back directly
			if (freeIndex < 0) {
				return;
			}
			// Use role names to put roles on ships
			string [] roleOnBoat = boatModel.GetRoleOnBoat();
			roleOnBoat[freeIndex] = roleName;
		}

		/* Leave the character on board */
		public void PutRoleOffBoat(string roleName) {
			string [] roleOnBoat = boatModel.GetRoleOnBoat();
			// If the ship has a role name in its place, leave it empty
			for (int i = 0; i < roleOnBoat.Length; i++) {
				if (roleOnBoat[i] == roleName) {
					roleOnBoat [i] = "";
					break;
				}
			}
		}

		/* Get the number of roles on board */
		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;
		}
	}

	/* Shore controller */
	public class ShoreController {
		private ShoreModel shoreModel; // Shore model
		private ShoreView shoreView; // Shore view

		// The position of the role on the right bank, while the position on the left bank simply multiplies the x value of the coordinates by -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]{"", "", "", "", "", ""});
		}

		/* Get Shoreline */
		public int GetShoreSide() {
			return shoreModel.GetSide();
		}

		/* Get free locations on the shore */
		public int GetFreeIndex() {
			string [] roleOnShore = shoreModel.GetRoleOnShore();
			for (int i = 0; i < roleOnShore.Length; i++) {
				if (roleOnShore[i] == "") {
					return i;
				}
			}
			// Return-1 if there is no idle location
			return -1;
		}

		/* Obtaining the free position on the shore in the corresponding direction based on the direction of the ship's docking */
		public Vector3 GetFreePosition() {
			int freeIndex = GetFreeIndex();
			// If there is no free location, go back directly
			if (freeIndex < 0) {
				return new Vector3(-1, -1, -1);
			}
			Vector3 pos = positions[freeIndex];
			// The x-value of a coordinate multiplied by 1 is the position on the right bank, and -1 gives the position on the left bank.
			pos.x *= shoreModel.GetSide();
			return pos;
		}

		/* Put the character ashore */
		public void PutRoleOnShore(string roleName) {
			// Get free location on shore
			int freeIndex = GetFreeIndex();
			// If there is no free location, go back directly
			if (freeIndex < 0) {
				return;
			}
			// Use role names to shore roles
			string [] roleOnShore = shoreModel.GetRoleOnShore();
			roleOnShore[freeIndex] = roleName;
		}

		/* Leave the character ashore */
		public void PutRoleOffShore(string roleName) {	// 0->priest, 1->devil
			string [] roleOnShore = shoreModel.GetRoleOnShore();
			// If the shore has a role name in its place, leave it empty
			for (int i = 0; i < roleOnShore.Length; i++) {
				if (roleOnShore[i] == roleName) {
					roleOnShore [i] = "";
					break;
				}
			}
		}

		/* Get the number of roles on the shore */
		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;
		}
	}

	/* Role Controller */
	public class RoleController {
		private RoleModel roleModel; // Role Model
		private RoleView roleView; // Role View

		private MoveController moveController; // Mobile Controller
		private ClickController clickController; // Click Controller

		ShoreController shoreController; // The shore controller on the shore where the role is located

		public RoleController(int roleType, string roleName, int number) {
			roleModel = new RoleModel(roleType);
			roleView = new RoleView(roleName, number);
			
			// Add a mobile controller
			moveController = roleView.AddMoveScript();
			// Add a click controller and record the controller of the click object
			clickController = roleView.AddClickScript();
			clickController.SetClickRole(this);
		}

		public void InitRoleController() {
			// Initialize the mobile controller
			moveController.InitMoveController();
			// Get the right-bank controller in the master controller
			shoreController = (SingleObject.getInstance().GetMainController() as MainController).GetRightShore();
			// Place the character on the right bank
			PutRoleOnShore(shoreController);
			SetRolePos(shoreController.GetFreePosition());
			// Information about roles in the right-hand controller is also initialized
			shoreController.PutRoleOnShore(this.GetRoleViewName());
		}

		public ShoreController GetShoreController() {
			return shoreController;
		}

		/* Set the position of the character game object */
		public void SetRolePos(Vector3 pos) {
			roleView.SetPos(pos);
		}

		/* Move role to specified location */
		public void MoveToPosition(Vector3 endPosination) {
			moveController.SetMovePos(endPosination);
		}

		/* Get Role Type */
		public int GetRoleModelType() {
			return roleModel.GetRoleType();
		}

		/* Get the name of the character game object */
		public string GetRoleViewName() {
			return roleView.GetName();
		}

		/* Gets whether the game object is on board the ship */
		public bool IsOnBoat() {
			return roleModel.GetIsOnBoat();
		}

		/* Put the character on the ship */
		public void PutRoleOnBoat(BoatController boatController) {
			// Setup role is not onshore, so there is no onshore controller
			shoreController = null;
			// Set up roles on board
			roleModel.SetIsOnBoat(true);
			// The parent of a character game object is a ship
			roleView.SetRoleParentTrans(boatController.GetBoat().transform);
		}

		/* Put the character ashore */
		public void PutRoleOnShore(ShoreController shoreController) {
			// Set up shore controllers with roles on the appropriate shore
			this.shoreController = shoreController;
			// Set role not on board
			roleModel.SetIsOnBoat(false);
			// Sets the parent object of a character game object to be none
			roleView.SetRoleParentTrans(null);
		}
	}

	/* main controller */
	public class MainController : MonoBehaviour {

		private BoatController boat; // Ship Controller
		private ShoreController leftShore; // Left bank controller
		private ShoreController rightShore; // Right bank controller
		private RoleController [] roles; // Controller for all roles
		private RiverView riverView; // River view
		private FunctionView functionView; // Functional view, including alert boxes, game information, etc.

		private int gameState = (int)GameState.Playing; // Game status, 0 means the game is in progress, 1 means the game has failed, 2 means the game has succeeded

		void Awake() {
			// Set up only one master controller in a single object
			SingleObject instance = SingleObject.getInstance();
			instance.SetMainController(this);
			// Show Game View
			ShowView();
		}

		/* Initialize the game view by creating a controller */
		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;
		}

		/* Create controllers for each role and initialize views */
		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());
			}
		}

		/* Initialize the game by initializing the controller and view */
		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;
		}

		/* Return different hint box contents depending on the state of the game */
		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 "";
			}
		}

		/* Move the ship through the ship controller */
		public void MoveBoat() {
			// If the game is not in progress, do not move
			if (gameState != (int)GameState.Playing) {
				return;
			}
			// Cannot sail if there is no role on board
			if (boat.IsNoRole()) {
				return;
			} else {
				// Otherwise drive the ship directly to the other side
				boat.MoveToOtherSide();
			}
			// Check Game Status
			gameState = CheckGameState();
			// Show corresponding prompt
			functionView.SetTipContent(StateToTip(gameState));
		}

		/* Moving roles through role controllers */
		public void MoveRole(RoleController role) {
			// If the game is not in progress, do not move
			if (gameState != (int)GameState.Playing) {
				return;
			}
			// If the character is on a ship, place the character on the shore
			if (role.IsOnBoat()) {
				// Get the shore where the ship is located
				ShoreController boatShore;
				if (boat.GetBoatSide() == (int)ShoreSide.Left) {
					boatShore = leftShore;
				} else {
					boatShore = rightShore;
				}

				/* Set up ship and shore and role controllers to put roles ashore */
				role.MoveToPosition(boatShore.GetFreePosition());
				boat.PutRoleOffBoat(role.GetRoleViewName());
				role.PutRoleOnShore(boatShore);
				boatShore.PutRoleOnShore(role.GetRoleViewName());
			} else {
				// Otherwise the character is ashore, to put the character on the ship, first get the controller on the shore where the character is located
				ShoreController boatShore = role.GetShoreController();

				// Return directly if there is no position on the ship or if the ship and the object are on a different shore
				if (boat.GetFreeIndex() == -1 || boatShore.GetShoreSide() != boat.GetBoatSide()) {
					return;
				}

				/* Set up ship and shore and role controllers to put roles on board */
				role.MoveToPosition(boat.GetFreePosition());
				boat.PutRoleOnBoat(role.GetRoleViewName());
				role.PutRoleOnBoat(boat);
				boatShore.PutRoleOffShore(role.GetRoleViewName());
			}
			// Check Game Status
			gameState = CheckGameState();
			// Show corresponding prompt
			functionView.SetTipContent(StateToTip(gameState));
		}

		/* Check Game Status */
		public int CheckGameState() {
			// Initialize the number of clergy and demons on the left and right sides to be 0
			int leftPriest = 0, rightPriest = 0;
			int leftDevil = 0, rightDevil = 0;

			// Get arrays of clergy and demons on the left and right banks and on board
			int [] leftShoreCount = leftShore.GetRoleCountOnShore();
			int [] rightShoreCount = rightShore.GetRoleCountOnShore();
			int [] boatCount = boat.GetRoleCountOnBoat();

			// If the ship is on the left, then the number of clergy and demons on the left side is the number on the left side plus the number in the ship
			if (boat.GetBoatSide() == (int)ShoreSide.Left) {
				leftPriest = leftShoreCount[0] + boatCount[0];
				leftDevil = leftShoreCount[1] + boatCount[1];
				rightPriest = rightShoreCount[0];
				rightDevil = rightShoreCount[1]; 
			} else {
				// If the ship is on the right side, the number of clergy and demons on the right side is the number on the right side plus the number in the ship
				leftPriest = leftShoreCount[0];
				leftDevil = leftShoreCount[1];
				rightPriest = rightShoreCount[0] + boatCount[0];
				rightDevil = rightShoreCount[1] + boatCount[1]; 
			}

			// If the number of clergy plus devils on the left equals 6 and all the devils go ashore, the game is successful
			if (leftPriest + leftDevil == 6 && leftShoreCount[1] == 3) {
				return (int)GameState.Win;
			} else if (leftPriest < leftDevil && leftPriest > 0) {
				// If the number of clergy on either side is less than the number of devils and there are clergy on either side, the game fails
				return (int)GameState.Lose;
			} else if (rightPriest < rightDevil && rightPriest > 0) {
				return (int)GameState.Lose;
			} else {
				// Otherwise the game is in progress
				return (int)GameState.Playing;
			}
		}
	}

	/* Single object with only one master control class */
	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;
		}
	}
}

Finally, in the main file, the main controller is called to play, and a basic MVC mode is implemented:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PriestsAndDevils {
	public class Main : MonoBehaviour {
        void Start() {
            // Create master controller
            MainController mainController = gameObject.AddComponent<MainController>() as MainController;
        }
    }
}

Summary: In the implementation of MVC mode, you can first draw the final effect, create the corresponding view class, analyze by the view class, design the corresponding model class and controller class, basically without logic, you can directly implement the corresponding view or logical control in the main control class, and finally realize the development of MVC mode.

Game Screenshot:

Game in progress:

The game failed:

Game success:

Tags: C# Unity3d mvc

Posted on Sat, 09 Oct 2021 13:59:55 -0400 by bsteimel