3D游戏设计第六次作业——打飞碟物理模式

3D游戏设计第六次作业——打飞碟物理模式

1 概述

在上一次的作业实现的基础上增加了物理模式,通过给飞碟增加刚体组件,实现飞碟拥有物理特性,会发生碰撞,也会收到重力影响。

2 代码讲解

2.1 与上一次相同的部分

本次作业新增一个物理模式,因此许多代码与上一次作业相同,没有发生改变。
单实例类Singleton.cs,定义了创建并调用单实例的方法。
导演基类SSSDirector.cs,单实例的导演类,协调场景控制器的使用,保证只有一个场景控制器在运行,不过本游戏中也只有一个飞碟场景控制器。
动作控制基类SSActionManager.cs,是所有动作类的基类,控制动作序列的进行或删除。组合工作管理器CCActionManager.cs、直线飞行动作CCFlyAtion.cs,这两个脚本主要涉及的是直线飞行的动作,没有发生改变。
飞碟信息disk.cs,保存飞碟的大小、速度、方向等信息。
飞碟工厂DiskFactory.cs,生产飞碟、销毁飞碟。
场景控制器接口IISceneController.cs,定义了场景控制器的抽象方法。
动作基类SSAction.cs,定义了与动作相关的成员对象和回调方法。
动作基类回调接口IISSActionCallback.cs,定义了动作回调事件的抽象方法。

2.2 物理模式涉及的添加和修改

  • 用户交互接口IIUserAction.cs
    添加了一个设定模式的抽象方法。
public interface IIUserAction{
    GameState getGS();
    void GameOver();
    void gameStart();
    void Hit(Vector3 pos);
    
    void setMode(int m);
}
  • 用户交互UUserGUI
    添加模式选择的按钮,普通模式与物理模式
public enum GameState{ running,start,end,beforeStart}

public class UUserGUI : MonoBehaviour
{
    int score=0;
    private IIUserAction action;
    // Start is called before the first frame update
    void Start()
    {   
        Debug.Log("action init");
        action = SSSDirector.getInstance().currentSceneController as IIUserAction;
        Debug.Log("action name"+action.ToString());
    }
    public void setScore(int s){
        score = s;
    }
    
    // Update is called once per frame
    void OnGUI(){
        
        GUI.Label(new Rect(10,10,100,50),"得分:"+score);
        // if(action.getGS() != GameState.running){
            if(action.getGS()!=GameState.running){
                if(GUI.Button(new Rect(100,150,100,50),"开始")){
                    action.gameStart();
                }
                if(GUI.Button(new Rect(100,205,100,50),"普通模式")){
                    action.setMode(1);
                }
                if(GUI.Button(new Rect(100,310,100,50),"物理模式")){
                    action.setMode(2);
                }
            }
            
            if(Input.GetMouseButtonDown(0)){
              
                action.Hit(Input.mousePosition);
            }
            if(action.getGS()==GameState.end){
                GUI.Label(new Rect(Screen.width/2-50,Screen.height/2-25,100,50),"<color=#000000>游戏结束!</color>");
            }
        // }
        
    }
}

  • 物理飞行动作PhysisFlyAciont.cs
    给物体添加刚体组件,并设定初速度,即可实现物理模式的飞碟飞行动作。
public class PhysisFlyAction : SSSAction
{
    public float speed;
    public Vector3 direction;
    public static PhysisFlyAction GetSSAction(Vector3 direction, float speed ){
        PhysisFlyAction action = ScriptableObject.CreateInstance<PhysisFlyAction>();
        action.speed = speed;
        action.direction = direction;
        return action;
    }
    // Start is called before the first frame update
    public override void Start()
    {
        this.gameObject.AddComponent<Rigidbody>();
        this.gameObject.GetComponent<Rigidbody>().velocity = speed*direction;
    }

    // Update is called once per frame
    public override void Update()
    {
        if(this.gameObject.transform.position.y<-7){
            Destroy(this.gameObject.transform.GetComponent<Rigidbody>());
            this.destroy = true;
            this.enable = false;
            this.callback.SSSActionEvent(this);
        }
    }
}

  • 物理飞行动作管理器PhysisActionManager.cs
    与组合动作管理器的功能相同,就是处理动作的进行和消除。
public class PhysisActionManager : SSActionManager, IISSActionCallback
{
    
    public DiskSceneController sceneController;
    public PhysisFlyAction fly;
    // Start is called before the first frame update
    protected void Start()
    {
        sceneController = (DiskSceneController)SSSDirector.getInstance().currentSceneController;
        sceneController.phyactionManager = this;
        
    }
    public void Fly(GameObject disk, float speed, Vector3 dir){
        fly = PhysisFlyAction.GetSSAction(dir,speed);
        RunAction(disk, fly, this);
    }
    // Update is called once per frame
    protected new void Update()
    {
        base.Update();
    }
    #region IISSActionCallback implementation
    public void SSSActionEvent(SSSAction source, SSActionEventType events = SSActionEventType.Completed,int intParam = 0,
    string strParam = null, Object objectParam = null){
        // Debug.Log("manager free");
        sceneController.FreeDisk(source.gameObject);
    }
    #endregion
}

  • 飞碟场景控制器DiskSceneController.cs
    增加一个方法setMode,用于在用户选择模式时改变关于模式的变量mode。同时在扔飞盘时根据mode选择不同的动作管理器,并且也适当调整了物理模式下的丢飞盘的频率。
public class DiskSceneController : MonoBehaviour, IISceneController, IIUserAction
{
    float time = 0;
    int throwCount = 0;
    public int disknum = 10;
    public GameState state = GameState.beforeStart;
    int score = 0;
    DiskFactory diskfactory;
    public CCActionManager actionManager;
    public PhysisActionManager phyactionManager;
    UUserGUI usergui;
    public int mode = 1;
    //要移动的物体
    public GameObject obj;
    // Start is called before the first frame update
    
    void Start(){
        SSSDirector director = SSSDirector.getInstance();
        director.currentSceneController = this;
        gameObject.AddComponent<DiskFactory>();
        gameObject.AddComponent<CCActionManager>();
        gameObject.AddComponent<PhysisActionManager>();
        gameObject.AddComponent<UUserGUI>();
        LoadResources();
    }
    public void LoadResources(){
        diskfactory = Singleton<DiskFactory>.Instance;
        usergui = Singleton<UUserGUI>.Instance;
        actionManager = Singleton<CCActionManager>.Instance;
        phyactionManager = Singleton<PhysisActionManager>.Instance;
    }
    public void Hit(Vector3 pos){
        Ray ray = Camera.main.ScreenPointToRay(pos);
        RaycastHit hit;
        bool isCollider = Physics.Raycast(ray, out hit);
        if(isCollider){
            var fa = hit.collider.gameObject.transform.parent;
            fa.position = new Vector3(0,-6,0);

            score += countScore(fa.gameObject.GetComponent<disk>());
            usergui.setScore(score);
        }
    }
    public GameState getGS(){
        return state;
    }
    private int countScore(disk d){
        return d.color + d.size +4- d.speed;
    }
    public void Pause(){

    }
    public void setMode(int m){
        mode = m;
    }
    public void Resume(){
        
        throwCount = 0;
        time = 0;
        score = 0;
        usergui.setScore(0);
        
    }
    void Update(){
        if(state==GameState.running){
            if(throwCount>=20){
                
                state = GameState.end;
                
            }
            time += Time.deltaTime;
            if(mode==1)
            if(time>0.5){
                time = 0;
                for(int i = 0;i<3;i++){
                    
                    throwCount++;
                    ThrowDisk();
                }
            }
            if(mode==2)
            if(time>0.5){
                time = 0;
                throwCount++;
                ThrowDisk();
            }
        }
        
        
    }
    public void ThrowDisk(){
        GameObject disk = diskfactory.getDisk();
        if(mode==1) actionManager.Fly(disk, disk.GetComponent<disk>().speed,disk.GetComponent<disk>().dir);
        else phyactionManager.Fly(disk,disk.GetComponent<disk>().speed,disk.GetComponent<disk>().dir);
    }
    public void gameStart(){
       
        Resume();
        state = GameState.running;
        
    }
    public void FreeDisk(GameObject disk){
        Debug.Log("scene free");     

        diskfactory.FreeDisk(disk.GetComponent<disk>());
    }
    public void GameOver(){
        
    }
}

3展示和代码地址

视频展示地址:https://www.bilibili.com/video/BV1G14y1K77y/?spm_id_from=333.999.0.0
代码地址:https://gitee.com/k_co/3-d-games/tree/master/HW6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值