改进Hit_Disk游戏

改进Hit_Disk游戏

1.内容与要求
  1. 按照adapter模式设计图修改飞碟游戏
  2. 使它同时支持物理学运动与运动学(变换)运动
2. 变换运动的实现

在之前的项目中已经实现了disk的变换运动,也就是一个disk会随着时间不断地改变其在空间中的位置,本次需要让disk实现物理运动的功能,也就是要给给一个重力让其实现初速度不为0的自由落体运动。通过实现adapter模式使得物理学运动与变换运动可以一起工作。同时不能放弃之前已经实现的模式:工厂对象、动作管理等

Adapter模式:将一个类的接口转换为客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。

3.实现adapter模式:
3.1 通过接口IActionManager接口来管理两种运动,接口中为两种运动具有的相同的动作。
public interface IActionManager
{
    void Pause();
    void Run();
    void StartThrow(GameObject disk);
}
3.2 定义实现disk的物理运动physicActionManger管理,通过回调实现。
public class PhysicActionManager : MonoBehaviour, IActionManager, ISSActionCallback
{
    public FirstController sceneController;//场记
    public int DiskNumber = 0;//统计disk数量


    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //保存所以已经注册的动作
    private List<SSAction> waitingAdd = new List<SSAction>();                           //动作的等待队列
    private List<int> waitingDelete = new List<int>();                                  //动作的删除队列
    private bool run;//是否开始运动

    public void Start()
    {
        sceneController = (FirstController)SSDirector.GetInstance().CurrentScenceController;
        sceneController.actionManager = this;
        run = true;

    }
    //实现fixedUpdate
    public void FixedUpdate()
    {
        if (run)
        {
            foreach (SSAction action in waitingAdd)
            {
                actions[action.GetInstanceID()] = action;
            }
            waitingAdd.Clear();//等待清除

            foreach (KeyValuePair<int, SSAction> kv in actions)
            {
                SSAction action = kv.Value;
                if (action.destroy)
                {
                    waitingDelete.Add(action.GetInstanceID());
                }
                else if (action.enable)
                {
                    action.FixedUpdate();
                }
            }

            //把删除队列里所有的动作删除
            foreach (int key in waitingDelete)
            {
                SSAction action = actions[key];
                actions.Remove(key);
                DestroyObject(action);
            }
            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();
    }

    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null)
    {
        if (source is UFOFlyAction)
        {
            DiskNumber--;
            source.gameobject.SetActive(false);
        }
    }

    public void StartThrow(GameObject disk)
    {
        FlyActionFactory factory = Singleton<FlyActionFactory>.Instance;
        RunAction(disk, factory.GetSSAction(), (ISSActionCallback)this);
    }
    //暂停
    public void Pause()
    {
        run = false;
    }
    //运行
    public void Run()
    {
        run = true;
    }
}

3.3 实现FlyActionManager类来管理Disks,主要实现action中的Update方法。
public class FlyActionManager : MonoBehaviour, ISSActionCallback, IActionManager
{
    public int DiskNumber = 0;//disk number
    public FirstController sceneController;//场记

    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //保存所以已经注册的动作
    private List<SSAction> waitingAdd = new List<SSAction>();                           //动作的等待队列,在这个对象保存的动作会稍后注册到动作管理器里
    private List<int> waitingDelete = new List<int>();
    private bool run;

    protected void Start()
    {
        sceneController = (FirstController)SSDirector.GetInstance().CurrentScenceController;
        sceneController.actionManager = this;
        run = true;//inital
    }

    protected void Update()
    {
        if (run)
        {   //动作在等待队列中
            foreach (SSAction ac in waitingAdd)
            {
                actions[ac.GetInstanceID()] = ac;
            }
            waitingAdd.Clear();
            //将action于value进行一对一映射,方便管理
            foreach (KeyValuePair<int, SSAction> kv in actions)
            {
                SSAction action = kv.Value;
                if (action.destroy)
                {
                    waitingDelete.Add(action.GetInstanceID());
                }
                else if (action.enable)
                {
                    action.Update();
                }
            }
            //删除队列中的某个action
            foreach (int key in waitingDelete)
            {
                SSAction action = actions[key];
                actions.Remove(key);
                DestroyObject(action);
            }
            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();
    }

    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null)
    {
        if (source is UFOFlyAction)
        {
            DiskNumber--;
            source.gameobject.SetActive(false);
        }
    }
    //飞碟开始按照action动作列表规定的动作序列运动
    public void StartThrow(GameObject disk)
    {
        FlyActionFactory cf = Singleton<FlyActionFactory>.Instance;
        RunAction(disk, cf.GetSSAction(), (ISSActionCallback)this);
    }
    public void Pause()
    {
        run = false;
    }

    public void Run()
    {
        run = true;
    }
}
3.5 通过实现FlyActionFactory类来实现动作序列额工厂模式,与Diskfactory类似,不必每次都实现新的动作,只需要调用保存在回收队列的action。
public class FlyActionFactory : MonoBehaviour
{
    private Dictionary<int, SSAction> used = new Dictionary<int, SSAction>();
    private List<SSAction> free = new List<SSAction>();
    private List<int> wait = new List<int>();

    public UFOFlyAction Fly;

    void Start()
    {
        Fly = UFOFlyAction.GetCCFlyAction();
    }

    //对判定为destroy的动作进行释放
    private void Update()
    {
        foreach (var action in used.Values)
        {
            if (action.destroy)
            {
                wait.Add(action.GetInstanceID());
            }
        }

        foreach (int ID in wait)
        {
            FreeSSAction(used[ID]);
        }
        wait.Clear();
    }
    //获得一个新的动作,先从free队列中找,没有就生成一个并加入到运行队列
    public SSAction GetSSAction()
    {
        SSAction action = null;
        if (free.Count > 0)
        {
            action = free[0];
            free.Remove(free[0]);
        }
        else
        {
            action = ScriptableObject.Instantiate<UFOFlyAction>(Fly);

        }

        used.Add(action.GetInstanceID(), action);
        return action;
    }
    //释放某个动作,加入到free队列
    public void FreeSSAction(SSAction action)
    {
        SSAction tmp = null;
        int key = action.GetInstanceID();
        //检查是否含有某动作
        if (used.ContainsKey(key))
        {
            tmp = used[key];
        }
        //有则释放
        if (tmp != null)
        {
            tmp.Reset();
            free.Add(tmp);
            used.Remove(key);
        }
    }
    //清除所有在使用的动作
    public void clear()
    {
        foreach (var action in used.Values)
        {
            action.enable = false;
            action.destroy = true;

        }
    }
}

3.6 在Singleton.cs与SSaction.cs文件中做相应的修改即可完成。
4. 效果展示:

在这里插入图片描述

5 不足与改进:
  1. 物理运动的动作实现太单一,只有自由落体运动。
  2. 部分disk的点击难度较大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值