物理系统与碰撞
程序员文章站
2022-03-13 14:50:41
...
改进飞碟(Hit UFO)游戏:
游戏内容要求:
1.按 adapter模式 设计图修改飞碟游戏
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
2.使它同时支持物理运动与运动学(变换)运动
实现Rigidbody的碰撞功能,采用adapter模式来增加新的(物理)动作管理者
代码实现
除了Action相关类之外的类变化不大,需要实现基类(接口)baseActionManager 和两个动作管理类 SSActionManager / PhysicActionManager
baseActionManager
public interface baseActionManager
{
//设置回调
void setCallback(ISSActionCallback _callback);
//停止所有动作,对应 nextRound / nextTrial / restart
void stop();
//发送UFO,两个Action Manager具有不同的实现,Adapter模式的体现
void FlyUFO(List<GameObject> waitToFly,Ruler ruler,int round);
}
SSActionManager
正常的发送UFO,按顺序发送,等到上一个发送完毕后再发送下一个,不产生碰撞
public void setCallback(ISSActionCallback _callback)
{
callback = _callback;
}
public void stop()
{
if(runSequence.Count <= 0) return;
//因为放入sequenceAction中执行,所以runSequence只有一个/零个action
runSequence[0].stop();
}
public void FlyUFO(List<GameObject> waitToFly,Ruler ruler,int round){
List<SSAction> toMove = new List<SSAction>();
for(int i = 0;i < waitToFly.Count; i++)
{
toMove.Add(CCMoveToAction.GetSSAction(waitToFly[i],ruler.getDes(waitToFly[i].transform.position),ruler.getSpeed(round)*AnimateSpeed,null));
}
sequenceAction action = sequenceAction.GetSSAction(1,0,toMove,this);
addAction(action);
}
回调函数
回调函数在管理器中十分重要,因为它涉及到UFO回收以及对于分数的处理,这里由于调用顺序为
SSActionManager -> sequenceAction -> CCMoveToAction
所以在前两个类中都需要实现回调
SSActionManager
public void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0,
string strParam = null){
runSequence.Remove(source);
if(this.callback!=null)
this.callback.SSActionEvent(source);
//回调告诉游戏场景控制器可以进入下一轮
}
sequenceAction
public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Competeted,int intParam = 0,string strParam = null)
{
Debug.Log("callback 0");
source.destroy = false;
this.start++;
//处理是否点击和分数
UFO ufo = source.gameobject.GetComponent<UFO>();
if(!ufo.isClicked){
Judge.getInstance().subScore(ufo.score);
}
//回收UFO
UFOFactory.getInstance().free(source.gameobject);
if(this.start>=sequence.Count){
this.start = 0;
if(repeat>0)repeat--;
if(repeat==0){
destroy = true;
Debug.Log("callback 1");
this.callback.SSActionEvent(this);
}
}
//告诉动作管理器当前Trial的UFO均已完成动作
}
PhysicActionManager
在实现同时发送多个UFO(中间间隔事件由Ruler设置)的过程中,我们通过协程来实现该功能
IEnumerator setNextFly(float time,SSAction action)
{
yield return new WaitForSeconds(time);
addAction(action);
waitSequence.Remove(action);
}
在该动作控制器中,还需要额外添加一个waitSequence队列来放置等待发送的UFO
public void setCallback(ISSActionCallback _callback)
{
callback = _callback;
}
public void stop()
{
//关闭协程
StopAllCoroutines();
//对于每一个已经执行的动作,手动终止
while(runSequence.Count>0)
{
runSequence[0].stop();
}
//对于为执行的动作,直接回收对象并清空该队列
for(int i = 0;i<waitSequence.Count;i++)
{
UFOFactory.getInstance().free(waitSequence[i].gameobject);
}
waitSequence.Clear();
}
public void FlyUFO(List<GameObject> waitToFly,Ruler ruler,int round){
SSAction action;
float waitTime = 0;
for(int i = 0;i < waitToFly.Count;i++){
Debug.Log("Flying");
action = CCMoveToAction.GetSSAction(waitToFly[i],ruler.getDes(waitToFly[i].transform.position),ruler.getSpeed(round)*AnimateSpeed,this);
if( i == 0 ){
addAction(action);
}else{
//通过协程间隔时间发送多个UFO
addWaitAction(action);
StartCoroutine(setNextFly(waitTime,action));
}
waitTime += ruler.getIntervals(round);
}
}
回调函数
相比于上一个动作控制器,这里少了一个sequenceAction作为过渡处理每一个单独action,所以只需要将sequenceAction的回调函数添加到这里即可
public void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0,
string strParam = null){
//处理是否点击和分数
UFO ufo = source.gameobject.GetComponent<UFO>();
if(!ufo.isClicked){
Judge.getInstance().subScore(ufo.score);
}
//回收UFO
UFOFactory.getInstance().free(source.gameobject);
runSequence.Remove(source);
//告诉游戏场景控制器需要进入下一Trial
if(runSequence.Count<=0)
{
if(this.callback!=null)
this.callback.SSActionEvent(source);
}
}
实际操作
上一篇: mfc 多边形裁剪算法
下一篇: 三中常见的加密算法