3D游戏编程与设计作业6-Unity实现打飞碟游戏改进版(Hit UFO)
改進飛碟(Hit UFO)游戲
游戲內容要求
編程實踐
本次作業直接在上一次打飛碟游戲的基礎上增加adapter設計模式(增加一個內含PhysisActionManager和CCActionManager接口的ActionManagers類),提供一個運動的統一接口,根據玩家的具體操作再決定是調用物理運動類還是運動學動作管理器類。也就是游戲同時存在兩個飛碟運動模式,支持物理運動和運動學互相切換。
- Adapter(適配器)模式:將一個類的接口轉換成客戶希望的另外一個接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作。做法是將類自己的接口包裹在一個已存在的類中。有時也稱為包裝樣式/包裝。
本次作業采用的Adapter模式屬于對象適配器模式,即adapter類持有不同的動作管理器對象,并實現對應的想提供的目標接口。
本次游戲的結構UML圖如下:
玩家切換運動模式的方法是在游戲界面點擊鼠標右鍵,但并不會馬上中斷游戲切換運動模式,而是在下一個trail開始時進行切換。
動作接口
首先在原來的SceneController類中再定義一個統一的動作接口(模板類),包含了物理運動和運動學動作管理器類都需要實現的方法addForceOnUFO(GameObject UFO),適配器類Adapter繼承該接口。
public interface IActionManager{void addForceOnUFO(GameObject UFO);}用戶接口
當用戶接口類UserInterface中的Update()方法檢測到鼠標右鍵被按下時,調用方法切換動作管理器。修改后的UserInterface類Update()方法如下:
// Update is called once per framevoid Update () {//檢測鼠標點擊(左鍵)if (Input.GetMouseButtonDown(0)){Vector3 mousePos = Input.mousePosition;action.hitUFO(mousePos);}//檢測用戶按下空格if (Input.GetKeyDown(KeyCode.Space)){action.launchUFO();}//檢測鼠標右鍵點擊if (Input.GetButtonDown("Fire2")){action.switchActionModeNextRound();}}相應地,在SceneController類的IUserAction接口中增加該switchActionInNextRound()方法的聲明:
public interface IUserAction{void launchUFO();void hitUFO(Vector3 mousePos);void switchActionModeNextRound();}適配器類
接著編寫最重要的適配器類UFOActionAdapter,該類需要實現IActionManager接口(實現不同模式的addForceOnUFO(GameObject UFO)方法的調用),并且持有PhysisActionManager和CCActionManager對象,用一個整數型成員變量WhichActionManager來記錄當前使用的是哪一個動作管理器,值為0表示當前處于物理運動模式,值為1表示當前處于運動學動作管理器模式,只需要WhichActionManager = 1-WhichActionManager就能實現切換運動模式。代碼如下:
public class UFOActionAdapter : IActionManager{private PhysisActionManager physisActionManager;private CCActionManager ccActionManager;int whichActionManager = 0; // 0 -> PhysisActionManager, 1 -> CCActionManagerpublic UFOActionAdapter(){physisActionManager = PhysisActionManager.getInstance();ccActionManager = CCActionManager.getInstance();}public void switchActionMode(){whichActionManager = 1 - whichActionManager;}public void addForceOnUFO(GameObject UFO){if(whichActionManager == 0){physisActionManager.addForce(UFO);}else{ccActionManager.addForce(UFO);}}}在SceneController中使用bool型成員變量switchActionManager來標記是否需要切換運動模式,初始化為false,表示初始不做模式切換時游戲處于物理運動模式。代碼如下:
private bool switchActionManager = false;如果switchActionModeNextRound()方法被調用,則將switchActionManager置為true:
public void switchActionModeNextRound(){myStatusCtrl.showSwitchText();switchActionManager = true;}并且在每一輪trail開始時檢測switchActionManager是否為true,若為true則切換運動模式并將switchActionManager重置為false:
public void launchUFO(){//每次發射之前清0分數if (switchActionManager){switchActionManager = false;myUFOCtrl.switchActionManager();}myStatusCtrl.resetScore();myUFOCtrl.launchUFO();}物理運動管理器類
定義物理運動管理器,主要實現給游戲對象添加一個xyz軸方向上都是在一定數值范圍內隨機生成的瞬時力,代碼如下:
public class PhysisActionManager{private SceneController scene;private static PhysisActionManager instance;private PhysisActionManager(){scene = SceneController.getInstance();}public static PhysisActionManager getInstance(){if (instance == null) instance = new PhysisActionManager();return instance;}private Vector3 getRandomForce(){int x = UnityEngine.Random.Range(-30, 31);int y = UnityEngine.Random.Range(30, 41);int z = UnityEngine.Random.Range(20, 31);float t = 0.7f + scene.getTrailNum() / 20;return new Vector3(x, y, z) * t;}public void addForce(GameObject UFO){Vector3 force = getRandomForce();UFO.GetComponent<Rigidbody>().useGravity = true;UFO.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);}}運動學運動管理器
運動學管理器模式下的物體不使用重力屬性,即把游戲對象的剛體屬性useGravity設為false,并且給剛體一個初速度使其沿某個方向運動,代碼如下:
public class CCActionManager{private SceneController scene;private static CCActionManager instance;private CCActionManager(){scene = SceneController.getInstance();}public static CCActionManager getInstance(){if (instance == null) instance = new CCActionManager();return instance;}public void addForce(GameObject UFO){// 控制飛碟向某個隨機方向持續移動UFO.GetComponent<Rigidbody>().useGravity = false;UFO.GetComponent<Rigidbody>().velocity = new Vector3(5, 15, 5);}}飛碟控制類
飛碟控制類UFOController中需要定義一個適配器成員對象,用來在launchUFOs(roundNum)函數里(發射飛碟時)調用不同模式下的addForceOnUFO(GameObject)方法。修改后的UFOController類如下:
using CarolSum.com; using System; using System.Collections; using System.Collections.Generic; using UnityEngine;public class UFOController : MonoBehaviour {//預設文件public GameObject PlaneItem, LauncherItem, ExplosionItem;public Material greenMat, redMat, blueMat;private GameObject plane, launcher, explosion;private SceneController scene;private UFOActionAdapter adapter;//發射每一個飛碟的時間間隔private const float LAUNCH_GAP = 0.1f;// Use this for initializationvoid Start () {scene = SceneController.getInstance();scene.setUFOController(this);plane = Instantiate(PlaneItem);launcher = Instantiate(LauncherItem);explosion = Instantiate(ExplosionItem);adapter = new UFOActionAdapter();}// Update is called once per framevoid Update () {UFOFactory.getInstance().detectLandingUFOs();}public void launchUFO(){int trailNum = scene.getTrailNum() > 3 ? 3 : scene.getTrailNum();Debug.Log("發射!");if (!UFOFactory.getInstance().isLaunching()){StartCoroutine(launchUFOs(trailNum));}}IEnumerator launchUFOs(int roundNum){for(int i = 0; i<roundNum; i++){GameObject UFO = UFOFactory.getInstance().getUFO();UFO.transform.position = launcher.transform.position;UFO.GetComponent<MeshRenderer>().material = getMaterial(scene.getTrailNum());adapter.addForceOnUFO(UFO);//每隔LAUNCH_GAP時間發射一個UFOyield return new WaitForSeconds(LAUNCH_GAP);}}public void switchActionManager(){adapter.switchActionMode();}public void hitUFO(Vector3 mousePos){Ray ray = Camera.main.ScreenPointToRay(mousePos);RaycastHit hit;if(Physics.Raycast(ray, out hit)){if (hit.collider.gameObject.tag.Equals("UFO")){createExplosion(hit.collider.gameObject.transform.position);scene.addScore();UFOFactory.getInstance().RecyclingUFO(hit.collider.gameObject);}}}private void createExplosion(Vector3 position){explosion.transform.position = position;explosion.GetComponent<ParticleSystem>().GetComponent<Renderer>().material = getMaterial(scene.getTrailNum());explosion.GetComponent<ParticleSystem>().Play();}private Material getMaterial(int roundNum){switch(roundNum % 3){case 0:return redMat;case 1:return greenMat;case 2:return blueMat;default:return redMat; }}}游戲各預制的屬性設置如下:
Canvas:
Explosion:
Launcher:
Plane:
UFO:
Main Camera掛載:
Empty對象掛載:
最終運行效果如下:
總結
以上是生活随笔為你收集整理的3D游戏编程与设计作业6-Unity实现打飞碟游戏改进版(Hit UFO)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Maven插件 [WARNING] 'p
- 下一篇: kafka 延迟队列