简介
就是一个简单的打飞碟游戏。。游戏难度会随着你获得的分数提升,胜利条件是获得1000分。
对象处理
就简单的一个飞碟预制就行了(十分简单,就一个圆柱体。。完毕)
还有一个粒子系统用来模拟飞碟被击中时的爆炸效果,粒子的参数如下:
就这么简单。。没了
UML
代码部分
其实这个飞碟的代码跟之前的那个牧师与魔鬼的代码十分的相似,主要是由于老师提供的框架可塑性实在是太强大了(膜拜一下老师)。只需要增加一个记分员,一个飞碟工厂,再加上之前的框架,就搞定了。
Singleton.cs(单例模型的模板)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> where T : MonoBehaviour
{
private static T instance;
public static T Instance {
get {
if (instance == null) {
instance = (T)Object.FindObjectOfType(typeof(T));
if (instance == null) {
Debug.LogError("Can't find instance of " + typeof(T));
}
}
return instance;
}
}
}
Director.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Director : System.Object {
public static Director _instance;
public ISceneController currentSceneController { get; set; }
public bool running { get; set; }
public static Director getInstance() {
if (_instance == null) _instance = new Director();
return _instance;
}
public int getFPS() {
return Application.targetFrameRate;
}
public void setFPS(int fps) {
Application.targetFrameRate = fps;
}
}
DiskData.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskData : MonoBehaviour {
public float size;
public Color color;
public float speed;
}
ScoreRecorder.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScoreRecorder : MonoBehaviour {
private float score;
public float getScore() {
return score;
}
public void Record(GameObject disk) {
score += (100 - disk.GetComponent<DiskData>().size *(20 - disk.GetComponent<DiskData>().speed));
Color c = disk.GetComponent<DiskData>().color;
switch (c.ToString()) {
case "red":
score += 50;
break;
case "green":
score += 40;
break;
case "blue":
score += 30;
break;
case "yellow":
score += 10;
break;
}
}
public void Reset() {
score = 0;
}
}
DiskFactory.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskFactory : MonoBehaviour {
private List<GameObject> used = new List<GameObject>();
private List<GameObject> free = new List<GameObject>();
private Color[] color = { Color.red, Color.green, Color.blue, Color.yellow };
public GameObject GetDisk(int ruler) {
GameObject a_disk;
if (free.Count > 0) {
a_disk = free[0];
free.Remove(free[0]);
} else {
a_disk = GameObject.Instantiate(Resources.Load("prefabs/Disk")) as GameObject;
}
switch (ruler) {
case 1:
a_disk.GetComponent<DiskData>().size = UnityEngine.Random.Range(0, 6);
a_disk.GetComponent<DiskData>().color = color[UnityEngine.Random.Range(0, 4)];
a_disk.GetComponent<DiskData>().speed = UnityEngine.Random.Range(10, 15);
a_disk.transform.localScale = new Vector3(a_disk.GetComponent<DiskData>().size * 2, a_disk.GetComponent<DiskData>().size * 0.1f, a_disk.GetComponent<DiskData>().size * 2);
a_disk.GetComponent<Renderer>().material.color = a_disk.GetComponent<DiskData>().color;
break;
case 2:
a_disk.GetComponent<DiskData>().size = UnityEngine.Random.Range(0, 4);
a_disk.GetComponent<DiskData>().color = color[UnityEngine.Random.Range(0, 4)];
a_disk.GetComponent<DiskData>().speed = UnityEngine.Random.Range(15, 20);
a_disk.transform.localScale = new Vector3(a_disk.GetComponent<DiskData>().size * 2, a_disk.GetComponent<DiskData>().size * 0.1f, a_disk.GetComponent<DiskData>().size * 2);
a_disk.GetComponent<Renderer>().material.color = a_disk.GetComponent<DiskData>().color;
break;
}
a_disk.SetActive(true);
used.Add(a_disk);
return a_disk;
}
public void FreeDisk(GameObject disk) {
for(int i = 0; i < used.Count; i++) {
if(used[i] == disk) {
disk.SetActive(false);
used.Remove(used[i]);
free.Add(disk);
}
}
}
}
RoundController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum State { WIN, LOSE, PAUSE, CONTINUE, START };
public class RoundController : MonoBehaviour, IUserAction, ISceneController {
public DiskFactory diskFactory;
public RoundActionManager actionManager;
public ScoreRecorder scoreRecorder;
private List<GameObject> disks;
private int round;
private GameObject shootAtSth;
GameObject explosion;
public State state { get; set; }
public int leaveSeconds;
public int count;
IEnumerator DoCountDown() {
while (leaveSeconds >= 0) {
yield return new WaitForSeconds(1);
leaveSeconds--;
}
}
void Awake() {
Director director = Director.getInstance();
director.setFPS(60);
director.currentSceneController = this;
LoadResources();
diskFactory = Singleton<DiskFactory>.Instance;
scoreRecorder = Singleton<ScoreRecorder>.Instance;
actionManager = Singleton<RoundActionManager>.Instance;
leaveSeconds = 60;
count = leaveSeconds;
state = State.PAUSE;
disks = new List<GameObject>();
}
void Start () {
round = 1;
LoadResources();
}
void Update() {
LaunchDisk();
Judge();
RecycleDisk();
}
public void LoadResources() {
Camera.main.transform.position = new Vector3(0, 0, -15);
explosion = Instantiate(Resources.Load("Prefabs/ParticleSys"), new Vector3(-40, 0, 0), Quaternion.identity) as GameObject;
}
public void shoot() {
if (Input.GetMouseButtonDown(0) && (state == State.START || state == State.CONTINUE)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
if ((Director.getInstance().currentSceneController.state == State.START || Director.getInstance().currentSceneController.state == State.CONTINUE)) {
shootAtSth = hit.transform.gameObject;
explosion.transform.position = hit.collider.gameObject.transform.position;
explosion.GetComponent<Renderer>().material = hit.collider.gameObject.GetComponent<Renderer>().material;
explosion.GetComponent<ParticleSystem>().Play();
}
}
}
}
public void LaunchDisk() {
if(count - leaveSeconds == 1) {
count = leaveSeconds;
GameObject disk = diskFactory.GetDisk(round);
Debug.Log(disk);
disks.Add(disk);
actionManager.addRandomAction(disk);
}
}
public void RecycleDisk() {
for(int i = 0; i < disks.Count; i++) {
if( disks[i].transform.position.z < -18) {
diskFactory.FreeDisk(disks[i]);
disks.Remove(disks[i]);
}
}
}
public void Judge() {
if(shootAtSth != null && shootAtSth.transform.tag == "Disk" && shootAtSth.activeInHierarchy) {
scoreRecorder.Record(shootAtSth);
diskFactory.FreeDisk(shootAtSth);
shootAtSth = null;
}
if(scoreRecorder.getScore() > 500 * round) {
round++;
leaveSeconds = count = 60;
}
if (round == 3) {
StopAllCoroutines ();
state = State.WIN;
} else if (leaveSeconds == 0 && scoreRecorder.getScore () < 500 * round) {
StopAllCoroutines ();
state = State.LOSE;
} else state = State.CONTINUE;
}
public void Pause() {
state = State.PAUSE;
StopAllCoroutines();
for (int i = 0; i < disks.Count; i++) disks[i].SetActive(false);
}
public void Resume() {
StartCoroutine(DoCountDown());
state = State.CONTINUE;
for (int i = 0; i < disks.Count; i++) disks[i].SetActive(true);
}
public void Restart() {
scoreRecorder.Reset();
Application.LoadLevel(Application.loadedLevelName);
Director.getInstance().currentSceneController.state = State.START;
}
}
RoundActionManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoundActionManager : SSActionManager, ISSActionCallback {
public RoundController scene;
public MoveToAction action1, action2;
float speed;
public void addRandomAction(GameObject gameObj) {
int[] X = { -20, 20 };
int[] Y = { -5, 5 };
int[] Z = { -20, -20 };
Vector3 startPos = new Vector3(
UnityEngine.Random.Range(-20, 20),
UnityEngine.Random.Range(-5, 5),
UnityEngine.Random.Range(50, 10)
);
gameObj.transform.position = startPos;
Vector3 randomTarget = new Vector3(
X[UnityEngine.Random.Range(0, 2)],
Y[UnityEngine.Random.Range(0, 2)],
Z[UnityEngine.Random.Range(0, 2)]
);
MoveToAction action = MoveToAction.GetSSAction(randomTarget, gameObj.GetComponent<DiskData>().speed);
RunAction(gameObj, action, this);
}
protected void Start() {
scene = (RoundController)Director.getInstance().currentSceneController;
scene.actionManager = this;
}
protected new void Update() {
base.Update();
}
public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
int intParam = 0,
string strParam = null,
Object objectParam = null) {
}
}
UserGUI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IUserAction {
void shoot();
}
public class UserGUI : MonoBehaviour {
private IUserAction action;
private float width, height;
private string countDownTitle;
void Start() {
countDownTitle = "Start";
action = Director.getInstance().currentSceneController as IUserAction;
}
float castw(float scale) {
return (Screen.width - width) / scale;
}
float casth(float scale) {
return (Screen.height - height) / scale;
}
void OnGUI() {
width = Screen.width / 12;
height = Screen.height / 12;
GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), ((RoundController)Director.getInstance().currentSceneController).leaveSeconds.ToString());
GUI.Button(new Rect(580, 10, 80, 30), ((RoundController)Director.getInstance().currentSceneController).scoreRecorder.getScore().ToString());
if (Director.getInstance().currentSceneController.state != State.WIN && Director.getInstance().currentSceneController.state != State.LOSE
&& GUI.Button(new Rect(10, 10, 80, 30), countDownTitle)) {
if (countDownTitle == "Start") {
countDownTitle = "Pause";
Director.getInstance().currentSceneController.Resume();
} else {
countDownTitle = "Start";
Director.getInstance().currentSceneController.Pause();
}
}
if (Director.getInstance().currentSceneController.state == State.WIN) {
if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Win!")) Director.getInstance().currentSceneController.Restart();
} else if (Director.getInstance().currentSceneController.state == State.LOSE) {
if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Lose!")) Director.getInstance().currentSceneController.Restart();
}
}
void Update() {
action.shoot();
}
}
剩下的就跟之前的牧师与魔鬼的代码一样啦。
这里最最最重要的是(红笔五角星),要调整脚本的调用顺序。否则会出错的。
没啦,就这么多了。希望玩得愉快