做一个简单的打飞碟游戏

简介

就是一个简单的打飞碟游戏。。游戏难度会随着你获得的分数提升,胜利条件是获得1000分。

对象处理

就简单的一个飞碟预制就行了(十分简单,就一个圆柱体。。完毕)
这里写图片描述
还有一个粒子系统用来模拟飞碟被击中时的爆炸效果,粒子的参数如下:
这里写图片描述
这里写图片描述
就这么简单。。没了

UML

这里写图片描述

代码部分

其实这个飞碟的代码跟之前的那个牧师与魔鬼的代码十分的相似,主要是由于老师提供的框架可塑性实在是太强大了(膜拜一下老师)。只需要增加一个记分员,一个飞碟工厂,再加上之前的框架,就搞定了。
Singleton.cs(单例模型的模板)

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

public class Singleton<T> where T : MonoBehaviour
{
    private static T instance;
    public static T Instance {
        get {
            if (instance == null) {
                instance = (T)Object.FindObjectOfType(typeof(T));
                if (instance == null) {
                    Debug.LogError("Can't find instance of " + typeof(T));
                }
            }
            return instance;
        }
    }
}

Director.cs

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

public class Director : System.Object {
    public static Director _instance;
    public ISceneController currentSceneController { get; set; }
    public bool running { get; set; }

    public static Director getInstance() {
        if (_instance == null) _instance = new Director();
        return _instance;
    }

    public int getFPS() {
        return Application.targetFrameRate;
    }

    public void setFPS(int fps) {
        Application.targetFrameRate = fps;
    }
}

DiskData.cs

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

public class DiskData : MonoBehaviour {
    public float size;
    public Color color;
    public float speed;
}

ScoreRecorder.cs

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

public class ScoreRecorder : MonoBehaviour {
    private float score;

    public float getScore() {
        return score;
    }

    public void Record(GameObject disk) {
        score += (100 - disk.GetComponent<DiskData>().size *(20 - disk.GetComponent<DiskData>().speed));

        Color c = disk.GetComponent<DiskData>().color;
        switch (c.ToString()) {
        case "red":
            score += 50;
            break;
        case "green":
            score += 40;
            break;
        case "blue":
            score += 30;
            break;
        case "yellow":
            score += 10;
            break;
        }
    }

    public void Reset() {
        score = 0;
    }
}

DiskFactory.cs

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

public class DiskFactory : MonoBehaviour {

    private List<GameObject> used = new List<GameObject>();
    private List<GameObject> free = new List<GameObject>();

    private Color[] color = { Color.red, Color.green, Color.blue, Color.yellow };

    public GameObject GetDisk(int ruler) {
        GameObject a_disk;
        if (free.Count > 0) {
            a_disk = free[0];
            free.Remove(free[0]);
        } else {
            a_disk = GameObject.Instantiate(Resources.Load("prefabs/Disk")) as GameObject;
        }
        switch (ruler) {
        case 1:
            a_disk.GetComponent<DiskData>().size = UnityEngine.Random.Range(0, 6);
            a_disk.GetComponent<DiskData>().color = color[UnityEngine.Random.Range(0, 4)];
            a_disk.GetComponent<DiskData>().speed = UnityEngine.Random.Range(10, 15);

            a_disk.transform.localScale = new Vector3(a_disk.GetComponent<DiskData>().size * 2, a_disk.GetComponent<DiskData>().size * 0.1f, a_disk.GetComponent<DiskData>().size * 2);
            a_disk.GetComponent<Renderer>().material.color = a_disk.GetComponent<DiskData>().color;
            break;
        case 2:
            a_disk.GetComponent<DiskData>().size = UnityEngine.Random.Range(0, 4);
            a_disk.GetComponent<DiskData>().color = color[UnityEngine.Random.Range(0, 4)];
            a_disk.GetComponent<DiskData>().speed = UnityEngine.Random.Range(15, 20);

            a_disk.transform.localScale = new Vector3(a_disk.GetComponent<DiskData>().size * 2, a_disk.GetComponent<DiskData>().size * 0.1f, a_disk.GetComponent<DiskData>().size * 2);
            a_disk.GetComponent<Renderer>().material.color = a_disk.GetComponent<DiskData>().color;
            break;
        }
        a_disk.SetActive(true);
        used.Add(a_disk);
        return a_disk;
    }

    public void FreeDisk(GameObject disk) {
        for(int i = 0; i < used.Count; i++) {
            if(used[i] == disk) {
                disk.SetActive(false);
                used.Remove(used[i]);
                free.Add(disk);
            }
        }
    }
}

RoundController.cs

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

public enum State { WIN, LOSE, PAUSE, CONTINUE, START };

public class RoundController : MonoBehaviour, IUserAction, ISceneController {

    public DiskFactory diskFactory;
    public RoundActionManager actionManager;
    public ScoreRecorder scoreRecorder;
    private List<GameObject> disks;
    private int round;
    private GameObject shootAtSth;
    GameObject explosion;

    public State state { get; set; }
    public int leaveSeconds;
    public int count;

    IEnumerator DoCountDown() {
        while (leaveSeconds >= 0) {
            yield return new WaitForSeconds(1);
            leaveSeconds--;
        }
    }

    void Awake() {
        Director director = Director.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;

        LoadResources();

        diskFactory = Singleton<DiskFactory>.Instance;
        scoreRecorder = Singleton<ScoreRecorder>.Instance;
        actionManager = Singleton<RoundActionManager>.Instance;

        leaveSeconds = 60;
        count = leaveSeconds;
        state = State.PAUSE;
        disks = new List<GameObject>();
    }


    void Start () {
        round = 1;
        LoadResources();
    }

    void Update() {
        LaunchDisk();
        Judge();
        RecycleDisk();
    }

    public void LoadResources() {
        Camera.main.transform.position = new Vector3(0, 0, -15);
        explosion = Instantiate(Resources.Load("Prefabs/ParticleSys"), new Vector3(-40, 0, 0), Quaternion.identity) as GameObject;

    }

    public void shoot() {
        if (Input.GetMouseButtonDown(0) && (state == State.START || state == State.CONTINUE)) {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit)) {
                if ((Director.getInstance().currentSceneController.state == State.START || Director.getInstance().currentSceneController.state == State.CONTINUE)) {
                    shootAtSth = hit.transform.gameObject;

                    explosion.transform.position = hit.collider.gameObject.transform.position;
                    explosion.GetComponent<Renderer>().material = hit.collider.gameObject.GetComponent<Renderer>().material;
                    explosion.GetComponent<ParticleSystem>().Play();
                }
            }
        }
    }

    public void LaunchDisk() {
        if(count - leaveSeconds == 1) {
            count = leaveSeconds;
            GameObject disk = diskFactory.GetDisk(round);
            Debug.Log(disk);
            disks.Add(disk);
            actionManager.addRandomAction(disk);
        }
    }

    public void RecycleDisk() {
        for(int i = 0; i < disks.Count; i++) {
            if( disks[i].transform.position.z < -18) {
                diskFactory.FreeDisk(disks[i]);
                disks.Remove(disks[i]);
            }
        }
    }

    public void Judge() {
        if(shootAtSth != null && shootAtSth.transform.tag == "Disk" && shootAtSth.activeInHierarchy) {
            scoreRecorder.Record(shootAtSth);
            diskFactory.FreeDisk(shootAtSth);
            shootAtSth = null;
        }

        if(scoreRecorder.getScore() > 500 * round) {
            round++;
            leaveSeconds = count = 60;
        }

        if (round == 3) {
            StopAllCoroutines ();
            state = State.WIN;
        } else if (leaveSeconds == 0 && scoreRecorder.getScore () < 500 * round) {
            StopAllCoroutines ();
            state = State.LOSE;
        } else state = State.CONTINUE;
    }

    public void Pause() {
        state = State.PAUSE;
        StopAllCoroutines();
        for (int i = 0; i < disks.Count; i++) disks[i].SetActive(false);
    }

    public void Resume() {
        StartCoroutine(DoCountDown());
        state = State.CONTINUE;
        for (int i = 0; i < disks.Count; i++) disks[i].SetActive(true);
    }

    public void Restart() {
        scoreRecorder.Reset();
        Application.LoadLevel(Application.loadedLevelName);
        Director.getInstance().currentSceneController.state = State.START;
    }
}

RoundActionManager.cs

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

public class RoundActionManager : SSActionManager, ISSActionCallback {
    public RoundController scene;
    public MoveToAction action1, action2;
    float speed;

    public void addRandomAction(GameObject gameObj) {
        int[] X = { -20, 20 };
        int[] Y = { -5, 5 };
        int[] Z = { -20, -20 };

        Vector3 startPos = new Vector3(
            UnityEngine.Random.Range(-20, 20),
            UnityEngine.Random.Range(-5, 5),
            UnityEngine.Random.Range(50, 10)
        );

        gameObj.transform.position = startPos;

        Vector3 randomTarget = new Vector3(
            X[UnityEngine.Random.Range(0, 2)],
            Y[UnityEngine.Random.Range(0, 2)],
            Z[UnityEngine.Random.Range(0, 2)]
        );

        MoveToAction action = MoveToAction.GetSSAction(randomTarget, gameObj.GetComponent<DiskData>().speed);
        RunAction(gameObj, action, this);
    }

    protected void Start() {
        scene = (RoundController)Director.getInstance().currentSceneController;
        scene.actionManager = this;
    }

    protected new void Update() {
        base.Update();
    }

    public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null) {
    }
}

UserGUI.cs

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

public interface IUserAction {
    void shoot();
}

public class UserGUI : MonoBehaviour {
    private IUserAction action;
    private float width, height;
    private string countDownTitle;

    void Start() {
        countDownTitle = "Start";
        action = Director.getInstance().currentSceneController as IUserAction;
    }

    float castw(float scale) {
        return (Screen.width - width) / scale;
    }

    float casth(float scale) {
        return (Screen.height - height) / scale;
    }

    void OnGUI() {
        width = Screen.width / 12;
        height = Screen.height / 12;

        GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), ((RoundController)Director.getInstance().currentSceneController).leaveSeconds.ToString());
        GUI.Button(new Rect(580, 10, 80, 30), ((RoundController)Director.getInstance().currentSceneController).scoreRecorder.getScore().ToString());

        if (Director.getInstance().currentSceneController.state != State.WIN && Director.getInstance().currentSceneController.state != State.LOSE
            && GUI.Button(new Rect(10, 10, 80, 30), countDownTitle)) {

            if (countDownTitle == "Start") {
                countDownTitle = "Pause";
                Director.getInstance().currentSceneController.Resume();
            } else {
                countDownTitle = "Start";
                Director.getInstance().currentSceneController.Pause();
            }
        }

        if (Director.getInstance().currentSceneController.state == State.WIN) {
            if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Win!")) Director.getInstance().currentSceneController.Restart();
        } else if (Director.getInstance().currentSceneController.state == State.LOSE) {
            if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Lose!")) Director.getInstance().currentSceneController.Restart();
        }
    }

    void Update() {
        action.shoot();
    }
}

剩下的就跟之前的牧师与魔鬼的代码一样啦。
这里最最最重要的是(红笔五角星),要调整脚本的调用顺序。否则会出错的。
这里写图片描述
没啦,就这么多了。希望玩得愉快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值