本文主要是介绍unity3D小游戏-牧师与魔鬼MVC版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、介绍
帮助三个牧师与三个魔鬼过河。过程中,河的两岸分别要满足:牧师数量不能少于魔鬼的数量。
二、实现
1、框架
Model:
(1)包含船、陆地、角色等游戏中涉及到的模型(物体、物件),
它们的基础类型都是GameObject,区别它们的是各自使用的预制件、初始化的位置等等
这些模型仅仅定义了其本身的属性(位置等),并不提供运动等操作函数。
(2)包含click、move两个“特殊”的模型:
click的点击事件(函数)触发的是Contorller中的IObjectController定义的点击函数;
同时船、陆地、角色等模型在定义时被赋予“click”(可点击?)
move:用于实现模型的移动(判断是否在移动、Update函数更新位置)
同样,这两个模型并没有自发的功能实现,更类似于可供其他类使用的“工具”。
View:
用户(玩家)操作的按钮等界面
Controller:
(1)Controllers文件夹包含各种控制器。FirstContorller是“主脑”,由它生成并管理其他控制器的实例(如船、陆地、角色等的控制器)
(2)船、陆地、角色等控制器定义了各种数据(位置、座位数等辅助数据)以及各种功能函数(创建物体、如何入座、点击事件等)
(3)这些物件都有一些共同的动作或功能函数,于是创建一些接口来统一定义:
IObjectController定义了物体的点击、生成、重置等函数
IUserAction定义了物体动作、场景状态等函数(物体动作、场景状态(重新开始等)都是由玩家来操控,所以叫IUserAction)
(4)ISceneController定义了场景初始化函数
(3)(4)这些controller只是对函数的“声明”(类似于基类,由firstcontroller继承?),具体的函数实现由firstcontroller完成。
只有当FirstController创建了船等其他控制器、调用其他控制器的“创建物件”函数,游戏实体才被创建出来。同样,只有当FirstController调用了其他控制器的功能函数,游戏实体才能实现运动。
玩家行为:
玩家动作 | 效果 | 备注 |
点击牧师或魔鬼 | 牧师或魔鬼:离岸上船、下船上岸 | 需要点中对象 |
点击船体 | 船从一岸移动到另一岸 | 1<=船上人数<=2 |
UML图:
2、实现:
Scripts脚本文件夹中分成三部分:Controllers、Models、Views,分别实现上述对应的代码。
在这里我参照了这位博主的博客https://www.cnblogs.com/LC32/p/15420714.html(或者说,我只是在他的代码、框架上做小修改,在此特别感谢)
3、游戏逻辑介绍
角色分为牧师与魔鬼
船上只可乘坐一个或两个角色(对应的,在boatcontroller定义座位数),无人时不可移动。
boatController(部分):
......public int[] seat; // 座位数组,存储船上的乘客座位号public Boat boatModel; // 船的模型对象public int seatNum=2; //船的座位 //添加这个是为了方便控制船的位置数//在下面的初始化、循环中统一用seatNumpublic BoatController(){userAction = SSDirector.GetInstance().CurrentSceneController as IUserAction; // 获取当前场景的用户操作接口seat = new int[seatNum]; // 初始化座位数组Reset(); // 重置船的状态}......
点击岸上、船上的角色,对应角色上船、下船。点击船体,船左右移动。船体或角色移动过程中,不响应其他点击事件。
角色上岸(回到左岸或上到右岸),则回到岸上一个空位置上(对应的,landconcroller定义位置等参数)
角色在左岸、右岸、船上转移,对应的rolecontroller定义角色位置等参数
最后,在游戏的适当时机(船载着角色移动时、角色上到右岸时),执行“check”,检查游戏状态:是否成功或者失败(所有角色到达右岸则为成功;存在某一岸上的魔鬼数量>牧师数量,则游戏失败)
firstController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class FirstController : MonoBehaviour, ISceneController, IUserAction
{public static int LEFTLAND = 0;public static int RIGHTLAND = 1;public static int BOAT = 2;public static int PRIEST = 0;public static int DEVIL = 1;public static int PLAYING = 0;public static int WIN = 1;public static int FAILED = 2;BoatController BoatCtrl;RoleController[] RoleCtrl = new RoleController[6];LandController[] LandCtrl = new LandController[2];MoveController MoveCtrl;int[] rolesID = new int[6]{0,1,2,3,4,5};int gameState;void Awake(){SSDirector director = SSDirector.GetInstance();director.CurrentSceneController = this;director.CurrentSceneController.Initialize();}public void Initialize(){//如果有,则释放原有的GameObjectfor(int i = 0; i < 6; i++){if(RoleCtrl[i] != null){Destroy(RoleCtrl[i].GetModelGameObject());}}for(int i = 0; i < 2; i++){if(LandCtrl[i] != null){Destroy(LandCtrl[i].GetModelGameObject());}}if(BoatCtrl != null){Destroy(BoatCtrl.GetModelGameObject());}// 加载控制器和模型BoatCtrl = new BoatController();BoatCtrl.CreateModel();for(int i = 0; i < 6; i++){int roleType = (i < 3) ? PRIEST : DEVIL;RoleCtrl[i] = new RoleController(roleType, rolesID[i]);RoleCtrl[i].CreateModel();}LandCtrl[0] = new LandController(LEFTLAND, rolesID);LandCtrl[1] = new LandController(RIGHTLAND, rolesID);LandCtrl[0].CreateModel();LandCtrl[1].CreateModel();MoveCtrl = new MoveController();//开始游戏gameState = PLAYING;}//将角色的ID转换成数组的下标int IDToNumber(int ID){for(int i = 0; i < 6; i++){if(rolesID[i] == ID){return i;}}return -1;}//点击船时执行public void MoveBoat(){if(gameState != PLAYING || MoveCtrl.IsMoving() || BoatCtrl.isEmpty()) return;CheckAndSetGameState();if(BoatCtrl.onLeftside){MoveCtrl.SetMove(BoatCtrl.GetModelGameObject(), Position.boatRightPos);for(int i = 0; i < BoatCtrl.seatNum; i++){if(BoatCtrl.seat[i] != -1){RoleController r = RoleCtrl[IDToNumber(BoatCtrl.seat[i])];MoveCtrl.SetMove(r.GetModelGameObject(), Position.seatRightPos[i]);}}}else{MoveCtrl.SetMove(BoatCtrl.GetModelGameObject(), Position.boatLeftPos);for(int i = 0; i < BoatCtrl.seatNum; i++){if(BoatCtrl.seat[i] != -1){RoleController r = RoleCtrl[IDToNumber(BoatCtrl.seat[i])];MoveCtrl.SetMove(r.GetModelGameObject(), Position.seatLeftPos[i]);}} }BoatCtrl.onLeftside = !BoatCtrl.onLeftside;}//点击角色时执行public void MoveRole(int id){int num = IDToNumber(id);if(gameState != PLAYING || MoveCtrl.IsMoving()) return;int seat;switch(RoleCtrl[num].roleState){case 0: // LEFTLANDif(!BoatCtrl.onLeftside || (BoatCtrl.getEmptySeat() == -1)) return;//增加判断getEmptySeat :LandCtrl[0].LeaveLand(id); //如果上不了船,就直接返回,而seat = BoatCtrl.embark(id); //不用改动role、land、boat的位置参数RoleCtrl[num].GoTo(BOAT);if(seat == -1) return; //增加判断getEmptySeat后,这句应该可以略去MoveCtrl.SetMove(RoleCtrl[num].GetModelGameObject(), Position.seatLeftPos[seat]);break;case 1: // RIGHTLANDif(BoatCtrl.onLeftside || (BoatCtrl.getEmptySeat() == -1)) return;//同上LandCtrl[1].LeaveLand(id);seat = BoatCtrl.embark(id);RoleCtrl[num].GoTo(BOAT);if(seat == -1) return;MoveCtrl.SetMove(RoleCtrl[num].GetModelGameObject(), Position.seatRightPos[seat]);break;case 2: //BOATif(BoatCtrl.onLeftside){seat = LandCtrl[0].getEmptySeat();BoatCtrl.disembark(id);LandCtrl[0].GoOnLand(id);RoleCtrl[num].GoTo(LEFTLAND);MoveCtrl.SetMove(RoleCtrl[num].GetModelGameObject(), Position.roleLeftPos[seat]);}else{UnityEngine.Debug.Log("mid_d");seat = LandCtrl[1].getEmptySeat();BoatCtrl.disembark(id);LandCtrl[1].GoOnLand(id);RoleCtrl[num].GoTo(RIGHTLAND);CheckAndSetGameState();//新添加一个在这里,在最后一个角色上右岸之后判定成功MoveCtrl.SetMove(RoleCtrl[num].GetModelGameObject(), Position.roleRightPos[seat]);}break;default: break;}}//判断游戏状态public void CheckAndSetGameState(){if(gameState != PLAYING) return;//判断是否失败int[,] rolePos = new int[2, 3]{{0, 0, 0}, {0, 0, 0}};foreach(RoleController r in RoleCtrl){rolePos[r.roleType, r.roleState]++; //roletype: 0天使、1魔鬼} //rolestate:0左岸、1右岸、2船上if((rolePos[0,0]>0 && rolePos[0,0]<rolePos[1,0]) || //左岸存在天使 && 左岸的天使数量少于左岸魔鬼的数量(rolePos[0,1]>0 && rolePos[0,1]<rolePos[1,1]) || //右岸存在天使 && 右岸的天使数量少于右岸魔鬼的数量(rolePos[0,2]>0 && rolePos[0,2] < rolePos[1,2])){ //船上最多只能承载两个角色时,这行可以删去gameState = FAILED;return;} //判断是否成功foreach(RoleController r in RoleCtrl){if(r.roleState != RIGHTLAND){//存在角色未到达右岸,则直接返回 //r.roleType == 0 && UnityEngine.Debug.Log("这里");return;}}UnityEngine.Debug.Log("其实是这里");gameState = WIN; //上面的情况都不符合,则说明所有角色都安全到达右岸,winreturn;}//Reset按钮执行的功能public void Restart(){Initialize();gameState = PLAYING;}//获取游戏当前状态public int GetGameState(){return gameState;}
}
视频链接:unity3D小游戏-牧师与魔鬼MVC版_哔哩哔哩_bilibili
这篇关于unity3D小游戏-牧师与魔鬼MVC版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!