欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

3D_HW6

程序员文章站 2022-05-30 19:35:48
...

3D_HW6

Hit UFO改进版

游戏的运行gif图如下:

3D_HW6

改进飞碟(Hit UFO)游戏:

  • 游戏内容要求:
    • 按 adapter模式 设计图修改飞碟游戏
    • 使它同时支持物理运动与运动学(变换)运动

UML图如下
3D_HW6
新增adapter模式, 使用工厂类Factory来控制UFO的生成和回收, 起到类似接口的作用, 同时在SSAction中增加了Rigidbody组件, 支持物理运动, 脚本代码如下:

UI.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UI : MonoBehaviour
{
    private GUIStyle style;

    private bool next;

    private float T = 1.0f;

    // Start is called before the first frame update
    void Start()
    {
        next = true;
        style = new GUIStyle();
        style.fontSize = 40;
        InvokeRepeating("runGame", 0, T);
    }

    // Update is called once per frame
    void Update()
    {
        if (Recorder.score >= 20) {
            if (Recorder.round < 3 && next) {
                Invoke("reset", 3);
                CancelInvoke("runGame");
                Invoke("goNext", 3);
                next = false;
            } else CancelInvoke("runGame");
        } else next = true;
    }

    private void OnGUI() {
        GUI.Label(new Rect(Screen.width / 8, Screen.height / 6, 200, 100), "Round: " + Recorder.round + "\nScore: " + Recorder.score + "\nMissed: " + Recorder.missed, style);
        if(Recorder.round >= 3 && Recorder.score >= 20) {
            GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 100, 200, 200), "You win!", style);
        }else if(Recorder.score >= 20) {
            GUI.Label(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 100, 200, 200), "Next round will start after 3s", style);
        }
    }

    void reset() {
        Recorder.score = Recorder.missed = 0;
        Recorder.round += 1;
        T /= 2;
    }

    void goNext() {
        InvokeRepeating("runGame", 0, T);
    }

    void runGame() {
        Player mplayer = new Player();
        mplayer.createObject();
    }
}

Recorder.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Recorder
{
    public static int score;
    public static int missed;

    public static int round;

    public Recorder() {
        score = missed = 0;
        round = 1;
    }

}

SceneController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SceneController : MonoBehaviour
{
    public SSAction actionManager { get; set; }
    public Factory factory { get; set; }
    public Recorder scoreRecorder { get; set; }
    public int round = 0;
    public string str;
    public int mtime = 0;
    public GameObject sth;

    void Start() {
        round = 1;
    }

    // Update is called once per frame
    void Update() {
        str = "Round:" + round.ToString();
        if (round == 4) {
            GameOver();
        }
    }
    public IEnumerator waitForOneSecond() 
    {
        while (mtime >= 0 && round == 3) {
            str = mtime.ToString(); 
            print("还剩" + mtime);
            yield return new WaitForSeconds(1);
            mtime--;
        }
        str = "";
        round = 1; 
    }
    public void GameOver() {
        str = "Game Over!!!";
    }
    public void StartGame()
    {
        if (round == 0) {
            round = 3;
            StartCoroutine(waitForOneSecond());
        }
    }
    public void ReStart()
    {
        round = 0;
    }
    public void hit()
    {
        if (round == 1) {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit)) {
                if (hit.transform.tag == "Disk") {
                    sth.transform.position = hit.collider.gameObject.transform.position;
                    sth.GetComponent<Renderer>().material = hit.collider.gameObject.GetComponent<Renderer>().material;
                    sth.GetComponent<ParticleSystem>().Play();
                    hit.collider.gameObject.SetActive(false);
                }
            }
        }
    }
    public void LoadResources()  
    {
        sth = Instantiate(Resources.Load("prefabs/Explosion"), new Vector3(-40, 0, 0), Quaternion.identity) as GameObject;
        Instantiate(Resources.Load("prefabs/Light"));
    }
}

Factory.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Factory : MonoBehaviour
{
    private static Player _instance;
    public SceneController sceneControler { get; set; }
    public Recorder scoreRecorder;
    GameObject diskPrefab;
    public List<GameObject> used;
    public List<GameObject> free;

    private void Awake() {
        diskPrefab = Instantiate(Resources.Load<GameObject>("Prefabs/cube"), new Vector3(40, 0, 0), Quaternion.identity);
    }
    public void Start() {
        sceneControler.factory = this;
        scoreRecorder = sceneControler.scoreRecorder;
    }

    public void freeDisk(GameObject disk1)
    {
        for (int i = 0; i < used.Count; i++) {
            if (used[i] == disk1) {
                used.Remove(disk1);
                disk1.SetActive(true);
                free.Add(disk1);
            }
        }
        return;
    }
}

Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player
{
    public GameObject cube;
    public GameObject cylinder;
    public GameObject sphere;
    public GameObject pie1;
    public GameObject pie2;

    public Material red;
    public Material green;
    public Material blue;

    /*
    public static int score;
    public static int missed;

    public static int round;
    */

    private const float x_min = 1;
    private const float x_max = 15 + 1;
    private const float y_init = -8;

    public Player() {
        red = Resources.Load<Material>("Materials/Red");
        green = Resources.Load<Material>("Materials/Green");
        blue = Resources.Load<Material>("Materials/Blue");
        cube = Resources.Load<GameObject>("Prefabs/Cube");
        cylinder = Resources.Load<GameObject>("Prefabs/Cylinder");
        sphere = Resources.Load<GameObject>("Prefabs/Sphere");
        pie1 = Resources.Load<GameObject>("Prefabs/Pie1");
        pie2 = Resources.Load<GameObject>("Prefabs/Pie2");
    }

    void changeColor(ref GameObject arg) {
        int color = Random.Range(0, 3);
        if (color == 0) arg.GetComponent<Renderer>().material = red;
        else if (color == 1) arg.GetComponent<Renderer>().material = green;
        else arg.GetComponent<Renderer>().material = blue;
    }

    float getPostionX() {
        float x = Random.Range(x_min, x_max);
        if (Random.Range(0, 2) == 0) return x;
        else return -x;
    }

    public void createObject() {
        GameObject sth;
        int c = Random.Range(0, 5);
        if (c == 0) sth = cube;
        else if (c == 1) sth = cylinder;
        else if (c == 2) sth = sphere;
        else if (c == 3) sth = pie1;
        else sth = pie2;
        sth.transform.position = new Vector3(getPostionX(), y_init, 0);
        changeColor(ref sth);
        sth = GameObject.Instantiate(sth);
        sth.AddComponent<SSActionManager>();
    }
}

SSAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SSAction : MonoBehaviour {
    protected static GameObject instance;
    public int ori_x;
    public int highest_x;
    public int a;
    public int b;
    public int c;


    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 pos = this.gameObject.transform.position;
        if (ori_x < highest_x) pos.x += Time.deltaTime;
        else pos.x -= Time.deltaTime;
        float x = pos.x;
        pos.y = a * Mathf.Pow(x, 2) + b * x + c;
        //Debug.Log("x: " + x + ", y: " + pos.y + ", ori_x: " + ori_x + ", ori_y: " + ori_y + ", h_x: " + highest_x + ", h_y: " + highest_y + ", a: " + a + ", b: " + b + ", c: " + c);
        this.gameObject.transform.position = pos;
        if (pos.y < -20) {
            Destroy(this.gameObject);
            Recorder.missed += 1;
        }
        if (Recorder.score >= 20) Destroy(this.gameObject);
    }
}

SSActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SSActionManager : MonoBehaviour
{
    public float ori_x;
    public float ori_y;
    public float highest_x;
    public float highest_y;

    private float a;
    private float b;
    private float c;

    private float x_min;
    private float x_max;
    private float y_min;
    private float y_max;

    // Start is called before the first frame update
    void Start()
    {
        x_min = 0;
        x_max = 10 + 1;
        y_min = 5;
        y_max = 20 + 1;
        ori_x = this.gameObject.transform.position.x;
        ori_y = this.gameObject.transform.position.y;
        highest_x = Random.Range(x_min, x_max);
        if (Random.Range(0, 2) == 0) highest_x = -highest_x;
        highest_y = Random.Range(y_min, y_max);
        while(Mathf.Abs(highest_x - ori_x) < 1) {
            highest_x = Random.Range(x_min, x_max);
        }

        float x2 = 2 * highest_x - ori_x, y2 = ori_y;
        float temp = (highest_y - y2) / (highest_x - x2);
        a = (ori_y - temp * ori_x - y2 + temp * x2) / (ori_x * ori_x - ori_x * (highest_x + x2) - x2 * x2 + x2 * (highest_x + x2));
        b = -2 * a * highest_x;
        c = y2 - a * (x2 * x2) - b * x2;
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 pos = this.gameObject.transform.position;
        if (ori_x < highest_x) pos.x += Time.deltaTime;
        else pos.x -= Time.deltaTime;
        float x = pos.x;
        pos.y = a * Mathf.Pow(x, 2) + b * x + c;
        this.gameObject.transform.position = pos;
        if (pos.y < -20) {
            Destroy(this.gameObject);
            Recorder.missed += 1;
        }
        if (Recorder.score >= 20) Destroy(this.gameObject);
    }

    void OnMouseDown() {
        Destroy(this.gameObject);
        Recorder.score += 1;
    }
}
相关标签: 3D

推荐阅读