魔鬼与牧师 游戏简介:
- 你要运用智慧帮助3个牧师(方块)和3个魔鬼(圆球)渡河。
- 船最多可以载2名游戏角色。
- 必须有一个游戏角色在船上开船,即船上有游戏角色时,你才可以点击这个船,让船移动到对岸。
- 当有一侧岸的魔鬼数多余牧师数时(包括船上的魔鬼和牧师),魔鬼就会失去控制,吃掉牧师(如果这一侧没有牧师则不会失败),游戏失败。
- 当所有游戏角色都上到对岸时,游戏胜利。
游戏运行效果展示视频:
“魔鬼与牧师”展示shi'p
MVC框架的UML设计图:
M——Model: 所有GameObject就是Model,它们受到Controller的控制,比如说牧师和魔鬼受到MyCharacterController类的控制,船受到BoatController类的控制,河岸受到CoastController类的控制。
V——View:展示游戏结果,为用户提供交互的渠道,包括了UserGUI和ClickGUI
C——Controller:控制类,控制Model和View以及游戏场景,保证游戏的正常运行。其中Director(导演类)是最高层的控制类,一次游戏中只能有一个Director的实例。它控制着场景的创建、切换、销毁、游戏暂停、游戏退出等等最高层次的功能。
游戏代码:
Director类:
public class Director : System.Object {
private static Director _instance;
public SceneController currentSceneController { get; set; }
public static Director getInstance() {
if (_instance == null) {
_instance = new Director ();
}
return _instance;
}
}
Director类使用了单例模式。第一次调用Director.getInstance()时,会创建一个新的Director对象,保存在_instance,此后每次调用getInstance,都回返回_instance。这样保证了Director最多只有一个实例。通过在其他地方调用getInstance,可以实现类与类之间的通信,使它做到导演的掌控全局的功能。
SceneController接口:
public interface SceneController {
void loadResources ();
}
SceneController是在Director类中实现的一个接口,它是导演类实现场景控制的渠道。
Moveable:
public class Moveable: MonoBehaviour {
readonly float move_speed = 20;
// change frequently
int moving_status; // 0->not moving, 1->moving to middle, 2->moving to dest
Vector3 dest;
Vector3 middle;
void Update() {
if (moving_status == 1) {
transform.position = Vector3.MoveTowards (transform.position, middle, move_speed * Time.deltaTime);
if (transform.position == middle) {
moving_status = 2;
}
} else if (moving_status == 2) {
transform.position = Vector3.MoveTowards (transform.position, dest, move_speed * Time.deltaTime);
if (transform.position == dest) {
moving_status = 0;
}
}
}
public void setDestination(Vector3 _dest) {
dest = _dest;
middle = _dest;
if (_dest.y == transform.position.y) { // boat moving
moving_status = 2;
}
else if (_dest.y < transform.position.y) { // character from coast to boat
middle.y = transform.position.y;
} else { // character from boat to coast
middle.x = transform.position.x;
}
moving_status = 1;
}
public void reset() {
moving_status = 0;
}
}
Moveable是一个可以挂载在GameObject上的类。GameObject挂载上Moveable以后,Controller就可以通过setDestinaton方法轻松地让GameObject移动起来。
MyCharacterController和BoatController:
CharacterController封装了一个GameObject,表示游戏角色(牧师或恶魔),而BoatController则封装了船。
UserAction:
public interface UserAction {
void moveBoat();
void characterIsClicked(MyCharacterController characterCtrl);
void restart();
}
这个接口实际上使用了门面模式。FirstController必须要实现这个接口才能对用户的输入做出反应。
ClickGUI
public class ClickGUI : MonoBehaviour {
UserAction action;
MyCharacterController characterController;
public void setController(MyCharacterController characterCtrl) {
characterController = characterCtrl;
}
void Start() {
action = Director.getInstance ().currentSceneController as UserAction;
}
void OnMouseDown() {
if (gameObject.name == "boat") {
action.moveBoat ();
} else {
action.characterIsClicked (characterController);
}
}
}
ClickGUI类是用来监测用户点击,并调用SceneController进行响应的类别。