UML图
具体实现
Disk属性
public class Disk : MonoBehaviour {
public int type;
public int score;
public Color color;
}
DiskFactory
public class DiskFactory : MonoBehaviour {
private List<Disk> useddisklist = new List<Disk>();
private List<Disk> freedisklist = new List<Disk>();
public GameObject GetDisk(int type) {
GameObject disk_prefab = null;
if (freedisklist.Count>0) {
for(int i = 0; i < freedisklist.Count; i++) {
if (freedisklist[i].type == type) {
disk_prefab = freedisklist[i].gameObject;
freedisklist.Remove(freedisklist[i]);
break;
}
}
}
if(disk_prefab == null) {
if(type == 1) {
disk_prefab = Instantiate(
Resources.Load<GameObject>("Prefabs/disk1"),
new Vector3(0, -10f, 0), Quaternion.Euler(-90, 0f, 0f));
}
else if (type == 2) {
disk_prefab = Instantiate(
Resources.Load<GameObject>("Prefabs/disk2"),
new Vector3(0, -10f, 0), Quaternion.Euler(-90, 0f, 0f));
}
else {
disk_prefab = Instantiate(
Resources.Load<GameObject>("Prefabs/disk3"),
new Vector3(0, -10f, 0), Quaternion.Euler(-90, 0f, 0f));
}
disk_prefab.GetComponent<Renderer>().material.color = disk_prefab.GetComponent<Disk>().color;
}
useddisklist.Add(disk_prefab.GetComponent<Disk>());
disk_prefab.SetActive(true);
return disk_prefab;
}
public void FreeDisk() {
for(int i=0; i<useddisklist.Count; i++) {
if (useddisklist[i].gameObject.transform.position.y <= -10f) {
freedisklist.Add(useddisklist[i]);
useddisklist.Remove(useddisklist[i]);
}
}
}
public void Reset() {
FreeDisk();
}
}
Interface
public interface ISceneController {
void LoadResources();
}
public interface IUserAction {
void Hit(Vector3 pos);
float GetScore();
int GetRound();
int GetTrial();
void GameOver();
void ReStart();
bool Getflag();
float GetTarget();
bool GetStatus();
}
public enum SSActionEventType : int {
Started, Competeted }
public interface ISSActionCallback {
void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null);
}
Action
DiskFlyACtion
public class DiskFlyAction : SSAction {
public float gravity = -1;//重力
private Vector3 start_vector;//初速度
private Vector3 gravity_vector = Vector3.zero;//y方向速度
private float time;
private DiskFlyAction() {
}
public static DiskFlyAction GetSSAction(int lor, float angle, float power) {
//初速度
DiskFlyAction action = CreateInstance<DiskFlyAction>();
if (lor == -1) {
action.start_vector = Quaternion.Euler(new Vector3(0, 0, -angle)) * Vector3.left * power;
}
else {
action.start_vector = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right * power;
}
return action;
}
public override void Update() {
time += Time.fixedDeltaTime;
gravity_vector.y = gravity * time * 0.1f;
transform.position += (start_vector + gravity_vector) * Time.fixedDeltaTime;
if (this.transform.position.y < -10) {
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
public override void Start() {
}
}
FlyActionManager
public class FlyActionManager : SSActionManager {
public DiskFlyAction fly;
public FirstController myscenecontroller;
protected void Start() {
myscenecontroller = (FirstController)SSDirector.GetInstance().CurrentScenceController;
myscenecontroller.actionmanager = this;
}
public void DiskFly(GameObject disk, float angle, float power) {
int lor = 1;
if (disk.transform.position.x > 0) lor = -1;
fly = DiskFlyAction.GetSSAction(lor, angle, power);
this.RunAction(disk, fly, this);
}
}
ScoreRecorder
public class ScoreRecorder : MonoBehaviour {
private float score;
void Start () {
score = 0;
}
public void Record(GameObject disk) {
score += disk.GetComponent<Disk>().score;
}
public float GetScore() {
return score;
}
public void Reset() {
score = 0;
}
}
Singleton
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;
}
}
}
UserGUI
public class UserGUI : MonoBehaviour {
private IUserAction action;
GUIStyle button_style = new GUIStyle();
GUIStyle start_style = new GUIStyle();
GUIStyle text_style = new GUIStyle();
GUIStyle text_style2 = new GUIStyle();
GUIStyle over_style = new GUIStyle();
GUIStyle round_style = new GUIStyle();
GUIStyle target_style = new GUIStyle();
GUIStyle red_style = new GUIStyle();
GUIStyle yellow_style = new GUIStyle();
GUIStyle green_style = new GUIStyle();
private bool game_start = false;
void Start () {
action = SSDirector.GetInstance().CurrentScenceController as IUserAction;
}
void OnGUI () {
start_style.fontSize = 35;
button_style.fontSize = 20;
text_style.fontSize = 18;
text_style2.fontSize = 16;
red_style.normal.textColor = Color.red;
red_style.fontSize = 18;
yellow_style.normal.textColor = Color.yellow;
yellow_style.fontSize = 18;
green_style.normal.textColor = Color.green;
green_style.fontSize = 18;
over_style.fontSize = 50;
round_style.fontSize = 50;
target_style.fontSize = 20;
if (game_start)
{
GUI.Label(new Rect(5, 5, 200, 50), "red disk=1", red_style);
GUI.Label(new Rect(105, 5, 50, 50), "yellow disk=2", yellow_style);
GUI.Label(new Rect(225, 5, 50, 50), "green disk=3", green_style);
GUI.Label(new Rect(Screen.width-300, 5, 50, 50), "Score:"+ action.GetScore().ToString(), text_style);
GUI.Label(new Rect(Screen.width-200, 5, 50, 50), "Round:" + action.GetRound().ToString(), text_style);
GUI.Label(new Rect(Screen.width-100, 5, 50, 50), "Num:" + action.GetTrial().ToString(), text_style);
if(action.Getflag())
{
GUI.Label(new Rect(Screen.width / 2 - 90, Screen.height / 2 - 60 , 100, 100), "Round"+(action.GetRound()+1).ToString(), round_style);
GUI.Label(new Rect(Screen.width / 2 - 80, Screen.height / 2 +20 , 100, 100), "Target Score:"+(action.GetTarget()).ToString(), target_style);
}
if (action.GetStatus()==false) {
GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 80, 100, 100), "You Lose!", over_style);
GUI.Label(new Rect(Screen.width / 2 - 45, Screen.height / 2, 50, 50), "Your Score:" + action.GetScore().ToString(), text_style2);
if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.height / 2+40, 100, 50), "Restart")) {
action.ReStart();
return;
}
action.GameOver();
}
else if(action.GetStatus()==true&&action.Getflag())
{
GUI.Label(new Rect(Screen.width / 2 - 90, Screen.height / 2 - 60 , 100, 100), "Round"+(action.GetRound()+1).ToString(), round_style);
GUI.Label(new Rect(Screen.width / 2 - 80, Screen.height / 2 +20 , 100, 100), "Target Score:"+(action.GetTarget()).ToString(), target_style);
}
if (action.GetRound() == 3 && action.GetTrial() == 11&&action.GetStatus()) {
GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 80, 100, 100), "You Win!", over_style);
GUI.Label(new Rect(Screen.width / 2 - 45, Screen.height / 2, 50, 50), "Your Score:" + action.GetScore().ToString(), text_style2);
if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.height / 2+40, 100, 50), "Restart")) {
action.ReStart();
return;
}
action.GameOver();
}
}
else {
GUI.Label(new Rect(Screen.width / 2 - 60, Screen.height / 2 - 100, 100, 100), "Hit UFO",start_style);
if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.height / 2-20, 100, 50), "Start")) {
game_start = true;
action.ReStart();
}
}
}
FirstController
public class FirstController : MonoBehaviour, ISceneController, IUserAction {
public UserGUI gui;
public DiskFactory diskfactory;
public FlyActionManager actionmanager;
public ScoreRecorder scorerecorder;
private int round = 0;//记录是第几回合
private int num = 0;//发射飞碟数
private bool status=true;//status标记游戏是否结束,true则不结束
public bool ifroundend=false;//如果回合结束则为ture,游戏暂停几秒,OnGUI中调用Getflag得到true,展示下一回合目标,然后开始下一回合
public bool flag=false;//flag用于标记记录curtime
public float []target=new float[3]{
10,25,40};//每回合的目标分数
private bool ifrun = false;//是否运行,点击游戏开始会调用ReStart使之变true
private float curtime=0;//进入回合前记录当前时间,用于等待
private int interval = 0;//每次发飞碟的间隔时间
void Start ()
{
SSDirector director = SSDirector.GetInstance();
director.CurrentScenceController = this;
gui = gameObject.AddComponent<UserGUI>() as UserGUI;
diskfactory = Singleton<DiskFactory>.Instance;
actionmanager = gameObject.AddComponent<FlyActionManager>() as FlyActionManager;
scorerecorder = Singleton<ScoreRecorder>.Instance;
}
void Update ()
{
if(ifrun)
{
if(round==0)
{
num=0;
ifroundend=true;
if(flag==false)
{
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
flag=true;
}
else
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//第一回合前等待3秒
ifroundend=false;
flag=false;
round+=1;
}
}
interval++;
if (Input.GetButtonDown("Fire1"))
{
Vector3 pos = Input.mousePosition;
Hit(pos);
}
if(round==1)
{
if (interval >= 180)
{
if(ifroundend)
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//第二回合前等待3秒
else
{
num=0;
round=2;
ifroundend=false;
}
}
if (num == 20)
{
if(flag==false)
{
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
flag=true;
}
else
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//等待三秒结算
flag=false;
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
checkstatus();
if(status==true)
{
ifroundend=true;
}
}
}
else{
interval = 0;
SendDisk(1);
num += 1;
}
}
}
if(round==2)
{
if (interval >= 120)
{
if(ifroundend)
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//第三回合前等待3秒
else
{
num=0;
round=3;
ifroundend=false;
flag=false;
}
}
if (num == 18)
{
if(flag==false)
{
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
flag=true;
}
else
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//等待三秒结算
flag=false;
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
checkstatus();
if(status==true)
{
ifroundend=true;
}
}
}
else
{
interval = 0;
if (num % 2 == 0) SendDisk(1);
else SendDisk(2);
num += 1;
}
}
}
if(round==3)
{
if (interval >= 80)
{
if (num == 10)
{
if(flag==false)
{
curtime=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
flag=true;
}
else
{
float tmp=System.DateTime.Now.Hour*3600+System.DateTime.Now.Minute*60+System.DateTime.Now.Second;
if(tmp<(curtime+3)) return;//等待三秒结算
flag=false;
ifrun=false;
num+=1;
checkstatus();
}
}
else{
interval = 0;
if (num % 3 == 0) SendDisk(1);
else if(num % 3 == 1)SendDisk(2);
else SendDisk(3);
num += 1;
}
}
}
diskfactory.FreeDisk();
}
}
public void LoadResources() {
diskfactory.GetDisk(round);
diskfactory.FreeDisk();
}
private void SendDisk(int type) {
GameObject disk = diskfactory.GetDisk(type);
float ran_y = 0;
float ran_x = Random.Range(-1f, 1f) < 0 ? -1 : 1;
float power = 0;
float angle = 0;
if (type == 1) {
ran_y = Random.Range(1f, 5f);
power = Random.Range(4f, 6f);
angle = Random.Range(25f,30f);
}
else if (type == 2) {
ran_y = Random.Range(2f, 3f);
power = Random.Range(5f, 7f);
angle = Random.Range(15f, 17f);
}
else {
ran_y = Random.Range(5f, 6f);
power = Random.Range(6f, 8f);
angle = Random.Range(10f, 12f);
}
disk.transform.position = new Vector3(ran_x*16f, ran_y, 0);
actionmanager.DiskFly(disk, angle, power*0.2f);
}
//检测游戏是否结束
public void checkstatus(){
status=GetScore()>=target[round-1] ? true:false;
}
//射击
public void Hit(Vector3 pos) {
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit[] hits;
hits = Physics.RaycastAll(ray);
for (int i = 0; i < hits.Length; i++) {
RaycastHit hit = hits[i];
if (hit.collider.gameObject.GetComponent<Disk>() != null) {
scorerecorder.Record(hit.collider.gameObject);
hit.collider.gameObject.transform.position = new Vector3(0, -10, 0);
}
}
}
public float GetScore() {
return scorerecorder.GetScore();
}
public bool GetStatus() {
return status;
}
public float GetTarget(){
return target[round];
}
public int GetRound() {
return round;
}
public bool Getflag() {
return ifroundend;
}
public int GetTrial() {
return num;
}
//重新开始
public void ReStart() {
ifrun = true;
scorerecorder.Reset();
diskfactory.Reset();
round = 0;
num = 1;
status=true;
}
//游戏结束
public void GameOver() {
ifrun = false;
}
}
演示效果