Unity3D学习之路Homework4—— 飞碟射击游戏

简单打飞碟小游戏

游戏规则与要求

  • 规则
    鼠标点击飞碟,即可获得分数,不同飞碟分数不一样,飞碟的初始位置与飞行速度随机,随着分数增加,游戏难度增加。初始时每个玩家都有6条生命,漏打飞碟扣除一条生命,直到生命为0游戏结束。

  • 要求:
    使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
    近可能使用前面 MVC 结构实现人机交互与游戏模型分离
    扩展:

    实现:

    • 第一阶段做的井字棋还是能了解透彻的,Homework2的MVC架构和Homework3里的动作分离管理开始吃力了,说实话,现在对动作分离管理还不怎么理解透,但还是能理解MVC了。所以这次作业我并没有用到动作分离管理,只是用了MVC架构,也只是简单的MVC,所以没有SSDirector类了,当然,还有这周要求的工厂模式也是有的。

    • 之前两次作业看了不少博客,感觉类与类之间的交叉很多,虽然有了MVC和动作管理,但我看得结构不是很清晰(好吧,可能是我能力的问题)。这次我学会了两个很基础但很好用的两个方法(原谅我到了现在才会。。。)——对象gameObject(注意g是小写不是大写)和GetComponent<>(),之前我一直想着用C++里面的方法实现封装,即该方法或动作是属于哪个类的就放在它里面,一个类不要去操作另一个类,可以通过函数调用。讲一下gameObject和GetComponent吧

      • GetComponent:先说这个比较好,我们创建每个游戏对象都是用GameObject的了,但不同对象有不同的方法和属性,所以就可以自己写脚本挂到物体上,让它实现你想要的方法。当然,通过这个方法也可以添加其它组件比如Rigibody 。
      • gameObject:这是GameObject的实例,但它是ReadOnly即只读,它有什么用呢,当你把一个组件(这里重点指的是脚本),怎么获得该脚本挂的物体呢,其实是有记录的,gameObject就是脚本当前挂的物体。

    下面讲下本实验的过程:

    成品图:
    这里写图片描述
    做的确实不好。。。
    玩法:每按一次空格能出来一个飞碟,然后点击鼠标去点它,点中了会消失,或者飞离一定距离也会消失。

代码:

功能少所以代码比较少。

  • GameModel类即disk的属性与方法:
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  

public class GameModel : MonoBehaviour{  

    static int count = 0;  
    public Color diskColor;  
    private Vector3 emitPosition;  
    private Vector3 emitDirection;  
    private float emitSpeed;  
    private bool is_used;  
    private int diskScale;  
    private int id;  
    public GameModel()  
    {  
        id = 0;  
        count++;  
    }  
    public int getID()  
    {  
        return id;  
    }  
    public void setColor(Color diskColor)  
    {  
        this.GetComponent<MeshRenderer>().material.color = diskColor;  
    }  
    public void setEmitPosition(Vector3 emitPosition_)  
    {  
        emitPosition = emitPosition_;  
        this.transform.position = emitPosition_;  
    }  
    public void setEmitDirection(Vector3 emitDirection_)  
    {  
        emitDirection = emitDirection_;  
        gameObject.GetComponent<Rigidbody>().AddForce(3000 * emitDirection_);  
    }  

    public void setState(bool state)  
    {  
        is_used = state;  
        gameObject.SetActive(is_used);  
    }  
    public bool getState()  
    {  
        return is_used;  
    }  
    public bool is_outOfEdge()  
    {  
        if(transform.position.z>150 || transform.position.z<-150   
            || transform.position.x < -50 || transform.position.x >50  
            || transform.position.y>10 || transform.position.y < -20)  
        {  
            return true;  
        }  
        else  
        {  
            return false;  
        }  
    }  
}  
  • DiskFactory类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DiskFactory{

    private static DiskFactory _instance;
    private static List<GameObject> unusedDiskList = new List<GameObject>();
    private static List<GameObject> usedDiskList = new List<GameObject>();
    public GameObject diskTemplate;
    public static DiskFactory getInstance()
    {
        if(_instance == null)
        {
            _instance = new DiskFactory();
        }
        return _instance;
    }
    private DiskFactory() { }
    public GameObject getDiskObject()
    {
        GameObject disk1;
        if (unusedDiskList.Count == 0)
        {
            disk1 = GameObject.Instantiate(diskTemplate) as GameObject;
            usedDiskList.Add(disk1);

        }
        else
        {
            disk1 = unusedDiskList[0];
            unusedDiskList.RemoveAt(0);
            usedDiskList.Add(disk1);
        }
        disk1.GetComponent<GameModel>().setState(true);
        return disk1;

    }

    public void removeDiskObject(GameObject obj)
    {
        if (usedDiskList.Count > 0)
        {
            GameObject disk1 = obj;
            disk1.GetComponent<Rigidbody>().velocity = Vector3.zero;
            disk1.GetComponent<GameModel>().setState(false);
            usedDiskList.Remove(obj);   
            unusedDiskList.Add(disk1);
        }
    }

    //返回出界的disk的数目
    public int updateList()
    {
        int count = 0;
        for(int i = 0; i < usedDiskList.Count; i++)
        {
            if(usedDiskList[i].GetComponent<GameModel>().is_outOfEdge())
            {
                removeDiskObject(usedDiskList[i]);
                count++;
            }
        }
        return count;
    }

    public void clear()
    {
        usedDiskList.Clear();
        unusedDiskList.Clear();
    }
}

public class DiskFactoryBC : MonoBehaviour
{
    public GameObject disk;
    private void Awake()
    {
        DiskFactory.getInstance().diskTemplate = disk;
    }
}
  • 记分员类scoreRecorder:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScoreRecorder {

    private int score;
    public ScoreRecorder()
    {
        score = 0;
    }
    public void addScore(int add)
    {
        score+=add;
    }
    public void subScore(int sub)
    {
        score=score-sub;
    }
    public int getScore()
    {
        return score;
    }
    public void resetScore()
    {
        score = 0;
    }
}
  • SceneController类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum GameState { BEFORESTART,ROUND1,ROUND2,END};
public class SceneController : MonoBehaviour{

    private static SceneController _instance;
    private DiskFactory diskFactory= DiskFactory.getInstance();
    private GameObject disk;
    private GameState gamestate = GameState.BEFORESTART;
    private ScoreRecorder scoreRecorder = new ScoreRecorder();
    private int cout=0;

    private float time = 0;
    public static SceneController getInstance()
    {
        if(_instance == null)
        {
            _instance = new SceneController();
        }
        return _instance;
    }

    void Awake () {
        _instance = this;

        _instance.gamestate = GameState.END;

    }

    // Update is called once per frame
    void Update () {
        int count =diskFactory.updateList();
        scoreRecorder.subScore(count);
    }

    public void emitDisk()
    {
        if (gamestate == GameState.BEFORESTART)
        {

        }
        else if (gamestate == GameState.ROUND1)
        {
            disk = diskFactory.getDiskObject();
            float x = Random.Range(0.1f, 1);
            float y = Random.Range(-1, 1)/10;
            float z = Random.Range(0.1f, 1);

            disk.GetComponent<GameModel>().setColor(selectColor());
            disk.GetComponent<GameModel>().setEmitPosition(new Vector3(-8, 0, 5));
            disk.GetComponent<GameModel>().setEmitDirection(new Vector3(x, y, z));
        }
        else if(gamestate == GameState.ROUND2)
        {
            disk = diskFactory.getDiskObject();
            float x = Random.Range(-0.8f, 1);
            float y = Random.Range(-1, 1) / 10;
            float z = Random.Range(0.1f, 1);
            disk.GetComponent<GameModel>().setColor(selectColor());
            disk.GetComponent<GameModel>().setEmitPosition(new Vector3(-8, 0, 5));
            disk.GetComponent<GameModel>().setEmitDirection(new Vector3(x, y, z));
        }
        else if (gamestate == GameState.END)
        {
            diskFactory.clear();
            scoreRecorder.resetScore();
            //print(cout);
        }
    }

    public void destroyDisk(GameObject obj)
    {
        if(gamestate == GameState.ROUND1)
        {
            diskFactory.removeDiskObject(obj);
            scoreRecorder.addScore(1);
        } 
    }
    public void setGameState(GameState state)
    {
        gamestate = state;
    }
    public GameState getGameState()
    {
        return gamestate;
    }
    public int getScore()
    {
        return scoreRecorder.getScore();
    }
    private Color selectColor()
    {
        int randomNumber = Random.Range(0, 5);
        Color color=Color.green;
        switch (randomNumber)
        {
            case 0:color = Color.red;
                break;
            case 1:color = Color.blue;
                break;
            case 2: color = Color.green;
                break;
            case 3: color = Color.yellow;
                break;
            case 4: color = Color.grey;
                break;
        }
        return color;
    }
    public int getRound()
    {
        int round=0;
        switch (gamestate)
        {
            case GameState.ROUND1:
                round = 1;
                break;
            case GameState.ROUND2:
                round = 2;
                break;
        }
        return round;
    }


}
  • UI类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UI : MonoBehaviour {

    private SceneController sceneController = SceneController.getInstance();
    // Use this for initialization
    void Start () {

    }
    private void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            sceneController.emitDisk();
        }
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if(Physics.Raycast(ray,out hit))
            {
                if(hit.transform.tag == "Disk")
                {
                    sceneController.destroyDisk(hit.collider.gameObject);
                }
            }
        }
    }
    private void OnGUI()
    {
        GUIStyle fontStyle = new GUIStyle();
        fontStyle.fontSize = 25;
        fontStyle.normal.textColor = new Color(0, 0, 0);

        if (GUI.Button(new Rect(0, 0, 100, 40), "Round1"))
        {
            sceneController.setGameState(GameState.ROUND1);
        }
        else if(GUI.Button(new Rect(0, 42, 100, 40), "Round2"))
        {
            sceneController.setGameState(GameState.ROUND2);
        }
        else if(GUI.Button(new Rect(0, 84, 100, 40), "End")){
            sceneController.setGameState(GameState.END);
        }
        GUI.Label(new Rect(Screen.width / 3, 0, 100, 50), "Round: " + sceneController.getRound(), fontStyle);
        GUI.Label(new Rect(Screen.width/3+150 , 0, 100, 50), "Score: " + sceneController.getScore(), fontStyle);

        if (sceneController.getGameState() == GameState.END)
        {
            if(GUI.Button(new Rect(Screen.width / 3, Screen.height / 3, 150, 80), "GameOver!\nEnter")){
                sceneController.setGameState(GameState.BEFORESTART);
            }
        }
    }
}

小结:

  • 我只是将自己学到的一点东西分享一下,可参考度不高,如果要参考建议还是看大神写的博客,我还有很多很多要改要学习要改进的地方,希望自己后面能学得更好
    (实训+3d+现操+计组已经够忙的了,每天都能看到深夜的月亮。。。)

猜你喜欢

转载自blog.csdn.net/ke1950523491/article/details/79982817
今日推荐