生活随笔
收集整理的這篇文章主要介紹了
unity实现鼠标打飞碟(Hit UFO)游戏
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
unity實現鼠標打飛碟(Hit UFO)游戲
游戲規則及要求
規則:玩家初始有5條生命,每漏過一個飛碟,生命減一。游戲分數的增加與命中飛碟時的位置有關,越早擊中飛碟分數越高。游戲有四檔難度,隨分數遞增。 要求:
使用帶緩存的工廠模式管理不同飛碟的生產與回收,該工廠必須是場景單實例的!具體實現見參考資源 Singleton 模板類 近可能使用前面 MVC 結構實現人機交互與游戲模型分離
UML類圖
代碼框架
基本沿用了牧師與魔鬼的框架,主要增加了場景單實例和飛碟工廠類。
代碼分析
與牧師與魔鬼2.0版本類似,將所有動作管理類合并成一個C#文件。許多類與之前的代碼類似,主要說明不同的部分。
CCMoveToAction(管理飛碟飛行的動作)
public class CCMoveToAction : SSAction
{ public float Power
= 10 ; public float Angle
= 45 ; public float Gravity
= - 10 ; private Vector3 MoveSpeed
; private Vector3 GritySpeed
= Vector3
. zero
; private float dTime
; private Vector3 currentAngle
; public DiskFactory diskfactory
; public UserGUI User
; public static CCMoveToAction
GetSSAction ( float Power
, float Angle
, float Gravity
, Vector3 MoveSpeed
) { CCMoveToAction action
= ScriptableObject
. CreateInstance
< CCMoveToAction
> ( ) ; action
. Power
= Power
; action
. Angle
= Angle
; action
. Gravity
= Gravity
; action
. MoveSpeed
= MoveSpeed
; return action
; } public override
void Update ( ) { GritySpeed
. y
= Gravity
* ( dTime
+= Time
. fixedDeltaTime
) ; transform
. position
+= ( MoveSpeed
+ GritySpeed
) * Time
. fixedDeltaTime
; currentAngle
. z
= Mathf
. Atan ( ( MoveSpeed
. y
+ GritySpeed
. y
) / MoveSpeed
. x
) * Mathf
. Rad2Deg
; transform
. eulerAngles
= currentAngle
; if ( this . transform
. position
. y
< - 7 || this . transform
. position
. x
> 10 ) { if ( this . transform
. position
. x
> 0 && User
. HP > 0 ) User
. HP -- ; diskfactory
. FreeDisk ( this . gameobject
) ; this . destroy
= true ; this . callback
. SSActionEvent ( this ) ; } } public override
void Start ( ) { MoveSpeed
= Quaternion
. Euler ( new Vector3 ( 0 , 0 , Angle
) ) * Vector3
. right
* Power
; currentAngle
= Vector3
. zero
; diskfactory
= Singleton
< DiskFactory
> . Instance
; User
= Singleton
< UserGUI
> . Instance
; }
}
按照飛碟的初始速度、所受到的重力、初始角度,控制飛碟飛行動作。當飛碟飛出屏幕時,表示飛碟飛行動作已做完,回收飛碟。
MySceneActionManager(飛碟的動作管理類,通過調用該類中的方法使得飛碟飛行)
public class MySceneActionManager : SSActionManager
{ private CCMoveToAction diskfly
; public Controll sceneController
; protected new void Start ( ) { sceneController
= ( Controll
) SSDirector
. GetInstance ( ) . CurrentScenceController
; sceneController
. actionManager
= this ; } public void fly_disk ( Disk disk
) { diskfly
= CCMoveToAction
. GetSSAction ( disk
. Power
, disk
. Angle
, disk
. Gravity
, disk
. MoveSpeed
) ; this . RunAction ( disk
. getGameObject ( ) , diskfly
, this ) ; }
}
Singleton(場景單實例,可以為每個 MonoBehaviour子類創建一個對象的實例)
public class Singleton < T > : MonoBehaviour where
T : MonoBehaviour
{ protected static T instance
; public static T Instance
{ get { if ( instance
== null ) { instance
= ( T ) FindObjectOfType ( typeof ( T ) ) ; if ( instance
== null ) { Debug
. LogError ( "An instance of " + typeof ( T ) + " is needed in the scene, but there is none." ) ; } } return instance
; } }
}
場景單實例的使用很簡單,僅需要將 MonoBehaviour 子類對象掛載任何一個游戲對象上即可。然后在任意位置使用代碼 Singleton< YourMonoType >.Instance 獲得該對象。
DiskFactory 飛碟工廠類,控制飛碟的產生和回收,當場景控制器需要飛碟時, 飛碟工廠從空閑飛碟列表中尋找飛碟傳遞給場景控制器,若空閑列表中無飛碟,則飛碟工廠需要產生一個新的飛碟。當飛碟飛出屏幕或被打擊后,會調用飛碟工廠回收飛碟的方法。通過工廠類,可以管理不同飛碟的發送和回收
using System
. Collections
;
using System
. Collections
. Generic
;
using UnityEngine
; public class DiskFactory : MonoBehaviour
{ public List
< Disk
> used
= new List < Disk
> ( ) ; public List
< Disk
> free
= new List < Disk
> ( ) ; public Disk
GetDisk ( ) { Disk disk_prefab
= null ; int rand
= Random
. Range ( 0 , 99 ) ; if ( free
. Count
> 10 ) { disk_prefab
= free
[ 0 ] ; disk_prefab
. getGameObject ( ) . SetActive ( true ) ; free
. Remove ( free
[ 0 ] ) ; } else { if ( rand
% 4 == 0 ) { disk_prefab
= new Disk ( "disk1" ) ; } else if ( rand
% 4 == 1 ) { disk_prefab
= new Disk ( "disk2" ) ; } else if ( rand
% 4 == 2 ) { disk_prefab
= new Disk ( "disk3" ) ; } else { disk_prefab
= new Disk ( "disk4" ) ; } } used
. Add ( disk_prefab
) ; return disk_prefab
; } public void ResetDisk ( Disk disk
) { disk
. Power
= 0 ; disk
. Angle
= 0 ; disk
. Gravity
= 0 ; } public void FreeDisk ( GameObject disk
) { for ( int i
= 0 ; i
< used
. Count
; i
++ ) { if ( disk
. GetInstanceID ( ) == used
[ i
] . getGameObject ( ) . GetInstanceID ( ) ) { ResetDisk ( used
[ i
] ) ; used
[ i
] . getGameObject ( ) . SetActive ( false ) ; free
. Add ( used
[ i
] ) ; used
. Remove ( used
[ i
] ) ; break ; } } }
}
Disk(飛碟類) 定義了飛碟所擁有的各項屬性,包括受到的力度、飛行角度、所受重力和移動速度。
public class Disk { public GameObject disk
; public float Power
= 3 ; public float Angle
= 15 ; public float Gravity
= - 0.5 f
; public Vector3 MoveSpeed
; public Disk ( string name
) { if ( name
== "disk1" ) { disk
= Object
. Instantiate ( Resources
. Load ( "disk1" , typeof ( GameObject
) ) , new Vector3 ( - 10 , 0 , 0 ) , Quaternion
. Euler ( 0 , - 90 , 0 ) ) as GameObject
; } else if ( name
== "disk2" ) { disk
= Object
. Instantiate ( Resources
. Load ( "disk2" , typeof ( GameObject
) ) , new Vector3 ( - 10 , 0 , 0 ) , Quaternion
. Euler ( 0 , - 90 , 0 ) ) as GameObject
; } else if ( name
== "disk3" ) { disk
= Object
. Instantiate ( Resources
. Load ( "disk3" , typeof ( GameObject
) ) , new Vector3 ( - 10 , 0 , 0 ) , Quaternion
. Euler ( 0 , - 90 , 0 ) ) as GameObject
; } else if ( name
== "disk4" ) { disk
= Object
. Instantiate ( Resources
. Load ( "disk4" , typeof ( GameObject
) ) , new Vector3 ( - 10 , 0 , 0 ) , Quaternion
. Euler ( 0 , - 90 , 0 ) ) as GameObject
; } } public GameObject
getGameObject ( ) { return disk
; } }
Controll 場景控制器 場景控制器通過設置游戲狀態和游戲所進行的輪數從而控制飛碟的發送頻率、一次發送所發送飛碟的個數和飛碟的屬性。游戲每達到10分難度就會提升一檔,總共有四檔難度,飛碟的發送頻率、速度、角度的變化幅度、發送位置的變化幅度都會隨著難度的提升而提升。當游戲進入第四檔時,則會一次發送兩個飛碟。 通過射線來判斷飛碟是否被擊中,若擊中飛碟,則得分增加,否則若飛碟飛出屏幕,則生命會減少。
using System
. Collections
;
using System
. Collections
. Generic
;
using UnityEngine
;
public class Controll : MonoBehaviour
, ISceneController
, IUserAction
{ private int gamestate
= 0 ; private int round
= 1 ; private int score
= 0 ; private float time
= 2 f
; private float i
= 0 ; public UserGUI User
; public MySceneActionManager actionManager
; public DiskFactory diskfactory
; void Start ( ) { SSDirector director
= SSDirector
. GetInstance ( ) ; director
. CurrentScenceController
= this ; User
= gameObject
. AddComponent
< UserGUI
> ( ) as UserGUI
; diskfactory
= Singleton
< DiskFactory
> . Instance
; actionManager
= gameObject
. AddComponent
< MySceneActionManager
> ( ) as MySceneActionManager
; } void Update ( ) { if ( gamestate
== 2 ) { gamestate
= 1 ; } if ( gamestate
== 1 ) { if ( i
>= time
) { if ( score
> 10 && round
== 1 ) { time
-= 0.3 f
; round
= 2 ; } else if ( score
> 20 && round
== 2 ) { time
-= 0.5 f
; round
= 3 ; } else if ( score
> 30 && round
== 3 ) { time
+= 0.3 f
; round
= 4 ; } SendDisk ( ) ; i
= 0 ; } i
+= Time
. deltaTime
; } } public void LoadResources ( ) { } public void SendDisk ( ) { Disk disk
= diskfactory
. GetDisk ( ) ; if ( round
== 1 ) { disk
. Power
= Random
. Range ( 2.5 f
, 3.5 f
) ; disk
. Angle
= Random
. Range ( 10 f
, 30 f
) ; disk
. Gravity
= Random
. Range ( - 0.5 f
, - 0.8 f
) ; disk
. disk
. transform
. position
= new Vector3 ( - 10 , Random
. Range ( - 3 f
, 2 f
) , 0 ) ; } else if ( round
== 2 ) { disk
. Power
= Random
. Range ( 3.5 f
, 5 f
) ; disk
. Angle
= Random
. Range ( 5 f
, 35 f
) ; disk
. Gravity
= Random
. Range ( - 0.6 f
, - 1 f
) ; disk
. disk
. transform
. position
= new Vector3 ( - 10 , Random
. Range ( - 4 f
, 1 f
) , 0 ) ; } else if ( round
== 3 ) { disk
. Power
= Random
. Range ( 5.5 f
, 8 f
) ; disk
. Angle
= Random
. Range ( 5 f
, 35 f
) ; disk
. Gravity
= Random
. Range ( - 1 f
, - 1.5 f
) ; disk
. disk
. transform
. position
= new Vector3 ( - 10 , Random
. Range ( - 5 f
, 3 f
) , 0 ) ; } else if ( round
== 4 ) { disk
. Power
= Random
. Range ( 7 f
, 10 f
) ; disk
. Angle
= Random
. Range ( 5 f
, 35 f
) ; disk
. Gravity
= Random
. Range ( - 2 f
, - 2.5 f
) ; disk
. disk
. transform
. position
= new Vector3 ( - 10 , Random
. Range ( - 5 f
, 2 f
) , 0 ) ; Disk disk2
= diskfactory
. GetDisk ( ) ; disk2
. Power
= Random
. Range ( 6 f
, 8 f
) ; disk2
. Angle
= Random
. Range ( 5 f
, 35 f
) ; disk2
. Gravity
= Random
. Range ( - 1 f
, - 3 f
) ; disk2
. disk
. transform
. position
= new Vector3 ( - 10 , Random
. Range ( - 4.5 f
, 1 f
) , 0 ) ; actionManager
. fly_disk ( disk2
) ; } actionManager
. fly_disk ( disk
) ; } public void Restart ( ) { score
= 0 ; gamestate
= 2 ; } public void Stopgame ( ) { gamestate
= 0 ; round
= 1 ; time
= 2 f
; } public void Startgame ( ) { gamestate
= 2 ; } public bool
Hit ( ) { Ray ray
= Camera
. main
. ScreenPointToRay ( Input
. mousePosition
) ; RaycastHit hit
; if ( Physics
. Raycast ( ray
, out hit
) ) { if ( hit
. collider
. gameObject
. transform
. position
. x
< 3 && gamestate
> 0 ) score
+= 2 ; else if ( hit
. collider
. gameObject
. transform
. position
. x
>= 3 && gamestate
> 0 ) score
+= 1 ; hit
. collider
. gameObject
. transform
. position
= new Vector3 ( - 10 , - 11 , 0 ) ; diskfactory
. FreeDisk ( hit
. collider
. gameObject
) ; return true ; } return false ; } public int
Getscore ( ) { return score
; }
}
using System
. Collections
;
using System
. Collections
. Generic
;
using UnityEngine
; public class UserGUI : MonoBehaviour
{ private IUserAction action
; private bool gamestart
= false ; public int
HP = 5 ; void Start ( ) { action
= SSDirector
. GetInstance ( ) . CurrentScenceController
as IUserAction
; } void OnGUI ( ) { GUIStyle fontStyle2
= new GUIStyle ( ) ; fontStyle2
. fontSize
= 20 ; fontStyle2
. normal
. textColor
= new Color ( 1 , 1 , 1 ) ; GUIStyle fontStyle1
= new GUIStyle ( ) ; fontStyle1
. fontSize
= 20 ; if ( GUI . Button ( new Rect ( Screen
. width
- 100 , Screen
. height
- 100 , 65 , 65 ) , "Exit" ) ) { Application
. Quit ( ) ; } if ( gamestart
== false ) { GUI . Label ( new Rect ( Screen
. width
/ 2 - 300 , 100 , 420 , 50 ) , "游戲目標:盡可能的射擊多的飛碟" , fontStyle2
) ; GUI . Label ( new Rect ( Screen
. width
/ 2 - 300 , 150 , 420 , 50 ) , "游戲難度會逐漸提升,祝君好運!" , fontStyle2
) ; if ( GUI . Button ( new Rect ( Screen
. width
/ 2 - 40 , Screen
. height
- 200 , 70 , 40 ) , "start" ) ) { action
. Startgame ( ) ; gamestart
= true ; } } else { GUI . Label ( new Rect ( Screen
. width
/ 2 - 300 , 10 , 420 , 50 ) , "分數:" , fontStyle1
) ; GUI . Label ( new Rect ( Screen
. width
/ 2 - 250 , 10 , 420 , 50 ) , action
. Getscore ( ) . ToString ( ) , fontStyle1
) ; GUI . Label ( new Rect ( Screen
. width
/ 2 - 300 , 40 , 420 , 50 ) , "剩余血量:" , fontStyle1
) ; GUI . Label ( new Rect ( Screen
. width
/ 2 - 210 , 40 , 420 , 50 ) , HP . ToString ( ) , fontStyle1
) ; } if ( Input
. GetButtonDown ( "Fire1" ) ) { action
. Hit ( ) ; } if ( HP <= 0 ) { GUI . Label ( new Rect ( Screen
. width
/ 2 - 50 , 150 , 60 , 40 ) , "Game Over!" , fontStyle1
) ; action
. Stopgame ( ) ; if ( GUI . Button ( new Rect ( Screen
. width
/ 2 - 40 , Screen
. height
- 200 , 70 , 40 ) , "Restart" ) ) { action
. Restart ( ) ; HP = 5 ; } } }
}
游戲截圖
視頻鏈接 項目代碼
總結
以上是生活随笔 為你收集整理的unity实现鼠标打飞碟(Hit UFO)游戏 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。