牧师与魔鬼游戏简介:
一个牧师与魔鬼的游戏,3个牧师与3个魔鬼都在河的一边,他们都想要度过一条河,但是只有一条船而且这条船一次只能搭载两个人,
而且每次都需要有一个人把船从河的一边划到另一边,你可以点击他们把它们移动,点击go按钮可以移动船到另一边,如果任一边魔鬼的数
量多于牧师的数量,游戏就结束了。
整个游戏的源代码在最下面,想要整个代码的可以在下面找
首先,先上一张最终的结果图,白球代表牧师,红色的正方形代表魔鬼,两个比较大的长方形代表岸边,剩下的小长方形代表小船
为了起到游戏原来的效果,下面是一些提前的设置,把3D物体投影到x-y平面,可以起到2D的效果
把摄像机的position,Background,Projection,Size设置成如下
把FristSceneController.cs和UserGUI.cs作为组件挂到摄像机或一个空对象上
文件总共包括六个文件,如下:
Director.cs
FristSceneController.cs
On_Off.cs
UserGUI.cs
IUserAction.cs
ISceneController.cs
UML图:
好了,下面就开始写游戏代码了:
public enum GameState { WIN, FAILED, NOT_ENDED } //表示游戏的状态 public enum BoatState { MOVING, STOPLEFT,STOPRIGHT} //表示船的状态 public GameObject Shore_l; public GameObject Shore_r; public GameObject boat; public Dictionary<int, GameObject> On_Boat = new Dictionary<int, GameObject>(); public Dictionary<int, GameObject> On_Shore_r = new Dictionary<int, GameObject>(); public Dictionary<int, GameObject> On_Shore_l = new Dictionary<int, GameObject>();用三个字典来组织人物,在船上的人物会被加入On_Boat,其它也如此
资源的加载,包括3个牧师和3个恶魔,2个岸边和一个小船,以及它们初始位置的设置,这里是直接用代码生成的
这里对牧师和魔鬼做了一个编号,固定了它们在岸边的位置以及判断它们是在船上还是在岸边,牧师的编号是0~2,恶魔的编号是3~5,
public void GenGameObjects() { Shore_l = GameObject.CreatePrimitive(PrimitiveType.Cube); Shore_l.name = "Shore_l"; Shore_l.transform.localScale = new Vector3(10, 2, 1); Shore_l.transform.position = new Vector3(-17, -9, 0); Shore_r = Instantiate<GameObject>(Shore_l, new Vector3(17, -9, 0), Quaternion.identity); Shore_r.name = "Shore_r"; boat = GameObject.CreatePrimitive(PrimitiveType.Cube); ; boat.transform.localScale = new Vector3(3, 1, 1); boat.transform.position = new Vector3(10.4f, -9.5f, 0); boat.name = "boat"; GameObject temp_priest = GameObject.CreatePrimitive(PrimitiveType.Sphere); temp_priest.transform.localScale = new Vector3(1, 1, 1); temp_priest.AddComponent<On_Off>(); //为牧师添加上下船的组件 GameObject temp_devil = GameObject.CreatePrimitive(PrimitiveType.Cube); temp_devil.transform.localScale = new Vector3(1, 1, 1); temp_devil.AddComponent<On_Off>(); //为魔鬼添加上下船的组件 for (int i = 0; i < 3; i++) { On_Shore_r.Add(i, Instantiate<GameObject>(temp_priest, new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity)); On_Shore_r[i].name = i.ToString(); } for (int i = 3; i < 6; i++) { GameObject tmp = Instantiate<GameObject>(temp_devil, new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity); tmp.name = i.ToString(); tmp.GetComponent<Renderer>().material.color = Color.red; On_Shore_r.Add(i, tmp); } boat_capicity = 2; //限制船最多有2个人 b_state = BoatState.STOPLEFT; Destroy(temp_devil); Destroy(temp_priest); }接下来来写魔鬼与牧师上下船的脚本,这是可以实现点击人物使其移动,主要用了OnMouseDown事件,
如果它们上船,就把它们的编号加6,如果下船,就减6
enum Pos { ON_BOAT, ON_SHORE} //用来表示人物的位置 private void OnMouseDown() { if (firstSceneControl.game_state == GameState.NOT_ENDED) { if (firstSceneControl.b_state == FirstSceneControl.BoatState.MOVING) return; int id = Convert.ToInt32(this.name); if (firstSceneControl.b_state == FirstSceneControl.BoatState.STOPRIGHT) { if (firstSceneControl.On_Shore_r.ContainsKey(id)) { if (find_Pos(id) == Pos.ON_SHORE && firstSceneControl.boat_capicity != 0) //find_Pos函数是根据人物的key来确定人物的位置,在船上或岸上 { firstSceneControl.On_Boat.Add(id + 6, firstSceneControl.On_Shore_r[id]); firstSceneControl.On_Shore_r.Remove(id); this.name = (id + 6).ToString(); this.transform.parent = firstSceneControl.boat.transform; firstSceneControl.boat_capicity--; } } if (find_Pos(id) == Pos.ON_BOAT) { firstSceneControl.On_Shore_r.Add(id - 6, firstSceneControl.On_Boat[id]); firstSceneControl.On_Boat.Remove(id); this.name = (id - 6).ToString(); this.transform.parent = null; firstSceneControl.boat_capicity++; } } if (firstSceneControl.b_state == FirstSceneControl.BoatState.STOPLEFT) { if (find_Pos(id) == Pos.ON_SHORE && firstSceneControl.boat_capicity != 0) { if (firstSceneControl.On_Shore_l.ContainsKey(id)) { firstSceneControl.On_Boat.Add(id + 6, firstSceneControl.On_Shore_l[id]); firstSceneControl.On_Shore_l.Remove(id); this.name = (id + 6).ToString(); this.transform.parent = firstSceneControl.boat.transform; firstSceneControl.boat_capicity--; } } if (find_Pos(id) == Pos.ON_BOAT) { firstSceneControl.On_Shore_l.Add(id - 6, firstSceneControl.On_Boat[id]); firstSceneControl.On_Boat.Remove(id); this.name = (id - 6).ToString(); this.transform.parent = null; firstSceneControl.boat_capicity++; } } } } 接下来是船移动的函数,这里实现的比较简陋,是直接改变船的位置 public void MoveBoat() { if (On_Boat.Count != 0) { if (b_state == BoatState.STOPLEFT) { boat.transform.position = new Vector3(10.3f, -9.5f, 0); } if (b_state == BoatState.STOPRIGHT) { boat.transform.position = new Vector3(-10.3f, -9.5f, 0); } } } 最后,说下检查游戏状态的函数 GameState check() { if (On_Shore_l.Count == 6) { return GameState.WIN; } else if (b_state == BoatState.STOPLEFT) { if (get_num(On_Boat, 1) + get_num(On_Shore_l, 1) != 0 && get_num(On_Boat, 1) + get_num(On_Shore_l, 1) < (get_num(On_Boat, -1) + get_num(On_Shore_l, -1))) //get_num是用来获取牧师或魔鬼的数量 { //第一个参数是地点,第二个参数1表示 //牧师,否则是魔鬼 return GameState.FAILED; } if(get_num(On_Shore_r, 1) != 0 && get_num(On_Shore_r, 1) < get_num(On_Shore_r, -1)) { return GameState.FAILED; } } else if (b_state == BoatState.STOPRIGHT) { if (get_num(On_Boat, 1) + get_num(On_Shore_r, 1) != 0 && get_num(On_Boat, 1) + get_num(On_Shore_r, 1) < (get_num(On_Boat, -1) + get_num(On_Shore_r, -1))) { return GameState.FAILED; } if (get_num(On_Shore_l, 1) != 0 && get_num(On_Shore_l, 1) < get_num(On_Shore_r, -1)) { return GameState.FAILED; } } return GameState.NOT_ENDED; }
整个游戏的主要内容就完了,下面是全部文件的源代码:
Director.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Director : System.Object { public ISceneControl currentSceneControl { get; set; } private static Director director; private Director() { } public static Director getInstance() { if (director == null) { director = new Director(); } return director; } }FristSceneController.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FirstSceneControl : MonoBehaviour, ISceneControl, IUserAction { // Use this for initialization //public enum GameState { WIN, FAILED, NOT_ENDED } public enum BoatState { MOVING, STOPLEFT,STOPRIGHT} public GameObject Shore_l; public GameObject Shore_r; public GameObject boat; public Dictionary<int, GameObject> On_Boat = new Dictionary<int, GameObject>(); public Dictionary<int, GameObject> On_Shore_r = new Dictionary<int, GameObject>(); public Dictionary<int, GameObject> On_Shore_l = new Dictionary<int, GameObject>(); //public Vector3 Boat_Left = new Vector3(-10.3f, -9.5f, 0); //public Vector3 Boat_Right = new Vector3(10.3f, -9.5f, 0); //public Vector3 Shore_Left = new Vector3(-12.5f, -7.5f, 0); //public Vector3 Shore_Right = new Vector3(19.5f, -7.5f, 0); public GameState game_state; float gab = 1.5f; public int boat_capicity; public BoatState b_state; void Awake () { Director director = Director.getInstance(); director.currentSceneControl = this; director.currentSceneControl.GenGameObjects(); } public void GenGameObjects() { Shore_l = GameObject.CreatePrimitive(PrimitiveType.Cube); Shore_l.name = "Shore_l"; Shore_l.transform.localScale = new Vector3(10, 2, 1); Shore_l.transform.position = new Vector3(-17, -9, 0); Shore_r = Instantiate<GameObject>(Shore_l, new Vector3(17, -9, 0), Quaternion.identity); Shore_r.name = "Shore_r"; boat = GameObject.CreatePrimitive(PrimitiveType.Cube); ; boat.transform.localScale = new Vector3(3, 1, 1); boat.transform.position = new Vector3(10.4f, -9.5f, 0); boat.name = "boat"; GameObject temp_priest = GameObject.CreatePrimitive(PrimitiveType.Sphere); temp_priest.transform.localScale = new Vector3(1, 1, 1); temp_priest.AddComponent<On_Off>(); GameObject temp_devil = GameObject.CreatePrimitive(PrimitiveType.Cube); temp_devil.transform.localScale = new Vector3(1, 1, 1); temp_devil.AddComponent<On_Off>(); //Shore_l = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Shore"), new Vector3(-17, -9, 0), Quaternion.identity); //Shore_r = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Shore"), new Vector3(17, -9, 0), Quaternion.identity); //boat = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/boat"), new Vector3(10.3f, -9.5f, 0), Quaternion.identity); for (int i = 0; i < 3; i++) { // On_Shore_r.Add(i, Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Priests"), new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity)); On_Shore_r.Add(i, Instantiate<GameObject>(temp_priest, new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity)); On_Shore_r[i].name = i.ToString(); } for (int i = 3; i < 6; i++) { //GameObject tmp = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Devils"), new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity); GameObject tmp = Instantiate<GameObject>(temp_devil, new Vector3(12.5f + i * gab, -7.5f, 0), Quaternion.identity); tmp.name = i.ToString(); tmp.GetComponent<Renderer>().material.color = Color.red; On_Shore_r.Add(i, tmp); } boat_capicity = 2; b_state = BoatState.STOPLEFT; Destroy(temp_devil); Destroy(temp_priest); } private void Update() { game_state = check(); if (game_state == GameState.NOT_ENDED) { if (boat.transform.position.x < 10.2f && boat.transform.position.x > -10.2f) { b_state = BoatState.MOVING; } else if (boat.transform.position.x > 10.2f) { b_state = BoatState.STOPRIGHT; } else { b_state = BoatState.STOPLEFT; } for (int i = 0; i < 6; i++) { if (On_Shore_l.ContainsKey(i)) On_Shore_l[i].transform.position = new Vector3(-12.5f - i * gab, -7.5f, 0); if (On_Shore_r.ContainsKey(i)) On_Shore_r[i].transform.position = new Vector3(12.5f + i * gab, -7.5f, 0); } int signed = 1; for (int i = 6; i < 12; i++) { if (On_Boat.ContainsKey(i)) { On_Boat[i].transform.localPosition = new Vector3(signed * 0.3f, 1, 0); signed = -signed; } } } } public void MoveBoat() { if (On_Boat.Count != 0) { if (b_state == BoatState.STOPLEFT) { //Debug.Log("left"); //boat.transform.position = new Vector3(10.3f, -9.5f, 0); boat.transform.position = new Vector3(10.3f, -9.5f, 0); //Vector3.MoveTowards(boat.transform.position, new Vector3(10.3f, -9.5f, 0), 1 * Time.deltaTime); } if (b_state == BoatState.STOPRIGHT) { // Debug.Log("right"); boat.transform.position = new Vector3(-10.3f, -9.5f, 0); //Vector3.MoveTowards(boat.transform.position, new Vector3(-10.3f, -9.5f, 0), 1 * Time.deltaTime); } } } public void GameOver() { GUI.color = Color.red; GUI.Label(new Rect(700, 300, 400, 400), "GAMEOVER"); } public int get_num(Dictionary<int, GameObject> dict, int ch) { var keys = dict.Keys; int d_num = 0; int p_num = 0; foreach(int i in keys) { if (i < 3 || (i >= 6 && i <= 8)) { p_num++; } else { d_num++; } } return (ch == 1 ? p_num : d_num); } GameState check() { if (On_Shore_l.Count == 6) { return GameState.WIN; } else if (b_state == BoatState.STOPLEFT) { if (get_num(On_Boat, 1) + get_num(On_Shore_l, 1) != 0 && get_num(On_Boat, 1) + get_num(On_Shore_l, 1) < (get_num(On_Boat, -1) + get_num(On_Shore_l, -1))) { return GameState.FAILED; } if(get_num(On_Shore_r, 1) != 0 && get_num(On_Shore_r, 1) < get_num(On_Shore_r, -1)) { return GameState.FAILED; } } else if (b_state == BoatState.STOPRIGHT) { if (get_num(On_Boat, 1) + get_num(On_Shore_r, 1) != 0 && get_num(On_Boat, 1) + get_num(On_Shore_r, 1) < (get_num(On_Boat, -1) + get_num(On_Shore_r, -1))) { return GameState.FAILED; } if (get_num(On_Shore_l, 1) != 0 && get_num(On_Shore_l, 1) < get_num(On_Shore_r, -1)) { return GameState.FAILED; } } return GameState.NOT_ENDED; } public GameState getGameState() { return game_state; } } On_Off.cs using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class On_Off : MonoBehaviour { // Use this for initialization private FirstSceneControl firstSceneControl; enum Pos { ON_BOAT, ON_SHORE} Pos find_Pos(int id) { if (id >= 6) return Pos.ON_BOAT; return Pos.ON_SHORE; } void Start() { firstSceneControl = (FirstSceneControl)Director.getInstance().currentSceneControl; } private void OnMouseDown() { if (firstSceneControl.game_state == GameState.NOT_ENDED) { if (firstSceneControl.b_state == FirstSceneControl.BoatState.MOVING) return; // firstSceneControl.boat_capicity--; // this.transform.parent = firstSceneControl.boat.transform; int id = Convert.ToInt32(this.name); if (firstSceneControl.b_state == FirstSceneControl.BoatState.STOPRIGHT) { if (firstSceneControl.On_Shore_r.ContainsKey(id)) { if (find_Pos(id) == Pos.ON_SHORE && firstSceneControl.boat_capicity != 0) { firstSceneControl.On_Boat.Add(id + 6, firstSceneControl.On_Shore_r[id]); firstSceneControl.On_Shore_r.Remove(id); this.name = (id + 6).ToString(); this.transform.parent = firstSceneControl.boat.transform; firstSceneControl.boat_capicity--; } } if (find_Pos(id) == Pos.ON_BOAT) { firstSceneControl.On_Shore_r.Add(id - 6, firstSceneControl.On_Boat[id]); firstSceneControl.On_Boat.Remove(id); this.name = (id - 6).ToString(); this.transform.parent = null; firstSceneControl.boat_capicity++; } } if (firstSceneControl.b_state == FirstSceneControl.BoatState.STOPLEFT) { if (find_Pos(id) == Pos.ON_SHORE && firstSceneControl.boat_capicity != 0) { if (firstSceneControl.On_Shore_l.ContainsKey(id)) { firstSceneControl.On_Boat.Add(id + 6, firstSceneControl.On_Shore_l[id]); firstSceneControl.On_Shore_l.Remove(id); this.name = (id + 6).ToString(); this.transform.parent = firstSceneControl.boat.transform; firstSceneControl.boat_capicity--; } } if (find_Pos(id) == Pos.ON_BOAT) { firstSceneControl.On_Shore_l.Add(id - 6, firstSceneControl.On_Boat[id]); firstSceneControl.On_Boat.Remove(id); this.name = (id - 6).ToString(); this.transform.parent = null; firstSceneControl.boat_capicity++; } } } } }UserGUI.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UserGUI : MonoBehaviour { private IUserAction action; // Use this for initialization void Start () { action = Director.getInstance().currentSceneControl as IUserAction; } private void OnGUI() { if (GUI.Button(new Rect(700, 100, 90, 90), "GO") && action.getGameState() == GameState.NOT_ENDED) { action.MoveBoat(); } if (action.getGameState() == GameState.WIN) { GUI.Label(new Rect(700, 300, 400, 400), "you win"); GUI.color = Color.red; } if ((action.getGameState() == GameState.FAILED)) { action.GameOver(); } } }IUserAction.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum GameState { WIN, FAILED, NOT_ENDED } public interface IUserAction { void MoveBoat(); void GameOver(); GameState getGameState(); }ISceneController.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public interface ISceneControl { void GenGameObjects(); }