3Dgame作業6:打飛碟修改版
簡單的打飛碟遊戲
設計結構
本次採用了MVC結構,在Driect.cs檔案中定義了Direct,UserAction,ISceneController三個類,對於
MVC結構的作用是重要的:
程式碼如下;
Direct.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Direct : System.Object
{
private static Direct instance;
public ISceneController currentScene{get;set;}
public static Direct getInstance(){
if (instance==null)
instance=new Direct();
return instance;
}
}
public interface ISceneController{
}
public interface UserAction{
void getScore(int n);
void getLost(int n);
}
public interface PAction{
void addGravity();
}
Direct類用於管理當前的場記類,做一些傳參(用instance指明瞭現在的場記),還有管理一些重要功能等。
ISceneController提供了每個場記必須要有的函式,這裡是空的,ISceneController主要起一個標記作用,這樣在其他物體的類裡面,就可以通過Direct找到當前的Controller了。
UserAction規定了使用者可能會發生的事情,在複雜的情況,可以一個場記,一個Action介面。這裡的GetScore是玩家獲得得分的事件,Getlost是玩家丟掉分數的事件(沒打到飛碟)。
新加內容
PAction介面是新加的,用於物理引擎的操作。在飛碟的管理類中實現addGravity函式給飛碟施加恆定的重力。
FirstController.cs
場記用於處理在該場景下的一切事務,包括資源的載入,物體的排程,事件的處理等。其他的許多物體類,也都收到FirstController類的管理。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstController : MonoBehaviour,ISceneController,UserAction
{
// Start is called before the first frame update
public GameObject[] terrain;
public UFOController uc;
public int score;
public int lost;
public yesyes[] yes;
public GUIStyle style;
public int round;
void Start()
{
Direct.getInstance().currentScene=this;
loadResources();
Random.InitState((int)System.DateTime.Now.Ticks);
uc.StartRound();
score=0; lost=0;
round=1;
}
// Update is called once per frame
void Update()
{
if (round>=4) return;
uc.UFOUpdate();
if (uc.isOver()==1){
round++;
if (round>=4)
return;
uc.setDifficulty(round);
uc.StartRound();
}
}
void FixedUpdate(){
uc.UFOFixedUpdate();
}
void OnGUI(){
if (round>=4){
style.alignment=TextAnchor.MiddleCenter;
style.normal.textColor=Color.black;
style.fontSize=250;
if (score>lost){
GUI.Label(new Rect(0,0,Screen.width,Screen.height),"你贏了",style);
}else{
GUI.Label(new Rect(0,0,Screen.width,Screen.height),"你輸了",style);
}
}
style.alignment=TextAnchor.MiddleLeft;
style.normal.textColor=Color.black;
style.fontSize=40;
GUI.Label(new Rect(0,Screen.height-100,Screen.width,100),"白 1 分 藍 2 分 紅 3 分"+" Score : "+score.ToString()+" Lost : "+lost.ToString()+" Round "+round.ToString(),style);
for(int i=1;i<=33;++i){
if (yes[i].isOn==1){
if (Time.time-yes[i].stime>=3){
yes[i].isOn=0;
continue;
}
else{
if (yes[i].color=="white") style.normal.textColor=Color.gray;
if (yes[i].color=="blue") style.normal.textColor=Color.blue;
if (yes[i].color=="red") style.normal.textColor=Color.red;
GUI.Label(new Rect(yes[i].x,yes[i].y,400,200),"YesYes",style);
}
}
}
}
public void loadResources(){
terrain=new GameObject[4];
terrain[0]=Instantiate(Resources.Load<GameObject>("Terrain"),new Vector3(0,0,0),Quaternion.identity);
terrain[1]=Instantiate(terrain[0],new Vector3(-1000,0,0),Quaternion.identity);
terrain[2]=Instantiate(terrain[0],new Vector3(-1000,0,-1000),Quaternion.identity);
terrain[3]=Instantiate(terrain[0],new Vector3(0,0,-1000),Quaternion.identity);
uc=new UFOController();
yes=new yesyes[34];
for (int i=0;i<=33;++i){
yes[i]=new yesyes();
}
}
public void getScore(int n){
score+=n;
for (int i=1;i<=33;++i){
if (yes[i].isOn==0){
yes[i].isOn=1;
yes[i].x=Input.mousePosition.x;
yes[i].y=Screen.height-Input.mousePosition.y;
yes[i].stime=Time.time;
if (n==1) yes[i].color="white";
if (n==2) yes[i].color="blue";
if (n==3) yes[i].color="red";
break;
}
}
}
public void getLost(int n){
lost+=n;
}
}
public class yesyes{
public int isOn;
public float x,y;
public float stime;
public string color;
public yesyes(){
isOn=0;
x=-200;y=-200;
stime=-100;
color="white";
}
public void over(){
isOn=0;
}
}
在FirstController裡面首先在Start中確立了自己和Direct類的關係。然後載入自己的資源。
在Update函式中呼叫UFOController類裡的函式UFOUpdate,這個是下一個檔案中的類。用於管理所有的UFO,減輕場記的程式碼負擔和混亂度。在Update中還判斷了遊戲結束的條件。因為遊戲分為3個round(關卡),隨著round的提高,遊戲的難度會變高。在Update函式中要處理這些變化。
FirstController還實現了介面UserAction的函式定義,獲取或者失去得分。
新加內容
FixedUpdate函式是新加的,用於物理引擎。FixUpdate函式會在每次運算物理引擎之前先進行運算。也就是在這個函式中,施加力或者改變速度等。可以和物理運算保持同步。
UFOController.cs
負責管理UFO的生成,移動,銷燬,等所有事物。在此檔案中還定義了有關UFO的其他類,記錄UFO的資訊或者管理UFO的點選事件。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UFOController :MonoBehaviour,PAction
{
public GameObject white,blue,red;
public UFO[] ufos;
public int diff;
public float stime;
private float lastCreateTime;
public void UFOUpdate(){
int number=getNumber();
if (Time.time-stime>=9.5f){
}else{
if (Time.time-lastCreateTime>=1){
lastCreateTime=Time.time;
for (int i=1;i<=diff;++i){
CreateUFO();
}
}
}
for(int i=1;i<=33;++i){
if (ufos[i].obj!=null){
//ufos[i].obj.transform.position=Vector3.MoveTowards(ufos[i].obj.transform.position,ufos[i].target,ufos[i].speed);
if (ufos[i].obj.transform.position==ufos[i].target || ufos[i].obj.transform.position.y<=4.5){
ufos[i].obj.GetComponent<UFOClass>().getOut();
number--;
}
}
}
}
public void UFOFixedUpdate(){
addGravity();
}
public void addGravity(){
for(int i=1;i<=33;++i){
if (ufos[i].obj!=null){
ufos[i].obj.GetComponent<Rigidbody>().AddForce(new Vector3(0,-10,0));
}
}
}
public void StartRound(){
stime=Time.time;
}
public int isOver(){
if (getNumber()==0 && Time.time-stime>=10){
return 1;
}
return 0;
}
public UFOController(){
white=Resources.Load<GameObject>("whiteUFO");
blue=Resources.Load<GameObject>("blueUFO");
red=Resources.Load<GameObject>("redUFO");
Rigidbody rb=new Rigidbody();
white.AddComponent<Rigidbody>();
white.GetComponent<Rigidbody>().detectCollisions=false;
white.GetComponent<Rigidbody>().useGravity=false;
white.GetComponent<Rigidbody>().mass=1;
white.GetComponent<Rigidbody>().drag=0;
white.GetComponent<Rigidbody>().angularDrag=10;
blue.AddComponent<Rigidbody>();
blue.GetComponent<Rigidbody>().detectCollisions=false;
blue.GetComponent<Rigidbody>().useGravity=false;
blue.GetComponent<Rigidbody>().mass=1;
blue.GetComponent<Rigidbody>().drag=0;
blue.GetComponent<Rigidbody>().angularDrag=10;
red.AddComponent<Rigidbody>();
red.GetComponent<Rigidbody>().detectCollisions=false;
red.GetComponent<Rigidbody>().useGravity=false;
red.GetComponent<Rigidbody>().mass=1;
red.GetComponent<Rigidbody>().drag=0;
red.GetComponent<Rigidbody>().angularDrag=10;
ufos=new UFO[34];
for (int i=0;i<34;++i){
ufos[i]=new UFO();
}
diff=1;
stime=-100;
lastCreateTime=-100;
}
public void setDifficulty(int d){
diff=d;
}
public int getNumber(){
int ans=0;
for (int i=1;i<=33;++i){
if (ufos[i].obj!=null)
ans++;
}
return ans;
}
public void CreateUFO(){
UFO u=new UFO();
for (int i=1;i<=33;++i){
if (ufos[i].obj==null){
u=ufos[i];
break;
}
}
u.init(diff);
int kind;
kind=Random.Range(0,100);
if (kind<=33){
u.obj=Instantiate(white,u.pos,Quaternion.identity);
u.obj.name="white";
}
else if (kind<=66){
u.obj=Instantiate(blue,u.pos,Quaternion.identity);
u.obj.name="blue";
}
else{
u.obj=Instantiate(red,u.pos,Quaternion.identity);
u.obj.name="red";
}
u.initVelocity(diff);
u.obj.AddComponent(typeof(UFOClass));
}
}
public class UFO {
public float speed;
public Vector3 target;
public GameObject obj;
public Vector3 pos;
public UFO(){
}
public void init(int diff){
Object.Destroy(obj);
float y=Random.Range(60,120f);
float x=150;
if (Random.Range(0,2)==0){
x=-x;
}
pos=new Vector3(x,y,80);
x=-x;
y=Random.Range(60f,120f);
target=new Vector3(x,y,80);
speed=Random.Range(0.04f,0.06f);
speed=speed*diff;
}
public void initVelocity(int diff){
Vector3 dir=target-pos;
dir=dir/dir.magnitude;
obj.GetComponent<Rigidbody>().velocity=dir*diff*50;
}
}
public class UFOClass:MonoBehaviour{
private UserAction action;
public UFOClass(){
action=Direct.getInstance().currentScene as UserAction;
}
void OnMouseDown(){
string s=gameObject.name;
if (s=="white"){
action.getScore(1);
}
if (s=="blue"){
action.getScore(2);
}
if (s=="red"){
action.getScore(3);
}
Destroy(gameObject);
}
public void getOut(){
string s=gameObject.name;
if (s=="white"){
action.getLost(1);
}
if (s=="blue"){
action.getLost(2);
}
if (s=="red"){
action.getLost(3);
}
Destroy(gameObject);
}
}
按照我設計的演算法,遊戲中最多可能出現33個UFO,所以用一個33的陣列就能存放下全部的內容。(不想用連結串列)
public UFO[] ufos;
CreateUFO用於建立UFO,根據難度值,對UFO的速度進行調整。
StartRound用於重新開始一個回合
SetDifficulty用於設定難度,一般用在每個回合開始前。
getNumber統計當前UFO的個數。
isOver判斷當前回合有沒有結束。如果飛碟數為0,並且已經開始了一段時間(防止剛開始就結束),那麼此回合就結束了。將有FirstController開啟下一回合。
UFOUpdate在FirstController中的Update中被呼叫,兩者的呼叫是同步進行的。UFOUpdate主要用於管理飛碟的移動,判斷建立新飛碟的條件,並且判斷飛碟出界或者到達目的地的條件,是這個類的核心。
下面的UFO和UFOClass兩個類:
UFO類是為了記錄每一個飛碟的資訊,比如初始位置,速度,目的地等,還有一個obj作為指標指向飛碟的GameObject。內部inti函式會根據當前的難度進行重新構造,完成了資源的重新利用。
UFOClass主要用於AddComponent函式,給飛碟的GameObject加入元件。該元件用於處理點選事件。裡面的action變數是利用MVC結構的特性,從而完成了對場記中玩家事件函式的呼叫。
程式碼部分至此介紹完畢。
新加物理引擎部分
UFOFixedUpdate函式。在每次FirstController執行FixedUpdate時,一起執行這裡的UFOFixedUpdate函式。在這裡主要進行給飛碟加重力的操作:
public void UFOFixedUpdate(){
addGravity();
}
public void addGravity(){
for(int i=1;i<=33;++i){
if (ufos[i].obj!=null){
ufos[i].obj.GetComponent<Rigidbody>().AddForce(new Vector3(0,-10,0));
}
}
}
另外,新加部分還有為每個飛碟新增剛體屬性,並調配引數。
在建構函式裡面。
white.AddComponent<Rigidbody>();
white.GetComponent<Rigidbody>().detectCollisions=false;
white.GetComponent<Rigidbody>().useGravity=false;
white.GetComponent<Rigidbody>().mass=1;
white.GetComponent<Rigidbody>().drag=0;
white.GetComponent<Rigidbody>().angularDrag=10;
blue.AddComponent<Rigidbody>();
blue.GetComponent<Rigidbody>().detectCollisions=false;
blue.GetComponent<Rigidbody>().useGravity=false;
blue.GetComponent<Rigidbody>().mass=1;
blue.GetComponent<Rigidbody>().drag=0;
blue.GetComponent<Rigidbody>().angularDrag=10;
red.AddComponent<Rigidbody>();
red.GetComponent<Rigidbody>().detectCollisions=false;
red.GetComponent<Rigidbody>().useGravity=false;
red.GetComponent<Rigidbody>().mass=1;
red.GetComponent<Rigidbody>().drag=0;
red.GetComponent<Rigidbody>().angularDrag=10;
成果
附加功能
說說下面這個yesyes類
位置: FirstController.cs裡面。額外定義的一個類。
作用:在滑鼠點選飛碟後,我希望螢幕上能顯示出一個與飛碟同顏色的“yesyes”字樣來提醒打到了。
引數:記錄了每一個yesyes字樣的應有顏色,位置,以及是否應該被顯示,開始顯示的時間是什麼。顯示時間超過三秒,就不再顯示了。這些都在OnGui函式中進行了判斷。
效果:
打掉的飛碟都變成了yesyes
斯卡文腐蝕+1
專案連結
專案使用方法
下載Asserts.zip解壓,用我的Asserts覆蓋你專案的Asserts。重新整理你的專案,雙擊UFOScene,點選執行。
相關文章
- 改進飛碟(Hit UFO)遊戲遊戲
- 團隊作業6
- 結對作業6
- 9月6日作業
- 神舟飛船用什麼作業系統?作業系統
- PTA4-6次作業
- OOP4-6次作業OOP
- Ventoy工具製作啟動隨身碟
- 隨身碟如何製作win10安裝盤|win10安裝隨身碟製作方法Win10
- 怎麼用軟碟通製作win10 u盤啟動盤_軟碟通製作win10啟動隨身碟的步驟Win10
- 電腦也能“打碟”,手把手教你成為DJ
- Java畢設期末作業原始碼6Java原始碼
- 機器學習第6次作業機器學習
- games101 作業6 詳解SAHGAM
- PTA4~6次作業總結
- 飛機上一般是什麼作業系統?作業系統
- 讓協作“飛”起來
- 演算法分析與設計 - 作業6演算法
- 團隊作業6——展示部落格(Alpha版本)
- 第4-6次OOP作業總結OOP
- OOP第4-6次作業總結OOP
- python 打飛機專案 ( 基類封裝 )Python封裝
- “打飛機”怎麼就成了流量遊戲?遊戲
- 對話李飛飛:下一代企業級資料庫6大技術方向資料庫
- 怎樣製作win10的iOS映象安裝隨身碟_製作win10 iso映象安裝隨身碟教程Win10iOS
- RHEL 6以上作業系統Yum提示This system is not registered作業系統
- 題目集6-8次作業總結
- 團隊作業6——事後諸葛亮分析
- 團隊作業6——複審與事後分析
- 形似“飛碟”的無人機你見過嗎?它還可以滅火!無人機
- 用threejs開發一個簡易的打飛機和飛機破碎效果JS
- java飛機大戰小遊戲作業二次開發Java遊戲
- 解決一億小學生作業難題《作業瘋了》6月14日上架
- 製作macOS 11 Big Sur 啟動隨身碟系統Mac
- 6月28日104班7組作業雨情況
- 結組作業,第二次衝刺(6)
- 總結與思考 :OOP課程PTA作業4 - 6OOP
- 團隊作業6-複審與事後分析