lab05:Preists and Devils 牧师与魔鬼游戏

2023-11-23 00:30

本文主要是介绍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 牧师与魔鬼游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/414019

相关文章

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

第四次北漂----挣个独立游戏的素材钱

第四次北漂,在智联招聘上,有个小公司主动和我联系。面试了下,决定入职了,osg/osgearth的。月薪两万一。 大跌眼镜的是,我入职后,第一天的工作内容就是接手他的工作,三天后他就离职了。 我之所以考虑入职,是因为 1,该公司有恒歌科技的freex平台源码,可以学学,对以前不懂的解解惑。 2,挣点素材钱,看看张亮002的视频,他用了6000多,在虚幻商城买的吸血鬼游戏相关的素材,可以玩两年。我

nyoj 1038 纸牌游戏

poj 的一道改编题,说是翻译题更恰当,因为只是小幅度改动。 一道模拟题,代码掌控能力比较好,思维逻辑清晰的话就能AC。 代码如下: #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{char c[5];int rk;char da[5];int nu

如果出一个名叫白神话悟空的游戏

最近黑神话由于与原著不符引起了原著派的争议。 所以我在摸鱼的时候想到如果游科或者某个别的公司“痛改前非”不夹带私货完全复刻吴承恩百回版剧情制作一个“重走西游路”的游戏,会有一个什么样的销量?(设定为原著派已经多方渠道认证,此游戏的确没有夹带私货,绝大部分复刻了原著剧情) 游戏玩法我想了几类 超长线性有岔路蜈蚣形状地图,蜈蚣的腿部是探索区域和支线,重走西游路线,开篇就是开始取经前唐玄宗御弟cg

《黑暗之魂2:原罪学者》是什么类型的游戏 《黑暗之魂》可以在苹果Mac电脑上玩吗?

在宏大的世界观游戏中,《黑暗之魂2:原罪学者》脱颖而出,以其探索性和挑战性征服了全球玩家的心灵。下面我们来看看《黑暗之魂2:原罪学者》是什么类型的游戏,《黑暗之魂2:原罪学者》可以在苹果电脑玩吗的相关内容。 一、《黑暗之魂2:原罪学者》是什么类型的游戏 《黑暗之魂2:原罪学者》作为《黑暗之魂2》的增强版和重制版,是一款FromSoftware制作、BANDAI NAMCO和FromSoft

简单取石子游戏~博弈

很坑爹的小游戏,至于怎么坑爹,嘎嘎~自己研究去吧~! #include<stdio.h>#include<windows.h>#include<iostream>#include<string.h>#include<time.h>using namespace std;void Loc(int x,int y);/*定位光标*/void Welcome(); /*创建欢迎界面*/

黑神话:悟空》增加草地绘制距离MOD使游戏场景看起来更加广阔与自然,增强了游戏的沉浸式体验

《黑神话:悟空》增加草地绘制距离MOD为玩家提供了一种全新的视觉体验,通过扩展游戏中草地的绘制距离,增加了场景的深度和真实感。该MOD通过增加草地的绘制距离,使游戏场景看起来更加广阔与自然,增强了游戏的沉浸式体验。 增加草地绘制距离MOD安装 1、在%userprofile%AppDataLocalb1SavedConfigWindows目录下找到Engine.ini文件。 2、使用记事本编辑

Unity3D在2D游戏中获取触屏物体的方法

我们的需求是: 假如屏幕中一个棋盘,每个棋子是button构成的,我们希望手指或者鼠标在哪里,就显示那个位置的button信息。 网上有很多获取触屏物体信息的信息的方法如下面代码所示: Camera cam = Camera.main; // pre-defined...if (touch.phase == TouchPhase.Bagan)){ // 如果触控点状态为按下Ray