牧师与魔鬼(动作分离版)
说明
这次游戏是基于上一次的牧师与魔鬼游戏,不同之处主要有两点。其一是将FirstController中的判断游戏结束代码逻辑分离,放到Judge裁判类中;其二是用CCActionManagement动作管理器,对所有游戏对象的动作进行管理,替换原本的move和moveCtrl。
裁判类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Judge : MonoBehaviour
{
private FirstController sceneController;
public bool gameOver = false;//是否结束
public bool gameWin = false;//是否胜利
int r_a = 0, r_d = 0;
int l_a = 3, l_d = 3;
void Start()
{
sceneController = (FirstController)SSDirector.getInstance().currentSceneController;
sceneController.gameJudge = this;
}
void Update()
{
//左右天使与魔鬼的数量
l_d = sceneController.leftD;
r_d = sceneController.rightD;
l_a = sceneController.leftA;
r_a = sceneController.rightA;
check();
}
void check()
{
if (l_a > 0 && l_a < l_d || r_a > 0 && r_a < r_d)
{
gameOver = true;
gameWin = false;
sceneController.GameOver();
}
else if (r_a == 3 && r_d == 3)
{
gameOver = true;
gameWin = true;
sceneController.GameOver();
}
}
}
start()函数用于初始化,获取场景控制器实例(有裁判对象),用于传递游戏结束和游戏胜利标志(gameOver和gameWin)
每次Update更新,左右河岸牧师与魔鬼的数量,裁判类judge根据这四个变量进行判断
动作管理相关类
SSAction是各种动作的父类,其子类CCSequenceAction和CCMoveToAction分别对应顺序组合动作和单个移动动作。
GetSSAction用于定义动作,例如,CCMoveToAction中,设置移动的目的地坐标、移动速度,而在CCSequenceAction中,设置动作组合顺序、重复次数、开始动作。
SSActionManager是动作管理器的父类,主要是管理动作何时执行和销毁。CCActionManger继承实现,主要用于场景控制器通信。
RunAction将动作绑定到游戏对象,并指定动作管理器。UpDate用于执行和销毁动作。
具体代码
SSAction类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSAction : ScriptableObject {
public bool enable = true;
public bool destory = false;
public GameObject gameobject { get; set; }
public Transform transform { get; set; }
public ISSActionCallback callback { get; set; }
protected SSAction () {}
// Use this for initialization
public virtual void Start () {
throw new System.NotImplementedException ();
}
// Update is called once per frame
public virtual void Update () {
throw new System.NotImplementedException ();
}
}
CCSequenceAction类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCSequenceAction : SSAction, ISSActionCallback
{
public List<SSAction> sequence;
public int repeat = -1; //repeat forever,循环执行次数
public int start = 0;
public static CCSequenceAction GetSSAction(int repeat, int start , List<SSAction> sequence){
//非持久化,该对象只存在于内存中,可以被GC垃圾回收,调用一次就创建一次。
CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction> ();
action.repeat = repeat;
action.sequence= sequence;
action.start = start;
return action;
}
// Update is called once per frame
public override void Update ()
{
if (sequence.Count == 0) return;
if (start < sequence.Count) {
sequence [start].Update ();
}
}
public void SSActionEvent (SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null)
{
source.destory = false;
this.start++;
if (this.start >= sequence.Count) {
this.start = 0;
if (repeat > 0) repeat--;
if (repeat == 0) { this.destory = true; this.callback.SSActionEvent (this); }
}
}
// Use this for initialization
public override void Start () {
foreach (SSAction action in sequence) {
action.gameobject = this.gameobject;
action.transform = this.transform;
action.callback = this;
action.Start ();
}
}
void OnDestory() {
//TODO: something
}
}
CCMoveToAction类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCMoveToAction : SSAction
{
public Vector3 target;
public float speed;
public static CCMoveToAction GetSSAction(Vector3 target, float speed){
CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction> ();
action.target = target;
action.speed = speed;
return action;
}
public override void Update ()
{
this.transform.position = Vector3.MoveTowards (this.transform.position, target, speed * Time.deltaTime);
if (this.transform.position == target) {
//waiting for destroy
this.destory = true;
this.callback.SSActionEvent (this);
}
}
public override void Start () {
}
}
SSActionManager类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSActionManager : MonoBehaviour {
private Dictionary <int, SSAction> actions = new Dictionary <int, SSAction> ();
private List <SSAction> waitingAdd = new List<SSAction> ();
private List<int> waitingDelete = new List<int> ();
// Update is called once per frame
protected void Update () {
//添加动作到管理器
//GetInstanceID是对象Object的id
foreach (SSAction ac in waitingAdd) actions [ac.GetInstanceID ()] = ac;
waitingAdd.Clear ();
//等待销毁or执行动作
foreach (KeyValuePair <int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.destory) {
waitingDelete.Add(ac.GetInstanceID()); // release action
} else if (ac.enable) {
ac.Update (); // update action
}
}
//销毁动作
foreach (int key in waitingDelete) {
SSAction ac = actions[key];
actions.Remove(key);
Object.Destroy(ac);
}
waitingDelete.Clear ();
}
//等待添加动作,要执行的动作
public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add (action);
action.Start ();
}
// Use this for initialization
protected void Start () {
}
}
CCActionManager类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCActionManager : SSActionManager, ISSActionCallback {
private FirstController sceneController;
private CCMoveToAction moveToA , moveToB, moveToC, moveToD;
protected new void Start() {
sceneController = (FirstController)SSDirector.getInstance ().currentSceneController;
sceneController.actionManager = this;
}
// Update is called once per frame
protected new void Update ()
{
//调用父类SSActionManager的函数
base.Update ();
}
//region--endregion用于折叠代码,无实际意义
#region ISSActionCallback implementation
public void SSActionEvent (SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null)
{
}
#endregion
}
ISSActionCallback接口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
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);
}
FirstController类中改动不大,主要是用CCActionManeger对象处理替换MoveController对象处理,以及定义相关action动作,传递给CCActionManeger动作管理器,另外还有把判断游戏结束的函数逻辑抽出放到Judge类,此处略过这部分代码。
游戏视频(最终效果与之前类似)
注:视频中的背景需要下载相关资源包,对该游戏没有影响。
游戏视频链接
牧师与魔鬼过河小游戏(动作分离版)