这次作业,主要使用了单实例的工厂类,从而可以让各个类之间的访问通过Singleton<T>来进行访问。
其次,这次的优化在于将Rule类分开来,把游戏的分数,胜利条件放在Rule类中,从而便于日后管理
而涉及到飞碟的颜色等等属性则放在UFO管理之中,从而实现了分离原则。
UI没有太多的改动,主要是显示内容和控制发射。
这次的场景控制器只有分数,关卡和游戏状态,大大简化了场景控制器所需要知道的东西。
UFO管理是整个游戏的核心之一,因为涉及到UFO的各个状态,所以包括资源的加载,回收和发射飞碟,都是在这个类之中实现的。
动作管理器很简单,写了两个函数用来调用UFO管理的函数。
加载在UFO实例上的两个Compent,一个实现了物理引擎,一个没有实现
这次单数关卡是物理,双数不是。可以继续优化的点在于可以创建一个按钮来实现切换,不过这次就没实现了。
爆炸效果和子弹也都是在UFO管理之中。下面上代码,UML图和效果图
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using UnityEngine.UI;
using rule;
public class UserControl : MonoBehaviour
{
public Text Main_Text; // 显示主提示
public Text Score_Text; // 显示得分
public Text Level_Text; // 显示回合
public Camera cam;
public bool IsFinish = false;
SceneController SC;
GameControl GC;
Rule RC;
UFOControl UF;
private void Awake()
{
SC = Singleton<SceneController>.Instance;
GC = Singleton<GameControl>.Instance;
RC = Singleton<Rule>.Instance;
UF = Singleton<UFOControl>.Instance;
}
void Start()
{
Score_Text.text = "Score: "+SC.getScore();
Level_Text.text = "Level: " + SC.getNowLevel();
Main_Text.text = "Gaming";
}
// Update is called once per frame
void Update()
{
if (IsFinish == true)
{
if (RC.CheckStatus() == 1)
Main_Text.text= "Win";
else
Main_Text.text = "False";
}
if (Input.GetKeyDown("space") && IsFinish == false)
{
GC.Launch_UFO();
}
else if (Input.GetMouseButtonDown(0))
{
Vector3 mp = Input.mousePosition;
Ray ray = Camera.main.ScreenPointToRay(mp); // 摄像机到鼠标射线
UF.bullet.GetComponent<Rigidbody>().velocity = Vector3.zero; // 子弹刚体速度重置
UF.bullet.GetComponent<Transform>().position = transform.position; // 子弹从摄像机位置射出
UF.bullet.GetComponent<Rigidbody>().AddForce(ray.direction*50, ForceMode.Impulse);
RaycastHit hit;
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "UFO")
{
// 播放爆炸粒子特效
UF.explosion.transform.position = hit.collider.gameObject.transform.position;
//UF.explosion.GetComponent<Renderer>().material.color = hit.collider.gameObject.GetComponent<Renderer>().material.color;
UF.explosion.Play();
GC.Hit_UFO(hit.collider.gameObject);
}
}
Level_Text.text = "Level: "+ SC.getNowLevel();
Score_Text.text = "Score: "+SC.getScore();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;
public class GameControl : MonoBehaviour
{
UFOControl UC;
private void Awake()
{
UC= Singleton<UFOControl>.Instance;
}
public void Launch_UFO()
{
UC.Launch_UFO();
}
public void Hit_UFO(GameObject temp)
{
UC.Hit_UFO(temp);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;
namespace MyGame
{
public class UFOControl : MonoBehaviour
{
private List<GameObject> UFO_Ready_List = new List<GameObject>();
private List<GameObject> UFO_Active_List = new List<GameObject>();
private List<GameObject> UFO_UnActive_List = new List<GameObject>();
public GameObject UFO_Pre; // UFO预制
public GameObject bullet; //子弹预制
public ParticleSystem explosion; //爆炸预制
private Vector3 UnusedPlace = new Vector3(1000f, 1000f, 1000f);
private Color UFO_Color; //颜色
private int UFO_Number = 10; // 飞碟一共的数量
private int UFO_Speed; //飞碟的速度
Rule Crule;
private void Awake()
{
Crule = Singleton<Rule>.Instance;
}
public Color getColor()
{
return UFO_Color;
}
public int getSpeed()
{
return UFO_Speed;
}
public void Start()
{
for(int i=0; i<10;i++)
{
GameObject Temp = GameObject.Instantiate(UFO_Pre, UnusedPlace, Quaternion.identity) as GameObject;
UFO_Ready_List.Add(Temp);
}
}
//资源加载
public void Load_Reources(Level level)
{
if (level == Level.Ready)
{
UFO_Color = Color.blue;
UFO_Speed = 1;
Launch_Ready_UFO();
}
else if (level == Level.First)
{
UFO_Color = Color.green;
UFO_Speed = 3;
Launch_Ready_UFO();
}
else if (level == Level.Second)
{
UFO_Color = Color.red;
UFO_Speed = 5;
Launch_Ready_UFO();
}
}
//发射准备
public void Launch_Ready_UFO()
{
Debug.Log("SSS");
for (int i = 0; i < 10; i++)
{
if (UFO_Active_List.Count != 0)
{
GameObject temp = UFO_Active_List[0];
temp.transform.position = UnusedPlace;
UFO_Ready_List.Add(temp);
UFO_Active_List.Remove(temp);
}
else if (UFO_UnActive_List.Count != 0)
{
GameObject temp = UFO_UnActive_List[0];
temp.transform.position = UnusedPlace;
UFO_Ready_List.Add(temp);
UFO_UnActive_List.Remove(temp);
}
}
}
public void Launch_UFO()
{
if (UFO_Ready_List.Count == 0)
{
isFlaseStatus();
}
else
{
GameObject Temp =UFO_Ready_List[0];
UFO_Ready_List.Remove(Temp);
Temp.GetComponent<Renderer>().material.color = UFO_Color;
if(Crule.getNowLevel() == Level.First || Crule.getNowLevel() == Level.Tird)
{
UFOCompent ac = Temp.AddComponent<UFOCompent>();
Temp.transform.position = new Vector3(0 + Random.Range(-10, 10), 8 + Random.Range(-4, 5), 0);
ac.setting(UFO_Speed);
}
else
{
UFOCompentP ac = Temp.AddComponent<UFOCompentP>();
Temp.transform.position = new Vector3(0 + Random.Range(-10, 10), 8 + Random.Range(-4, 5), 0);
ac.setting(UFO_Speed);
}
UFO_Active_List.Add(Temp);
}
}
public void Hit_UFO(GameObject temp)
{
UFO_Active_List.Remove(temp);
UFO_UnActive_List.Add(temp);
temp.transform.position = new Vector3(1000f, 1000f, 1000f);
Crule.HitUFO();
}
public void Miss_UFO(GameObject temp)
{
UFO_Active_List.Remove(temp);
UFO_UnActive_List.Add(temp);
}
//游戏结束判断
public void isFlaseStatus()
{
Crule.IsFalseStatus();
}
}
}
using MyGame;
using rule;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UFOCompent : MonoBehaviour
{
private float time;
public float UFO_Speed;
public float UFO_Speed_y;
public float UFO_Speed_x;
// Use this for initialization
Rule Srule;
UFOControl UC;
private void Awake()
{
Srule = Singleton<Rule>.Instance;
UC = Singleton<UFOControl>.Instance;
}
public void setting(float Speed)
{
time = Time.time;
UFO_Speed = Speed;
}
// Update is called once per frame
void Update()
{
UFO_Speed_y = UnityEngine.Random.Range(0, 3) + UFO_Speed;
UFO_Speed_x = UnityEngine.Random.Range(-10, 10) + UFO_Speed;
transform.Translate(Vector3.down * Time.deltaTime * UFO_Speed_y, Space.World);
transform.Translate(Vector3.left * Time.deltaTime * UFO_Speed_x);
if (this.gameObject.transform.position.y < -3)
{
this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
}
if (Time.time - time > 8 || this.gameObject.transform.position.y < -3)
{
UC.Miss_UFO(this.gameObject);
this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
Destroy(this);
}
}
}
using MyGame;
using rule;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UFOCompentP : MonoBehaviour
{
private float time;
public float UFO_Speed;
// Use this for initialization
Rule Srule;
UFOControl UC;
private void Awake()
{
Srule = Singleton<Rule>.Instance;
UC = Singleton<UFOControl>.Instance;
}
public void setting(float Speed)
{
time = Time.time;
UFO_Speed = Speed;
}
// Update is called once per frame
void FixedUpdate()
{
this.gameObject.AddComponent<Rigidbody>();
Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();
if (rigid)
{
rigid.AddForce(Vector3.down * 3.3f);
if (Random.Range(-1, 1) < 0)
rigid.AddForce(Vector3.left * 1.0f);
else
rigid.AddForce(Vector3.right * 1.0f);
}
if (this.gameObject.transform.position.y < -3)
{
this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
}
if (Time.time - time > 8 || this.gameObject.transform.position.y < -3)
{
UC.Miss_UFO(this.gameObject);
this.gameObject.transform.position = new Vector3(1000f, 1000f, 1000f);
UC.explosion.GetComponent<Transform>().position = new Vector3(1000f, 1000f, 1000f);
Destroy(this);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
//Rule类负责这个游戏的核心规则
//游戏的胜负,游戏的关卡变化,游戏的分数变化
namespace rule
{
public enum Level { Ready, First, Second, Tird }; //关卡信息
public class Rule : MonoBehaviour
{
private int Score = 0; //游戏的分数
private int GoalScore = 5; // 目标分数
private Level NowLevel = Level.Ready; // 游戏的关卡
private bool isWin = false;
private bool isFalse = false;
UFOControl RUFOControl;
public int getScore()
{
return Score;
}
public Level getNowLevel()
{
return NowLevel;
}
// 得分
public void HitUFO()
{
Score++;
Debug.Log("Good! Now Score: " + Score);
}
//关卡判断
public void IsNextLevel()
{
if (NowLevel == Level.Ready)
{
RUFOControl.Load_Reources(NowLevel);
NowLevel = Level.First;
}
else if (NowLevel == Level.First && Score >= GoalScore)
{
RUFOControl.Load_Reources(NowLevel);
Score = 0;
NowLevel = Level.Second;
}
else if (NowLevel == Level.Second && Score >= GoalScore)
{
RUFOControl.Load_Reources(NowLevel);
Score = 0;
NowLevel = Level.Tird;
}
else if (NowLevel == Level.Tird && Score >= GoalScore)
isWin = true;
else
{
if (Score < 0)
isFalse = true;
}
}
//检查游戏是否结束
public int CheckStatus()
{
if (isWin == true)
return 1;
else if (isFalse == true)
return -1;
else
return 0;
}
public void IsFalseStatus()
{
if (Score < GoalScore)
{
isFalse = true;
}
}
private void Awake()
{
RUFOControl = Singleton<UFOControl>.Instance;
}
public void Start()
{
IsNextLevel();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;
using rule;
namespace MyGame
{
//场景单实例
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;
}
}
}
public class SceneController : MonoBehaviour
{
private int Now_Score; //当前分数
private Level Now_Level;//当前关卡
private int IsStatus = 0;//游戏状态
Rule Srule;
UserControl USC;
private void Awake()
{
Srule = Singleton<Rule>.Instance;
USC = Singleton<UserControl>.Instance;
}
public int getScore()
{
return Now_Score;
}
public Level getNowLevel()
{
return Now_Level;
}
public void Start()
{
Now_Score = Srule.getScore();
Now_Level = Srule.getNowLevel();
}
public void Update()
{
Srule.IsNextLevel();
Now_Score = Srule.getScore();
Now_Level = Srule.getNowLevel();
IsStatus = Srule.CheckStatus();
if (IsStatus == -1)
USC.IsFinish = true;
else if (IsStatus == 1)
USC.IsFinish = true;
}
}
}