Unity3D游戏编程-牧师与恶魔

Unity3D游戏编程-牧师与恶魔

前置说明

牧师与恶魔

牧师与恶魔需要从岸的一端到达另一端,河上只有一条船,一条船只能坐两个角色,并且至少需要一个角色在船上船才可以行驶。并且,如果在某一侧(包括岸上和船上),恶魔的数量大于牧师的数量,牧师就会被恶魔吃掉(如果仅有恶魔则无事发生),游戏失败。玩家要安排牧师与恶魔的过河顺序,让牧师与恶魔全部到达另一边岸上,才能游戏通关。

MVC架构

MVC是界面人机交互程序设计的一种架构模式。它把程序分为三个部分:

  1. 模型(Model):数据对象及关系
    · 游戏对象、空间关系
  2. 控制器(Controller):接受用户事件,控制模型的变化
    · 一个场景一个主控制器
    · 至少实现与玩家交互的接口(IPlayerAction)
    · 实现或管理运动
  3. 界面(View):显示模型,将人机交互事件交给控制器处理
    · 处收Input 事件
    · 渲染GUI ,接收事件

例子:
应用程序浏览网页,是一个把信息拉取下来并显示到页面上的过程,页面就是view,拉取信息的类就是model,当用户进行了点击后,负责通知model去拉去信息,并且通知view进行显示的就是controller。

而基于职责的设计与游戏的MVC总体框架包括:

  1. 导演,1名(仅要一个)
    ·类型:SSDriector
    ·职责:把握全局;控制场景
  2. 场记若干,话剧有很多场,每场需要一个。
    ·抽象类型(角色):ISceneController
    ·具体类型:FirstController
    ·职责:第一场的场记,控制布景、演员的上下场、管理动作等执行
  3. 吃瓜群众,1个
    · 抽象类型:IUserAction
    · 具体类型:IUserAction
    · 职责:门面,与controller沟通

两种结合,导演和场记相当于controller,游戏中的object就是model,GUI就是view。


作业要求

完成牧师与恶魔游戏,程序需要满足要求:
· play the game
· 列出游戏中提及的事物(Objects)
· 用表格列出玩家动作表(规则表)
· 将游戏中对象做成预制
· 在 GenGameObjects 中创建长方形、正方形、 及其色彩代表游戏中的对象。
· 使用C#集合类型有效组织对象
· 整个游戏仅主摄像机和一个Empty对象,其他对象必须代码动态生成。整个游戏不许出现Find游戏对象,SendMessage这类突破程序结构的通讯耦合语句。
· 使用课件架构图编程,不接受非MVC结构程序
· 船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件


项目配置

Windows 10
Unity 2020.3.17f1c1


Object

游戏中主要包括的Object有以下:

object数量
牧师3
恶魔3
1
1
岸边2

玩家动作(规则表)

动作条件效果
玩家点击岸上角色船上有空位角色上船
玩家点击船上角色角色上岸
玩家点击船船上有至少一个角色开船
玩家点击restart重新开始游戏

项目演示

视频演示

点击此处可以前往

项目下载

下载Assets文件夹,项目代码在Assets>Scripts中
点击此处可以前往gitee

文字说明

  1. 创建unity专案后,将保存的文件夹中的Assets替换成在上面项目下载的Assets文件夹
  2. 打开专案,然后点选Assets中的ass加载场景
  3. 运行即可开始游戏
  4. 白色长方体为牧师,红色圆球为恶魔

项目截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


实现过程和方法(算法)

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是单例模式并且是懒汉模式的,因此如果在程序的其他地方进行调用getInstance,得到的_instance会是同一个,就可以实现类之间的通信。

  1. 单例模式:一些东西在整个游戏中只有一个,而又想可以方便地随时访问它,这时就可以考虑单例模式。单例模式保证应用只有全局惟一的实例,并且提供一个访问它的全局访问点。单例包含一个静态方法,叫做getInstance(),调用这个静态方法,它就立刻现身,随时可以工作。
  2. 懒汉模式:在启动时并不创建单例对象,仅在调用getInstance()的时候才创建。程序运行中,调用Director.getInstance会判断_instance是否为空。如果为空,就创建一个返回。如果不为空,说明之前已经创建过了,直接返回。

Controller

然后是场记的部分,对于不同的对象设置不同的Controller:

SceneController

Director中有:

public SceneController currentSceneController { get; set; }

而SceneController是一个接口:

public interface SceneController {
    void loadResources ();
}

SceneController是导演Director控制场景控制器的渠道,Director可以调用SceneController接口中的方法。而实现SceneController的currentSceneController类,在FirstSceneController中就会被定义为FirstSceneController本身,loadResources需要在FirstSceneController中实现。


Moveable

(程序在BaseCode.cs中的31行开始)
Moveable是为了给角色对象、船只移动而准备的类,因此需要先写。
update主要利用MoveTowards来使得对象移动到目的位置。
当角色对象控制器和船只控制器需要移动某一个对象时,可以调用setDestination函数来进行移动。
Moveable中还设置了reset用于重新开始,初始化游戏对象的移动状态。


CharacterController

(程序在BaseCode.cs中的73行开始)
MyCharacterController类主要用于控制游戏中的牧师与恶魔,其构造函数会根据传入的字符串来创建牧师/恶魔对象,并且给他们每一个对象挂载ClickGUI函数用于判断用户点击,由于角色对象会运动,所以也需要挂载Moveable类。
类中还有其他可调用的函数:

  1. setName设置名称(如“牧师1/恶魔1”)
  2. setPosition设置对象位置
  3. moveToPosition设置对象移动到目标位置,调用moveable的setDestination
  4. getType返回对象的类型(如“牧师”、“恶魔”)
  5. getName返回对象的名称(如“牧师1/恶魔1”)
  6. getOnBoat对象上船,并且修改对象的状态(_isOnBoat)
  7. getOnCoast对象下船,并且修改对象的状态(_isOnBoat)
  8. isOnBoat返回对象_isOnBoat的状态
  9. getCoastController返回岸边控制器
  10. reset用于重新初始化

CoastController

(程序在BaseCode.cs中的148行开始)
CoastController用于控制河岸对象,而河岸因为要用于判断获胜条件,也需要像角色对象分为牧师与恶魔一样,分成此岸和对岸(from和to)。
因为河岸需要给角色对象站立,游戏中的角色对象总共有六个,因此在构造函数需要构造六个空对象,并且根据传入的字符串,标记此次创建的是此岸还是对岸。
其他函数:

  1. getEmptyIndex获取岸上的空位置的下标,passengerPlaner是用来记录在一个河岸上的角色位置,如果为NULL表示该位置为空没有角色站立在此。
  2. getEmptyPosition获取岸上的空位置
  3. getOnCoast有角色下船,修改对应的岸上状态
  4. getOffCoast有角色上船,修改对应的岸上状态
  5. get_to_or_from返回这个河岸是此岸还是对岸
  6. getCharacterNum返回当前河岸牧师与恶魔的数量
  7. reset重置

BoatController

(程序在BaseCode.cs中的230行开始)
BoatController用于控制船只,因为船只会移动到两个岸边,因此它的状态也分成在此岸或对岸(from和to)。
因为船上拥有两个位置,因此需要构造两个空对象;并且由玩家点击船只行驶,需要挂载ClickGUI类判断用户点击;由于船只会运动,所以也需要挂载Moveable类。
其他函数:

  1. Move控制船只在两岸中移动
  2. getEmptyIndex返回船上空余位置下标
  3. getEmptyPosition返回船上空余位置
  4. isEmpty返回船只是否空的
  5. GetOnBoat有角色上船,修改船的属性
  6. GetOffBoat角色下船,修改船的属性
  7. getGameobj返回船本体的游戏对象
  8. get_to_or_from返回船只当前所在河岸
  9. getCharacterNum返回船上牧师和恶魔的数量
  10. reset重置船只

UserAction

UserAction

UserAction是门面模式,与用户交互相关的,与玩家动作有关:

public interface UserAction {
    void moveBoat();
    void characterIsClicked(MyCharacterController characterCtrl);
    void restart();
}

这里就包括了移动船只,角色被点击,游戏重新开始这三个动作,UserAction接收到UI传来的信号,告知FirstSceneController调用对应动作的函数作出反应。而UserAction里面的函数就要在FirstSceneController中定义。而ClickGUI与UserGUI则通过UserAction这个门面接口来与FirstSceneController打交道。

  1. 门面模式:定义一个用户动作接口,实现用户行为与游戏系统规则计算的分离,称这个接口就是游戏逻辑与用户之间交互的门面(Fasàde)。

ClickGUI

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判断被鼠标点击的对象是谁来进行下一步操作,调用UserAction(action)的接口来完成功能。


UserGUI

UserGUI是用于当游戏结束(失败或者成功)时显示说明文字和重玩游戏按钮的。
游戏状态分别为:0-游戏进行中,1-游戏失败,2-游戏通关。


FirstController

FirstController就要负责实现loadResources、moveBoat、characterIsClicked、restart函数。

  1. Awake函数是负责游戏的初始化加载
  2. loadResources是从Aseets中取出对象,生成水面、船只、两个河岸,以及调用loadCharacter生成牧师和恶魔。
  3. loadCharacter负责在出发的河岸上生成三个牧师和三个恶魔。
  4. moveBoat检测船只上的人员是否为空,如果不是的话则可以移动船只,并且判断游戏的状态(是不是gameover)
  5. characterIsClicked检查被点击的对象,
    若处于船上:取得船在哪个岸边、人物下船、调用函数修改游戏属性(包括船、河岸);
    若处于岸上:取得人物所在哪个岸边、判断船还有没有空位、判断船和人物是否处于同一侧岸、调用函数修改游戏属性(包括船、河岸);
    最后也要判断游戏的状态(是不是gameover)。
  6. check_game_over就是数出发岸和目标岸(包括船上)各自的牧师与恶魔数量,如果目标岸的角色总数=6,则游戏通关(状态为2);如果某一个岸恶魔的数量大于牧师,则游戏失败(状态为1);其余情况游戏继续(状态为0);
  7. restart重置游戏,分别调用各个对象自己的reset。

参考资料

1.学习Unity(5)小游戏实例——牧师与魔鬼
2.Unity中的单例模式
3.Unity3d-learning 牧师与恶魔

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值