與遊戲世界互動-作業與練習(5)
1、編寫一個簡單的滑鼠打飛碟(Hit UFO)遊戲
遊戲內容要求:
1.遊戲有 n 個 round,每個 round 都包括10 次 trial;
2.每個 trial 的飛碟的色彩、大小、發射位置、速度、角度、同時出現的個數都可能不同。它們由該 round 的 ruler 控制;
3.每個 trial 的飛碟有隨機性,總體難度隨 round 上升;
4.滑鼠點中得分,得分規則按色彩、大小、速度不同計算,規則可自由設定。
遊戲的要求:
- 使用帶快取的工廠模式管理不同飛碟的生產與回收,該工廠必須是場景單例項的! 具體實現見參考資源 Singleton 模板類
- 近可能使用前面 MVC 結構實現人機互動與遊戲模型分離
設計過程
這次大部分的程式碼其實都可以沿用之前的,只需稍作修改就好。(那誰能想到被githubgank了呢)
主要改動的有:IUserAction;FirstController;ClickAction;CCActionManager,以及新增的有關UFO的指令碼。
IUserAction:很簡單,刪除幾個沒用的介面就好。
public interface IUserAction
{
// void MoveBoat();
// void MoveRole(RoleModel roleModel);
void Restart();
//void Check();
}
FirstController:FirstController涉及的改動較多,主要是UFO函式的呼叫,主體還是update,按輪次去產生或放出飛碟。(順手就把輪次變化實現了,他真不值得再建一個檔案)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstController : MonoBehaviour, ISceneController, IUserAction {
private bool isRuning;
public UFOFactory ufoFactory;
private int[] roundUFOs;
private int score;
private int round;
private float sendTime;
int sendCnt;
// the first scripts
void Awake () {
SSDirector director = SSDirector.getInstance ();
director.setFPS (60);
director.currentSceneController = this;
director.currentSceneController.LoadResources ();
this.gameObject.AddComponent<UserGUI>();
this.gameObject.AddComponent<CCActionManager>();
ufoFactory=UFOFactory.getInstance();
roundUFOs=new int[]{3,5,9,11,15};
score=round=sendCnt=0;
sendTime=0;
sendCnt =0;
}
// loading resources for the first scence
public void LoadResources () {
isRuning=true;
}
public void SendUFO(){
GameObject ufo=ufoFactory.GetUFO(round);
ufo.transform.position=new Vector3(-ufo.GetComponent<UFOData>().direction.x * 7, UnityEngine.Random.Range(0f, 8f), 0);
ufo.SetActive(true);
this.gameObject.GetComponent<CCActionManager>().Fly(ufo,ufo.GetComponent<UFOData>().speed,ufo.GetComponent<UFOData>().direction);
}
public bool GetIsRuning(){
return isRuning;
}
public void JudgeCallback(bool isRuning,int score){
this.score+=score;
this.gameObject.GetComponent<UserGUI>().score=this.score;
this.isRuning=isRuning;
}
public void Pause ()
{
throw new System.NotImplementedException ();
}
public void Resume ()
{
throw new System.NotImplementedException ();
}
#region IUserAction implementation
public void Restart ()
{
isRuning=true;
this.gameObject.GetComponent<UserGUI>().gameMessage="";
this.gameObject.GetComponent<UserGUI>().score=0;
score=round=sendCnt=0;
sendTime=0;
ufoFactory.FreeALL();
}
#endregion
void Start () {
}
void Update () {
sendTime+=Time.deltaTime;
if(sendTime>2){
sendTime=0;
for(int i = 0; i < 5 && sendCnt < roundUFOs[round]; i++){
sendCnt++;
SendUFO();
}
if(sendCnt == roundUFOs[round]&&round==roundUFOs.Length-1){
isRuning=false;
gameObject.GetComponent<UserGUI>().gameMessage = "Time Out!";
}
if(sendCnt == roundUFOs[round] && round < roundUFOs.Length - 1){
sendCnt = 0;
round++;
}
}
}
}
UFOFactory:涉及飛碟的生成與回收,它實現ClickAction的DealClick介面,在飛碟觸發點選事件之後,它就會獲得一定的分數。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UFOFactory : ClickAction
{
private static UFOFactory _instance;
public GameObject UFORed_Prefab;
public GameObject UFOGreen_Prefab;
public GameObject UFOBlue_Prefab;
private List<UFOData> used;
private List<UFOData> free;
public FirstController controller;
private UFOFactory(){
used=new List<UFOData>();
free=new List<UFOData>();
UFORed_Prefab=GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("UFORed"), Vector3.zero, Quaternion.identity);
UFOGreen_Prefab=GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("UFOGreen"), Vector3.zero, Quaternion.identity);
UFOBlue_Prefab=GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("UFOBlue"), Vector3.zero, Quaternion.identity);
UFORed_Prefab.SetActive(false);
UFOGreen_Prefab.SetActive(false);
UFOBlue_Prefab.SetActive(false);
controller=SSDirector.getInstance().currentSceneController as FirstController;
}
public static UFOFactory getInstance() {
if (_instance == null) {
_instance = new UFOFactory();
}
return _instance;
}
public GameObject GetUFO(int round){
GameObject ufo;
if(free.Count>0){
ufo=free[0].gameObject;
free.Remove(free[0]);
}
else{
float kind=UnityEngine.Random.Range(0f,round+1);
if(kind<0.5f){
ufo=GameObject.Instantiate<GameObject>(UFOBlue_Prefab, Vector3.zero, Quaternion.identity);
ufo.AddComponent<UFOData>();
ufo.AddComponent<BoxCollider>();
ufo.AddComponent<Click>();
ufo.GetComponent<UFOData>().score=1;
}
else if(kind<2.5f){
ufo=GameObject.Instantiate<GameObject>(UFOGreen_Prefab, Vector3.zero, Quaternion.identity);
ufo.AddComponent<UFOData>();
ufo.AddComponent<BoxCollider>();
ufo.AddComponent<Click>();
ufo.GetComponent<UFOData>().score=2;
}
else{
ufo=GameObject.Instantiate<GameObject>(UFORed_Prefab, Vector3.zero, Quaternion.identity);
ufo.AddComponent<UFOData>();
ufo.AddComponent<BoxCollider>();
ufo.AddComponent<Click>();
ufo.GetComponent<UFOData>().score=3;
}
ufo.GetComponent<Click>().setClickAction(this);
}
ufo.GetComponent<UFOData>().direction=new Vector3(UnityEngine.Random.Range(-2f,2f),1,0);
float level=UnityEngine.Random.Range(0f,round);
if(level<3){
ufo.GetComponent<UFOData>().speed=2.0f+round/6;
}
else if(level<6){
ufo.GetComponent<UFOData>().speed=4.0f+round/6;
}
else{
ufo.GetComponent<UFOData>().speed=5.0f+round/6;
}
level=UnityEngine.Random.Range(0f,round);
if(level<3){
ufo.GetComponent<UFOData>().scale=3;
ufo.GetComponent<BoxCollider>().size=new Vector3(3f,2f,3f);
}
else if(level<6){
ufo.GetComponent<UFOData>().scale=2;
ufo.GetComponent<BoxCollider>().size=new Vector3(4f,3f,4f);
}
else{
ufo.GetComponent<UFOData>().scale=1;
ufo.GetComponent<BoxCollider>().size=new Vector3(5f,4f,5f);
}
used.Add(ufo.GetComponent<UFOData>());
return ufo;
}
public void FreeUFO(GameObject ufo){
foreach(UFOData ufoData in used){
if(ufoData.gameObject.GetInstanceID()==ufo.GetInstanceID()){
ufo.SetActive(false);
free.Add(ufoData);
used.Remove(ufoData);
break;
}
}
}
public void FreeALL(){
foreach(UFOData ufoData in used){
ufoData.gameObject.SetActive(false);
free.Add(ufoData);
used.Remove(ufoData);
}
used.Clear();
}
public void DealClick(GameObject ufo){
controller.JudgeCallback(true,ufo.GetComponent<UFOData>().score+(int)ufo.GetComponent<UFOData>().speed-3+ufo.GetComponent<UFOData>().scale-1);
FreeUFO(ufo);
}
}
CCFlyAction:這個還是比較關鍵的部分,控制飛碟的飛行。(不想它白給或者拉高人的血壓就多調調)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCFlyAction : SSAction
{
float gravity;
float speed;
Vector3 direction;
float time;
public static CCFlyAction GetSSAction(Vector3 direction, float speed){
CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();
action.gravity = 9.8f;
action.time = 0;
action.speed = speed;
action.direction = direction;
return action;
}
public override void Start()
{
}
public override void Update(){
time+=Time.deltaTime;
transform.Translate(Vector3.down*gravity*time*Time.deltaTime);
transform.Translate(direction*speed*Time.deltaTime);
if (this.transform.position.y<-8){
this.destroy=true;
this.enable=false;
this.callback.SSActionEvent(this);
}
}
}
CCActionManager只是改改變數,實現好回撥函式就差不多了。
最後,改動UserGUI,加個計分板。ok!
UserGUI:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UserGUI : MonoBehaviour {
private IUserAction action;
public string gameMessage;
public int score;
void Start () {
action = SSDirector.getInstance ().currentSceneController as IUserAction;
score=0;
}
void OnGUI() {
float width = Screen.width / 8;
float height = Screen.height / 13;
//action.Check();
GUIStyle style = new GUIStyle();
style.normal.textColor = Color.red;
style.fontSize = 30;
GUIStyle style2 = new GUIStyle();
style2.normal.textColor = Color.red;
style2.fontSize = 50;
GUI.Label(new Rect(340,200,50,200),gameMessage,style2);
GUI.Label(new Rect(width*5, 0, width, height),"Your Score: ",style);
GUI.Label(new Rect(width*7, 0, width, height),score.ToString(),style);
if (GUI.Button(new Rect(0, 0, width, height), "Restart")) {
action.Restart();
}
string paused_title = SSDirector.getInstance ().Paused ? "Resume" : "Pause";
if (GUI.Button(new Rect(width, 0, width, height), paused_title)) {
SSDirector.getInstance ().Paused = !SSDirector.getInstance ().Paused;
}
}
}
效果展示視訊
發現可以通過暫停作弊,加個暫停不接受點選應該就好了
2、編寫一個簡單的自定義 Component (選做)
用了4個圓柱體,合成飛碟四不像
- 將UFOData掛上去就可以附屬性了。
- 當然通過GetComponent的方式也可以修改對相應的屬性。
相關文章
- 3D遊戲:五、與遊戲世界互動3D遊戲
- 《鬼泣5》、《只狼》:動作遊戲設計思考與分析遊戲設計
- 設計的藝術(二):遊戲與遊戲性與互動藝術遊戲
- 3D遊戲-作業三-空間與運動3D遊戲
- H5 與 APP 互動!H5APP
- 手遊UI互動動作設計研究:點選、滑動與拖拽UI
- 敘事:遊戲中角色與劇情的互動遊戲
- 開放世界遊戲的5A級未來與展望遊戲
- Java 與底層作業系統的互動細節Java作業系統
- 遊戲世界觀創作:《黑暗之魂》與古希臘悲劇遊戲
- 《淡夜未央》:互動敘事遊戲如何提升玩家參與感和互動性?遊戲
- Python 作業練習Python
- 動作與射擊漫談:格鬥遊戲中的動作設計遊戲
- 遊戲敘事與互動:情感代入、積蓄與昇華——以《Florence》為例遊戲
- “遊戲中的遊戲世界”——遊戲副本的起源與發展史遊戲
- 談遊戲世界互動設計帶來的「意外之喜」遊戲
- Phaser遊戲框架與HTML Dom元素之間的通訊互動遊戲框架HTML
- 外媒:遊戲開發者與貓咪互動對工作有益遊戲開發
- 淺談神話思維與遊戲世界觀的創作-理論篇遊戲
- 選擇,互動與制衡 關於RPG遊戲職業劃分必要性的思考遊戲
- 動作遊戲打擊感到底從何而來?(上):幀與動作屬性遊戲
- 四、遊戲物件與圖形基礎(牧師與魔鬼 動作分離版)遊戲物件
- 歸納動作遊戲中的主動行為與被動行為遊戲
- 新聞遊戲:概念、意義、功能與互動敘事規律研究遊戲
- MySQL與Python的互動學習筆記MySqlPython筆記
- MySQL資料庫5:Go與MySQL的互動MySql資料庫Go
- 遊戲與商業的奧祕:網路遊戲、付費與人性遊戲
- 遊戲文案策劃——能力構成與訓練遊戲
- js 與WKWebView 互動JSWebView
- 動作與射擊漫談:格鬥遊戲進化簡史遊戲
- 團隊作業5——測試與釋出
- 演算法分析與設計 - 作業5演算法
- swift之與h5之間的互動(一)SwiftH5
- H5與安卓/IOS進行原生互動H5安卓iOS
- 遊戲與遊戲引擎遊戲引擎
- 遊戲資料分析練習遊戲
- 多執行緒-作業練習執行緒
- 遊戲論·現實的媒介:MOBA遊戲與一個世界的症狀遊戲