本文主要是介绍lab05:Preists and Devils 牧师与魔鬼游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这里写自定义目录标题
- 游戏简介
- Objects
- 玩家动作表
- MVC结构组织
- 制作预制prefabs
- 程序UML图
- 文件结构
- 最终效果
- 游戏演示视频
- 详细代码
- MODELS
- VIEWS
- CONTROLLERS
- 源码仓库
游戏简介
《牧师与魔鬼》是一款益智游戏,目标是帮助三个牧师和三个魔鬼在规定时间内安全过河。游戏中只有一艘船,每次只能容纳两个人,而且船的移动必须由一个人完成。需要注意的是,如果河岸上的牧师人数多于魔鬼,魔鬼会被牧师杀死,导致游戏失败。因此,在游戏中需要运用策略,巧妙地安排牧师和魔鬼的上下船顺序,以确保所有牧师都能够安全过河。
Objects
- 河岸地形×2,
- 河流地形
- 船对象
- 牧师对象x3
- 魔鬼对象x3
玩家动作表
动作 | 满足条件 | 事件 |
---|---|---|
启动游戏 | 无 | 加载游戏资源 |
点击牧师或魔鬼 | 游戏未结束and船有空位and船在附近 | 上船 |
点击船只 | 游戏未结束and船上有人 | 船移动到对岸 |
无 | 每一帧 | 检测游戏是否结束 |
点击重新开始 | 游戏结束 | 初始化游戏元素 |
MVC结构组织
- Model:存储数据对象,以及基本的对数据操作的方法
- Controller:接受用户事件,操作Model数据
- View:视图模型,将事件转发到Controller
制作预制prefabs
在这里采用了一些免费的unity素材,大家可以到assests store下载免费的资源
- 魔鬼和牧师
- 船只
- 河岸
- 河流
另外我还添加了一个天空盒挂载在摄像机上
制作完成后将他们拖入Assets中成为预制
程序UML图
这里我们使用的是umlet这个工具
当然staruml之类的工具都可以
设计阶段的UML图
表示继承类
表示实现接口
表示类的关联
表示依赖关系
文件结构
最终效果
游戏演示视频
魔鬼与牧师小游戏 unity3D
详细代码
MODELS
在这里每类只放出代表性的几个类,不然文章太长
├─Models
│ Boat.cs 定义了船模型,挂载了click组件
│ Click.cs 定义了点击模型,重载了monobehavior里的点击事件函数
│ DefaultPosition.cs 存储了一些static的预设位置信息
│ Land.cs 定义了河岸模型
│ Move.cs 定义了移动gameobject的模型
│ River.cs 定义了河流模型
│ Role.cs 定义了人物模型
using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 船只模型
public class Boat
{//船对象public GameObject boat;//关联船上人员public Role[] roles;public bool isRight;public int priestCount, devilCount;public Boat(Vector3 position){// 载入船预制件boat = GameObject.Instantiate(Resources.Load("Prefabs/Boat", typeof(GameObject))) as GameObject;// 设置属性boat.name = "boat";boat.transform.position = position;boat.transform.localScale = new Vector3(2.8f, 0.4f, 2);// 人员对象创建roles = new Role[2];isRight = false;priestCount = devilCount = 0;// 添加碰撞盒与点击组件boat.AddComponent<BoxCollider>();boat.AddComponent<Click>();}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Move : MonoBehaviour
{public bool isMoving = false;public float speed = 5;// 需要经过的轨迹点public Vector3 destination;public Vector3 mid_destination;// Update is called once per framevoid Update(){// 已到达终点 do nothingif (transform.localPosition == destination){isMoving = false;return;}// else movingelse if (transform.localPosition.x != destination.x && transform.localPosition.y != destination.y){transform.localPosition = Vector3.MoveTowards(transform.localPosition, mid_destination, speed * Time.deltaTime);}else{transform.localPosition = Vector3.MoveTowards(transform.localPosition, destination, speed * Time.deltaTime);}isMoving = true;}
}
VIEWS
─Views
UserGUI.cs 视图类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class UserGUI : MonoBehaviour
{// 用户动作接口实例IUserAction userAction;public string message;GUIStyle msgStyle, titleStyle;bool isGameEnd;public void SetMessage(string msg) { message = msg; }void Start(){// 侧向转型实例化用户动作对象userAction = SSDirector.GetInstance().CurrentSceneController as IUserAction;// 设置一些stylemsgStyle = new GUIStyle();msgStyle.normal.textColor = Color.red;msgStyle.fontSize = 40;titleStyle = new GUIStyle();titleStyle.normal.textColor = Color.white;titleStyle.fontSize = 50;isGameEnd = false;}void OnGUI(){// 检查游戏是否结束isGameEnd = userAction.Check();// 设置游戏标题GUI.Label(new Rect(Screen.width * 0.3f, Screen.height * 0.1f, 50, 200), "Preists and Devils", titleStyle);// 设置游戏的提示信息GUI.Label(new Rect(Screen.width * 0.4f, 150, 50, 200), message, msgStyle);// 重新开始if (isGameEnd && GUI.Button(new Rect(Screen.width * 0.45f, Screen.height * 0.5f, 100, 50), "Restart")){Restart();}}void Restart(){userAction.Restart();}
}
CONTROLLERS
─Controllers
│ BoatController.cs 船控制相关的控制器
│ FirstController.cs 场记,控制对象的加载与总控其他控制器
│ IClickAction.cs 接口,定义了一个点击动作接口
│ ISceneController.cs 接口,控制布景、演员的上下场、管理动作等执行
│ IUserAction.cs 接口,定义了玩家的操作
│ LandController.cs 陆地相关控制器
│ MoveController.cs 移动相关控制器
│ RoleController.cs 人物相关控制器
│ SSDirector.cs 总导演,关联ISceneController的一个对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 场记实例
public class FirstController : MonoBehaviour, ISceneController, IUserAction
{// 控制器private LandController leftLandController, rightLandController;private BoatController boatController;private RoleController[] roleControllers;private MoveController moveController;// 比较简单不单独创建控制器River river;// 场景是否正在运行bool isRunning;// 实现加载资源方法public void LoadResources(){// 场景是否正在运行isRunning = true;// 实例化role ControllersroleControllers = new RoleController[6];for (int i = 0; i < 6; ++i){roleControllers[i] = new RoleController();roleControllers[i].CreateRole(DefaultPosition.role_land[i], i < 3 ? true : false, i);}// 实例化land controllerleftLandController = new LandController();leftLandController.CreateLand(DefaultPosition.left_land);leftLandController.GetLand().land.name = "left_land";rightLandController = new LandController();rightLandController.CreateLand(DefaultPosition.right_land);rightLandController.GetLand().land.name = "right_land";// 添加人物并放置在左岸 foreach (RoleController roleController in roleControllers){roleController.GetRoleModel().role.transform.localPosition =leftLandController.AddRole(roleController.GetRoleModel());}// 添加船只控制器boatController = new BoatController();boatController.CreateBoat(DefaultPosition.left_boat);// 创建河流对象river = new River(DefaultPosition.river);// 创建移动控制器moveController = new MoveController();}// 实现移动船只方法public void MoveBoat(){// 船只在移动无法操作if (isRunning == false || moveController.GetIsMoving()) return;// 移动方向if (boatController.GetBoatModel().isRight){moveController.MoveObj(boatController.GetBoatModel().boat, DefaultPosition.left_boat);}else{moveController.MoveObj(boatController.GetBoatModel().boat, DefaultPosition.right_boat);}boatController.GetBoatModel().isRight = !boatController.GetBoatModel().isRight;}// 实现移动人物方法public void MoveRole(Role roleModel){// 正在移动无操作if (isRunning == false || moveController.GetIsMoving()) return;// 判断上船还是下船 if (roleModel.inBoat){// 判断上岸是左边还是右边if (boatController.GetBoatModel().isRight){moveController.MoveObj(roleModel.role, rightLandController.AddRole(roleModel));}else{moveController.MoveObj(roleModel.role, leftLandController.AddRole(roleModel));}roleModel.onRight = boatController.GetBoatModel().isRight;boatController.RemoveRole(roleModel);}else{if (boatController.GetBoatModel().isRight == roleModel.onRight){if (roleModel.onRight){rightLandController.RemoveRole(roleModel);}else{leftLandController.RemoveRole(roleModel);}moveController.MoveObj(roleModel.role, boatController.AddRole(roleModel));}}}// 实现判断游戏是否结束方法public bool Check(){// 未在运行if (isRunning == false) return true;this.gameObject.GetComponent<UserGUI>().SetMessage("");// 胜利条件if (rightLandController.GetLand().priestCount == 3){this.gameObject.GetComponent<UserGUI>().SetMessage("你胜利了!");isRunning = false;return true;}// 获取两边的人员数量int leftPriestCount, rightPriestCount, leftDevilCount, rightDevilCount;leftPriestCount = leftLandController.GetLand().priestCount +(boatController.GetBoatModel().isRight ? 0 : boatController.GetBoatModel().priestCount);rightPriestCount = rightLandController.GetLand().priestCount +(boatController.GetBoatModel().isRight ? boatController.GetBoatModel().priestCount : 0);leftDevilCount = leftLandController.GetLand().devilCount +(boatController.GetBoatModel().isRight ? 0 : boatController.GetBoatModel().devilCount);rightDevilCount = rightLandController.GetLand().devilCount +(boatController.GetBoatModel().isRight ? boatController.GetBoatModel().devilCount : 0);// 失败条件if (leftPriestCount != 0 && leftPriestCount < leftDevilCount ||rightPriestCount != 0 && rightPriestCount < rightDevilCount){this.gameObject.GetComponent<UserGUI>().SetMessage("Game Over!");isRunning = false;return true;}return false;}public void Restart(){SSDirector.ReloadCurrentScene();}// 在游戏对象被实例化后立即调用void Awake(){SSDirector.GetInstance().CurrentSceneController = this;LoadResources();// 不添加GUI组件无法显示this.gameObject.AddComponent<UserGUI>();}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BoatController : IClickAction
{private Boat boatModel;private IUserAction userAction;public void OnClick(){// 前置条件:船没有满员// 如果能上船,角色应到的位置就是船所在的位置// 如果不能上船,角色应到的位置就是原来的位置// 船上有人才能移动if (boatModel.roles[0] != null || boatModel.roles[1] != null){userAction.MoveBoat();}}public BoatController(){userAction = SSDirector.GetInstance().CurrentSceneController as IUserAction;}public void CreateBoat(Vector3 position){boatModel = new Boat(position);boatModel.boat.GetComponent<Click>().ClickAction = this;}public Boat GetBoatModel(){return boatModel;}// 人物上船public Vector3 AddRole(Role roleModel){int index = -1;if (boatModel.roles[0] == null) index = 0;else if (boatModel.roles[1] == null) index = 1;// 无空位不上船if (index == -1) return roleModel.role.transform.localPosition;// 有空位上船boatModel.roles[index] = roleModel;roleModel.inBoat = true;roleModel.role.transform.parent = boatModel.boat.transform;if (roleModel.isPriest) boatModel.priestCount++;else boatModel.devilCount++;return DefaultPosition.role_boat[index];}// 将角色从船上移到岸上public void RemoveRole(Role roleModel){for (int i = 0; i < 2; ++i){if (boatModel.roles[i] == roleModel){boatModel.roles[i] = null;if (roleModel.isPriest) boatModel.priestCount--;else boatModel.devilCount--;break;}}}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 定义点击动作接口
public interface IClickAction
{void OnClick();
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 定义用户的行为
public interface IUserAction
{void MoveBoat();void MoveRole(Role roleModel);bool Check();void Restart();
}
源码仓库
源码链接
这篇关于lab05:Preists and Devils 牧师与魔鬼游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!