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;//重力的速度向量,t时为0private 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(){//User = gameObject.AddComponent<UserGUI>() as UserGUI;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 Disk disk_prefab = null;                 //飞碟预制体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);//disk_prefab.getGameObject().transform.position = new Vector3(-10,0,0);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.5f;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;                                              // 0 游戏未开始,1 游戏进行 ,2 游戏开始private int round = 1;private int score = 0;private float time = 2f;private float i = 0;public UserGUI User;public MySceneActionManager actionManager;//public Disk disk;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;//LoadResources();}void Update(){if (gamestate == 2){gamestate = 1;}if (gamestate == 1){if (i >= time){   if (score > 10 && round == 1){time -= 0.3f;round = 2;}else if(score > 20 && round == 2){time -= 0.5f;round = 3;}else if(score > 30 && round == 3){time += 0.3f;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.5f, 3.5f);disk.Angle = Random.Range(10f, 30f);disk.Gravity = Random.Range(-0.5f, -0.8f);disk.disk.transform.position = new Vector3(-10,Random.Range(-3f, 2f),0);}else if (round == 2){disk.Power = Random.Range(3.5f, 5f);disk.Angle = Random.Range(5f, 35f);disk.Gravity = Random.Range(-0.6f, -1f);disk.disk.transform.position = new Vector3(-10,Random.Range(-4f, 1f),0);}else if (round == 3){disk.Power = Random.Range(5.5f, 8f);disk.Angle = Random.Range(5f, 35f);disk.Gravity = Random.Range(-1f, -1.5f);disk.disk.transform.position = new Vector3(-10,Random.Range(-5f, 3f),0);}else if (round == 4){disk.Power = Random.Range(7f, 10f);disk.Angle = Random.Range(5f, 35f);disk.Gravity = Random.Range(-2f, -2.5f);disk.disk.transform.position = new Vector3(-10,Random.Range(-5f, 2f),0);Disk disk2 = diskfactory.GetDisk();disk2.Power = Random.Range(6f, 8f);disk2.Angle = Random.Range(5f, 35f);disk2.Gravity = Random.Range(-1f, -3f);disk2.disk.transform.position = new Vector3(-10,Random.Range(-4.5f, 1f),0);actionManager.fly_disk(disk2);}actionManager.fly_disk(disk);}public void Restart(){score = 0;gamestate = 2;}public void Stopgame(){gamestate = 0;round = 1;time = 2f;}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;}
}
  • UserGui (用户界面)
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)游戏相关推荐

  1. Unity实现简易打飞碟(Hit UFO)

    Unity实现简易打飞碟(Hit UFO) 前言 这是中山大学数据科学与计算机学院2019年3D游戏编程与设计的第四次作业 所有项目与代码已上传至github当中,欢迎大家访问. github个人主页 ...

  2. Unity实现鼠标打飞碟(Hit UFO)adapter模式

    Unity实现鼠标打飞碟(Hit UFO)adapter模式 与上一版本的变化 按 adapter模式设计图修改飞碟游戏 使它同时支持物理运动与运动学(变换)运动 适配器模式 适配器模式(Adapte ...

  3. 3D游戏编程与设计作业6-Unity实现打飞碟游戏改进版(Hit UFO)

    改进飞碟(Hit UFO)游戏 游戏内容要求 按adapter模式设计图修改飞碟游戏 使它同时支持物理运动与运动学(交换)运动 编程实践 本次作业直接在上一次打飞碟游戏的基础上增加adapter设计模 ...

  4. Unity3d Note5(鼠标打飞碟(Hit UFO)游戏)

    1.作业要求 2.具体设计 (1).制备预制体作为飞碟 (2).了解一下Singleton模板类 (3).了解一下工厂模式 (3).设计具体要实现的类 3.程序代码 成果视频 1.作业要求 编写一个简 ...

  5. Unity游戏Hit UFO实现

    Unity游戏Hit UFO 实现 一.游戏内容 游戏有n个round,每个round都包括10次trial 每个trail的飞碟颜色.大小.发射位置.速度.角度.同时出现的个数不同. 每个飞碟出现有 ...

  6. Unity实现简易打飞碟改进版(Hit UFO)

    Unity实现简易打飞碟改进版(Hit UFO) 前言 这是中山大学数据科学与计算机学院2019年3D游戏编程与设计的第六次作业 所有项目与代码已上传至github当中,欢迎大家访问. github个 ...

  7. 改进飞碟(Hit UFO)游戏

    1.改进飞碟(Hit UFO)游戏: 游戏内容要求: 按 adapter模式 设计图修改飞碟游戏 使它同时支持物理运动与运动学(变换)运动 新增的类或者有修改的类如下: ActionManagerAd ...

  8. 3D游戏设计作业5:改进飞碟(Hit UFO)游戏

    改进飞碟(Hit UFO)游戏: 游戏截图: 1,作业要求 游戏内容要求: 1,按adapter模式设计图修改飞碟游戏 2,使它同时支持物理运动与运动学(变换)运动 2,设计思路 1,分析adapte ...

  9. Unity3D游戏编程-鼠标打飞碟

    Unity3D游戏编程-鼠标打飞碟 文章目录 Unity3D游戏编程-鼠标打飞碟 一.作业要求 二.项目配置 三.项目演示 视频演示 项目下载 文字说明 项目截图 四.前置内容 MVC模式 动作管理器 ...

最新文章

  1. 锁的算法,隔离级别的问题
  2. LongAdder解析 1
  3. python hdfs初体验
  4. 多重签名(Multisig)
  5. 强化学习总结(3-4)——无模型的价值函数的预测,蒙特卡洛和TD时序差分方法
  6. bootstrapV4.6.0实现标签页(改造v3.3.7)- 代码篇
  7. 检测商品简码是否唯一,不重复
  8. Linux c学习--进程基础学习
  9. cocos creator横竖屏适配方案及常用设计尺寸
  10. 爬取豆瓣音乐Top250详细教程
  11. C# 切换中英文输入法
  12. CSS层叠样式表(Cascading Style Sheets)
  13. 【数值分析】Doolittle分解和Cholesky分解的Python实现
  14. python分割压缩_python实现文件压缩与解压
  15. Neocities 免费HTML 网站空间,每月200 GB 流量托管静态网页超简单
  16. Python神秘的魔法函数
  17. RNA-seq流程学习笔记(10)-使用HTSeq-count软件对reads进行计数
  18. html怎么渲染到css,css是怎么渲染的?
  19. Could not reserve enough space for 2097152KB object heap 解决
  20. 做什么样的软件更赚钱之案例分析

热门文章

  1. html标签中加入颜色,html怎么给span添加颜色
  2. 诺基亚Lumia630传感器并未缩水
  3. Week4 常用类 麻了
  4. day05循环结构while循环嵌套控制条件语句方法(函数)
  5. Python学习-列表的常见操作
  6. 企业WAP建站的10个理由
  7. 浅谈SPICE原理及应用
  8. Nginx服务器启停命令
  9. linux 远程扫描仪,技术|如何在ubuntu桌面配置一个网络打印机和扫描仪
  10. Vijos P1836 HYS与七夕节大作战