unity3d开发鼠标打飞碟游戏(Hit UFO)
這次我們用Unity3d開發(fā)一個簡單的打飛碟游戲
游戲簡介
游戲有3個回合,每個回合會發(fā)射n中顏色的飛碟,擊中飛碟會得到相應(yīng)的分數(shù),其中,擊中黃色飛碟得1分,擊中藍色飛碟得2分,紅色飛碟4分,擊不中不扣分
游戲思想
為了減少開銷,提升游戲的運行速度,采用工廠模式對飛碟進行管理,飛碟的生產(chǎn)與回收由工廠來執(zhí)行,剩下的場景管理,動作管理和上次牧師與魔鬼相同:牧師與魔鬼
代碼實現(xiàn)
飛碟的工廠類
using System.Collections; using System.Collections.Generic; using UnityEngine;public class DiskFactory : MonoBehaviour {//存放飛碟的隊列,獲取飛碟出隊,回收飛碟入隊private Queue<GameObject> diskFactory = new Queue<GameObject>();//飛碟生產(chǎn)方法public GameObject GetDisk(int round){GameObject newDisk = null;if (diskFactory.Count > 0){newDisk = diskFactory.Dequeue();}else{newDisk = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("prefab/disk"), Vector3.zero, Quaternion.identity);newDisk.AddComponent<DiskData>();newDisk.SetActive(false);}/*通過回合生產(chǎn)不同顏色的飛碟,第一回合黃色,第二回合黃色和藍色,第三回合黃色、藍色和紅色,不同顏色的飛行速度不一樣*/round = Random.Range(0, round + 1);switch (round){case 0:newDisk.GetComponent<Renderer>().material.color = Color.yellow;newDisk.GetComponent<DiskData>().speed = 4.0f;int diraction = UnityEngine.Random.Range(-1f, 1f) > 0 ? -1 : 1;newDisk.GetComponent<DiskData>().flyDiraction = diraction;break;case 1:newDisk.GetComponent<Renderer>().material.color = Color.blue;newDisk.GetComponent<DiskData>().speed = 8.0f;int diraction1 = UnityEngine.Random.Range(-1f, 1f) > 0 ? -1 : 1;newDisk.GetComponent<DiskData>().flyDiraction = diraction1;break;case 2:newDisk.GetComponent<Renderer>().material.color = Color.red;newDisk.GetComponent<DiskData>().speed = 10.0f;int diraction2 = UnityEngine.Random.Range(-1f, 1f) > 0 ? -1 : 1;newDisk.GetComponent<DiskData>().flyDiraction = diraction2;break;}return newDisk;}//回收飛碟,入隊public void FreeDisk(GameObject disk){disk.SetActive(false);diskFactory.Enqueue(disk);}// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {} }場景控制之baseCode.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.MyGame; namespace Com.MyGame {public enum GameState { ROUND_START,ROUND_FINISH, RUNNING, PAUSE,START}//游戲?qū)а?/span>public class Director : System.Object{private static Director _instance;public SceneController currentSceneController { get; set; }public static Director getInstance(){if (_instance == null){_instance = new Director();}return _instance;}}public interface SceneController{void loadResources();}public interface UserAction{GameState GetGameState();void SetGameState(GameState state);void GameOver();int getScore();void restart();void hit();int GetRound();}/*感覺積分器放在這里不是很好,不過管它呢*/public class ScoreRecorder : MonoBehaviour{/** * score是玩家得到的總分 */public int score;/** * scoreTable是一個得分的規(guī)則表,每種飛碟的顏色對應(yīng)著一個分數(shù) */private Dictionary<Color, int> scoreTable = new Dictionary<Color, int>();// Use this for initialization void Start(){score = 0;scoreTable.Add(Color.yellow, 1);scoreTable.Add(Color.blue, 2);scoreTable.Add(Color.red, 4);}public void Record(GameObject disk){score += scoreTable[disk.GetComponent<Renderer>().material.color];}public void Reset(){score = 0;}}}場景控制之firstController:負責(zé)加載資源
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.MyGame;public class FirstController : MonoBehaviour, SceneController, UserAction {//動作管理器public CCActionManager actionManger { get; set; }//飛碟public Queue<GameObject> disks = new Queue<GameObject>();//分數(shù)public ScoreRecorder scoreRecorder { get; set; }//飛碟數(shù)量public int diskNum;//當(dāng)前回合private int currentRound = -1;//回合數(shù)private int round = 3;//發(fā)射飛碟得時間間隔private float time;//游戲狀態(tài)private GameState state = GameState.START;UserGUI userGUI;void Awake(){Director dir = Director.getInstance();dir.currentSceneController = this;this.gameObject.AddComponent<ScoreRecorder>();this.gameObject.AddComponent<DiskFactory>();scoreRecorder = Singleton<ScoreRecorder>.Instance;diskNum = 10;userGUI = this.gameObject.AddComponent<UserGUI>() as UserGUI;}private void Update(){if (currentRound == 3){return;}if (actionManger.diskNum == 0 && state == GameState.RUNNING){state = GameState.ROUND_FINISH;}if (actionManger.diskNum ==0 && state == GameState.ROUND_START){currentRound = currentRound + 1;NextRound();actionManger.diskNum = 10;state = GameState.RUNNING;}if (time > 1){if (state == GameState.RUNNING){ThrowDisk();}time = 0;}else{time += Time.deltaTime;}}//加載飛碟,每個回合獲取10飛碟public void NextRound(){DiskFactory df = Singleton<DiskFactory>.Instance;for (int i = 0; i < diskNum; ++i){disks.Enqueue(df.GetDisk(currentRound));}actionManger.StartThrow(disks);}//發(fā)射飛碟public void ThrowDisk(){if (disks.Count != 0){GameObject disk = disks.Dequeue();float y = Random.Range(0, 7);float x = Random.Range(-8, 8);disk.transform.position = new Vector3(x, y, 0);disk.SetActive(true);}}/*因為頁面比較單一,所以這個方法沒有實現(xiàn),如果想讓場景多彩一點,可以試著實現(xiàn)該方法*/public void loadResources(){}public void restart(){currentRound = -1;//state = GameState.ROUND_START;state = GameState.START;}public GameState GetGameState(){return state;}public void SetGameState(GameState state){this.state = state;}/*因為游戲沒有設(shè)置Gameover這個功能,所以就沒有實現(xiàn)該功能*/public void GameOver(){//throw new System.NotImplementedException();}public int getScore(){//throw new System.NotImplementedException();return scoreRecorder.score;}//監(jiān)視鼠標(biāo)點擊的方法public void hit(){GameObject gameObject = null;if (Input.GetMouseButton(0)){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit)) gameObject = hit.collider.gameObject;}if (gameObject != null && gameObject.GetComponent<DiskData>()!=null){scoreRecorder.Record(gameObject);gameObject.transform.position = new Vector3(0, -5, 0);}}public int GetRound(){return currentRound;//throw new System.NotImplementedException();} }場景控制之UserGUI:用來顯示按鈕,分數(shù)等
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.MyGame;public class UserGUI : MonoBehaviour {public FirstController scene;public int status = 0;public bool isFirst = true;GUIStyle style;GUIStyle buttonStyle;float time = 60;float second = 0;void Start(){//scene = Director.getInstance().currentSceneController as FirstController;scene = Director.getInstance().currentSceneController as FirstController;style = new GUIStyle();style.fontSize = 40;style.normal.textColor = Color.red;style.alignment = TextAnchor.MiddleCenter;buttonStyle = new GUIStyle("button");buttonStyle.fontSize = 25;}private void Update(){//scene.click();}void OnGUI() {scene.hit();GUI.Label(new Rect(1000, 0, 400, 400), scene.getScore().ToString(),style);int buttonX = Screen.width / 2 - 45;int buttonY = Screen.height / 2 - 45;int labelX = Screen.width / 2 - 45;int labelY = Screen.height;游戲的暫停與繼續(xù)if (scene.GetGameState() == GameState.RUNNING && GUI.Button(new Rect(10, 10,90,90 ), "Pause",buttonStyle) ){scene.SetGameState(GameState.PAUSE);}if (scene.GetGameState() == GameState.PAUSE && GUI.Button(new Rect(10, 10, 90,90), "Run", buttonStyle)){scene.SetGameState(GameState.RUNNING);}//其實后面這幾個用來控制游戲開始和進入下一輪的的按鈕的出現(xiàn)邏輯我總覺得怪怪的if (scene.GetRound() == 2 && scene.GetGameState() == GameState.ROUND_FINISH){GUI.Label(new Rect(labelX, labelY, 90, 90), "You Have Finish All The Round");if (GUI.Button(new Rect(buttonX, buttonY, 90, 90), "Restart", buttonStyle)){scene.restart();}return;}if (scene.GetRound() == -1 && GUI.Button(new Rect(buttonX, buttonY, 90, 90), "Start",buttonStyle)) {scene.SetGameState(GameState.ROUND_START);}if (scene.GetGameState() == GameState.ROUND_FINISH && scene.GetRound() < 2 && GUI.Button(new Rect(buttonX, buttonY, 90, 90), "Next Round", buttonStyle)){scene.SetGameState(GameState.ROUND_START);}} }動作管理之SSAction: SSAction是所有動作的基類,通過實現(xiàn)SSAciton來指定不同的動作
public class SSAction : ScriptableObject{public bool enable = false;public bool distroy = true;// Use this for initializationpublic GameObject gameObject { get; set; }public Transform transform { get; set; }public ISSActionCallback callback { get; set; }public virtual void Start(){throw new System.NotImplementedException();}// Update is called once per framepublic virtual void Update(){throw new System.NotImplementedException();}public void reset(){enable = false;distroy = true;gameObject = null;transform = null;callback = null;}}動作管理之CCFlyAction: 飛碟的飛行動作
public class CCFlyAction: SSAction{private float gravityAcceleration = 9.8f;private int diraction;private float speed;private float flyTime;public override void Start(){diraction = gameObject.GetComponent<DiskData>().flyDiraction;speed = gameObject.GetComponent<DiskData>().speed;enable = true;distroy = false;flyTime = 0;}public override void Update(){if (gameObject.activeSelf){flyTime += Time.deltaTime;this.transform.Translate(new Vector3(diraction * Time.deltaTime * speed, -1 * flyTime * Time.deltaTime * gravityAcceleration, 0));if (this.transform.position.y < -4){this.enable = false;this.distroy = true;this.callback.SSActionEvent(this);}}}public static CCFlyAction GetAction(){CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();return action;}}動作管理之動作管理器SSActionManager:這是所有動作管理器的基類
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.Action; public class SSActionManager : MonoBehaviour {private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();private List<SSAction> waitingAdd = new List<SSAction>();private List<int> waitingDelete = new List<int>();protected void Update(){foreach (SSAction ac in waitingAdd){actions[ac.GetInstanceID()] = ac;}waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> kv in actions){SSAction ac = kv.Value;if (ac.distroy){waitingDelete.Add(ac.GetInstanceID());}else if (ac.enable){ac.Update();}}foreach (int key in waitingDelete){SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager){action.gameObject = gameobject;action.transform = gameobject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}protected void Start() {} }動作管理之動作管理器CCActionManager:對SSManager進行了加強,用于管理某個對象的具體動作,為了減少開銷,CCActionManager也作為了一個工廠,用來管理CCFlyAction
using System.Collections; using System.Collections.Generic; using UnityEngine; using Com.Action; using Com.MyGame;public class CCActionManager :SSActionManager, ISSActionCallback {public int diskNum;public FirstController scene;float speed = 20f;Queue<SSAction> actions = new Queue<SSAction>();void ISSActionCallback.SSActionEvent(SSAction source, SSActionEventType events, int intParam, string strParam, Object objectParam){if (source is CCFlyAction) {diskNum --;DiskFactory df = Singleton<DiskFactory>.Instance;df.FreeDisk(source.gameObject);FreeAction(source);}}public void FreeAction(SSAction action){action.reset();actions.Enqueue(action);}void Start(){scene = Director.getInstance().currentSceneController as FirstController;scene.actionManger = this;}void Update(){//游戲處于運行狀態(tài)時飛碟才會飛if (scene.GetGameState() == GameState.RUNNING)base.Update();}SSAction GetAction(){SSAction action = null;if (actions.Count > 0){action = actions.Dequeue();}else{action = CCFlyAction.GetAction();}return action;}public void StartThrow(Queue<GameObject> disks){foreach(GameObject disk in disks) {RunAction(disk, GetAction(),(ISSActionCallback)this);}}}動作管理之ISSActionCallback:這個我也不知道怎么描述他的功能,說是用來作為ActionManager和Action之間的通信,但我感覺也能用來規(guī)定動作執(zhí)行完之后需要執(zhí)行的行為
public enum SSActionEventType : int { Started, Competeted }public interface ISSActionCallback{void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null);}用來實現(xiàn)單例模式的模板
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Singleton<T> : MonoBehaviour where T: MonoBehaviour {protected static T instance;public static T Instance{get{if (instance == null){instance = (T)FindObjectOfType(typeof(T));if (instance == null){}}return instance;}} }總結(jié)
以上是生活随笔為你收集整理的unity3d开发鼠标打飞碟游戏(Hit UFO)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NES模拟器开发笔记(001)缘起、资料
- 下一篇: 嵌入式系统设计 (考试题+答案)