#视频链接牧师与恶魔
#github链接https://github.com/someoneLikeC/PriADev
游戏介绍
游戏名称:牧师与恶魔
游戏规则介绍:有三个牧师正在押送三个恶魔,现在他们到了一条河前,河面上有一艘船,船上只能承载两个人。我们要控制牧师将恶魔押送过河。值得注意的是:当河的一岸牧师的数量少于恶魔时,恶魔将杀死牧师,押送任务就失败了,船上必须至少有一个人才能移动。聪明的你需要想办法帮助牧师成功完成此次押送任务。
规则表
当前状态 | 玩家操作 | 结果 |
---|---|---|
牧师或恶魔在岸边,船上有空位 | 玩家点击靠近船一侧岸上的相应的恶魔按钮或牧师 | 相应的恶魔或牧师上船 |
牧师或恶魔在船上 | 玩家点击船上的恶魔或牧师对于的按钮 | 恶魔或牧师上靠近船的岸 |
其中一侧的恶魔的数量大于牧师的数量 | —— | 显示玩家输 |
恶魔和牧师全部到河边另一侧 | —— | 显示玩家赢 |
船上有人且船未移动 | 玩家点击开船按钮 | 船开往另一侧 |
在开始实现游戏之前先创建一个Resources文件夹,再在其中创建三个文件夹,Prefabs,Scripts,Materials
游戏对象
河
形状:Cube
名称:River
缩放参数:X:10; Y:1; Z:6
河岸
形状:Cube
名称:Bank
缩放参数:X:10; Y:1; Z:2
牧师(不同牧师只是颜色不同)
形状:Cube
名称:Priest
缩放参数:X:0.5; Y:1; Z:0.5
恶魔(不同恶魔只是颜色不同)
形状:Capsule
名称:Devil
缩放参数:X:0.5; Y:0.5; Z:0.5
船
形状:Cube
名称:Boat
缩放参数:X:0.5; Y:0.25; Z:1.5
将所有对象都做成预制体。创建步骤如下(以创建河为例):
1. 创建对象:
在红框区域鼠标右键点击,选择立方体
创建完成后,在检查器中调整他的位置与大小。
将方块重命名为River
2. 给对象加颜色
在红框处点击鼠标右键
在创建中选择材质,命名为riverColor
在检查器中点击箭头所指位置,在取色框内选择自己喜欢的颜色
将材质通过点击鼠标左键不松手拖动到River上即可
3. 创建对象预制体(就是提前制作好的东西,需要的时候可以直接用)
将River拖到箭头所指的位置即可
完成后将场景中的River删除
设计过程
UML图
具体实现
controller
SSDirector.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSDirector : System.Object
{
// singlton instance
private static SSDirector _instance;
public ISceneController currentSceneController { get; set; }
// https://blog.csdn.net/qiaoquan3/article/details/51339242
public bool Paused { get { return Time.timeScale == 0; } set { Time.timeScale = value ? 0 : 1; } }
// get instance anytime anywhare!
public static SSDirector getInstance()
{
if (_instance == null)
{
_instance = new SSDirector();
}
return _instance;
}
public int getFPS()
{
return Application.targetFrameRate;
}
public void setFPS(int fps)
{
Application.targetFrameRate = fps;
}
public void NextScene()
{
Debug.Log("Waiting next Scene now...");
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
//UnityEditor.EditorApplication.Exit(0);
#else
Application.Quit();
#endif
}
}
ISceneController.cs
using System;
/// <summary>
/// Abstact Scene Controller. Interface between scene controllers and the director
/// </summary>
public interface ISceneController
{
void LoadResources();
Role[] getRole();
void Reset();
}
FirstController.cs
using UnityEngine;
public class FirstController : MonoBehaviour,ISceneController
{
public River river;
public Boat boat;
public Bank[] banks = new Bank[2];
public Role[] devilsAndpriests = new Role[6];
void Awake()
{
SSDirector director = SSDirector.getInstance();
director.setFPS(60);
director.currentSceneController = this;
director.currentSceneController.LoadResources();
}
// loading resources for the first scence
public void LoadResources()
{
river = new River();
boat = new Boat();
for (int i = 0; i < 2; i++)
{
banks[i] = new Bank(i);
banks[i].SetName("bank" + i);
}
for(int i = 0; i < 3; i++)
{
devilsAndpriests[i] = new Role("Priest", new Vector3(2 + i, 0.5f, -3.5f));
devilsAndpriests[i].SetName("priest" + i);
devilsAndpriests[i].SetPosition(devilsAndpriests[i].posRight);
}
for (int i = 0; i < 3; i++)
{
devilsAndpriests[i + 3] = new Role("Devil", new Vector3(-4 + i, 0.5f, -3.5f));
devilsAndpriests[i + 3].SetName("devil" + i);
devilsAndpriests[i + 3].SetPosition(devilsAndpriests[i + 3].posRight);
}
}
public Role[] getRole()
{
return devilsAndpriests;
}
public void Reset()
{
foreach(Role role in devilsAndpriests)
{
Destroy(role.character);
}
foreach(Bank bank in banks)
{
Destroy(bank.bank);
}
Destroy(boat.thisboat);
Destroy(river.river);
LoadResources();
}
}
model
Role.cs
using Unity.VisualScripting;
using UnityEngine;
public class Role
{
public bool isOnBoat;
public bool isLeft;
public GameObject character;
public Vector3 posRight;
public Vector3 posLeft;
public Role(string name, Vector3 v)
{
character = Object.Instantiate(Resources.Load("Prefabs/" + name, typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
isOnBoat = false;
isLeft = false;
posRight = v;
posLeft = new Vector3(v.x, v.y, -v.z);
}
public void SetName(string name)
{
character.name = name;
}
public void SetPosition(Vector3 pos)
{
character.transform.position = pos;
}
public void MoveTo(Boat boat, Bank[] banks)
{
if (isOnBoat)
{
if (!isLeft)
{
if(character.transform.position == boat.pos1)
{
boat.pos1Full = false;
}else if(character.transform.position == boat.pos2)
{
boat.pos2Full = false;
}
character.transform.position = posRight;
character.transform.SetParent(null);
isOnBoat = false;
boat.peopleOnboat--;
if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
{
boat.P--;
banks[0].Pnum++;
}
else
{
boat.D--;
banks[0].Dnum++;
}
}
else
{
if (character.transform.position == boat.pos1)
{
boat.pos1Full = false;
}
else if (character.transform.position == boat.pos2)
{
boat.pos2Full = false;
}
character.transform.position = posLeft;
character.transform.SetParent(null);
isOnBoat = false;
boat.peopleOnboat--;
if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
{
boat.P--;
banks[1].Pnum++;
}
else
{
boat.D--;
banks[1].Dnum++;
}
}
}
else
{
if(boat.isLeft == isLeft)
{
if (!boat.pos1Full)
{
character.transform.position = boat.pos1;
boat.pos1Full = true;
character.transform.SetParent(boat.thisboat.transform);
isOnBoat = true;
boat.peopleOnboat++;
if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
{
boat.P++;
if (!isLeft)
{
banks[0].Pnum--;
}
else
{
banks[1].Pnum--;
}
}
else
{
boat.D++;
if (!isLeft)
{
banks[0].Dnum--;
}
else
{
banks[1].Dnum--;
}
}
}
else if (!boat.pos2Full)
{
character.transform.position = boat.pos2;
boat.pos2Full = true;
character.transform.SetParent(boat.thisboat.transform);
isOnBoat = true;
boat.peopleOnboat++;
if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
{
boat.P++;
if (!isLeft)
{
banks[0].Pnum--;
}
else
{
banks[1].Pnum--;
}
}
else
{
boat.D++;
if (!isLeft)
{
banks[0].Dnum--;
}
else
{
banks[1].Dnum--;
}
}
}
}
}
}
}
River.cs
using UnityEngine;
public class River
{
public GameObject river;
public River()
{
river = Object.Instantiate(Resources.Load("Prefabs/River", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
river.name = "river";
}
}
Boat.cs
using UnityEngine;
public class Boat
{
public int peopleOnboat;
public int P;
public int D;
public Vector3 pos1;
public Vector3 pos2;
public bool pos1Full;
public bool pos2Full;
public GameObject thisboat;
public bool isLeft;
public Vector3 posLeft;
public Vector3 posRight;
public Boat()
{
peopleOnboat = 0;
thisboat = Object.Instantiate(Resources.Load("Prefabs/Boat", typeof(GameObject)), new Vector3(0, 0.5f, -2.25f), Quaternion.identity, null) as GameObject;
thisboat.name = "boat";
pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
pos1Full = false;
pos2Full = false;
isLeft = false;
posLeft = new Vector3(0, 0.5f, 2.25f);
posRight = new Vector3(0, 0.5f, -2.25f);
}
public void Move(Bank[] banks, UserGUI userGUI)
{
if (isLeft)
{
thisboat.transform.position = posRight;
pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
isLeft = !isLeft;
foreach(Transform child in thisboat.transform)
{
Role[] roles = SSDirector.getInstance().currentSceneController.getRole();
for (int i = 0; i < roles.Length; i++)
{
if (roles[i].character.transform == child)
{
roles[i].isLeft = !roles[i].isLeft;
}
}
}
if (banks[1].Pnum + P == 3 && banks[1].Dnum + D == 3)
{
userGUI.Win();
}
else if ((banks[0].Dnum + D > banks[0].Pnum + P && banks[0].Pnum != 0) || (banks[1].Dnum + D > banks[1].Pnum + P && banks[1].Pnum != 0))
{
userGUI.Lose();
}
}
else
{
thisboat.transform.position = posLeft;
pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
isLeft = !isLeft;
foreach (Transform child in thisboat.transform)
{
Role[] roles = SSDirector.getInstance().currentSceneController.getRole();
for (int i = 0; i < roles.Length; i++)
{
if (roles[i].character.transform == child)
{
roles[i].isLeft = !roles[i].isLeft;
}
}
}
if (banks[1].Pnum + P == 3 && banks[1].Dnum + D == 3)
{
userGUI.Win();
}
else if ((banks[0].Dnum > banks[0].Pnum && banks[0].Pnum != 0) || (banks[1].Dnum > banks[1].Pnum && banks[1].Pnum != 0))
{
userGUI.Lose();
}
}
}
}
Bank.cs
using UnityEngine;
public class Bank
{
public int Pnum;
public int Dnum;
public bool isLeft;
public GameObject bank;
public Bank(int id)
{
bank = Object.Instantiate(Resources.Load("Prefabs/Bank", typeof(GameObject)), new Vector3(0, 0, 4.0f * (id - 0.5f) * 2), Quaternion.identity, null) as GameObject;
if (id == 0)
{
Pnum = 3;
Dnum = 3;
isLeft = false;
}
else
{
Pnum = 0;
Dnum = 0;
isLeft = true;
}
}
public void SetName(string name)
{
bank.name = name;
}
}
view
IUserAction
public interface IUserAction
{
void MoveRole(Role role, Boat boat, Bank[] banks);
void CrossRiver(Boat boat, Bank[] banks);
void Lose();
void Win();
void Reset();
}
UserGUI
using UnityEngine;
public class UserGUI : MonoBehaviour,IUserAction
{
private int state;
public UserGUI()
{
state = -1;
}
public void Win()
{
state = 0;
}
public void Lose()
{
state = 1;
}
public void Reset()
{
state = -1;
}
public void MoveRole(Role role,Boat boat, Bank[] banks)
{
role.MoveTo(boat,banks);
}
public void CrossRiver(Boat boat, Bank[] banks)
{
boat.Move(banks,this);
}
private void OnGUI()
{
if (GUI.Button(new Rect(35, 25, 70, 30), "重新开始")) {
SSDirector.getInstance().currentSceneController.Reset();
Reset();
}
if(state == -1)
{
for (int i = 0; i < GetComponent<FirstController>().devilsAndpriests.Length; i++)
{
if (i < 3)
{
if (GUI.Button(new Rect(20, 60 + i * 35, 100, 30), "牧师" + i + "上/下船"))
{
MoveRole(GetComponent<FirstController>().devilsAndpriests[i], GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
}
}
else
{
if (GUI.Button(new Rect(20, 60 + i * 35, 100, 30), "恶魔" + (i - 3) + "上/下船"))
{
MoveRole(GetComponent<FirstController>().devilsAndpriests[i], GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
}
}
}
if(GetComponent<FirstController>().boat.peopleOnboat > 0)
{
if (GUI.Button(new Rect(35, 270, 70, 30), "开船")) CrossRiver(GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
}
}else if(state == 0)
{
GUI.Box(new Rect(375, 150, 100, 100), "你赢了");
}else if(state == 1)
{
GUI.Box(new Rect(375, 150, 100, 100), "你输了");
}
}
}