游戏介绍:
与上一作业牧师与恶魔mvc版相同。
演示视频:
整体效果与上一作业相同,不再另外演示。详见作业4演示视频。
具体介绍:
一、动作分离架构
相较于上一作业的mvc架构将动作与对象绑定,并尽数交由scenecontroller管理,这一架构将controller层另外分出一动作层,由actionmanager管理,而actionmanager又受scenecontroller调用。同时,所有动作类由ssaction特化,而ssaction又继承自非组件的scriptableobject,使得动作与对象解耦。由此,action与上下两层独立开来,获得了更好的可复用性。
二、代码框架
与上一作业相同,firstcontroller依旧与SSDirector等类有关联,此处不再重复绘制。
三、具体实现
SSAction类:
public class SSAction : ScriptableObject {
public bool enable = true;
public bool destory = false;
public GameObject gameobject { get; set; }
public Transform transform { 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 ();
}
}
enable和destory用于标记动作状态,重点在于gameobject和transform成员,消除了原先的控制反转。
CCMoveToAction类:
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;
}
}
public override void Start () {
}
}
getssaction返回一个ccmovetoaction实例,update执行动作
SSActionManager类:
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 () {
foreach (SSAction ac in waitingAdd) actions [ac.GetInstanceID ()] = ac;
waitingAdd.Clear ();
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) {
action.gameobject = gameobject;
action.transform = gameobject.transform;
waitingAdd.Add (action);
action.Start ();
}
// Use this for initialization
protected void Start () {
}
}
waitingAdd,actions和waitingDelete分别为存储待执行、正在执行和待销毁动作的列表。Update函数维护这三个列表并调用actions中动作的update函数。RunAction被外部调用以向waitingAdd列表添加动作。
CCActionManager类:
public class CCActionManager : SSActionManager {
private FirstController sceneController;
private CCMoveToAction moveToShip, moveToBank, moveShip;
protected new void Start() {
sceneController = (FirstController)SSDirector.getInstance ().currentSceneController;
sceneController.actionManager = this;
}
// Update is called once per frame
protected new void Update ()
{
base.Update ();
}
public void setMoveShip(GameObject gameobject, int boatstate){
Vector3 vector;
if(boatstate == 2)
vector = new Vector3(4f, 0, 0);
else
vector = new Vector3(-4f, 0, 0);
moveShip = CCMoveToAction.GetSSAction(vector, 10);
this.RunAction(gameobject,moveShip);
}
public void setMoveToShip(GameObject gameobject,int seat,int boatstate){
Vector3 vector;
if(boatstate == 1)
vector = new Vector3(-4f + (seat==1?1:-1), 0.5f, 0);
else
vector = new Vector3(4f + (seat==1?1:-1), 0.5f, 0);
moveToShip = CCMoveToAction.GetSSAction(vector, 10);
Debug.Log("movetoship,target:"+vector);
this.RunAction(gameobject,moveToShip);
}
public void setMoveToBank(GameObject gameobject, int boatstate, int number){
Vector3 vector;
if(boatstate == 1)
vector = new Vector3(-6.5f+(number>2?-1:0),1f,-1f+number%3);
else
vector = new Vector3(6.5f+(number>2?1:0),1f,-1f+number%3);
moveToBank = CCMoveToAction.GetSSAction(vector,10);
Debug.Log("movetobank,target:"+vector);
this.RunAction(gameobject,moveToBank);
}
}
sceneController保存当前场景控制器对象,moveToShip等为三个moveto动作。Start为初始化函数,三个set函数分别创建新的moveto动作对象并执行。
Judger类:
public class Judger : ScriptableObject
{
private FirstController sceneController;
public int[] leftbank;
public int[] rightbank;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void Initialize(){
sceneController = (FirstController)SSDirector.getInstance ().currentSceneController;
leftbank = new int[6]{1,1,1,-1,-1,-1};
rightbank = new int[6]{0,0,0,0,0,0};
}
public void Check_if_lose(){
if ((leftbank.Sum() < 0 && leftbank.Take(3).Sum() > 0)|| (rightbank.Sum() < 0 && rightbank.Take(3).Sum() > 0)){
sceneController.winflag = false;
sceneController.GameOver();
}
}
public void Check_if_win(){
sceneController.winflag = false;
for(int i = 0;i<6;i++){
if(rightbank[i] == 0)
return;
}
sceneController.winflag = true;
sceneController.GameOver();
}
public void UpdateBank(){
for(int i = 0;i<3;i++){
leftbank[i] = 0;
leftbank[i+3] = 0;
rightbank[i] = 0;
rightbank[i+3] = 0;
if(sceneController.chastate[i] == 1)
leftbank[i] = 1;
else if(sceneController.chastate[i] == 2)
rightbank[i] = 1;
if(sceneController.chastate[i+3] == 1)
leftbank[i+3] = -1;
else if(sceneController.chastate[i+3] == 2)
rightbank[i+3] = -1;
}
}
}
将胜负判断逻辑独立于FirstController。
FirstController类基本与作业4一致,仅将对动作和对象的直接操作变为调用actionManager中函数,以及将胜负判断逻辑分离至Judger,故不再重复展示。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。