编程实践:
改进飞碟(Hit UFO)游戏:
- 游戏内容要求:
- 按 adapter模式 设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
Adapter模式
按照题目要求,我们知道这次游戏与上次的差别在于我们这次需要使用adapter模式对游戏进行重新设计,并使其符同时合物理学和运动学规律,我们先来看adapter模式具体是什么。
如上图, 我们可以总结为adapter模式是实现了将一个类的接口转换到用户需要的那个接口上,使得原本不能调用的类可以被用户统一调用。由于我们要同时实现物理学运动和运动学运动,所以这次我们在这里是将上一次实现中的脚本FlyActionManager和这次需要实现的PhysicActionManager创建一个统一的接口作为Adapter,从而可以实现这两个类的统一调用。
刚体Rigibody
要实现让飞碟符合物理学运动规律,我们还需要用到一个叫做刚体的组件,在Add Componenet->Physics->Rigibody中,具体如下:
其中,mass表示物体治理,drag表示物体受到的阻力,angular drag表示角阻力,use gravity表 示是否使用重力,is kinematic表示是否受运动学控制,interpolate表示差值,collision detection表示碰撞检测,constraints表示自由度,info表示物体的相关信息。
然后我们看代码的具体实现。
我们新增一个IActionManager类,作为新的接口。在IActionManager中调用之前的实现飞碟运动的方法,我们让FlyActionManager和这次需要实现的PhysicManager分别调用该接口,就实现了适配器模式的应用,具体代码为:
public interface IActionManager{
void UFOFly(GameObject disk, float angle, float power);
}
实现了适配器后,我们需要修改之前的FlyActionManager,使其可以调用IActionManager,具体如下:
public class FlyActionManager : SSActionManager,IActionManager
{
public UFOFlyAction fly; //飞碟飞行的动作
public FirstController scene_controller; //当前场景的场景控制器
protected void Start()
{
scene_controller = (FirstController)SSDirector.GetInstance().CurrentScenceController;
scene_controller.action_manager = this;
}
//飞碟飞行
public void UFOFly(GameObject disk, float angle, float power)
{
fly = UFOFlyAction.GetSSAction(disk.GetComponent<DiskData>().direction, angle, power);
this.RunAction(disk, fly, this);
}
}
接下来我们需要实现一个新的物理动作类PhysicAction,以使得我们的游戏可以支持物理运动,这里主要是实现重力效果,我们先调用一个GameObject.GetComponent<Rigidbody>().useGravity = true,使得物体可以始终受到一个向下的重力;然后是调用
-
this.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(speedx, 0, 0), ForceMode.VelocityChange);
给物体一个瞬时的力,从而使物体或得一个初速度,代码具体实现如下:
public class PhysicAction : SSAction{
public float speedx;
public override void Start(){
//添加刚体
if (!this.gameObject.GetComponent<Rigidbody>()){
this.gameObject.AddComponent<Rigidbody>();
}
//设置重力
this.gameObject.GetComponent<Rigidbody>().useGravity = true;
//设置初速度
this.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(speedx, 0, 0), ForceMode.VelocityChange);
}
private PhysicAction(){}
public static PhysicAction getAction(float speed){
PhysicAction action = CreateInstance<PhysicAction>();
action.speedx = speed;
return action;
}
override public void Update(){
if (transform.position.y <= -8)
{
//摧毁刚体
Destroy(this.gameObject.GetComponent<Rigidbody>());
destory = true;
callback.SSActionEvent(this);
}
}
最后是实现一个PhysicActionManager,我们仿照之前的FlyActionManager,并将动作调用改为调用PhysicAction:
public class PhysicActionManager : SSActionManager,IActionManager
{
public UFOFlyAction flyphy; //将飞碟飞行的动作改为物理模式
public FirstController scene_controller; //当前场景的场景控制器
protected void Start()
{
scene_controller = (FirstController)SSDirector.GetInstance().CurrentScenceController;
scene_controller.action_manager = this;
}
//飞碟飞行变为物理学模式,调用了物理学动作类
public void UFOFly(GameObject disk, float angle, float power)
{
flyphy = PhysicAction.GetSSAction(disk.GetComponent<DiskData>().direction, angle, power);
this.RunAction(disk, fly, this);
}
}
最后,我们在UserGUI中为用户界面设计模式选择按钮(即可选两个按钮),如下:
if (GUI.Button(new Rect(Screen.width / 2 - 60, 200, 100, 50), "物理学模式"))
{
action.chooseAction(0);
action.BeginGame();
}
if (GUI.Button(new Rect(Screen.width / 2 - 60, 270, 100, 50), "运动学模式"))
{
action.chooseAction(1);
action.BeginGame();
}
然后在Basescript中加入相关可以供用户选择飞行模式的函数,若用户选择运动学模式,则返回chooseAction(1),从而调用FlyActionManager;若用户选择物理学模式,则返回chooseAction(0),从而调用PhysicActionManager。并在FirstController中添加代码使得用户可以通过在用户界面中选择模式来改变飞碟的运动模式。
游戏效果图如下: