3D游戏编程与设计Hw5(牧师与魔鬼动作分离版)

阅读: 评论:0

3D游戏编程与设计Hw5(牧师与魔鬼动作分离版)

3D游戏编程与设计Hw5(牧师与魔鬼动作分离版)

动作分离:即 将游戏达到结束条件时的判断从场景控制器中分离出来处理。

同时也要将管理物体移动的程序从场景控制器中分离,以便独立管理游戏对象的动作。

首先:删除Moveable文件,新建Action和Judge文件

Action

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSAction : ScriptableObject{           //动作public bool enable = true;                      //是否正在进行此动作public bool destroy = false;                    //是否需要被销毁public GameObject gameobject{get;set;}                   //动作对象public Transform transform{get;set;}                     //动作对象的transformpublic ISSActionCallback callback{get;set;}              //回调函数protected SSAction() { }                        //保证SSAction不会被newpublic virtual void Start()                    //子类可以使用这两个函数{throw new System.NotImplementedException();}public virtual void Update(){throw new System.NotImplementedException();}
}public class SSMoveToAction : SSAction                        //移动
{public Vector3 target;        //移动到的目的地public float speed;           //移动的速度private SSMoveToAction() { }public static SSMoveToAction GetSSAction(Vector3 target, float speed){SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();//让unity自己创建一个MoveToAction实例,并自己回收action.target = target;action.speed = speed;return action;}public override void Update(){ansform.position = Vector3.ansform.position, target, speed * Time.deltaTime);if (ansform.position == target){this.destroy = true;this.callback.SSActionEvent(this);      //告诉动作管理或动作组合这个动作已完成}}public override void Start(){//移动动作建立时候不做任何事情}
}public class SequenceAction : SSAction, ISSActionCallback
{public List<SSAction> sequence;    //动作的列表public int repeat = -1;            //-1就是无限循环做组合中的动作public int start = 0;              //当前做的动作的索引public static SequenceAction GetSSAcition(int repeat, int start, List<SSAction> sequence){SequenceAction action = ScriptableObject.CreateInstance<SequenceAction>();//让unity自己创建一个SequenceAction实例peat = repeat;action.sequence = sequence;action.start = start;return action;}public override void Update(){if (sequence.Count == 0) return;if (start < sequence.Count){sequence[start].Update();     //一个组合中的一个动作执行完后会调用接口,所以这里看似没有start++实则是在回调接口函数中实现}}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null){source.destroy = false;          //先保留这个动作,如果是无限循环动作组合之后还需要使用this.start++;if (this.start >= sequence.Count){this.start = 0;if (repeat > 0) repeat--;if (repeat == 0){this.destroy = true;               //整个组合动作就删除this.callback.SSActionEvent(this); //告诉组合动作的管理对象组合做完了}}}public override void Start(){foreach (SSAction action in sequence){action.gameobject = this.ansform = ansform;action.callback = this;                //组合动作的每个小的动作的回调是这个组合动作action.Start();}}void OnDestroy(){//如果组合动作做完第一个动作突然不要它继续做了,那么后面的具体的动作需要被释放}
}public enum SSActionEventType : int { Started, Competeted }public interface ISSActionCallback
{void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null);
}public class SSActionManager : MonoBehaviour, ISSActionCallback                      //action管理器
{private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();    //将执行的动作的字典集合,int为key,SSAction为valueprivate List<SSAction> waitingAdd = new List<SSAction>();                       //等待去执行的动作列表private List<int> waitingDelete = new List<int>();                              //等待删除的动作的key                //不断更新待处理的动作protected void Update(){foreach (SSAction ac in waitingAdd){actions[ac.GetInstanceID()] = ac;                                      //获取动作实例的ID作为key}waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> kv in actions){SSAction ac = kv.Value;if (ac.destroy){waitingDelete.Add(ac.GetInstanceID());}else if (ac.enable){ac.Update();}}foreach (int key in waitingDelete){SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager){action.gameobject = ansform = ansform;action.callback = manager;waitingAdd.Add(action);action.Start();}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null){//牧师与魔鬼的游戏对象移动完成后就没有下一个要做的动作了,所以回调函数为空}
}public class MySceneActionManager : SSActionManager  //本游戏管理器
{private SSMoveToAction moveBoatToEndOrStart;     //移动船到结束岸,移动船到开始岸private SequenceAction moveRoleToLandorBoat;     //移动角色到陆地,移动角色到船上public FirstController sceneController;protected new void Start(){sceneController = (Instance().currentSceneController;sceneController.actionManager = this;}public void moveBoat(GameObject boat, Vector3 target, float speed){moveBoatToEndOrStart = SSMoveToAction.GetSSAction(target, speed);//创建移动动作this.RunAction(boat, moveBoatToEndOrStart, this);//执行动作}public void moveCharacter(GameObject role, Vector3 middle_pos, Vector3 end_pos, float speed){SSAction action1 = SSMoveToAction.GetSSAction(middle_pos, speed);//创建前半部分路径的移动动作SSAction action2 = SSMoveToAction.GetSSAction(end_pos, speed);//创建后半部分路径的移动动作moveRoleToLandorBoat = SequenceAction.GetSSAcition(1, 0, new List<SSAction> { action1, action2 });//将两个动作组合成一个动作序列this.RunAction(role, moveRoleToLandorBoat, this);//执行动作序列}
}

Judge

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Judge : MonoBehaviour{private Land startLand;// 起始河岸private Land endLand;// 终点河岸private Boat boat;// 船public Judge(Land _startLand, Land _endLand, Boat _boat){startLand = _startLand;endLand = _endLand;boat = _boat;}public int checkGameState() {	// 船在出发点int startNumOfPriest = NumOfPriest();int startNumOfDevil = NumOfDevil();int endNumOfPriest = NumOfPriest();int endNumOfDevil = NumOfDevil();int boatNumOfPriest = NumOfPriest();int boatNumOfDevil = NumOfDevil();if(endNumOfPriest + endNumOfDevil + boatNumOfPriest + boatNumOfDevil == 6){return 2;}CurPosition() == 1){if((startNumOfPriest  < startNumOfDevil && startNumOfPriest > 0)||(endNumOfPriest +  boatNumOfPriest < endNumOfDevil + boatNumOfDevil && endNumOfPriest +  boatNumOfPriest > 0)){return 1;}}else{if((startNumOfPriest + boatNumOfPriest < startNumOfDevil + boatNumOfDevil && startNumOfPriest + boatNumOfPriest > 0) || (endNumOfPriest < endNumOfDevil && endNumOfPriest > 0)){return 1;}}return 0;}
}

修改Judge时同时需要更改FirstController的代码,在FirstController中调用Judge中的判断游戏结束的函数,因此FirstController的代码更改如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class FirstController : MonoBehaviour, SceneController, UserAction{readonly Vector3 water_pos = new Vector3(0,-0.4F,0);// 河流预制的位置public Land startLand;// 起始河岸public Land endLand;// 终点河岸public Boat boat;// 船public int state;//游戏状态 0-gaming 1-lose 2-win private Character[] characters;// 六个游戏角色private _GUI userGUI;// GUI组件private Judge judge;// 新增的裁判类public MySceneActionManager actionManager;   //新增的动作管理void Awake() {// 将自身设置为当前场记Director director = Instance ();director.currentSceneController = this;// 将GUI作为一个组件userGUI = gameObject.AddComponent <_GUI>() as _GUI;characters = new Character[6];// 加载游戏资源loadResources();// 将游戏动作管理器作为一个组件actionManager = gameObject.AddComponent<MySceneActionManager>() as MySceneActionManager; }// 实现SceneController接口,加载游戏资源public void loadResources() {GameObject water = Instantiate (Resources.Load ("Prefabs/river", typeof(GameObject)), water_pos, Quaternion.identity, null) as GameObject;water.name = "water";startLand = new Land ("start");endLand = new Land ("end");boat = new Boat();judge = new Judge(startLand, endLand, boat);// 新增裁判类的初始化loadCharacter ();}// 实现SceneController接口,检查游戏状态 0->not finish, 1->lose, 2->win// public void checkGameState() {	// 	// 船在出发点// 	int startNumOfPriest = NumOfPriest();// 	int startNumOfDevil = NumOfDevil();// 	int endNumOfPriest = NumOfPriest();// 	int endNumOfDevil = NumOfDevil();// 	int boatNumOfPriest = NumOfPriest();// 	int boatNumOfDevil = NumOfDevil();// 	if(endNumOfPriest + endNumOfDevil + boatNumOfPriest + boatNumOfDevil == 6){// 		state = 2;// 		return ;// 	}// 	CurPosition() == 1){// 		if((startNumOfPriest  < startNumOfDevil && startNumOfPriest > 0)||(endNumOfPriest +  boatNumOfPriest < endNumOfDevil + boatNumOfDevil && endNumOfPriest +  boatNumOfPriest > 0)){// 			state = 1;// 			return ;// 		}// 	}// 	else{// 		if((startNumOfPriest + boatNumOfPriest < startNumOfDevil + boatNumOfDevil && startNumOfPriest + boatNumOfPriest > 0) || (endNumOfPriest < endNumOfDevil && endNumOfPriest > 0)){// 			state = 1;// 			return ;// 		}// 	}// 	state = 0;// }// 加载游戏对象private void loadCharacter() {for (int i = 0; i < 3; i++) {Character ch = new Character("priest");ch.setName("priest" + i);ch.getOnLand(startLand);ch.setPosition (OnLand(ch));characters[i] = ch;}for (int i = 0; i < 3; i++) {Character ch = new Character("devil");ch.setName("devil" + i);ch.setPosition (OnLand(ch));ch.getOnLand(startLand);characters [i+3] = ch;}}// 动作分离版新增,获取游戏对象到达目的地的路径上的中间位置,以便实现折线移动public Vector3 getMiddlePosition(GameObject gameObject,Vector3 dest){Vector3 middle = dest;if (dest.y < ansform.position.y) {	// character from coast to boatmiddle.y = ansform.position.y;} else {								// character from boat to coastmiddle.x = ansform.position.x;}return middle;}// 动作分离版修改,修改了原有的goButtonIsClickedpublic void goButtonIsClicked(){                 if (!boat.isEmpty()){GameObject(),boat.boatMoveToPosition(),ve_speed);   //动作分离版本改变state = judge.checkGameState();}}// 动作分离版修改,修改了原有的characterIsClickedpublic void characterIsClicked(Character ch){// 角色在船上IsOnBoat()){CurPosition() == 0){Vector3 end_pos = OnLand(ch);////ch.OnLand(ch));// 原来的//Vector3 end_pos = land.GetEmptyPosition();                                         //动作分离版本改变Vector3 middle_pos = GameObject(),end_pos);  //动作分离版本改变GameObject(), middle_pos, end_pos, ch.move_speed);  //动作分离版本改变ch.getOnLand(startLand);}else{Vector3 end_pos = OnLand(ch);Vector3 middle_pos = GameObject(),end_pos);  //动作分离版本改变GameObject(), middle_pos, end_pos, ch.move_speed);  //动作分离版本改变//ch.OnLand(ch));ch.getOnLand(endLand);}ch.getOffBoat();vePassenger(ch);}// 角色在岸上else{if(!boat.isFull()){IsFinished() && CurPosition() == 1){ch.getOnBoat(boat);endLand.leaveLand(ch);Vector3 end_pos = EmptyPosition();Vector3 middle_pos = GameObject(),end_pos);//ch.EmptyPosition());GameObject(), middle_pos, end_pos, ch.move_speed);  //动作分离版本改变boat.addPassenger(ch);}if(!ch.getIsFinished() && CurPosition() == 0){ch.getOnBoat(boat);startLand.leaveLand(ch);Vector3 end_pos = EmptyPosition();Vector3 middle_pos = GameObject(),end_pos);GameObject(), middle_pos, end_pos, ch.move_speed);  //动作分离版本改变//ch.EmptyPosition());boat.addPassenger(ch);}}}}// 实现UserAction接口的goButtonIsClicked函数// public void goButtonIsClicked(){// 	if(!boat.isEmpty()){// 		ve();// 		checkGameState();// 	}// }// 实现UserAction接口的characterIsClicked函数// public void characterIsClicked(Character ch){// 	// 角色在船上// 	IsOnBoat()){// 		CurPosition() == 0){// 			ch.OnLand(ch));// 			ch.getOnLand(startLand);// 		}// 		else{// 			ch.OnLand(ch));// 			ch.getOnLand(endLand);// 		}// 		ch.getOffBoat();// 		vePassenger(ch);// 	}// 	// 角色在岸上// 	else{// 		if(!boat.isFull()){// 			IsFinished() && CurPosition() == 1){// 				ch.getOnBoat(boat);// 				endLand.leaveLand(ch);// 				ch.EmptyPosition());// 				boat.addPassenger(ch);// 			}// 			if(!ch.getIsFinished() && CurPosition() == 0){// 				ch.getOnBoat(boat);// 				startLand.leaveLand(ch);// 				ch.EmptyPosition());// 				boat.addPassenger(ch);// 			}// 		}// 	}// }// 重置游戏public void restart(){state = 0;for(int i = 0;i < 6;++i){characters[i].reset();}set();set();set();		}}

以及SceneController中的checkGameState()函数也不需要了,因为功能在Judge里实现了。

游戏实际效果不变,因此链接如下

3D作业魔鬼与牧师

本文发布于:2024-02-02 13:27:00,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170685161944105.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:牧师   魔鬼   动作   游戏
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23