my射飞碟小游戏
# 射飛碟游戲 #
### 具體要求如下: ###
假設有一支槍在攝像機位置(0,1,-10),在(0,0,0-10-20)放置三個小球作為距離標記,調整視角直到小球在下中部
將鼠標所在平面坐標,轉換為子彈(球體)射出的角度方向。子彈使用物理引擎,初速度恒定。(U3d 坐標變換: http://www.cnblogs.com/tekkaman/p/3809409.html )
`Vector3 mp = Input.mousePosition; //get Screen Position
print (mp.ToString());
Vector3 mp1 = cam.camera.ScreenToViewportPoint (mp);
mp1.z = 10; //距攝像頭 10 位置立面
mp1 = cam.camera.ViewportToWorldPoint (mp1);
print (mp1.ToString());`
游戲要分多個 round , 飛碟數量每個 round 都是 n 個,但色彩,大小;發射位置,速度,角度,每次發射數量按預定規則變化。
用戶按空格后,321倒數3秒,飛碟飛出(物理引擎控制),點擊鼠標,子彈飛出。飛碟落地,或被擊中,則準備下一次射擊。
以下是一些技術要求:
子彈僅需要一個,不用時處于 deactive 狀態
飛碟用一個帶緩存的工廠生產,template 中放置預制的飛碟對象
程序類圖設計大致如下:
下面是游戲的組件代碼:
###1、GameModel.cs###
????using UnityEngine;
????using System.Collections;
????using System.Collections.Generic;
????using Com.Mygame;
????public class GameModel : MonoBehaviour {
????public float countDown = 3f;??
????public float timeToEmit;??????
????private bool counting;??????
????private bool shooting;?????
?????
????public bool isCounting() {
????????return counting;
????}
????public bool isShooting() {
????????return shooting;
????}?
????private List<GameObject> disks = new List<GameObject>();????// 飛碟對象列表??
????private List<int> diskIds = new List<int>();?????????????
????private int diskScale;????????
????private Color diskColor;???????????
????private Vector3 emitPosition;??????
????private Vector3 emitDirection;???????
????private float emitSpeed;????????????
????private int emitNumber;??????????????
????private bool emitEnable;???????????
????private SceneController scene;
????void Awake() {
????????scene = SceneController.getInstance();
????????scene.setGameModel(this);
????}
????public void setting(int scale, Color color, Vector3 emitPos, Vector3 emitDir, float speed, int num) {??// 場景設置
????????diskScale = scale;??// 沒什么好說的,賦值
????????diskColor = color;
????????emitPosition = emitPos;
????????emitDirection = emitDir;
????????emitSpeed = speed;
????????emitNumber = num;
????}
????// 準備下一次發射??
????public void prepareToEmitDisk() {
????????if (counting == false && shooting == false) {
????????????timeToEmit = countDown;
????????????emitEnable = true;??// 可發射變為真
????????}
????}
????// 發射飛碟??
????void emitDisks() {
????????for (int i = 0; i < emitNumber; ++i) {
????????????diskIds.Add(Factory.getInstance().getDisk());
????????????disks.Add(Factory.getInstance().getDiskObject(diskIds[i]));
????????????disks[i].transform.localScale *= diskScale;
????????????disks[i].transform.position = new Vector3(emitPosition.x, emitPosition.y + i, emitPosition.z);
????????????disks[i].SetActive(true);
????????????disks[i].rigidbody.AddForce(emitDirection * Random.Range(emitSpeed * 5, emitSpeed * 10) / 10, ForceMode.Impulse);
????????}
????}
????// 回收??
????void freeADisk(int i) {
????????Factory.getInstance().free(diskIds[i]);
????????disks.RemoveAt(i);
????????diskIds.RemoveAt(i);
????}
????void FixedUpdate() {
????????if (timeToEmit > 0) {
????????????counting = true;
????????????timeToEmit -= Time.deltaTime;
????????} else {
????????????counting = false;
????????????if (emitEnable == true) {
????????????????emitDisks();
????????????????emitEnable = false;??// 改變之后可發射變為假
????????????????shooting = true;
????????????}
????????}
????}
????void Update() {
????????for (int i = 0; i < disks.Count; i++) {
????????????if (!disks[i].activeInHierarchy) {
????????????????scene.getJudge().scoreADisk();
????????????????freeADisk(i);
????????????} else if (disks[i].transform.position.y < 0) {
????????????????scene.getJudge().failADisk();
????????????????freeADisk(i);
????????????}
????????}
????????if (disks.Count == 0) {??// 如果不存在飛碟了,停止射擊
????????????shooting = false;
????????}
????}
????}
這個文件控制的是游戲場景,通過調用Factory.getInstance()功能來獲取飛碟的實例,當飛碟被擊中或者自己落地的時候,將被freeDisk()函數回收,并且通過調用Judge類中的函數,來決定分數的獲得和扣除,并以此來決定是否結束游戲或者進入下一關卡。FixedUpdate()和Update()函數通過bool條件判斷,來決定是否可以繼續射擊。
###2、UserInterface###
????using UnityEngine;
????using UnityEngine.UI;
????using System.Collections;
????using Com.Mygame;
????public class UserInterface : MonoBehaviour {
????public Text mainText;
????public Text scoreText;??
????public Text roundText;?
????private int round;??// 判定當前回合?
????public GameObject bullet;????????
????public ParticleSystem explosion;???
????public float fireRate = .25f;??????
????public float speed = 500f;?????
????private float nextFireTime;????????
????private IUserInterface userInt;
????private IQueryStatus queryInt;??
????void Start() {??// 游戲開始,加載
????????bullet = GameObject.Instantiate(bullet) as GameObject;
????????explosion = GameObject.Instantiate(explosion) as ParticleSystem;
????????userInt = SceneController.getInstance() as IUserInterface;
????????queryInt = SceneController.getInstance() as IQueryStatus;
????}
????void Update() {
????????if (queryInt.isCounting()) {
????????????mainText.text = ((int)queryInt.getEmitTime()).ToString();
????????} else {
????????????if (Input.GetKeyDown("space")) {??// 輸入空格開始
????????????????yield return new WaitforSeconds(3f);??// 倒數3秒后開始
????????????????userInt.emitDisk();
????????????}
????????????if (queryInt.isShooting()) {
????????????????mainText.text = "";?????// 隱藏maintext
????????????}
????????????// 發射子彈??
????????????if (queryInt.isShooting() && Input.GetMouseButtonDown(0) && Time.time > nextFireTime) {
????????????????nextFireTime = Time.time + fireRate;??// 開火冷卻時間
????????????????Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
????????????????bullet.rigidbody.velocity = Vector3.zero;???????????????????????// 重置子彈速度?
????????????????bullet.transform.position = transform.position;??????????????????// 子彈射出??
????????????????bullet.rigidbody.AddForce(ray.direction * speed, ForceMode.Impulse);
????????????????RaycastHit hit;
????????????????if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "Disk") {
????????????????????explosion.transform.position = hit.collider.gameObject.transform.position;
????????????????????explosion.Play();
????????????????????// 擊中飛碟自動回收??
????????????????????hit.collider.gameObject.SetActive(false);
????????????????}
????????????}
????????}
????????roundText.text = "Round: " + queryInt.getRound().ToString();
????????scoreText.text = "Score: " + queryInt.getPoint().ToString();?
????????if (round != queryInt.getRound()) {
????????????round = queryInt.getRound();
????????????mainText.text = "Round " + round.ToString() + " Start";
????????}
????}
????}
該文件創建用戶界面,其中包含著加載、提示、游戲主體等部分。作業要求中,用戶按空格后,321倒數3秒,飛碟飛出(物理引擎控制),點擊鼠標左鍵,子彈飛出。飛碟落地,或被擊中,則準備下一次射擊。我用了waitforSeconds函數來實現,在等待3秒之后,開始飛出飛碟,飛碟落地或被擊中的函數已經在GameModel.cs文件中寫出,這里就不再贅述。值得一提的是,剛開始我測試游戲的時候,子彈的速度會越來越快,這是因為我沒有將其清零的緣故,后來我令其velocity賦值為0來進行清零。上一次的作業中我的子彈使用的是射線判定,這次則用的是有碰撞體積的物理引擎,這點可以在裝載之后發現。
###3、SceneController.cs###
????using UnityEngine;
????using System.Collections;
????using Com.Mygame;
????namespace Com.Mygame {
????public interface IUserInterface {??// 場景控制器,是游戲中十分重要的一個環節
????????void emitDisk();
????}
????public interface IQueryStatus {??// 記錄回合和得分
????????bool isCounting();
????????bool isShooting();
????????int getRound();
????????int getPoint();
????????int getEmitTime();
????}
????public interface IJudgeEvent {
????????void nextRound();
????????void setPoint(int point);
????}
????public class SceneController : System.Object, IQueryStatus, IUserInterface, IJudgeEvent {??// 繼承各類
????????private static SceneController _instance;
????????private SceneControllerBC _baseCode;??// 分別為SceneControllerBC、GameModel、Judege
????????private GameModel _gameModel;
????????private Judge _judge;
????????private int _round;
????????private int _point;
????????public static SceneController getInstance() {
????????????if (_instance == null) {
????????????????_instance = new SceneController();??// 返回SceneController的實例
????????????}
????????????return _instance;
????????}
????????public void setGameModel(GameModel obj) {
????????????_gameModel = obj;
????????}
????????internal GameModel getGameModel() {
????????????return _gameModel;
????????}
????????public void setJudge(Judge obj) {
????????????_judge = obj;
????????}
????????internal Judge getJudge() {
????????????return _judge;
????????}
????????public void setSceneControllerBC(SceneControllerBC obj) {
????????????_baseCode = obj;
????????}
????????internal SceneControllerBC getSceneControllerBC() {
????????????return _baseCode;
????????}
????????public void emitDisk() {
????????????_gameModel.prepareToEmitDisk();
????????}
????????public bool isCounting() {
????????????return _gameModel.isCounting();
????????}
????????public bool isShooting() {
????????????return _gameModel.isShooting();
????????}
????????public int getRound() {
????????????return _round;
????????}
????????public int getPoint() {
????????????return _point;
????????}
????????public int getEmitTime() {
????????????int result = (int)_gameModel.timeToEmit + 1;
????????????return result;
????????}
????????public void setPoint(int point) {
????????????_point = point;
????????}
????????public void nextRound() {
????????????_point = 0; _baseCode.loadRoundData(++_round);
????????}
????}
????}
場景控制器,實現各種成員變量的返回實現,以及接口定義和保存注入對象。其中它有兩個私有變量round和point,分別記錄游戲正在進行的回合,以及玩家目前的得分,應用在GameModel中實現。
###4、SceneControllerBC.cs###
????UnityEngine;
????using System.Collections;
????using Com.Mygame;
????public class SceneControllerBC : MonoBehaviour {
????private Color color;
????private Vector3 emitPos;
????private Vector3 emitDir;
????private float speed;
????void Awake() {
????????SceneController.getInstance().setSceneControllerBC(this);
????}
????public void loadRoundData(int round) {??// 關卡的設計
????????switch (round) {
????????????case 1:?????// 第一關??
????????????????color = Color.green;
????????????????emitPos = new Vector3(-2.5f, 0.2f, -5f);??// 初始條件
????????????????emitDir = new Vector3(24.5f, 40.0f, 67f);
????????????????speed = 4;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 1);
????????????????break;
????????????case 2:?????// 第二關??
????????????????color = Color.red;
????????????????emitPos = new Vector3(2.5f, 0.2f, -5f);
????????????????emitDir = new Vector3(-24.5f, 35.0f, 67f);
????????????????speed = 4;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 2);??// 設定條件
????????????????break;
????????????case 3:?????// 第三關??
????????????????color = Color.red;
????????????????emitPos = new Vector3(2.5f, 0.2f, -5f);
????????????????emitDir = new Vector3(-24.5f, 35.0f, 67f);??// 飛碟初始位置不變,僅改變速度
????????????????speed = 5;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 4);??// 其實改一下飛碟的速度就可以了
????????????????break;
????????}
????}
????}
此文件為關卡類的定義,我只做了3個關卡,題目要求我:游戲要分多個 round , 飛碟數量每個 round 都是 n 個,但色彩,大小;發射位置,速度,角度,每次發射數量按預定規則變化。因此我沒有改變飛碟的數量,位置和角度,從速度入手,越到后面的關卡越快。函數Awake()用來獲取場景控制器實例,loadRoundData()用來初始化游戲場景,即定義飛碟的屬性。
###5、Factory.cs###
????using UnityEngine;
????using System.Collections;
????using System.Collections.Generic;
????using Com.Mygame;
????namespace Com.Mygame {
????public class Factory : System.Object {
????????private static Factory _instance;??// 獲取實例
????????private static List<GameObject> diskList;
????????public GameObject diskTemplate;????????
????????public static Factory getInstance() {??// 工廠實例
????????????if (_instance == null) {
????????????????_instance = new Factory();
????????????????diskList = new List<GameObject>();
????????????}
????????????return _instance;
????????}
????????public int getDisk() {
????????????for (int i = 0; i < diskList.Count; i++) {
????????????????if (!diskList[i].activeInHierarchy) {??//??判斷是否飛碟空閑
????????????????????return i;?
????????????????}
????????????}
????????????diskList.Add(GameObject.Instantiate(diskTemplate) as GameObject);??// 設置新的飛碟
????????????return diskList.Count-1;
????????}
????????public void free(int id) {
????????????if (id >= 0 && id < diskList.Count) {??// 判斷是否有效
????????????????diskList[id].rigidbody.velocity = Vector3.zero;??// 速度清零
????????????????diskList[id].transform.localScale = diskTemplate.transform.localScale;
????????????????diskList[id].SetActive(false);??// 活動能力重置
????????????}
????????}
????????public GameObject getDiskObject(int id) {
????????????if (id > -1 && id < diskList.Count) {
????????????????return diskList[id];
????????????}
????????????return null;
????????}
????????
????}
????}
????public class DiskFactoryBC : MonoBehaviour {??// 另一個類BC
????public GameObject disk;
????void Awake() {
????????Factory.getInstance().diskTemplate = disk;??// 用于獲取飛碟實例
????}
????}
題目要求:飛碟用一個帶緩存的工廠生產,template 中放置預制的飛碟對象。這個就是飛碟工廠,管理飛碟實例,同時對外屏蔽飛碟實例的的提取和回收細節。它定義了獲取、回收飛碟的功能,并且由于是public函數,可以被其他函數直接調用,來管理、應用飛碟。
###6、Judge.cs###
????using UnityEngine;
????using System.Collections;
????using Com.Mygame;
????public class Judge : MonoBehaviour {??// 判定得分失分,能否進入下一回合
????public int oneDiskScore = 10;
????public int oneDiskFail = 10;
????public int disksToWin = 4;
????private SceneController scene;
????void Awake() {
????????scene = SceneController.getInstance();
????????scene.setJudge(this);??// 設定規則
????}
????void Start() {
????????scene.nextRound();??// 第一關??
????}
?
????public void scoreADisk()??// 得分
????{
????????scene.setPoint(scene.getPoint() + oneDiskScore);
????????if (scene.getPoint() == disksToWin * oneDiskScore) {
????????????scene.nextRound();
????????}
????}
????public void failADisk() {??// 失分
????????scene.setPoint(scene.getPoint() - oneDiskFail);??// 判定條件,飛碟掉落
????}
????}
用以判斷得失分的類,當符合得分條件時,調用得分函數;當符合失分條件時(即飛碟未擊中而掉落時),調用失分函數。當得分符合條件時,進入下一回合。
*題目條件:有一支槍在攝像機位置(0,1,-10),在(0,0,0-10-20)放置三個小球作為距離標記,調整視角直到小球在下中部。*
部件設定:
攝像機:# 射飛碟游戲 #
### 具體要求如下: ###
假設有一支槍在攝像機位置(0,1,-10),在(0,0,0-10-20)放置三個小球作為距離標記,調整視角直到小球在下中部
將鼠標所在平面坐標,轉換為子彈(球體)射出的角度方向。子彈使用物理引擎,初速度恒定。(U3d 坐標變換: http://www.cnblogs.com/tekkaman/p/3809409.html )
`Vector3 mp = Input.mousePosition; //get Screen Position
print (mp.ToString());
Vector3 mp1 = cam.camera.ScreenToViewportPoint (mp);
mp1.z = 10; //距攝像頭 10 位置立面
mp1 = cam.camera.ViewportToWorldPoint (mp1);
print (mp1.ToString());`
游戲要分多個 round , 飛碟數量每個 round 都是 n 個,但色彩,大小;發射位置,速度,角度,每次發射數量按預定規則變化。
用戶按空格后,321倒數3秒,飛碟飛出(物理引擎控制),點擊鼠標,子彈飛出。飛碟落地,或被擊中,則準備下一次射擊。
以下是一些技術要求:
子彈僅需要一個,不用時處于 deactive 狀態
飛碟用一個帶緩存的工廠生產,template 中放置預制的飛碟對象
程序類圖設計大致如下:
下面是游戲的組件代碼:
###1、GameModel.cs###
????using UnityEngine;
????using System.Collections;
????using System.Collections.Generic;
????using Com.Mygame;
????public class GameModel : MonoBehaviour {
????public float countDown = 3f;??
????public float timeToEmit;??????
????private bool counting;??????
????private bool shooting;?????
?????
????public bool isCounting() {
????????return counting;
????}
????public bool isShooting() {
????????return shooting;
????}?
????private List<GameObject> disks = new List<GameObject>();????// 飛碟對象列表??
????private List<int> diskIds = new List<int>();?????????????
????private int diskScale;????????
????private Color diskColor;???????????
????private Vector3 emitPosition;??????
????private Vector3 emitDirection;???????
????private float emitSpeed;????????????
????private int emitNumber;??????????????
????private bool emitEnable;???????????
????private SceneController scene;
????void Awake() {
????????scene = SceneController.getInstance();
????????scene.setGameModel(this);
????}
????public void setting(int scale, Color color, Vector3 emitPos, Vector3 emitDir, float speed, int num) {??// 場景設置
????????diskScale = scale;??// 沒什么好說的,賦值
????????diskColor = color;
????????emitPosition = emitPos;
????????emitDirection = emitDir;
????????emitSpeed = speed;
????????emitNumber = num;
????}
????// 準備下一次發射??
????public void prepareToEmitDisk() {
????????if (counting == false && shooting == false) {
????????????timeToEmit = countDown;
????????????emitEnable = true;??// 可發射變為真
????????}
????}
????// 發射飛碟??
????void emitDisks() {
????????for (int i = 0; i < emitNumber; ++i) {
????????????diskIds.Add(Factory.getInstance().getDisk());
????????????disks.Add(Factory.getInstance().getDiskObject(diskIds[i]));
????????????disks[i].transform.localScale *= diskScale;
????????????disks[i].transform.position = new Vector3(emitPosition.x, emitPosition.y + i, emitPosition.z);
????????????disks[i].SetActive(true);
????????????disks[i].rigidbody.AddForce(emitDirection * Random.Range(emitSpeed * 5, emitSpeed * 10) / 10, ForceMode.Impulse);
????????}
????}
????// 回收??
????void freeADisk(int i) {
????????Factory.getInstance().free(diskIds[i]);
????????disks.RemoveAt(i);
????????diskIds.RemoveAt(i);
????}
????void FixedUpdate() {
????????if (timeToEmit > 0) {
????????????counting = true;
????????????timeToEmit -= Time.deltaTime;
????????} else {
????????????counting = false;
????????????if (emitEnable == true) {
????????????????emitDisks();
????????????????emitEnable = false;??// 改變之后可發射變為假
????????????????shooting = true;
????????????}
????????}
????}
????void Update() {
????????for (int i = 0; i < disks.Count; i++) {
????????????if (!disks[i].activeInHierarchy) {
????????????????scene.getJudge().scoreADisk();
????????????????freeADisk(i);
????????????} else if (disks[i].transform.position.y < 0) {
????????????????scene.getJudge().failADisk();
????????????????freeADisk(i);
????????????}
????????}
????????if (disks.Count == 0) {??// 如果不存在飛碟了,停止射擊
????????????shooting = false;
????????}
????}
????}
這個文件控制的是游戲場景,通過調用Factory.getInstance()功能來獲取飛碟的實例,當飛碟被擊中或者自己落地的時候,將被freeDisk()函數回收,并且通過調用Judge類中的函數,來決定分數的獲得和扣除,并以此來決定是否結束游戲或者進入下一關卡。FixedUpdate()和Update()函數通過bool條件判斷,來決定是否可以繼續射擊。
###2、UserInterface###
????using UnityEngine;
????using UnityEngine.UI;
????using System.Collections;
????using Com.Mygame;
????public class UserInterface : MonoBehaviour {
????public Text mainText;
????public Text scoreText;??
????public Text roundText;?
????private int round;??// 判定當前回合?
????public GameObject bullet;????????
????public ParticleSystem explosion;???
????public float fireRate = .25f;??????
????public float speed = 500f;?????
????private float nextFireTime;????????
????private IUserInterface userInt;
????private IQueryStatus queryInt;??
????void Start() {??// 游戲開始,加載
????????bullet = GameObject.Instantiate(bullet) as GameObject;
????????explosion = GameObject.Instantiate(explosion) as ParticleSystem;
????????userInt = SceneController.getInstance() as IUserInterface;
????????queryInt = SceneController.getInstance() as IQueryStatus;
????}
????void Update() {
????????if (queryInt.isCounting()) {
????????????mainText.text = ((int)queryInt.getEmitTime()).ToString();
????????} else {
????????????if (Input.GetKeyDown("space")) {??// 輸入空格開始
????????????????yield return new WaitforSeconds(3f);??// 倒數3秒后開始
????????????????userInt.emitDisk();
????????????}
????????????if (queryInt.isShooting()) {
????????????????mainText.text = "";?????// 隱藏maintext
????????????}
????????????// 發射子彈??
????????????if (queryInt.isShooting() && Input.GetMouseButtonDown(0) && Time.time > nextFireTime) {
????????????????nextFireTime = Time.time + fireRate;??// 開火冷卻時間
????????????????Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
????????????????bullet.rigidbody.velocity = Vector3.zero;???????????????????????// 重置子彈速度?
????????????????bullet.transform.position = transform.position;??????????????????// 子彈射出??
????????????????bullet.rigidbody.AddForce(ray.direction * speed, ForceMode.Impulse);
????????????????RaycastHit hit;
????????????????if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "Disk") {
????????????????????explosion.transform.position = hit.collider.gameObject.transform.position;
????????????????????explosion.Play();
????????????????????// 擊中飛碟自動回收??
????????????????????hit.collider.gameObject.SetActive(false);
????????????????}
????????????}
????????}
????????roundText.text = "Round: " + queryInt.getRound().ToString();
????????scoreText.text = "Score: " + queryInt.getPoint().ToString();?
????????if (round != queryInt.getRound()) {
????????????round = queryInt.getRound();
????????????mainText.text = "Round " + round.ToString() + " Start";
????????}
????}
????}
該文件創建用戶界面,其中包含著加載、提示、游戲主體等部分。作業要求中,用戶按空格后,321倒數3秒,飛碟飛出(物理引擎控制),點擊鼠標左鍵,子彈飛出。飛碟落地,或被擊中,則準備下一次射擊。我用了waitforSeconds函數來實現,在等待3秒之后,開始飛出飛碟,飛碟落地或被擊中的函數已經在GameModel.cs文件中寫出,這里就不再贅述。值得一提的是,剛開始我測試游戲的時候,子彈的速度會越來越快,這是因為我沒有將其清零的緣故,后來我令其velocity賦值為0來進行清零。上一次的作業中我的子彈使用的是射線判定,這次則用的是有碰撞體積的物理引擎,這點可以在裝載之后發現。
###3、SceneController.cs###
????using UnityEngine;
????using System.Collections;
????using Com.Mygame;
????namespace Com.Mygame {
????public interface IUserInterface {??// 場景控制器,是游戲中十分重要的一個環節
????????void emitDisk();
????}
????public interface IQueryStatus {??// 記錄回合和得分
????????bool isCounting();
????????bool isShooting();
????????int getRound();
????????int getPoint();
????????int getEmitTime();
????}
????public interface IJudgeEvent {
????????void nextRound();
????????void setPoint(int point);
????}
????public class SceneController : System.Object, IQueryStatus, IUserInterface, IJudgeEvent {??// 繼承各類
????????private static SceneController _instance;
????????private SceneControllerBC _baseCode;??// 分別為SceneControllerBC、GameModel、Judege
????????private GameModel _gameModel;
????????private Judge _judge;
????????private int _round;
????????private int _point;
????????public static SceneController getInstance() {
????????????if (_instance == null) {
????????????????_instance = new SceneController();??// 返回SceneController的實例
????????????}
????????????return _instance;
????????}
????????public void setGameModel(GameModel obj) {
????????????_gameModel = obj;
????????}
????????internal GameModel getGameModel() {
????????????return _gameModel;
????????}
????????public void setJudge(Judge obj) {
????????????_judge = obj;
????????}
????????internal Judge getJudge() {
????????????return _judge;
????????}
????????public void setSceneControllerBC(SceneControllerBC obj) {
????????????_baseCode = obj;
????????}
????????internal SceneControllerBC getSceneControllerBC() {
????????????return _baseCode;
????????}
????????public void emitDisk() {
????????????_gameModel.prepareToEmitDisk();
????????}
????????public bool isCounting() {
????????????return _gameModel.isCounting();
????????}
????????public bool isShooting() {
????????????return _gameModel.isShooting();
????????}
????????public int getRound() {
????????????return _round;
????????}
????????public int getPoint() {
????????????return _point;
????????}
????????public int getEmitTime() {
????????????int result = (int)_gameModel.timeToEmit + 1;
????????????return result;
????????}
????????public void setPoint(int point) {
????????????_point = point;
????????}
????????public void nextRound() {
????????????_point = 0; _baseCode.loadRoundData(++_round);
????????}
????}
????}
場景控制器,實現各種成員變量的返回實現,以及接口定義和保存注入對象。其中它有兩個私有變量round和point,分別記錄游戲正在進行的回合,以及玩家目前的得分,應用在GameModel中實現。
###4、SceneControllerBC.cs###
????UnityEngine;
????using System.Collections;
????using Com.Mygame;
????public class SceneControllerBC : MonoBehaviour {
????private Color color;
????private Vector3 emitPos;
????private Vector3 emitDir;
????private float speed;
????void Awake() {
????????SceneController.getInstance().setSceneControllerBC(this);
????}
????public void loadRoundData(int round) {??// 關卡的設計
????????switch (round) {
????????????case 1:?????// 第一關??
????????????????color = Color.green;
????????????????emitPos = new Vector3(-2.5f, 0.2f, -5f);??// 初始條件
????????????????emitDir = new Vector3(24.5f, 40.0f, 67f);
????????????????speed = 4;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 1);
????????????????break;
????????????case 2:?????// 第二關??
????????????????color = Color.red;
????????????????emitPos = new Vector3(2.5f, 0.2f, -5f);
????????????????emitDir = new Vector3(-24.5f, 35.0f, 67f);
????????????????speed = 4;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 2);??// 設定條件
????????????????break;
????????????case 3:?????// 第三關??
????????????????color = Color.red;
????????????????emitPos = new Vector3(2.5f, 0.2f, -5f);
????????????????emitDir = new Vector3(-24.5f, 35.0f, 67f);??// 飛碟初始位置不變,僅改變速度
????????????????speed = 5;
????????????????SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 4);??// 其實改一下飛碟的速度就可以了
????????????????break;
????????}
????}
????}
此文件為關卡類的定義,我只做了3個關卡,題目要求我:游戲要分多個 round , 飛碟數量每個 round 都是 n 個,但色彩,大小;發射位置,速度,角度,每次發射數量按預定規則變化。因此我沒有改變飛碟的數量,位置和角度,從速度入手,越到后面的關卡越快。函數Awake()用來獲取場景控制器實例,loadRoundData()用來初始化游戲場景,即定義飛碟的屬性。
###5、Factory.cs###
????using UnityEngine;
????using System.Collections;
????using System.Collections.Generic;
????using Com.Mygame;
????namespace Com.Mygame {
????public class Factory : System.Object {
????????private static Factory _instance;??// 獲取實例
????????private static List<GameObject> diskList;
????????public GameObject diskTemplate;????????
????????public static Factory getInstance() {??// 工廠實例
????????????if (_instance == null) {
????????????????_instance = new Factory();
????????????????diskList = new List<GameObject>();
????????????}
????????????return _instance;
????????}
????????public int getDisk() {
????????????for (int i = 0; i < diskList.Count; i++) {
????????????????if (!diskList[i].activeInHierarchy) {??//??判斷是否飛碟空閑
????????????????????return i;?
????????????????}
????????????}
????????????diskList.Add(GameObject.Instantiate(diskTemplate) as GameObject);??// 設置新的飛碟
????????????return diskList.Count-1;
????????}
????????public void free(int id) {
????????????if (id >= 0 && id < diskList.Count) {??// 判斷是否有效
????????????????diskList[id].rigidbody.velocity = Vector3.zero;??// 速度清零
????????????????diskList[id].transform.localScale = diskTemplate.transform.localScale;
????????????????diskList[id].SetActive(false);??// 活動能力重置
????????????}
????????}
????????public GameObject getDiskObject(int id) {
????????????if (id > -1 && id < diskList.Count) {
????????????????return diskList[id];
????????????}
????????????return null;
????????}
????????
????}
????}
????public class DiskFactoryBC : MonoBehaviour {??// 另一個類BC
????public GameObject disk;
????void Awake() {
????????Factory.getInstance().diskTemplate = disk;??// 用于獲取飛碟實例
????}
????}
題目要求:飛碟用一個帶緩存的工廠生產,template 中放置預制的飛碟對象。這個就是飛碟工廠,管理飛碟實例,同時對外屏蔽飛碟實例的的提取和回收細節。它定義了獲取、回收飛碟的功能,并且由于是public函數,可以被其他函數直接調用,來管理、應用飛碟。
###6、Judge.cs###
????using UnityEngine;
????using System.Collections;
????using Com.Mygame;
????public class Judge : MonoBehaviour {??// 判定得分失分,能否進入下一回合
????public int oneDiskScore = 10;
????public int oneDiskFail = 10;
????public int disksToWin = 4;
????private SceneController scene;
????void Awake() {
????????scene = SceneController.getInstance();
????????scene.setJudge(this);??// 設定規則
????}
????void Start() {
????????scene.nextRound();??// 第一關??
????}
?
????public void scoreADisk()??// 得分
????{
????????scene.setPoint(scene.getPoint() + oneDiskScore);
????????if (scene.getPoint() == disksToWin * oneDiskScore) {
????????????scene.nextRound();
????????}
????}
????public void failADisk() {??// 失分
????????scene.setPoint(scene.getPoint() - oneDiskFail);??// 判定條件,飛碟掉落
????}
????}
用以判斷得失分的類,當符合得分條件時,調用得分函數;當符合失分條件時(即飛碟未擊中而掉落時),調用失分函數。當得分符合條件時,進入下一回合。
*題目條件:有一支槍在攝像機位置(0,1,-10),在(0,0,0-10-20)放置三個小球作為距離標記,調整視角直到小球在下中部。*
部件設定:
攝像機:
飛碟:
子彈:
標記球:
1、
2、
3、
最后在攝像機上掛載文件就可以了。一個射飛碟的小游戲就做好了。
總結
- 上一篇: Unity3D-打飞碟小游戏
- 下一篇: 交互入门2——射击打靶游戏