1、改进飞碟(Hit UFO)游戏:
- 游戏内容要求:
- 按adapter模式设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
游戏规则的变化:
游戏开始前增加了一个模式选择,可以选择运动学模式和物理学模式。选择后游戏开始,和改进前规则一样。
原游戏规则:
- 一共有三个回合。第一个回合获得5分可以进入第二个回合,第二个回合获得15分可以进入第三个回合,第三回合获得30分就获胜。每个回合的飞碟速度依次增加,飞碟发射的间隔时间依次减少。每回合生命值会恢复初始值。
- 击中飞碟加上相应分数,错过飞碟扣除生命值,当生命值降为0时,游戏失败。每个回合有10次trial,如果10次trial结束,没有进入下一回合,游戏失败。游戏失败会跳出restart按键,游戏界面右上角也有restart按键,点击可以重新开始游戏。
- 游戏界面右上角有pause按键,点击可以暂停发射飞碟,并且页面中间出现continue按键,点击continue按键可以继续游戏。
代码:
https://github.com/loudax/3d-game/tree/master/hw6-FlyingSaucer(Adapter)
项目设置:
- 创建三个飞碟预设,挂载上DiskData,设置score、scale、color。这就是作业5中第二道选做题实现的自定义组件。
- 新建一个空对象,挂载上Controllor和DiskFactory。
代码说明:
大部分代码没有改变,只对改进的部分进行说明。
- Actions.cs
新增ActionManagerAdapter类,作用是根据flag变量的值,选择调用不同的类的实例来实现飞碟的运动。如果flag为真,说明是物理学,那么调用PhysicsFlyActionManager类的UFOfly函数,如果flag为假,说明是运动学,那么调用FlyActionManager类的UFOfly函数。
public class ActionManagerAdapter : MonoBehaviour, IActionManager
{
public FlyActionManager action_manager;
public PhysicsFlyActionManager phy_action_manager;
public void UFOFly(GameObject disk, float angle, float power, bool go, bool flag) { //flag == true 物理学, flag == false 运动学
if(flag) phy_action_manager.UFOfly(disk, angle, power, go); //如果是物理学,调用PhysicsFlyActionManager类的UFOfly
else action_manager.UFOfly(disk, angle, power, go); //如果是运动学,调用FlyActionManager类的UFOfly
}
void Start ()
{
action_manager = gameObject.AddComponent<FlyActionManager>() as FlyActionManager;
phy_action_manager = gameObject.AddComponent<PhysicsFlyActionManager>() as PhysicsFlyActionManager;
}
}
FlyActionManager类和FlyAction类,用于管理和实现运动学方式下飞碟的运动。其中FlyAction类和原项目一致,FlyActionManager类稍有改动,去掉了Controllor类实例。
public class FlyActionManager : SSActionManager
{
public FlyAction fly;
protected void Start()
{
}
public void UFOfly(GameObject disk, float angle, float power, bool go)
{
fly = FlyAction.GetSSAction (disk.GetComponent<DiskData> ().direction, angle, power, go);
this.RunAction (disk, fly, this);
}
}
public class FlyAction : SSAction
{
public float gravity = -0.1f; //飞碟飞行时受重力
public bool go = true; //用于表示是否暂停,go为false时表示游戏暂停
private float time;
private Vector3 start_vector;
private Vector3 gravity_vector = Vector3.zero;
private Vector3 current_angle = Vector3.zero;
private FlyAction()
{
}
public static FlyAction GetSSAction(Vector3 direction, float angle, float power, bool go_)
{
FlyAction action = CreateInstance<FlyAction>();
action.go = go_;
action.start_vector = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right * power;
return action;
}
public override void Update()
{
if(go){
time += Time.fixedDeltaTime;
gravity_vector.y = gravity * time;
transform.position += (start_vector + gravity_vector) * Time.fixedDeltaTime;
current_angle.z = Mathf.Atan((start_vector.y + gravity_vector.y) / start_vector.x) * Mathf.Rad2Deg;
transform.eulerAngles = current_angle;
}
if (this.transform.position.x > 20){ //当x坐标大于20时,回收飞碟
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
public override void Start()
{
}
}
PhysicsFlyActionManager类和PhysicsFlyAction类,用于管理和实现物理学方式下飞碟的运动,方法是给刚体加上向右方的速度。
public class PhysicsFlyActionManager : SSActionManager
{
public PhysicsFlyAction fly;
protected void Start()
{
}
public void UFOfly(GameObject disk, float angle, float power, bool go)
{
fly = PhysicsFlyAction.GetSSAction(disk.GetComponent<DiskData>().direction, angle, power, go);
this.RunAction(disk, fly, this);
}
}
public class PhysicsFlyAction : SSAction
{
private Vector3 start_vector;
public float power;
public bool go = true; //用于表示是否暂停,go为false时表示游戏暂停
private PhysicsFlyAction() { }
public static PhysicsFlyAction GetSSAction(Vector3 direction, float angle, float power, bool go_)
{
PhysicsFlyAction action = CreateInstance<PhysicsFlyAction>();
action.start_vector = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right * power;
action.power = power;
return action;
}
public override void Update()
{
if(go == false){
gameobject.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
gameobject.GetComponent<Rigidbody>().useGravity = false;
}
else{
gameobject.GetComponent<Rigidbody>().velocity = power * 2 * start_vector;
gameobject.GetComponent<Rigidbody>().useGravity = true;
}
if (this.transform.position.x > 20) {
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
public override void Start()
{
gameobject.GetComponent<Rigidbody>().velocity = power * 2 * start_vector;
gameobject.GetComponent<Rigidbody>().useGravity = true;
}
}
- Controllor.cs
加入了两个变量mode和modeSetting。mode指的是运动模式,如果是物理学模式,mode为真;如果是运动学模式,mode为假。modeSetting指是否在模式选择界面,如果还在模式选择,modeSetting为真,游戏还不能开始;如果已选择,modeSetting为假,且可以开始发射飞碟。
加入了与以上两个变量相关的get、set函数。
public class Controllor : MonoBehaviour,ISceneControllor,IUserAction
{
public IActionManager ima;
public DiskFactory df;
public UserGUI ug;
public ScoreRecorder sr;
public RoundControllor rc;
private Queue<GameObject> dq = new Queue<GameObject> ();
private List<GameObject> dfree = new List<GameObject> ();
private int round = 1;
private int trail = 0;
private float t = 1;
private float speed = 2; //飞碟发射间隔时间
private bool mode = false; //mode == true 物理学, mode == false 运动学
private bool modeSetting = true;
void Start(){
SSDirector director = SSDirector.GetInstance();
director.CurrentSceneControllor = this;
df = Singleton<DiskFactory>.Instance;
sr = gameObject.AddComponent<ScoreRecorder> () as ScoreRecorder;
ima = gameObject.AddComponent<ActionManagerAdapter>() as IActionManager;
ug = gameObject.AddComponent<UserGUI>() as UserGUI;
rc = gameObject.AddComponent<RoundControllor> () as RoundControllor;
t = speed;
}
void Update ()
{
if(ug.go){
t-=Time.deltaTime;
if(trail > 10){ //超过10次trial后,判为游戏失败
ug.life = 0;
}
if (t < 0) { //发射一个飞碟
LoadResources ();
SendDisk ();
t = speed;
trail++;
}
if ((sr.score >= 5 && round == 1) || (sr.score >= 15 && round == 2) || (sr.score >= 30 && round == 3)) { //判断是否进入下一轮
round++;
trail = 0;
rc.loadRoundData (round);
ug.RecoverBlood();
}
}
}
public void setting(float speed_)
{
speed = speed_;
}
public void LoadResources()
{
dq.Enqueue(df.GetDisk(round));
}
private void SendDisk() //发射飞碟
{
float position_x = 16;
if (dq.Count != 0)
{
GameObject disk = dq.Dequeue();
dfree.Add(disk);
disk.SetActive(true);
float ran_y = Random.Range(1f, 4f);
disk.GetComponent<DiskData>().direction = new Vector3(1f, ran_y, 0);
Vector3 position = new Vector3(-disk.GetComponent<DiskData>().direction.x * position_x, ran_y, 0);
disk.transform.position = position;
float power = Random.Range(1f * round, 2f * round);
float angle = Random.Range(0f, 5f);
ima.UFOFly(disk, angle, power, ug.go, mode);
}
for (int i = 0; i < dfree.Count; i++)
{
GameObject temp = dfree[i];
if (temp.transform.position.x > 20 && temp.gameObject.activeSelf == true)
{
df.FreeDisk(dfree[i]);
dfree.Remove(dfree[i]);
ug.ReduceBlood();
}
}
}
public void Hit (Vector3 pos){ //集中飞碟
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit[] hits;
hits = Physics.RaycastAll(ray);
bool not_hit = false;
for (int i = 0; i < hits.Length; i++)
{
RaycastHit hit = hits[i];
if (hit.collider.gameObject.GetComponent<DiskData>() != null)
{
for (int j = 0; j < dfree.Count; j++)
{
if (hit.collider.gameObject.GetInstanceID() == dfree[j].gameObject.GetInstanceID())
{
not_hit = true;
}
}
if(!not_hit)
{
return;
}
dfree.Remove(hit.collider.gameObject);
sr.Record(hit.collider.gameObject);
hit.collider.gameObject.transform.position = new Vector3(0, -100, 0);
df.FreeDisk(hit.collider.gameObject);
break;
}
}
}
public void Restart (){ //重启游戏
SceneManager.LoadScene(0);
}
public int GetScore (){ //得到得分
return sr.score;
}
public int GetRound(){ //得到轮次
return round;
}
public int GetTrail(){
return trail;
}
public bool GetMode(){
return mode;
}
public void SetMode(bool flag){
mode = flag;
}
public bool GetModeSetting(){
return modeSetting;
}
public void StartGame(){
modeSetting = false;
ug.go = true;
}
}
- UserGUI.cs
OnGUI函数加了一个if else判断。如果action.GetModeSetting()为真,说明处在模式选择阶段,显示模式选择的两个按键,选择后相应的调用函数设置mode的值并开始游戏。如果action.GetModeSetting()为假,说明可以开始游戏,此处代码和原项目的代码是相同的,不再解释了。
public class UserGUI : MonoBehaviour
{
private IUserAction action;
public int life = 6;
public bool go = false;
void Start ()
{
action = SSDirector.GetInstance().CurrentSceneControllor as IUserAction;
}
void OnGUI ()
{
if(action.GetModeSetting()){
GUI.Label(new Rect(Screen.width / 2 - 30, Screen.width / 2 - 320, 100, 50), "模式选择");
if (GUI.Button(new Rect(Screen.width / 2 - 55, Screen.width / 2 - 200, 100, 50), "物理学模式"))
{
action.SetMode(true);
action.StartGame();
return;
}
if (GUI.Button(new Rect(Screen.width / 2 - 55, Screen.width / 2 - 270, 100, 50), "运动学模式"))
{
action.SetMode(false);
action.StartGame();
return;
}
}
else{
if (Input.GetButtonDown("Fire1")){
Vector3 pos = Input.mousePosition;
action.Hit(pos);
}
GUI.Label(new Rect(20, 10, 200, 50), "score:");
GUI.Label(new Rect(60, 10, 200, 50), action.GetScore().ToString());
GUI.Label(new Rect(20, 30, 50, 50), "hp:");
for (int i = 0; i < life; i++){
GUI.Label(new Rect(40 + 10 * i, 30, 50, 50), "X");
}
GUI.Label(new Rect(20, 50, 50, 50), "trail:");
GUI.Label(new Rect(60, 50, 50, 50), action.GetTrail().ToString());
if(action.GetRound() == 1){
GUI.Label(new Rect(200, 10, 200, 50), "ROUND");
GUI.Label(new Rect(250, 10, 200, 50), action.GetRound().ToString());
GUI.Label(new Rect(200, 30, 300, 50), "分数到达5分进入下一关,打中一个飞碟得1分,错过一个飞碟生命值减1,生命值归零时游戏失败。");
}
else if(action.GetRound() == 2){
GUI.Label(new Rect(200, 10, 200, 50), "ROUND");
GUI.Label(new Rect(250, 10, 200, 50), action.GetRound().ToString());
GUI.Label(new Rect(200, 30, 300, 50), "分数到达15分进入下一关,打中一个飞碟得2分,错过一个飞碟生命值减1,生命值归零时游戏失败。");
}
else if(action.GetRound() == 3){
GUI.Label(new Rect(200, 10, 200, 50), "ROUND");
GUI.Label(new Rect(250, 10, 200, 50), action.GetRound().ToString());
GUI.Label(new Rect(200, 30, 300, 50), "分数到达30分获得胜利,打中一个飞碟得3分,错过一个飞碟生命值减1,生命值归零时游戏失败。");
}
else{
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.width / 2 - 300, 100, 100), "You Win!");
}
if(GUI.Button(new Rect(550, 10, 100, 40), "Pause")){
go = false;
}
if(go == false){
if(GUI.Button(new Rect(Screen.width / 2 - 60, Screen.width / 2 - 250, 100, 40), "Continue")){
go = true;
}
}
if (GUI.Button(new Rect(670, 10, 100, 40), "Restart")){
action.Restart();
return;
}
if (life == 0){
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.width / 2 - 300, 100, 100), "Game Over!");
if (GUI.Button(new Rect(Screen.width / 2 - 60, Screen.width / 2 - 250, 100, 40), "Restart")){
action.Restart();
return;
}
}
}
}
public void ReduceBlood() //生命值减1
{
if(life > 0)
life--;
}
public void RecoverBlood() //生命值恢复初始状态
{
life = 6;
}
}
- interface.cs
加上了Controllor中新增的函数,修改了Action中的函数的参数。
public interface IUserAction
{
void Hit(Vector3 pos);
void Restart();
int GetScore();
void setting(float speed);
int GetRound();
int GetTrail();
bool GetMode();
void SetMode(bool flag);
bool GetModeSetting();
void StartGame();
}
public interface IActionManager
{
void UFOFly(GameObject disk, float angle, float power, bool go, bool flag); // flag == true 物理学, flag == false 运动学
}
游戏效果:
和修改前基本一致,运动学部分是相同的,不再展示,以下动图展示物理学模式的效果。
2、打靶游戏(可选作业):
- 游戏内容要求:
- 靶对象为 5 环,按环计分;
- 箭对象,射中后要插在靶上
- 增强要求:射中后,箭对象产生颤抖效果,到下一次射击 或 1秒以后
- 游戏仅一轮,无限 trials;
- 增强要求:添加一个风向和强度标志,提高难度
游戏规则:
点击空格,产生一根箭,点击鼠标左键可以随鼠标方向发射箭,风向和强度标志在屏幕右上角,会影响箭的飞行。箭射到箭靶上有颤抖效果,根据射到箭靶上的位置计分,从外环到内环分别是1到5分,分数显示在左上角。左下角有一个第二摄像机,近距离观看箭靶,可以通过这个部分看到箭射的位置。
代码:
https://github.com/loudax/3d-game/tree/master/hw6-Archery
项目设置:
- 新建arrow预设,由长圆柱pole和球tip组成。
pole加上Capsule Collider,和棕色Material。
tip加上Sphere Collider、灰色Material和Arrow Collider。
- 新建预设target。由5个圆柱叠起来,为它们加上不同的颜色Material进行环和环之间的区分,加上Capsule Collider和Mesh Collider,且选择Convex和IsTrigger
- 新建Camera,设置Viewport Rect。
- 新建一个空对象,放入Controller和ArrowFactory。
代码说明:
- SSDirector.cs
和前面的打飞碟项目相同,不再说明了。
- Singletion.cs
和前面的打飞碟项目相同,不再说明了。
- Actions.cs
用于控制箭的飞行和颤抖。飞行时,给箭加上一个受风影响的力,当击中或是z>20时回收箭,在ArrowFlyActionManager类和ArrowFlyAction类实现。颤抖时间是0.8s,在ArrowTremble类中实现。
public class ArrowFlyActionManager : SSActionManager
{
private ArrowFlyAction fly;
public Controllor scene_controller;
protected void Start()
{
scene_controller = (Controllor)SSDirector.GetInstance().CurrentSceneControllor;
scene_controller.action_manager = this;
}
public void ArrowFly(GameObject arrow,Vector3 wind,Vector3 f)
{
fly = ArrowFlyAction.GetSSAction(wind, f);
this.RunAction(arrow, fly, this);
}
}
public class ArrowFlyAction : SSAction
{
public Vector3 force;
public Vector3 wind;
private ArrowFlyAction() { }
public static ArrowFlyAction GetSSAction(Vector3 wind,Vector3 force_)
{
ArrowFlyAction action = CreateInstance<ArrowFlyAction>();
action.force = force_;
action.wind = wind;
return action;
}
public override void Update(){}
public override void FixedUpdate()
{
this.gameobject.GetComponent<Rigidbody>().AddForce(wind, ForceMode.Force);
if (this.transform.position.z > 25 || this.gameobject.tag == "hit"){
this.destroy = true;
this.callback.SSActionEvent(this,this.gameobject);
}
}
public override void Start()
{
gameobject.transform.LookAt(force);
gameobject.GetComponent<Rigidbody>().isKinematic = false;
gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
gameobject.GetComponent<Rigidbody>().velocity = Vector3.zero;
gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
}
}
public class ArrowTremble : SSAction
{
public float radian = 0;
public float per_radian = 3f;
public float radius = 0.01f;
public float left_time = 0.8f;
Vector3 old_pos;
private ArrowTremble()
{
}
public override void Start()
{
old_pos = transform.position;
}
public static ArrowTremble GetSSAction()
{
ArrowTremble action = CreateInstance<ArrowTremble>();
return action;
}
public override void Update()
{
left_time -= Time.deltaTime;
if (left_time <= 0){
transform.position = old_pos;
this.destroy = true;
this.callback.SSActionEvent(this);
}
radian += per_radian;
float dy = Mathf.Cos(radian) * radius;
transform.position = old_pos + new Vector3(0, dy, 0);
}
public override void FixedUpdate()
{
}
}
- ArrowCollider.cs
控制箭射中箭靶后的操作,调用ScoreRecorder计算分数,加上环数对应的分数。
public class ArrowCollider : MonoBehaviour
{
public Controllor scene_controller;
public ScoreRecorder recorder;
void Start()
{
scene_controller = SSDirector.GetInstance().CurrentSceneControllor as Controllor;
recorder = Singleton<ScoreRecorder>.Instance;
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.name == "Cylinder1"||c.gameObject.name == "Cylinder2"||c.gameObject.name == "Cylinder3"||c.gameObject.name == "Cylinder4"||c.gameObject.name == "Cylinder5") {
gameObject.transform.parent.gameObject.GetComponent<Rigidbody>().isKinematic = true;
gameObject.SetActive(false);
float point = Mathf.Sqrt (this.gameObject.transform.position.x * this.gameObject.transform.position.x + this.gameObject.transform.position.y * this.gameObject.transform.position.y);
recorder.Record(5-(int)Mathf.Floor(point*2));
}
}
}
- ArrowFactory.cs
用于管理arrow。调用GetArrow得到箭,如果unusedArrowList中有箭,就可以直接用,如果没有就需要使用预制创造新的箭。调用FreeArrow释放箭,将usingArrowList中的箭转移到unusedArrowList中。
public class ArrowFactory : MonoBehaviour {
public GameObject arrow = null;
private List<GameObject> usingArrowList = new List<GameObject>();
private Queue<GameObject> unusedArrowList = new Queue<GameObject>();
public Controllor sceneControler;
public GameObject GetArrow()
{
if (unusedArrowList.Count == 0){
arrow = Instantiate(Resources.Load<GameObject>("Prefabs/arrow"));
}
else{
arrow = unusedArrowList.Dequeue();
arrow.gameObject.SetActive(true);
}
arrow.transform.position = new Vector3 (0, 0, -10);
usingArrowList.Add(arrow);
return arrow;
}
public void FreeArrow()
{
for (int i = 0; i < usingArrowList.Count; i++) {
if (usingArrowList[i].transform.position.y <= -8||usingArrowList[i].transform.position.y >= 8) {
usingArrowList[i].GetComponent<Rigidbody>().isKinematic = true;
usingArrowList[i].SetActive(false);
usingArrowList[i].transform.position = new Vector3 (0, 0, 0);
unusedArrowList.Enqueue(usingArrowList[i]);
usingArrowList.Remove(usingArrowList[i]);
i--;
}
}
}
}
- Controllor.cs
进行一些操作的控制。Update函数用于在游戏开始时释放箭,LoadResources函数用于加载资源,haveArrowOnPort函数用于确认有箭准备发射,create函数用于得到箭(依赖于Arrow.cs的GetArrow函数),MoveBow函数使箭随着鼠标移动,Shoot函数用于控制箭的发射,CreateWind函数用于随机生成风(具体来说是风的向量的x和y值)并生成右上角显示的字符串,还包括一些基础的set变量、get变量的函数。
public class Controllor : MonoBehaviour, IUserAction, ISceneControllor
{
public ScoreRecorder recorder;
public ArrowFactory arrow_factory;
public ArrowFlyActionManager action_manager;
public UserGUI user_gui;
private GameObject arrow;
private GameObject target;
private bool game_start = false;
private string wind = "";
private float wind_directX;
private float wind_directY;
void Update()
{
if(game_start) arrow_factory.FreeArrow ();
}
public void LoadResources()
{
target = Instantiate(Resources.Load("Prefabs/target", typeof(GameObject))) as GameObject;
}
public bool haveArrowOnPort()
{
return (arrow != null);
}
void Start ()
{
SSDirector director = SSDirector.GetInstance();
director.CurrentSceneControllor = this;
arrow_factory = Singleton<ArrowFactory>.Instance;
recorder = gameObject.AddComponent<ScoreRecorder>() as ScoreRecorder;
user_gui = gameObject.AddComponent<UserGUI> () as UserGUI;
action_manager = gameObject.AddComponent<ArrowFlyActionManager>() as ArrowFlyActionManager;
LoadResources();
}
public void create(){
if (arrow == null) {
CreateWind();
arrow = arrow_factory.GetArrow();
}
}
public void MoveBow(Vector3 mousePos)
{
if (!game_start){
return;
}
arrow.transform.LookAt(mousePos * 30);
}
public void Shoot(Vector3 mousePos)
{
if(game_start){
Vector3 wind = new Vector3(wind_directX, wind_directY, 0);
action_manager.ArrowFly(arrow, wind,mousePos*30);
arrow = null;
}
}
public void CreateWind()
{
string Horizontal = "", Vertical = "", level = "";
wind_directX = Random.Range(-4, 4);
wind_directY = Random.Range(-4, 4);
if (wind_directX > 0){
Horizontal = "西";
}
else if (wind_directX <= 0){
Horizontal = "东";
}
if (wind_directY > 0){
Vertical = "南";
}
else if (wind_directY <= 0){
Vertical = "北";
}
if ((wind_directX + wind_directY) / 2 > -1 && (wind_directX + wind_directY) / 2 < 1){
level = "1 级";
}
else if ((wind_directX + wind_directY) / 2 > -2 && (wind_directX + wind_directY) / 2 < 2){
level = "2 级";
}
else if ((wind_directX + wind_directY) / 2 > -3 && (wind_directX + wind_directY) / 2 < 3){
level = "3 级";
}
else if ((wind_directX + wind_directY) / 2 > -5 && (wind_directX + wind_directY) / 2 < 5){
level = "4 级";
}
wind = Horizontal + Vertical + "风" + " " + level;
}
public int GetScore()
{
return recorder.score;
}
public string GetWind()
{
return wind;
}
public void Restart()
{
SceneManager.LoadScene(0);
}
public void BeginGame()
{
game_start = true;
}
}
- Interface.cs
public interface ISceneControllor
{
void LoadResources();
}
public interface IUserAction
{
void MoveBow(Vector3 mousePos);
void Shoot (Vector3 mousePos);
int GetScore();
void Restart();
string GetWind();
void BeginGame();
void create ();
bool haveArrowOnPort();
}
- ScoreRecorder.cs
用于计算分数,比较简单,将point加到score就完成了。
public class ScoreRecorder : MonoBehaviour
{
public int score = 0;
void Start()
{
score = 0;
}
public void Record(int point)
{
score = score + point;
}
}
- UserGUI.cs
game_start变量标志游戏是否开始。OnGUI函数中,game_start为false时,显示游戏开始按键,game_start为true时,显示分数、风向和重新开始的按键。Update函数中,按动空格可以得到箭,有箭准备发射时,箭跟随鼠标移动,鼠标按动时发射。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UserGUI : MonoBehaviour {
private IUserAction action;
GUIStyle style1 = new GUIStyle();
GUIStyle style2 = new GUIStyle();
private bool game_start = false;
void Start ()
{
action = SSDirector.GetInstance().CurrentSceneControllor as IUserAction;
style1.fontSize = 15;
style2.fontSize = 25;
}
void Update()
{
if(game_start)
{
if (action.haveArrowOnPort ()) {
if (Input.GetMouseButton(0)) {
Vector3 mousePos = Camera.main.ScreenPointToRay(Input.mousePosition).direction;
action.MoveBow(mousePos);
}
if (Input.GetMouseButtonUp(0)) {
Vector3 mousePos = Camera.main.ScreenPointToRay(Input.mousePosition).direction;
action.Shoot(mousePos);
}
}
if (Input.GetKeyDown(KeyCode.Space)) action.create();
}
}
private void OnGUI()
{
if(game_start){
GUI.Label(new Rect(10, 10, 200, 50), "分数:", style1);
GUI.Label(new Rect(55, 10, 200, 50), action.GetScore().ToString(), style1);
GUI.Label(new Rect(Screen.width - 170, 30, 200, 50), "风向:", style1);
GUI.Label(new Rect(Screen.width - 140, 30, 200, 50), action.GetWind(), style1);
if (GUI.Button(new Rect(Screen.width - 170, 0, 100, 30), "重新开始")){
action.Restart();
return;
}
}
else{
GUI.Label(new Rect(Screen.width / 2 - 80, Screen.width / 2 - 320, 100, 100), "Arrow Shooting", style2);
if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.width / 2 - 200, 100, 50), "游戏开始")){
game_start = true;
action.BeginGame();
}
}
}
}