[3D游戏编程]Priests And Devils——动作分离版

2024-01-24 21:40

本文主要是介绍[3D游戏编程]Priests And Devils——动作分离版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前情提要

上次已经实现了Priests And Devils小游戏,链接如下(游戏效果和上一次一样,就不再制作视频了):

[3D游戏编程]Priests And Devils-CSDN博客

本次任务

在上一次的代码中,可以看到FirstController里完成了几乎所有操作,包括人物状态的记录,人物的上下船,游戏结束的判断等等,使得FirstController非常繁杂和臃肿。

本次任务就是要在上次代码的基础上,将动作分离给更多的角色实现。

实现效果

将之前写在FirstController中的PriestsStatus,DevilsStatus,BoatBehaviour独立出来,并提供必要的Get和Set函数作为接口获取和修改类里面的值。

增加了一个IGameJudge类,负责实现各种判断,比如哪个人物可以上下船,游戏结束等等。

游戏框架设计

具体代码

主要是FirstController和IGameJudge有比较大的变化,所以只展示这两个类的代码。由于FirstController和IGameJudge紧密关联,所以在解释其中的函数时会一起讲。

FirstController.priestsGetOn与FirstController.devilsGetOn

两个函数实现逻辑相似,只展示priestsGetOn

    public void priestsGetOn(){// 如果船正在动,那么不能响应用户事件if (judge.BoatIsMoving())return;List<int> temp = judge.PriestGotoBoat();// 如果temp为空,说明没找到该上船的priestif(temp.Count == 0) return;}

其中调用了IGameJudge中的BoatIsMoving函数,用于判断船是否在动

    // 判断船是否在动public bool BoatIsMoving(){return boatBehaviour.GetisMoving();}

还调用了 IGameJudge中的PriestGotoBoat函数,该函数实现了找岸上是否有priest可以上船,同样的,这里只展示船在左岸,左岸上有priest并且船左边有空位的判断逻辑。

    // 返回哪个priest应该上船public List<int> PriestGotoBoat(){List<int> temp = new List<int>(); //第一个参数是哪个priest,第二个是船位置,第三个是岸位置// 船在左边if (boatBehaviour.GetatLeftSide()){for (int i = 0; i < 3; i++){// 左侧岸上有牧师if (p_status[i].GetonBankLeft()){// 上船位置if (boatBehaviour.GetleftPosEmpty()){temp.Add(i);temp.Add(0);temp.Add(1);return temp;}if (boatBehaviour.GetrightPosEmpty()){}}}}else{}return temp;}

可以看到,如果没有找到priest,返回的temp将为空,这也就正好和if(temp.Count == 0)相对应。

接下来继续看priestsGetOn(只展示船在左岸,priest上船左边):

    public void priestsGetOn(){    // 接上文int i = temp[0];p_status[i].SetonBankLeft(false);p_status[i].SetonBankRight(false);judge.ModifyPersonCountOnBank(false, true, temp[2]);judge.ModifyPersonCountOnBoat(true, true);// 上船的左边if (temp[1] == 0){p_status[i].SetonBoatLeft(true);myBoatBehaviour.SetleftPosEmpty(false);// 船在左岸if (myBoatBehaviour.GetatLeftSide())Priests[i].transform.position = new Vector3(-3.3f, 1.5f, 0);elsePriests[i].transform.position = new Vector3(1, 1.5f, 0);}else{}}

可以看到,这里调用了judge的两个函数ModifyPersonCountOnBank和ModifyPersonCountOnBoat

ModifyPersonCountOnBank用于修改当前岸上人数还有多少个(只展示左岸priest加人):

    // 修改岸上priest和devil的值// 第一个参数表示加减,第二个参数表示身份,第三个参数表示哪个岸public void ModifyPersonCountOnBank(bool plus, bool identify, int bank){// 区分加减if (plus){// 区分priest和devilif (identify){   // 区分左右岸if (bank == 1)leftBankPriests++;elserightBankPriests++;}else{}}else{}}

ModifyPersonCountOnBoat用于修改当前船上还有多少人(只展示priest加人):

    // 修改船上priest和devil的值// 第一个参数表示加减,第二个参数表示身份public void ModifyPersonCountOnBoat(bool plus, bool identify){// 区分加减if(plus) {// 区分priest和devilif(identify)boatPriest++;elseboatDevil++;}else {}}

FirstController.priestsGetOff与FirstController.devilsGetOff

两个函数实现逻辑相似,只展示priestsGetOff(且只展示船在左岸的判断逻辑)

priestsGetOff和priestsGetOn判断逻辑其实几乎一样,主要不同点只是在于调用函数时输入的参数要变。

public void priestsGetOff(){if (judge.BoatIsMoving())return;List<int> temp = judge.PriestGoOffBoat();// 如果temp为空,说明没找到该上船的priestif (temp.Count == 0)return;int i = temp[0];judge.ModifyPersonCountOnBank(true, true, temp[2]);judge.ModifyPersonCountOnBoat(false, true);p_status[i].SetonBoatLeft(false);p_status[i].SetonBoatRight(false);// 船在左岸if (temp[2] == 1){p_status[i].SetonBankLeft(true);Priests[i].transform.position = new Vector3((-8.6f + i * 1.3f), 3, 0);if (temp[1] == 0)myBoatBehaviour.SetleftPosEmpty(true);elsemyBoatBehaviour.SetrightPosEmpty(true);}else{}}

FirstController.boatMove和FirstController.onBoatMoving

这两个函数和上一次任务实现逻辑基本相同,只是将确定船上有什么人物的逻辑移到IGameJudge中实现,在IGameJudge中,PersonOnBoat函数实现了找人逻辑,并返回船上人物的下标。

    // 0-2代表priest,3-5代表devil// 找出船上有谁public List<int> PersonOnBoat(){List<int> ans = new();int i1 = -1;int i2 = -1;for (int i = 0; i < 3; i++){if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i1 = i;break;}if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i1 = i + 3;break;}}for (int i = 0; i < 3; i++){//第一个选了priestif (i == i1){if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i2 = i + 3;break;}}//第一个选了devilelse if (i == i1 - 3){if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i2 = i;break;}}else{if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i2 = i;break;}if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i2 = i + 3;break;}}}ans.Add(i1);ans.Add(i2);return ans;}

IGameJudge.GameOver

此外,原来在FirstController中实现的GameOver函数,现在移到IGameJudge中实现

    // 判断游戏结束public int GameOver(){// 船靠岸分情况讨论if (boatBehaviour.GetatLeftSide()){if ((leftBankPriests + boatPriest > 0&& leftBankDevils + boatDevil > leftBankPriests + boatPriest)|| (rightBankDevils > rightBankPriests && rightBankPriests > 0)){return 1;}}else{if ((rightBankPriests + boatPriest > 0&& rightBankDevils + boatDevil > rightBankPriests + boatPriest)|| (leftBankDevils > leftBankPriests && leftBankPriests > 0)){return 1;}if (rightBankDevils + boatDevil == 3 && rightBankPriests + boatPriest == 3){return 2;}}return 0;}

总结

这次的代码在实现逻辑上,是和上次的代码一样的,不同点在于,通过添加更多的“角色”,分担了FirstController的任务。首先,原本在FirstController中定义的有关状态的类,都独立出来,并通过提供接口实现获取和修改值的操作;其次,原本在FirstController中有关判断的逻辑,都在IGameJudge中实现。这种做法使得FirstController变得简洁,符合面向对象基于职责的原则。

代码大放送

使用方法:将FirstController和UserInterface挂载到MainCamera就可以使用了

SSDirector

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSDirector : System.Object
{// singlton instanceprivate static SSDirector _instance;public ISceneController currentSceneController { get; set; }// get instance anytime anywhare!public static SSDirector getInstance(){if (_instance == null){_instance = new SSDirector();}return _instance;}public int getFPS(){return Application.targetFrameRate;}public void setFPS(int fps){Application.targetFrameRate = fps;}public void NextScene(){Debug.Log("Waiting next Scene now...");
#if UNITY_EDITORUnityEditor.EditorApplication.isPlaying = false;//UnityEditor.EditorApplication.Exit(0);
#elseApplication.Quit();  
#endif}
}

IUserAction

using System;public interface IUserAction
{void boatMove();void priestsGetOn();void priestsGetOff();void devilsGetOn();void devilsGetOff();
}

 ISceneController

using System;/// <summary>
/// Abstact Scene Controller. Interface between scene controllers and the director
/// </summary>
public interface ISceneController
{void LoadResources();int GameOver();void restart();
}

UserInterface

using UnityEngine;
using System.Collections;public class UserInterface : MonoBehaviour
{private IUserAction myActions;private ISceneController mySceneController;float btnWidth = (float)Screen.width / 6.0f;float btnHeight = (float)Screen.height / 6.0f;void Start(){mySceneController = SSDirector.getInstance().currentSceneController;myActions = mySceneController as IUserAction;}void Update(){}void OnGUI(){//游戏正常进行if (mySceneController.GameOver() == 0){if (GUI.Button(new Rect(btnWidth / 2, 250, btnWidth, btnHeight), "Priests GetOn")){myActions.priestsGetOn();}if (GUI.Button(new Rect(btnWidth / 2 + btnWidth, 250, btnWidth, btnHeight), "Priests GetOff")){myActions.priestsGetOff();}if (GUI.Button(new Rect(btnWidth / 2 + 2 * btnWidth, 250, btnWidth, btnHeight), "Go!")){myActions.boatMove();}if (GUI.Button(new Rect(btnWidth / 2 + 3 * btnWidth, 250, btnWidth, btnHeight), "Devils GetOn")){myActions.devilsGetOn();}if (GUI.Button(new Rect(btnWidth / 2 + 4 * btnWidth, 250, btnWidth, btnHeight), "Devils GetOff")){myActions.devilsGetOff();}}//loseelse if (mySceneController.GameOver() == 1){GUI.Box(new Rect(2 * btnWidth, btnHeight, 2 * btnWidth, btnHeight), "\nYOU LOSE");if (GUI.Button(new Rect(2.5f * btnWidth, 2 * btnHeight, btnWidth, btnHeight), "Restart")){mySceneController.restart();}}//winelse{GUI.Box(new Rect(2 * btnWidth, btnHeight, 2 * btnWidth, btnHeight), "\nYOU WIN");if (GUI.Button(new Rect(2.5f * btnWidth, 2 * btnHeight, btnWidth, btnHeight), "Restart")){mySceneController.restart();}}}
}

PriestsStatus 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PriestsStatus
{private bool onBoatLeft, onBoatRight;private bool onBankLeft, onBankRight;public PriestsStatus(){this.onBoatLeft = false;this.onBoatRight = false;this.onBankLeft = true;this.onBankRight = false;}// 一些必要的get函数public bool GetonBoatLeft() { return onBoatLeft; }public bool GetonBoatRight() { return onBoatRight; }public bool GetonBankLeft() { return onBankLeft; }public bool GetonBankRight() { return onBankRight; }// 一些必要的set函数public void SetonBoatLeft(bool value) { onBoatLeft= value; }public void SetonBoatRight(bool value) { onBoatRight= value; }public void SetonBankLeft(bool value) { onBankLeft= value; }public void SetonBankRight(bool value) { onBankRight= value;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

DevilsStatus

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DevilsStatus
{private bool onBoatLeft, onBoatRight;private bool onBankLeft, onBankRight;public DevilsStatus() {this.onBoatLeft = false;this.onBoatRight = false;this.onBankLeft = true;this.onBankRight = false;}// 一些必要的get函数public bool GetonBoatLeft() { return onBoatLeft; }public bool GetonBoatRight() { return onBoatRight; }public bool GetonBankLeft() { return onBankLeft; }public bool GetonBankRight() { return onBankRight; }// 一些必要的set函数public void SetonBoatLeft(bool value) { onBoatLeft = value; }public void SetonBoatRight(bool value) { onBoatRight = value; }public void SetonBankLeft(bool value) { onBankLeft = value; }public void SetonBankRight(bool value) { onBankRight = value; }// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

BoatBehaviour

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BoatBehaviour
{private bool isMoving;private bool atLeftSide;private bool leftPosEmpty, rightPosEmpty;public BoatBehaviour(){this.isMoving = false;this.atLeftSide = true;this.leftPosEmpty = true;this.rightPosEmpty = true;}// 一些必要的get函数public bool GetisMoving() { return isMoving; }public bool GetatLeftSide() { return atLeftSide; }public bool GetleftPosEmpty() { return leftPosEmpty; }public bool GetrightPosEmpty() { return rightPosEmpty; }// 一些必要的set函数public void SetisMoving(bool value) { isMoving = value; }public void SetatLeftSide(bool value) { atLeftSide = value;}public void SetleftPosEmpty(bool value) { leftPosEmpty = value;}public void SetrightPosEmpty(bool value) { rightPosEmpty = value;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

IGameJudge

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class IGameJudge
{public List<PriestsStatus> p_status;public List<DevilsStatus> d_status;public BoatBehaviour boatBehaviour;// 记录船上有多少个priest(devil)private int boatPriest, boatDevil;// 记录某个位置有多少个priest(devil)private int leftBankPriests, rightBankPriests;private int leftBankDevils, rightBankDevils;public IGameJudge(){boatPriest = 0;boatDevil = 0;leftBankPriests = 3;rightBankPriests = 0;leftBankDevils = 3;rightBankDevils = 0;p_status = new List<PriestsStatus>();d_status = new List<DevilsStatus>();boatBehaviour = new BoatBehaviour();}// 实时修改状态值public void reflash(){// priests devilsp_status = new List<PriestsStatus>();d_status = new List<DevilsStatus>();for (int i = 0; i < 3; i++){p_status.Add(new PriestsStatus());d_status.Add(new DevilsStatus());}//boatboatBehaviour = new BoatBehaviour();// 初始化leftBankDevils = 3;leftBankPriests = 3;rightBankDevils = 0;rightBankPriests = 0;boatPriest = 0;boatDevil = 0;}// 修改船上priest和devil的值// 第一个参数表示加减,第二个参数表示身份public void ModifyPersonCountOnBoat(bool plus, bool identify){// 区分加减if (plus) {// 区分priest和devilif (identify)boatPriest++;elseboatDevil++;}else {if(identify)boatPriest--;elseboatDevil--;}}// 修改岸上priest和devil的值// 第一个参数表示加减,第二个参数表示身份,第三个参数表示哪个岸public void ModifyPersonCountOnBank(bool plus, bool identify, int bank){// 区分加减if (plus){// 区分priest和devilif (identify){   // 区分左右岸if (bank == 1)leftBankPriests++;elserightBankPriests++;}else{if (bank == 1)leftBankDevils++;elserightBankDevils++;}}else{if (identify){if (bank == 1)leftBankPriests--;elserightBankPriests--;}else{if (bank == 1)leftBankDevils--;elserightBankDevils--;}}}// 找出船上有谁// 0-2代表priest,3-5代表devilpublic List<int> PersonOnBoat(){List<int> ans = new();int i1 = -1;int i2 = -1;for (int i = 0; i < 3; i++){if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i1 = i;break;}if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i1 = i + 3;break;}}for (int i = 0; i < 3; i++){//第一个选了priestif (i == i1){if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i2 = i + 3;break;}}//第一个选了devilelse if (i == i1 - 3){if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i2 = i;break;}}else{if (p_status[i].GetonBoatLeft() || p_status[i].GetonBoatRight()){i2 = i;break;}if (d_status[i].GetonBoatLeft() || d_status[i].GetonBoatRight()){i2 = i + 3;break;}}}ans.Add(i1);ans.Add(i2);return ans;}// 判断船能不能动public bool CanMove(){// 船在动或者船上没人时不能开船if (!boatBehaviour.GetisMoving() && (boatPriest + boatDevil > 0)){return true;}return false;}// 判断船是否在动public bool BoatIsMoving(){return boatBehaviour.GetisMoving();}// 返回哪个priest应该上船public List<int> PriestGotoBoat(){List<int> temp = new List<int>(); //第一个参数是哪个priest,第二个是船位置,第三个是岸位置// 船在左边if (boatBehaviour.GetatLeftSide()){for (int i = 0; i < 3; i++){// 左侧岸上有牧师if (p_status[i].GetonBankLeft()){// 上船位置if (boatBehaviour.GetleftPosEmpty()){temp.Add(i);temp.Add(0);temp.Add(1);return temp;}if (boatBehaviour.GetrightPosEmpty()){temp.Add(i);temp.Add(1);temp.Add(1);return temp;}}}}else{for (int i = 0; i < 3; i++){//右侧岸上有牧师if (p_status[i].GetonBankRight()){// 上船位置if (boatBehaviour.GetleftPosEmpty()){temp.Add(i);temp.Add(0);temp.Add(0);return temp;}if (boatBehaviour.GetrightPosEmpty()){temp.Add(i);temp.Add(1);temp.Add(0);return temp;}}}}return temp;}// 返回哪个priest应该下船public List<int> PriestGoOffBoat(){List<int> temp = new List<int>(); //第一个参数是哪个priest,第二个是船位置,第三个是岸位置// 船在左边if (boatBehaviour.GetatLeftSide()){for (int i = 0; i < 3; i++){//船左侧有priestif (p_status[i].GetonBoatLeft()){temp.Add(i);temp.Add(0);temp.Add(1);return temp;}//船右侧有priestif (p_status[i].GetonBoatRight()){temp.Add(i);temp.Add(1);temp.Add(1);return temp;}}}else{for (int i = 0; i < 3; i++){//船左侧有priestif (p_status[i].GetonBoatLeft()){temp.Add(i);temp.Add(0);temp.Add(0);return temp;}//船右侧有priestif (p_status[i].GetonBoatRight()){temp.Add(i);temp.Add(1);temp.Add(0);return temp;}}}return temp;}// 返回哪个devil应该上船public List<int> DevilGotoBoat(){List<int> temp = new List<int>(); //第一个参数是哪个devil,第二个是船位置,第三个是岸位置// 船在左边if (boatBehaviour.GetatLeftSide()){for (int i = 0; i < 3; i++){// 左侧岸上有恶魔if (d_status[i].GetonBankLeft()){// 上船位置if (boatBehaviour.GetleftPosEmpty()){temp.Add(i);temp.Add(0);temp.Add(1);return temp;}if (boatBehaviour.GetrightPosEmpty()){temp.Add(i);temp.Add(1);temp.Add(1);return temp;}}}}else{for (int i = 0; i < 3; i++){//右侧岸上有恶魔if (d_status[i].GetonBankRight()){// 上船位置if (boatBehaviour.GetleftPosEmpty()){temp.Add(i);temp.Add(0);temp.Add(0);return temp;}if (boatBehaviour.GetrightPosEmpty()){temp.Add(i);temp.Add(1);temp.Add(0);return temp;}}}}return temp;}// 返回哪个priest应该下船public List<int> DevilGoOffBoat(){List<int> temp = new List<int>(); //第一个参数是哪个devil,第二个是船位置,第三个是岸位置// 船在左边if (boatBehaviour.GetatLeftSide()){for (int i = 0; i < 3; i++){//船左侧有devilif (d_status[i].GetonBoatLeft()){temp.Add(i);temp.Add(0);temp.Add(1);return temp;}//船右侧有devilif (d_status[i].GetonBoatRight()){temp.Add(i);temp.Add(1);temp.Add(1);return temp;}}}else{for (int i = 0; i < 3; i++){//船左侧有devilif (d_status[i].GetonBoatLeft()){temp.Add(i);temp.Add(0);temp.Add(0);return temp;}//船右侧有devilif (d_status[i].GetonBoatRight()){temp.Add(i);temp.Add(1);temp.Add(0);return temp;}}}return temp;}// 判断游戏结束public int GameOver(){// 船靠岸分情况讨论if (boatBehaviour.GetatLeftSide()){if ((leftBankPriests + boatPriest > 0&& leftBankDevils + boatDevil > leftBankPriests + boatPriest)|| (rightBankDevils > rightBankPriests && rightBankPriests > 0)){return 1;}}else{if ((rightBankPriests + boatPriest > 0&& rightBankDevils + boatDevil > rightBankPriests + boatPriest)|| (leftBankDevils > leftBankPriests && leftBankPriests > 0)){return 1;}if (rightBankDevils + boatDevil == 3 && rightBankPriests + boatPriest == 3){return 2;}}return 0;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}

 FirstController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// Scene Controller
/// Usage: host on a gameobject in the scene   
/// responsiablities:
///   acted as a scene manager for scheduling actors.log something ...
///   interact with the director and players
/// </summary>
public class FirstController : MonoBehaviour, ISceneController, IUserAction
{// 对每种物体新建类记录当前状态// 记录物体样式、位置等等public List<GameObject> Priests, Devils;public GameObject boat, bankLeft, bankRight;// 物体状态public List<PriestsStatus> p_status;public List<DevilsStatus> d_status;public BoatBehaviour myBoatBehaviour;// GameJudgepublic IGameJudge judge;// the first scriptsvoid Awake(){SSDirector director = SSDirector.getInstance();director.setFPS(60);director.currentSceneController = this;director.currentSceneController.LoadResources();}// loading resources for the first scencepublic void LoadResources(){// GameJudgejudge = new IGameJudge();// priestsPriests = new List<GameObject>();p_status = judge.p_status;for (int i = 0; i < 3; i++){GameObject priests = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Priests"),Vector3.zero, Quaternion.identity);priests.name = "Priest " + (i + 1);//priests.tag = "Priest";Priests.Add(priests);}//devilsDevils = new List<GameObject>();d_status = judge.d_status;for (int i = 0; i < 3; i++){GameObject devils = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Devils"),Vector3.zero, Quaternion.identity);devils.name = "Devil " + (i + 1);//devils.tag = "Devil";Devils.Add(devils);}//boatboat = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Boat"),Vector3.zero, Quaternion.identity);boat.name = "Boat";//bankbankLeft = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Shore"),Vector3.zero, Quaternion.identity);bankLeft.name = "BankLeft";bankRight = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Shore"),Vector3.zero, Quaternion.identity);bankRight.name = "BankRight";// 初始化restart();}public void boatMove(){// 船在动或者船上没人时不能开船if (judge.CanMove()){myBoatBehaviour.SetisMoving(true);}}public void onBoatMoving(){if (myBoatBehaviour.GetisMoving()){Vector3 moveDir;// 判断向左向右走List<int> place = judge.PersonOnBoat();if (place.Count == 0)return;// 向左int i1 = place[0];int i2 = place[1]; if (!myBoatBehaviour.GetatLeftSide()){moveDir = new Vector3(-0.1f, 0, 0);boat.transform.Translate(moveDir);// 判断第一个位置if (i1 != -1){if (i1 < 3)Priests[i1].transform.Translate(moveDir);elseDevils[i1 - 3].transform.Translate(moveDir);}// 判断第二个位置if (i2 != -1){if (i2 < 3)Priests[i2].transform.Translate(moveDir);elseDevils[i2 - 3].transform.Translate(moveDir);}//到达对岸if (boat.transform.position.x == -2.4f){myBoatBehaviour.SetisMoving(false);myBoatBehaviour.SetatLeftSide(true);}}// 向右else{moveDir = new Vector3(0.1f, 0, 0);boat.transform.Translate(moveDir);// 判断第一个位置if (i1 != -1){if (i1 < 3)Priests[i1].transform.Translate(moveDir);elseDevils[i1 - 3].transform.Translate(moveDir);}// 判断第二个位置if (i2 != -1){if (i2 < 3)Priests[i2].transform.Translate(moveDir);elseDevils[i2 - 3].transform.Translate(moveDir);}//到达对岸if (boat.transform.position.x == 1.7f){myBoatBehaviour.SetisMoving(false);myBoatBehaviour.SetatLeftSide(false);}}}}public void priestsGetOn(){// 如果船正在动,那么不能响应用户事件if (judge.BoatIsMoving())return;List<int> temp = judge.PriestGotoBoat();// 如果temp为空,说明没找到该上船的priestif(temp.Count == 0) return;int i = temp[0];p_status[i].SetonBankLeft(false);p_status[i].SetonBankRight(false);judge.ModifyPersonCountOnBank(false, true, temp[2]);judge.ModifyPersonCountOnBoat(true, true);// 上船的左边if (temp[1] == 0){p_status[i].SetonBoatLeft(true);myBoatBehaviour.SetleftPosEmpty(false);// 船在左岸if (myBoatBehaviour.GetatLeftSide())Priests[i].transform.position = new Vector3(-3.3f, 1.5f, 0);elsePriests[i].transform.position = new Vector3(1, 1.5f, 0);}else{p_status[i].SetonBoatRight(true);myBoatBehaviour.SetrightPosEmpty(false);// 船在右岸if (myBoatBehaviour.GetatLeftSide())Priests[i].transform.position = new Vector3(-1.8f, 1.5f, 0);elsePriests[i].transform.position = new Vector3(2.5f, 1.5f, 0);}}public void priestsGetOff(){if (judge.BoatIsMoving())return;List<int> temp = judge.PriestGoOffBoat();// 如果temp为空,说明没找到该上船的priestif (temp.Count == 0)return;int i = temp[0];judge.ModifyPersonCountOnBank(true, true, temp[2]);judge.ModifyPersonCountOnBoat(false, true);p_status[i].SetonBoatLeft(false);p_status[i].SetonBoatRight(false);// 船在左岸if (temp[2] == 1){p_status[i].SetonBankLeft(true);Priests[i].transform.position = new Vector3((-8.6f + i * 1.3f), 3, 0);if (temp[1] == 0)myBoatBehaviour.SetleftPosEmpty(true);elsemyBoatBehaviour.SetrightPosEmpty(true);}else{p_status[i].SetonBankRight(true);Priests[i].transform.position = new Vector3((6 + i * 1.3f), 3, 0);if (temp[1] == 0)myBoatBehaviour.SetleftPosEmpty(true);elsemyBoatBehaviour.SetrightPosEmpty(true);}}public void devilsGetOn(){// 如果船正在动,那么不能响应用户事件if (judge.BoatIsMoving())return;List<int> temp = judge.DevilGotoBoat();// 如果temp为空,说明没找到该上船的devilif (temp.Count == 0)return;int i = temp[0];d_status[i].SetonBankLeft(false);d_status[i].SetonBankRight(false);judge.ModifyPersonCountOnBank(false, false, temp[2]);judge.ModifyPersonCountOnBoat(true, false);// 上船的左边if (temp[1] == 0){d_status[i].SetonBoatLeft(true);myBoatBehaviour.SetleftPosEmpty(false);// 船在左岸if (myBoatBehaviour.GetatLeftSide())Devils[i].transform.position = new Vector3(-3.3f, 1.5f, 0);elseDevils[i].transform.position = new Vector3(1, 1.5f, 0);}else{d_status[i].SetonBoatRight(true);myBoatBehaviour.SetrightPosEmpty(false);// 船在右岸if (myBoatBehaviour.GetatLeftSide())Devils[i].transform.position = new Vector3(-1.8f, 1.5f, 0);elseDevils[i].transform.position = new Vector3(2.5f, 1.5f, 0);}}public void devilsGetOff(){if (judge.BoatIsMoving())return;List<int> temp = judge.DevilGoOffBoat();// 如果temp为空,说明没找到该上船的devilif (temp.Count == 0)return;int i = temp[0];judge.ModifyPersonCountOnBank(true, false, temp[2]);judge.ModifyPersonCountOnBoat(false, false);d_status[i].SetonBoatLeft(false);d_status[i].SetonBoatRight(false);// 船在左岸if (temp[2] == 1){d_status[i].SetonBankLeft(true);Devils[i].transform.position = new Vector3((-12.9f + i * 1.3f), 3, 0);if (temp[1] == 0)myBoatBehaviour.SetleftPosEmpty(true);elsemyBoatBehaviour.SetrightPosEmpty(true);}else{d_status[i].SetonBankRight(true);Devils[i].transform.position = new Vector3((10.3f + i * 1.3f), 3, 0);if (temp[1] == 0)myBoatBehaviour.SetleftPosEmpty(true);elsemyBoatBehaviour.SetrightPosEmpty(true);}}public int GameOver(){return judge.GameOver();}public void restart(){// priestsPriests[0].transform.position = new Vector3(-8.6f, 3, 0);Priests[1].transform.position = new Vector3(-7.3f, 3, 0);Priests[2].transform.position = new Vector3(-6, 3, 0);//devilsDevils[0].transform.position = new Vector3(-12.9f, 3, 0);Devils[1].transform.position = new Vector3(-11.6f, 3, 0);Devils[2].transform.position = new Vector3(-10.3f, 3, 0);//boatboat.transform.position = new Vector3(-2.4f, 0.5f, 0);//bankbankLeft.transform.position = new Vector3(-8.5f, 1.5f, 0);bankRight.transform.position = new Vector3(8.5f, 1.5f, 0);judge.reflash();}// Use this for initializationvoid Start(){//give advice first}// Update is called once per framevoid Update(){//give advice first// 将状态实时修改传回FirstControllerp_status = judge.p_status;d_status = judge.d_status;myBoatBehaviour = judge.boatBehaviour;//用于船和人的移动onBoatMoving();}}

这篇关于[3D游戏编程]Priests And Devils——动作分离版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

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

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

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)