牧师与魔鬼(动作分离版)

简介

用 Unity实现一个简单的小游戏,就做牧师与魔鬼,没玩过的童鞋们可以去玩一玩,一个益智小游戏传送门
(之前做了个没有动作分离的。。但是那时忘了发博客。。于是。。只能做动作分离版的了)

UML图

这里写图片描述
这个框架主要参考了老师上课给的框架。。而且大部分代码都是参考老师的代码。。

对象处理

由于是做一个简单的小游戏,所以人物什么的模型也没有花心思去找了。
这里写图片描述
蓝色的矩形表示船
这里写图片描述
红色的球表示魔鬼(注意:在Tag那里也要设为魔鬼,方便代码调用)
这里写图片描述
绿色的球表示牧师(注意项跟魔鬼相同)

代码

代码。。貌似有点多
SSDirector.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum State { WIN, LOSE, PAUSE, CONTINUE , START };
public class SSDirector : System.Object {

    private static SSDirector _instance;
    public int totalSeconds = 60;
    public int leaveSeconds;
    public bool onCountDown = false;
    public string countDownTitle = "Start";

    public ISceneController currentSceneController { get; set; }
    public State state { get; set; }
    public bool running { get; set; }

    // get instance anytime anywhere!
    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 IEnumerator DoCountDown() {
        while (leaveSeconds > 0) {
            yield return new WaitForSeconds (1f);
            leaveSeconds--;
        }
    }
}

FirstController.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FirstController : MonoBehaviour, IUserAction, ISceneController {

    public CCActionManager actionManager;

    List<GameObject> LeftObjList = new List<GameObject>();
    List<GameObject> RightObjList = new List<GameObject>();
    GameObject[] boat = new GameObject[2];

    GameObject boat_obj, leftShore_obj, rightShore_obj;

    Vector3 LeftShorePos = new Vector3(-12, 0, 0);
    Vector3 RightShorePos = new Vector3(12, 0, 0);
    Vector3 BoatLeftPos = new Vector3(-4, 0, 0);
    Vector3 BoatRightPos = new Vector3(4, 0, 0);

    void Awake() {
        SSDirector director = SSDirector.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;
        director.currentSceneController.LoadResources();
        director.leaveSeconds = director.totalSeconds;
    }

    void Start () {
        SSDirector.getInstance().state = State.PAUSE;
        SSDirector.getInstance().countDownTitle = "Start";
        actionManager = GetComponent<CCActionManager>() as CCActionManager;
    }

    void Update() {
        check();
    }

    public void LoadResources() {
        GameObject priest_obj, devil_obj;
        Camera.main.transform.position = new Vector3(0, 0, -20);

        leftShore_obj = Instantiate(Resources.Load("prefabs/Shore"), LeftShorePos, Quaternion.identity) as GameObject;
        rightShore_obj = Instantiate(Resources.Load("prefabs/Shore"), RightShorePos, Quaternion.identity) as GameObject;
        leftShore_obj.name = "left_shore";
        rightShore_obj.name = "right_shore";

        boat_obj = Instantiate(Resources.Load("prefabs/Boat"), BoatLeftPos, Quaternion.identity) as GameObject;
        boat_obj.name = "boat";
        boat_obj.transform.parent = leftShore_obj.transform;

        for (int i = 0; i < 3; ++i) {
            priest_obj = Instantiate(Resources.Load("prefabs/Priest")) as GameObject;
            priest_obj.name = i.ToString();
            priest_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(priest_obj.name), 2.7f, 0);
            priest_obj.transform.parent = leftShore_obj.transform;
            LeftObjList.Add(priest_obj);

            devil_obj = Instantiate(Resources.Load("prefabs/Devil")) as GameObject;
            devil_obj.name = (i + 3).ToString();
            devil_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(devil_obj.name), 2.7f, 0);
            devil_obj.transform.parent = leftShore_obj.transform;
            LeftObjList.Add(devil_obj);
        }
    }

    public void click() {
        GameObject gameObj = null;

        if (Input.GetMouseButtonDown(0) && 
            (SSDirector.getInstance().state == State.START || SSDirector.getInstance().state == State.CONTINUE)) {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit)) gameObj = hit.transform.gameObject;
        }

        if (gameObj == null) return;
        else if (gameObj.name == "0" || gameObj.name == "1" || gameObj.name == "2"
            || gameObj.name == "3" || gameObj.name == "4" || gameObj.name == "5")
            MovePeople(gameObj);
        else if(gameObj.name == "boat") MoveBoat();
    }

    void MovePeople(GameObject people) {
        int shoreNum, seatNum;

        if (people.transform.parent == boat_obj.transform.parent && (boat[0] == null || boat[1] == null)) {
            seatNum = boat[0] == null ? 0 : 1;
            if (people.transform.parent == leftShore_obj.transform) {
                shoreNum = 0;
                for (int i = 0; i < LeftObjList.Count; i++) {
                    if (people.name == LeftObjList[i].name) {
                        Debug.Log (actionManager);
                        actionManager.getOnBoat(people, shoreNum, seatNum);
                        LeftObjList.Remove(LeftObjList[i]);
                    }
                }
            } else {
                shoreNum = 1;
                for (int i = 0; i < RightObjList.Count; i++) {
                    if (people.name == RightObjList[i].name) {
                        actionManager.getOnBoat(people, shoreNum, seatNum);
                        RightObjList.Remove(RightObjList[i]);
                    }
                }
            }
            boat[seatNum] = people;
            people.transform.parent = boat_obj.transform;
        } else if (people.transform.parent == boat_obj.transform) {
            shoreNum = boat_obj.transform.parent == leftShore_obj.transform ? 0 : 1;
            seatNum = (boat[0] != null && boat[0].name == people.name) ? 0 : 1;

            actionManager.getOffBoat(people, shoreNum);

            boat[seatNum] = null;
            if(shoreNum == 0) {
                people.transform.parent = leftShore_obj.transform;
                LeftObjList.Add(people);
            } else {
                people.transform.parent = rightShore_obj.transform;
                RightObjList.Add(people);
            }
        }
    }

    void MoveBoat() {
        if (!(boat[0]==null && boat[1] == null)) {
            actionManager.moveBoat(boat_obj);
            boat_obj.transform.parent = boat_obj.transform.parent == leftShore_obj.transform ? rightShore_obj.transform : leftShore_obj.transform;
        }
    }

    public void check() {
        int left_d = 0, left_p = 0, right_d = 0, right_p = 0;

        foreach (GameObject element in LeftObjList) {
            if (element.tag == "Priest") left_p++;
            if (element.tag == "Devil") left_d++;
        }

        foreach (GameObject element in RightObjList) {
            if (element.tag == "Priest") right_p++;
            if (element.tag == "Devil") right_d++;
        }

        for (int i = 0; i < 2; i++) {
            if (boat[i] != null && boat_obj.transform.parent == leftShore_obj.transform) {
                if (boat[i].tag == "Priest") left_p++;
                else left_d++;
            }
            if (boat[i] != null && boat_obj.transform.parent == rightShore_obj.transform) {
                if (boat[i].tag == "Priest") right_p++;
                else right_d++;
            }
        }

        if ((left_d > left_p && left_p != 0) || (right_d > right_p && right_p != 0) || SSDirector.getInstance().leaveSeconds == 0)
            SSDirector.getInstance().state = State.LOSE;
        else if (right_d == right_p && right_d == 3) SSDirector.getInstance().state = State.WIN;
    }

    public void Pause() {
        SSDirector.getInstance().state = State.PAUSE;
    }

    public void Resume() {
        SSDirector.getInstance().state = State.CONTINUE;
    }

    public void Restart() {
        Application.LoadLevel(Application.loadedLevelName);
        SSDirector.getInstance().state = State.START;
    }
}

SSActionManager.cs

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>();
    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());
            } 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 = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }

    protected void Start() {}
}

SSAction.cs

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() {}

    public virtual void Start () {
        throw new System.NotImplementedException();
    }

    public virtual void Update () {
        throw new System.NotImplementedException ();
    }
}

CCMoveToAction.cs

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) {
            this.destory = true;
            this.callback.SSActionEvent (this);
        }
    }

    public override void Start () {}
}

CCSequenceAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CCSequenceAction : SSAction, ISSActionCallback {

    public List<SSAction> sequence;
    public int repeat = -1;
    public int start = 0;


    public static CCSequenceAction GetSSAction (int repeat, int start, List<SSAction> sequence) {
        CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction> ();
        action.repeat = 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 ();
        }
    }

    public void SSActionEvent (SSAction source, SSActionEventType events = SSActionEventType.Completed, int Param = 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() {}
}

ISSActionCallback.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum SSActionEventType:int {Started, Completed}

public interface ISSActionCallback {
    void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null);
}

ISceneController.cs

public interface ISceneController {
    void LoadResources();
    void Pause();
    void Resume();
    void Restart();
}

UserGUI.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IUserAction {
    void click();
}

public class UserGUI : MonoBehaviour {

    private IUserAction action;
    float width, height;

    void Start() {
        action = SSDirector.getInstance().currentSceneController as IUserAction;
    }

    float castw(float scale) {
        return (Screen.width - width) / scale;
    }

    float casth(float scale) {
        return (Screen.height - height) / scale;
    }

    void OnGUI() {
        width = Screen.width / 12;
        height = Screen.height / 12;

        GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), SSDirector.getInstance().leaveSeconds.ToString());// 倒计时秒数 //  
        if (SSDirector.getInstance().state != State.WIN && SSDirector.getInstance().state != State.LOSE
            && GUI.Button(new Rect(10, 10, 80, 30), SSDirector.getInstance().countDownTitle)) {
            if (SSDirector.getInstance().countDownTitle == "Start") {

                SSDirector.getInstance().currentSceneController.Resume();
                SSDirector.getInstance().countDownTitle = "Pause";
                SSDirector.getInstance().onCountDown = true;
                StartCoroutine(SSDirector.getInstance().DoCountDown());
            } else {
                SSDirector.getInstance().currentSceneController.Pause();
                SSDirector.getInstance().countDownTitle = "Start";
                SSDirector.getInstance().onCountDown = false;
                StopAllCoroutines();
            }
        }

        if (SSDirector.getInstance().state == State.WIN) {
            StopAllCoroutines();
            if (GUI.Button(new Rect(castw(2f), casth(6f), Screen.width / 8, height), "Win!")) SSDirector.getInstance().currentSceneController.Restart();
        } else if (SSDirector.getInstance().state == State.LOSE) {
            StopAllCoroutines();
            if (GUI.Button(new Rect(castw(2f), casth(6f), Screen.width / 7, height), "Lose!")) SSDirector.getInstance().currentSceneController.Restart();
        }
    }

    void Update() {
        action.click();
    }

}

CCActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CCActionManager : SSActionManager, ISSActionCallback {

    public FirstController scene;
    public CCMoveToAction action1, action2;
    public CCSequenceAction saction;
    float speed = 30f;

    public void moveBoat(GameObject boat) {
        action1 = CCMoveToAction.GetSSAction((boat.transform.position ==  new Vector3(4, 0, 0)? new Vector3(-4, 0, 0) : new Vector3(4, 0, 0)), speed);
        this.RunAction(boat, action1, this);
    }

    public void getOnBoat(GameObject people, int shore, int seat) {
        if (shore == 0 && seat == 0) {
            action1 = CCMoveToAction.GetSSAction(new Vector3(-5f, 2.7f, 0), speed);
            action2 = CCMoveToAction.GetSSAction(new Vector3(-5f, 1.2f, 0), speed);
        }
        else if(shore==0 && seat == 1) {
            action1 = CCMoveToAction.GetSSAction(new Vector3(-3f, 2.7f, 0), speed);
            action2 = CCMoveToAction.GetSSAction(new Vector3(-3f, 1.2f, 0), speed);
        }
        else if (shore == 1 && seat == 0) {
            action1 = CCMoveToAction.GetSSAction(new Vector3(3f, 2.7f, 0), speed);
            action2 = CCMoveToAction.GetSSAction(new Vector3(3f, 1.2f, 0), speed);
        }
        else if (shore == 1 && seat == 1) {
            action1 = CCMoveToAction.GetSSAction(new Vector3(5f, 2.7f, 0), speed);
            action2 = CCMoveToAction.GetSSAction(new Vector3(5f, 1.2f, 0), speed);
        }

        CCSequenceAction saction = CCSequenceAction.GetSSAction(0, 0, new List<SSAction> { action1, action2 });
        this.RunAction(people, saction, this);
    }

    public void getOffBoat(GameObject people, int shoreNum) {
        action1 = CCMoveToAction.GetSSAction(new Vector3(people.transform.position.x, 2.7f, 0), speed);
        if (shoreNum == 0)  action2 = CCMoveToAction.GetSSAction(new Vector3(-16f + 1.5f * System.Convert.ToInt32(people.name), 2.7f, 0), speed);
        else action2 = CCMoveToAction.GetSSAction(new Vector3(16f - 1.5f * System.Convert.ToInt32(people.name), 2.7f, 0), speed);

        CCSequenceAction saction = CCSequenceAction.GetSSAction(0, 0, new List < SSAction >{ action1, action2});
        this.RunAction(people, saction, this);
    }

    protected void Start() {
        scene = (FirstController)SSDirector.getInstance().currentSceneController;
        scene.actionManager = this;
    }

    protected new void Update() {
        base.Update();
    }

    public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null) {
        Debug.Log("Done");
    }
}

其中UserGUI是挂在摄像机上的,CCActionManager和FirstController是挂在Main对象上的。
由于代码。。大多数都是参考老师的框架。。所以我先投为转的吧。

效果

gif录制器突然。。找不到了。。找几个过场图片撑撑场面。
这里写图片描述
结果。。输了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值