簡單打飛碟小游戲
游戲規則與要求
規則
鼠標點擊飛碟,即可獲得分數,不同飛碟分數不一樣,飛碟的初始位置與飛行速度隨機,隨著分數增加,游戲難度增加。初始時每個玩家都有6條生命,漏打飛碟扣除一條生命,直到生命為0游戲結束。
要求:
使用帶緩存的工廠模式管理不同飛碟的生產與回收,該工廠必須是場景單實例的!具體實現見參考資源 Singleton 模板類
近可能使用前面 MVC 結構實現人機交互與游戲模型分離
擴展:
實現:
第一階段做的井字棋還是能了解透徹的,Homework2的MVC架構和Homework3里的動作分離管理開始吃力了,說實話,現在對動作分離管理還不怎么理解透,但還是能理解MVC了。所以這次作業我并沒有用到動作分離管理,只是用了MVC架構,也只是簡單的MVC,所以沒有SSDirector類了,當然,還有這周要求的工廠模式也是有的。
之前兩次作業看了不少博客,感覺類與類之間的交叉很多,雖然有了MVC和動作管理,但我看得結構不是很清晰(好吧,可能是我能力的問題)。這次我學會了兩個很基礎但很好用的兩個方法(原諒我到了現在才會。。。)——對象gameObject(注意g是小寫不是大寫)和GetComponent<>(),之前我一直想著用C++里面的方法實現封裝,即該方法或動作是屬于哪個類的就放在它里面,一個類不要去操作另一個類,可以通過函數調用。講一下gameObject和GetComponent吧
- GetComponent:先說這個比較好,我們創建每個游戲對象都是用GameObject的了,但不同對象有不同的方法和屬性,所以就可以自己寫腳本掛到物體上,讓它實現你想要的方法。當然,通過這個方法也可以添加其它組件比如Rigibody 。
- gameObject:這是GameObject的實例,但它是ReadOnly即只讀,它有什么用呢,當你把一個組件(這里重點指的是腳本),怎么獲得該腳本掛的物體呢,其實是有記錄的,gameObject就是腳本當前掛的物體。
下面講下本實驗的過程:
成品圖:
做的確實不好。。。
玩法:每按一次空格能出來一個飛碟,然后點擊鼠標去點它,點中了會消失,或者飛離一定距離也會消失。
代碼:
功能少所以代碼比較少。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameModel : MonoBehaviour{
static int count =
0;
public Color diskColor;
private Vector3 emitPosition;
private Vector3 emitDirection;
private float emitSpeed;
private bool is_used;
private int diskScale;
private int id;
public GameModel() { id =
0; count++; }
public int getID() {
return id; }
public void setColor(Color diskColor) {
this.GetComponent<MeshRenderer>().material.color = diskColor; }
public void setEmitPosition(Vector3 emitPosition_) { emitPosition = emitPosition_;
this.transform.position = emitPosition_; }
public void setEmitDirection(Vector3 emitDirection_) { emitDirection = emitDirection_; gameObject.GetComponent<Rigidbody>().AddForce(
3000 * emitDirection_); }
public void setState(
bool state) { is_used = state; gameObject.SetActive(is_used); }
public bool getState() {
return is_used; }
public bool is_outOfEdge() {
if(transform.position.z>
150 || transform.position.z<-
150 || transform.position.x < -
50 || transform.position.x >
50 || transform.position.y>
10 || transform.position.y < -
20) {
return true; }
else {
return false; } }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskFactory{
private static DiskFactory _instance;
private static List<GameObject> unusedDiskList =
new List<GameObject>();
private static List<GameObject> usedDiskList =
new List<GameObject>();
public GameObject diskTemplate;
public static DiskFactory
getInstance(){
if(_instance ==
null){_instance =
new DiskFactory();}
return _instance;}
private DiskFactory() { }
public GameObject
getDiskObject(){GameObject disk1;
if (unusedDiskList.Count ==
0){disk1 = GameObject.Instantiate(diskTemplate)
as GameObject;usedDiskList.Add(disk1);}
else{disk1 = unusedDiskList[
0];unusedDiskList.RemoveAt(
0);usedDiskList.Add(disk1);}disk1.GetComponent<GameModel>().setState(
true);
return disk1;}
public void removeDiskObject(GameObject obj){
if (usedDiskList.Count >
0){GameObject disk1 = obj;disk1.GetComponent<Rigidbody>().velocity = Vector3.zero;disk1.GetComponent<GameModel>().setState(
false);usedDiskList.Remove(obj); unusedDiskList.Add(disk1);}}
public int updateList(){
int count =
0;
for(
int i =
0; i < usedDiskList.Count; i++){
if(usedDiskList[i].GetComponent<GameModel>().is_outOfEdge()){removeDiskObject(usedDiskList[i]);count++;}}
return count;}
public void clear(){usedDiskList.Clear();unusedDiskList.Clear();}
}
public class DiskFactoryBC : MonoBehaviour
{
public GameObject disk;
private void Awake(){DiskFactory.getInstance().diskTemplate = disk;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScoreRecorder {
private int score;
public ScoreRecorder(){score =
0;}
public void addScore(
int add){score+=add;}
public void subScore(
int sub){score=score-sub;}
public int getScore(){
return score;}
public void resetScore(){score =
0;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum GameState { BEFORESTART,ROUND1,ROUND2,END};
public class SceneController : MonoBehaviour{
private static SceneController _instance;
private DiskFactory diskFactory= DiskFactory.getInstance();
private GameObject disk;
private GameState gamestate = GameState.BEFORESTART;
private ScoreRecorder scoreRecorder =
new ScoreRecorder();
private int cout=
0;
private float time =
0;
public static SceneController
getInstance(){
if(_instance ==
null){_instance =
new SceneController();}
return _instance;}
void Awake () {_instance =
this;_instance.gamestate = GameState.END;}
void Update () {
int count =diskFactory.updateList();scoreRecorder.subScore(count);}
public void emitDisk(){
if (gamestate == GameState.BEFORESTART){}
else if (gamestate == GameState.ROUND1){disk = diskFactory.getDiskObject();
float x = Random.Range(
0.1f,
1);
float y = Random.Range(-
1,
1)/
10;
float z = Random.Range(
0.1f,
1);disk.GetComponent<GameModel>().setColor(selectColor());disk.GetComponent<GameModel>().setEmitPosition(
new Vector3(-
8,
0,
5));disk.GetComponent<GameModel>().setEmitDirection(
new Vector3(x, y, z));}
else if(gamestate == GameState.ROUND2){disk = diskFactory.getDiskObject();
float x = Random.Range(-
0.8f,
1);
float y = Random.Range(-
1,
1) /
10;
float z = Random.Range(
0.1f,
1);disk.GetComponent<GameModel>().setColor(selectColor());disk.GetComponent<GameModel>().setEmitPosition(
new Vector3(-
8,
0,
5));disk.GetComponent<GameModel>().setEmitDirection(
new Vector3(x, y, z));}
else if (gamestate == GameState.END){diskFactory.clear();scoreRecorder.resetScore();}}
public void destroyDisk(GameObject obj){
if(gamestate == GameState.ROUND1){diskFactory.removeDiskObject(obj);scoreRecorder.addScore(
1);} }
public void setGameState(GameState state){gamestate = state;}
public GameState
getGameState(){
return gamestate;}
public int getScore(){
return scoreRecorder.getScore();}
private Color
selectColor(){
int randomNumber = Random.Range(
0,
5);Color color=Color.green;
switch (randomNumber){
case 0:color = Color.red;
break;
case 1:color = Color.blue;
break;
case 2: color = Color.green;
break;
case 3: color = Color.yellow;
break;
case 4: color = Color.grey;
break;}
return color;}
public int getRound(){
int round=
0;
switch (gamestate){
case GameState.ROUND1:round =
1;
break;
case GameState.ROUND2:round =
2;
break;}
return round;}}
using System
.Collections
using System
.Collections.Generic
using UnityEnginepublic class UI : MonoBehaviour {private SceneController sceneController = SceneController
.getInstance()// Use this for initializationvoid Start () {}private void Update(){if (Input
.GetKeyDown(
"space")){sceneController
.emitDisk()}if (Input
.GetMouseButtonDown(
0)){Ray ray = Camera
.main.ScreenPointToRay(Input
.mousePosition)RaycastHit hitif(Physics
.Raycast(ray,
out hit)){if(hit
.transform.tag ==
"Disk"){sceneController
.destroyDisk(hit
.collider.gameObject)}}}}private void OnGUI(){GUIStyle fontStyle = new GUIStyle()fontStyle
.fontSize =
25fontStyle
.normal.textColor = new Color(
0,
0,
0)if (GUI
.Button(new Rect(
0,
0,
100,
40),
"Round1")){sceneController
.setGameState(GameState
.ROUND1)}else if(GUI
.Button(new Rect(
0,
42,
100,
40),
"Round2")){sceneController
.setGameState(GameState
.ROUND2)}else if(GUI
.Button(new Rect(
0,
84,
100,
40),
"End")){sceneController
.setGameState(GameState
.END)}GUI
.Label(new Rect(Screen
.width /
3,
0,
100,
50),
"Round: " + sceneController
.getRound(), fontStyle)GUI
.Label(new Rect(Screen
.width/
3+
150 ,
0,
100,
50),
"Score: " + sceneController
.getScore(), fontStyle)if (sceneController
.getGameState() == GameState
.END){if(GUI
.Button(new Rect(Screen
.width /
3, Screen
.height /
3,
150,
80),
"GameOver!\nEnter")){sceneController
.setGameState(GameState
.BEFORESTART)}}}
}
小結:
- 我只是將自己學到的一點東西分享一下,可參考度不高,如果要參考建議還是看大神寫的博客,我還有很多很多要改要學習要改進的地方,希望自己后面能學得更好
(實訓+3d+現操+計組已經夠忙的了,每天都能看到深夜的月亮。。。)
總結
以上是生活随笔為你收集整理的Unity3D学习之路Homework4—— 飞碟射击游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。