成品图

球体代表牧师,正方体代表魔鬼。

目的

​ 使用unity3D做出一个牧师与魔鬼的游戏,程序需要满足以下要求:

  • play the game ( http://www.flash-game.net/game/2535/priests-and-devils.html )
  • 列出游戏中提及的事物(Objects)
  • 用表格列出玩家动作表(规则表),注意,动作越少越好
  • 请将游戏中对象做成预制
  • 在 GenGameObjects 中创建 长方形、正方形、球 及其色彩代表游戏中的对象。
  • 使用 C# 集合类型 有效组织对象
  • 整个游戏仅 主摄像机 和 一个 Empty 对象, 其他对象必须代码动态生成!!! 。 整个游戏不许出现 Find 游戏对象, SendMessage 这类突破程序结构的 通讯耦合 语句。 违背本条准则,不给分
  • 请使用课件架构图编程,不接受非 MVC 结构程序
  • 注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!
MVC简介

​ MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。

规则表
动作 条件
开船 船上必须有一个人,船在左岸或者右岸
牧师在左岸上船 左岸必须有牧师,船上有空位,船在左岸
牧师在右岸上船 右岸必须有牧师,船上有空位,船在右岸
牧师在左岸下船 船上有牧师,船在左岸
牧师在右岸下船 船上有牧师,船在有岸
恶魔在左岸上船 左岸必须有恶魔,船上有空位,船在左岸
恶魔在右岸上船 右岸必须有恶魔,船上有空位,船在右岸
恶魔在左岸下船 船上有恶魔,船在左岸
恶魔在右岸下船 船上有恶魔,船在右岸
具体实现

首先在Assets中创建Resources文件夹,在Resources中创建Prefabs文件夹,将做好的对象拖入Prefabs中成为预制。在Assets文件下创建Scripts文件用以放置C#文件。

Director

Director类利用了单例模式,第一次调用getInstance()时,因为instance为null,所以instance会保存一个新的Director对象。往后的每次getInstance(),都会获得相同的值。也就是说所有的C#文件都将获得相同的Director对象,从而可以获得一个相同的controller,实现不同类之间的通信。

//Director.cs
public class Director : System.Object {private static Director instance;public Controller controller;public static Director getInstance(){if (instance == null){instance = new Director();}return instance;}
}
Controller

Controller类实现了IUserActions接口的方法,并通过一个GenGameObject类型的model变量对游戏对象进行操作。Awake()将Controller注入到单实例中。

//IUserActions.cs
public interface IUserActions
{void priestOn();void priestOnEnd();void devilOn();void devilOnEnd();void changeState();int Check();void priestOff();void devilOff();void Restart();
}//Controller.cs
public class Controller : MonoBehaviour, IUserActions
{private GenGameObject model;private void Awake(){Director director = Director.getInstance();director.controller = this;}public void setModel(GenGameObject Model){model = Model;}public void priestOn(){model.priestOn();}public void devilOn(){model.devilOn();}public void changeState(){model.change_state();}public void priestOnEnd(){model.priestOnEnd();}public void devilOnEnd(){model.devilOnEnd();}public int Check(){return model.Check();}public void priestOff(){model.priestOff();}public void devilOff(){model.devilOff();}public void Restart(){model.Restart();}
}
GenGameObject

GenGameObject类定义了一系列变量。其中priests_start保存左岸牧师的游戏对象,priests_end保存右岸牧师的游戏对象,恶魔同理。onBoat用于存储当前船只上物体的数量。boat_state记录船只的状态,boat_state为1时,船不可移动;值为0时,船在左岸;值为2时,船在右岸。船的移动通过Update()调用boatMove()实现,必须满足两个条件,boat_state不为1和游戏正在进行。通过Check(),可以判断游戏是否结束,当Check()返回1时,游戏胜利并结束;返回2时,游戏失败并结束;返回3时游戏进行中。具体代码如下。

//GenGameObject.cs部分代码private Director instance;int onBoat;public int speed;int boat_state = 1;GameObject[] objectOnBoat = new GameObject[2];readonly Vector3 shore_begin = new Vector3(10, 0, 0);readonly Vector3 shore_end = new Vector3(-10, 0, 0);readonly Vector3 boat_begin = new Vector3(-3, 0, 0);readonly Vector3 boat_end = new Vector3(3, 0, 0);readonly Vector3 priests_begin = new Vector3(-9f, 2, 0);readonly Vector3 priests_last = new Vector3(9f, 2, 0);readonly Vector3 devils_begin = new Vector3(-15f, 2, 0);readonly Vector3 devils_last = new Vector3(15f, 2, 0);readonly Vector3 gap = new Vector3(-1.5f, 0, 0);Stack<GameObject> priests_start = new Stack<GameObject>();Stack<GameObject> devils_start = new Stack<GameObject>();Stack<GameObject> priests_end = new Stack<GameObject>();Stack<GameObject> devils_end = new Stack<GameObject>();GameObject boat;

Start()初始化部分变量,并且将GenGameObject注入到单实例中,同时调用Load()实例化所有预制的游戏对象。

//GenGameObject.csprivate void Start(){speed = 10;onBoat = 0;boat_state = 1;instance = Director.getInstance();instance.controller.setModel(this);Load();}private void Load(){Instantiate(Resources.Load("Prefabs/Shore"), shore_begin, Quaternion.identity);Instantiate(Resources.Load("Prefabs/Shore"), shore_end, Quaternion.identity);boat = Instantiate(Resources.Load("Prefabs/Boat"), boat_begin, Quaternion.identity) as GameObject;boat.name = "boat";for (int i = 0; i < 3; i++){GameObject priest = Instantiate(Resources.Load("Prefabs/Priest"), (priests_begin - gap * i), Quaternion.identity) as GameObject;priests_start.Push(priest);GameObject devil = Instantiate(Resources.Load("Prefabs/Devil"), (devils_begin - gap * i), Quaternion.identity) as GameObject;devils_start.Push(devil);}}public int Check(){if (devils_end.Count == 3 && priests_end.Count == 3){return 1;}if ((devils_start.Count > priests_start.Count && priests_start.Count != 0)){if (boat.transform.position == boat_end){return 2;}if (boat.transform.position == boat_begin && onBoat == 0){return 2;}}if ((devils_end.Count > priests_end.Count && priests_end.Count != 0)){if (boat.transform.position == boat_begin){return 2;}if (boat.transform.position == boat_end && onBoat == 0){return 2;}}return 3;}private void Update(){if (Check() == 3){boatMove();}}

priestOn()让左岸的牧师上船,priestOnEnd()让右岸的牧师上船,priestsOff则让牧师下船,恶魔同理。priestsOn()中首先判断priests_start这个栈是否为空,是的话就直接return,不做任何操作。onBoat小于2时,牧师可以上船,同时设置上船牧师的transform.parent为boat.parent,这样改变boat的位置,牧师也会跟着移动。priestOff()通过物体标签tag判断船上物体是否为Priest,从而确定是否让它下船。

    public void priestOn(){if (priests_start.Count == 0)return;if (onBoat < 2){GameObject temp = priests_start.Pop();temp.transform.parent = boat.transform;if (objectOnBoat[0] == null){temp.transform.localPosition = new Vector3(0.3f, 1.5f, 0);objectOnBoat[0] = temp;}else{temp.transform.localPosition = new Vector3(-0.3f, 1.5f, 0);objectOnBoat[1] = temp;}onBoat++;}}public void priestOff(){for (int i = 0; i < 2; i++){if (objectOnBoat[i] != null && objectOnBoat[i].tag == "Priest"){if (boat.transform.position != boat_begin && boat.transform.position != boat_end)return;GameObject pri = objectOnBoat[i];pri.transform.parent = null;if (boat.transform.position == boat_end){pri.transform.position = priests_last + gap * priests_end.Count;priests_end.Push(pri);}else if (boat.transform.position == boat_begin){pri.transform.position = priests_begin - gap * priests_start.Count;priests_start.Push(pri);}objectOnBoat[i] = null;onBoat--;return;}}}

Restart()则通过设置物体对象,让游戏重新开始

    public void Restart(){int num = priests_end.Count;for (int i = 0; i < num; i++){GameObject temp = priests_end.Pop();temp.transform.position = priests_begin - gap * priests_start.Count;priests_start.Push(temp);}num = devils_end.Count;for (int i = 0; i < num; i++){GameObject temp = devils_end.Pop();temp.transform.position = devils_begin - gap * devils_start.Count;devils_start.Push(temp);}for (int i = 0; i < onBoat; i++){if (objectOnBoat[i] == null){i += 1;}GameObject temp = objectOnBoat[i];temp.transform.parent = null;if (temp.tag == "Priest"){temp.transform.position = priests_begin - gap * priests_start.Count;priests_start.Push(temp);}else{temp.transform.position = devils_begin - gap * devils_start.Count;priests_start.Push(temp);}objectOnBoat[i] = null;}onBoat = 0;boat.transform.position = boat_begin;boat_state = 1;}
UserInterface

为界面添加按钮,并调用按钮对应的接口函数

public class UserInterface : MonoBehaviour
{Director instance;IUserActions action;void Start(){
        instance = Director.getInstance();action = instance.controller as IUserActions;}private void OnGUI(){GUIStyle fontStyle = new GUIStyle();fontStyle.fontSize = 40;fontStyle.normal.textColor = new Color(255, 255, 255);if (action.Check() == 1){GUI.Label(new Rect(440, 200, 100, 100), "Win", fontStyle);if (GUI.Button(new Rect(435, 360, 80, 50), "Restart")){action.Restart();}}if (action.Check() == 2){GUI.Label(new Rect(390, 200, 100, 100), "GameOver", fontStyle);if (GUI.Button(new Rect(435, 360, 80, 50), "Restart")){action.Restart();}}if (GUI.Button(new Rect(130, 300, 50, 50), "On")){action.devilOn();}if (GUI.Button(new Rect(270, 300, 50, 50), "On")){action.priestOn();}if (GUI.Button(new Rect(600, 300, 50, 50), "On")){action.priestOnEnd();}if (GUI.Button(new Rect(750, 300, 50, 50), "On")){action.devilOnEnd();}if (GUI.Button(new Rect(450, 300, 50, 50), "Move")){action.changeState();}if (GUI.Button(new Rect(450, 500, 50, 50), "POff")){action.priestOff();}if (GUI.Button(new Rect(450, 600, 50, 50), "DOff")){action.devilOff();}}
}
详细代码

https://github.com/Limsanity/Priest_and_Devils

unity3D_牧师与魔鬼相关推荐

  1. 牧师与魔鬼——动作分离版

    牧师与魔鬼--动作分离版 在上周的作业中,牧师与魔鬼游戏中的各个事件,都是写在Director中,并且都是继承Monobehavior的.在这周动作分离的设计中,我将上船.下船以及船的移动都分离出来. ...

  2. Unity实战之牧师与魔鬼(动作分离版)

    Unity实战之牧师与魔鬼(动作分离版) 项目链接 整体描述 本次项目在第一版牧师与魔鬼的基础上,将动作从场记中分离出来,并设计一个裁判类实时监测游戏进行的情况.这样改进的优点有很多: 降低了不同功能 ...

  3. 牧师与魔鬼 -- version2 动作分离

    目录 一.基本操作演练 1.下载 Fantasy Skybox FREE, 构建自己的游戏场景 2.写一个简单的总结,总结游戏对象的使用 二.编程实践 1.牧师与魔鬼 动作分离版 面向对象的游戏编程 ...

  4. Unity牧师与魔鬼小游戏(动作分离版)

    Unity牧师与魔鬼小游戏(动作分离版) 前言 这是中大计算机学院3D游戏编程课的一次作业,在这里分享一下设计思路. 主要代码上传到了gitee上,请按照后文的操作运行. 项目地址:https://g ...

  5. Unity3D学习—牧师与魔鬼—MVC模式和ECS架构应用

    需求 Priests and Devils Priests and Devils is a puzzle game in which you will help the Priests and Dev ...

  6. unity编程实践-牧师与魔鬼动作分离版

    作业要求 牧师与魔鬼 动作分离版 [2019开始的新要求]:设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束 目标:建立动作管理器,使动作抽象出来,可以应用到任何游戏对象上,以此提高代码复 ...

  7. 3D游戏设计-牧师与魔鬼_动作分离版

    天空盒 天空盒 前情提要 3D游戏设计-牧师与魔鬼 游戏改进 将每个需要移动的游戏对象的移动方法提取出来,建立一个动作管理器来管理这些移动方法. 优点: 程序更能适应需求变化 对象更容易被复用 程序更 ...

  8. 简易太阳系及牧师与魔鬼

    3D游戏作业3 1.使用Unity实现完整的太阳系 要求:行星围绕太阳的转速必须不同,且不在一个法平面上. 过程:首先寻找太阳系各星球的贴图,并将其加载到项目的assets中.[行星贴图网址](Sol ...

  9. 空间与运动——简单太阳系+牧师与魔鬼

    作业内容 一.简答并用程序验证 1.游戏对象运动的本质是什么? 2.请用三种方法以上方法,实现物体的抛物线运动 3.简单太阳系 二.编程实践 1.脚本设计 2.效果图 一.简答并用程序验证 1.游戏对 ...

最新文章

  1. 计算机ppt继续教育,泰州市专业技术人员继续教育公需科目PPT2010试卷及答案
  2. 深入浅出谈cuda 书_入门和基础——9本关于美学的书
  3. LVM的创建与快照和SSM存储管理器的使用
  4. CentOS7的/tmp目录自动清理规则(转)
  5. Linux 下挂载新硬盘方法
  6. opencv计算图像亮度调节_OpenCV教程创建Trackbar图像对比度、亮度值调整
  7. Flutter中ListView动画OpenContainer动画Flutter径向过渡OpenContainer
  8. HDU 1301 - Jungle Roads( Prim求最小生成树 )
  9. Map的使用和遍历方法示例
  10. java计算机毕业设计租车管理系统源码+mysql数据库+系统+部署+lw文档
  11. java扫描器创建,老司机帮您Java 创建条形码扫描器
  12. 端游网易我的世界服务器未响应,我的世界 PC 端游戏启动异常处理指引(2018.09.21)...
  13. GoJS学习-节点渐变背景色
  14. 【APPInventor\腾讯云】使用APPInventor开发连接腾讯云的安卓物联网遥控APP
  15. RBAC权限框架_MVC权限框架
  16. java sorted 方法_多个.sorted(…)调用java 8流
  17. switch调试软件+金手指
  18. python读取heic/heif后缀的图像
  19. Blo Tx Pending
  20. python使用scrapy爬虫总是提示ModuleNotFoundError: No module named ‘‘

热门文章

  1. h5移动端实现物理返回键关闭弹框而非返回上一级页面
  2. 最有效的萨克斯弱音器_一种萨克斯弱音器的制作方法
  3. py几局代码能写出九九乘法表_Python 九九乘法表
  4. 基于企业服务架构的新一代企业管理应用软件
  5. 最新公司OKR案例集
  6. IT从业人员必看的10个论坛[转自zOS/OS390中国技术社区]
  7. matlab化石墨烯,锯齿石墨烯磁性hubbard matlab计算程序
  8. 《问道》1月28日三区组体验1.43新版
  9. CSS:内边距padding的设置,值的个数表达的意思是什么?
  10. Django笔记六之外键ForeignKey介绍