牧师和魔鬼游戏是一款益智类游戏,游戏的目标是将3个牧师和3个魔鬼从河的一端安全地送到河的另一端。在运送过程中,船可以搭载两个人,而且必须有一人掌船。无论何时,只要河一边的魔鬼数量多于牧师的数量,游戏就会以失败结束。想玩玩的话请走传送门:Priests and Devils
先上个成品草图:
游戏需要的对象:
游戏角色:3个牧师、3个魔鬼
游戏场景:2个河岸、1艘小船
游戏的架构:
UserInterface用来创建GUI对象接受玩家动作,处理GUI事件,使用 IUserActions 接口控制游戏。
SceneController是单实例对象,用来处理对象间通信和实现 IUserActions 接口。
BaseCode用来保存游戏名称和游戏简介,它注册在 SceneController 中。
GenGameObject用来创建游戏对象和处理对象运动,它也注册在 SceneController 中。IUserActions 接口通过与 GenGameObject 互动完成游戏逻辑。
想看完整的代码请直接跳至结尾~
一、新建一个3d游戏项目,建立 BaseCode 脚本,并挂载到主摄像机。
在根目录 Assets 下创建 Scripts 文件夹,在 Scripts 文件夹下创建BaseCode 脚本:
在 BaseCode 脚本里面声明一个新的命名空间 Com.Mygame,并把单实例对象 GameSceneController 定义其中。这样的话,其它脚本要使用 GameSceneController 只需要在脚本开头添加 “using Com.Mygame” 就可以使用对象了,同时命名空间也将我们自己的类和系统类分别开来。BaseCode 脚本的代码如下:
using UnityEngine;
using System.Collections;
using Com.Mygame;
namespace Com.Mygame {
public class GameSceneController: System.Object {
private static GameSceneController _instance;
private BaseCode _base_code;
public static GameSceneController GetInstance() {
if (null == _instance) {
_instance = new GameSceneController();
}
return _instance;
}
public BaseCode getBaseCode() {
return _base_code;
}
internal void setBaseCode(BaseCode bc) {
if (null == _base_code) {
_base_code = bc;
}
}
}
}
public class BaseCode : MonoBehaviour {
public string gameName;
public string gameRule;
void Start () {
GameSceneController my = GameSceneController.GetInstance();
my.setBaseCode(this);
}
}
所谓单例类,即是全局中只能存在唯一一个对象的类,通过函数GetInstance()可以获得这个类的实例对象。因为 GameSceneController 单例类直接声明在 Com.Mygame 命名空间里,因此是全局的,在其中注入的对象都可以看作是全局对象,比如 BaseCode 对象。
这样做的目的是实现代码的MVC架构,通过在单例类中注入对象可以实现对象间的通信,而无需使用 Find、SendMessage 这类破坏程序结构的通讯耦合语句。
我希望用 BaseCode 记录游戏的名字和游戏的简介,因此在 BaseCode 中声明了两个公有变量 gameName、gameRule,它们会被将来的GUI对象获取并显示。
二、新建脚本GenGameObjects,挂载到主摄相机。新建脚本IUserInterface,挂载到一个Empty对象。
三、在 GenGameObjects 中创建长方形、正方形、球及其色彩代表游戏中的对象。并把组件自己注入到 GameSceneController 单例模式对象。
先在游戏面板创建游戏对象,在 Assets 文件夹下新建 Resources 文件夹,在 Resources 文件夹下新建 Prefabs 文件夹,然后将创建的对象拖入 Prefabs 中成为预设物体。
我假设牧师为球体、魔鬼为正方体、河岸为长方体、船也为长方体:
设置主摄像机的投影模式为正交投影,调整大小,这样看到的所有物体都是平面的了。
GenGameObect 部分代码:
public class GenGameObject : MonoBehaviour {
Stack<GameObject> priests_start = new Stack<GameObject>();
Stack<GameObject> priests_end = new Stack<GameObject>();
Stack<GameObject> devils_start = new Stack<GameObject>();
Stack<GameObject> devils_end = new Stack<GameObject>();
GameObject[] boat = new GameObject[2];
GameObject boat_obj;
public float speed = 100f;
GameSceneController my;
Vector3 shoreStartPos = new Vector3(0, 0, -12);
Vector3 shoreEndPos = new Vector3(0, 0, 12);
Vector3 boatStartPos = new Vector3(0, 0, -4);
Vector3 boatEndPos = new Vector3(0, 0, 4);
float gap = 1.5f;
Vector3 priestStartPos = new Vector3(0, 2.7f, -11f);
Vector3 priestEndPos = new Vector3(0, 2.7f, 8f);
Vector3 devilStartPos = new Vector3(0, 2.7f, -16f);
Vector3 devilEndPos = new Vector3(0, 2.7f, 13f);
这部分声明了 GenGameObject 各变量,其中我打算用 Stack 集合类型存储牧师和魔鬼对象