3D游戏编程与设计作业六

改进飞碟(Hit UFO)游戏

要求

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

实现

原项目:3D编程与游戏设计作业五
仅仅对其中的一些类进行改动就能实现。

飞碟预设

由于要求支持物理运动,因此飞碟的预设需要在原来的基础上加上刚体:
在这里插入图片描述

Adapter的实现

adapter是通过不同的状态选择不同的接口,在本作业中是选择不同的动作实现方式(物理/运动学),发现与之前的flyActionController的功能类似,因此把它改写成Adapter:

public class Adapter : SSActionManager {
    public DiskFlyAction fly;
    public PhysisFlyAction fly_;

    public void DiskFly(GameObject disk, int mode, mes information) {
        int leftOrRight = 1;
        if (disk.transform.position.x > 0){
            leftOrRight = -1;
        }

        if(mode == 2){
            fly = DiskFlyAction.GetSSAction(leftOrRight, information.angle, information.speed);
            this.StartAction(disk, fly);
        }
        else{
            fly_ = PhysisFlyAction.GetSSAction(leftOrRight, information.speed);
            this.StartAction(disk, fly_);
        }
    }
}

通过mode控制运动类型,然后分别调用DiskFlyAction和PhysisFlyAction,这里用到的information是自定义类型,用于存储相关信息。

public struct mes{
    public float speed;
    public float angle;
}

PhysisFlyAction && SSAction && DiskFlyAction

PhysisFlyAction类,代码如下:

public class PhysisFlyAction : SSAction
{
    private bool start_position;
    public float force;

    public static PhysisFlyAction GetSSAction(int pos, float force_){
        PhysisFlyAction action = CreateInstance<PhysisFlyAction>();
        if(pos == 1){
            action.start_position = true;
        }
        else{
            action.start_position = false;
        }
        action.force = force_;
        
        return action;
    }
    // Start is called before the first frame update
    public override void Start()
    {
        Rigidbody disk = gameobject.GetComponent<Rigidbody>();
        
        gameobject.GetComponent<Rigidbody>().useGravity = true;
        if(gameobject.GetComponent<Rigidbody>().position.y <= 3){
            if(start_position){
                gameobject.GetComponent<Rigidbody>().AddForce(new Vector3(0.4f,0.2f,0)*force*15f, ForceMode.Impulse);
            }
            else{
                gameobject.GetComponent<Rigidbody>().AddForce(new Vector3(-0.4f,0.2f,0)*force*15f, ForceMode.Impulse);
            }
        }
    }

    // Update is called once per frame
    public override void Update()
    {
        
    }

    public override void FixedUpdate() {
        if (transform.position.y <= -10f) {
            Debug.Log(transform.position.y);
            gameobject.GetComponent<Rigidbody>().useGravity = false;
            gameobject.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
            this.enable = false;
        }
    }
}

总体与物理学运动实现类似,但是这里用到了FixedUpdate。
这个类设计的小细节有对重力的改变,在start中,开启了重力,在一个初始力和重力的作用下,飞碟进行抛体运动,当飞碟运动到我们摄像机视线之外(这里是FixedUpdate中提到的-10f)时,则关闭重力。因为如果不关闭重力,飞碟仍然会继续下落,然后等到DiskFactory回收该飞碟进行下一次使用的时候会具有很大的速度,影响游戏体验,如下图(可以看到第三次绿色飞碟出现在右下角的时候具有很大的竖直速度,一闪而过):
在这里插入图片描述

由于physic增加了FixedUpdate,因此SSAction、DiskFlyAction也增加了一个空的FixedUpdate:

public class SSAction : ScriptableObject {
	……    
    public virtual void FixedUpdate() {
        throw new System.NotImplementedException();
    }
    ……
}

public class DiskFlyAction : SSAction {
	……
    public override void FixedUpdate() {
        
    }
    ……
}

FirstController && Interfaces

FirstController的改动有:
增加了一个bool变量,用于记录是物理运动还是运动学变换运动,为了通过UserGUI改变这个变量,还增加了一个setPhysic函数,并且同时在Interfaces中加上方便UserGUI修改。

private bool physic = false;
……
public void setPhysic(bool physic_){
	physic = physic_;
}

SSActionManager

增加FixedUpdate:

……
if (action.enable) {
    	action.Update();
    	action.FixedUpdate();
} 
……

UserGUI

在第一个界面增加了两个按钮,用于选择是否是physic模式。


效果

physic模式:
在这里插入图片描述
原本运动学模式仍然正常运行:
在这里插入图片描述

源代码:

GitHub

猜你喜欢

转载自blog.csdn.net/Floating__dust/article/details/109633997