牧师与魔鬼游戏简介:
一个牧师与魔鬼的游戏,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);
}
如果它们上船,就把它们的编号加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();
}