文章目录

  • Hit UFO改进版
    • 一、改进要求
    • 二、MVC图
    • 三、gitee
    • 四、程序实现
      • 4.1 FirstController
      • 4.2 Interface
      • 4.3 ActionManagerAdapter
      • 4.4 PhsisFlyActionManager
      • 4.5 PhysisUFOFlyAction
      • 4.5 DiskFactory
    • 五、效果展示
  • 射箭游戏
    • 一、实现功能:
    • 二、程序实现:
      • 2.1 SceneController & interface
      • 2.2 GameStateController
      • 2.3 UserInterface
      • 2.4 ArrowFactory
      • 2.5 ArrowCollider
      • 2.6 ArrowController
      • 2.7 bodytremble
    • 三、实现效果

Hit UFO改进版

一、改进要求

  1. 按 adapter模式 设计图修改飞碟游戏
  2. 使它同时支持物理运动与运动学(变换)运动

二、MVC图

三、gitee

gitee

四、程序实现

本次作业使用上一次作业Hit UFO来进行改进,主要实现部分为增加了适配器和物理模式的切换,其余部分几乎没有改变,详情见上一次博客 hit ufo 基础版

4.1 FirstController

沿用之前的代码,只不过增加了一个用户操作changeStyle,在其中要调用飞碟工厂类中的rmgrivity函数来取消调刚体重力,和刚体速度

    public void changeStyle(){if (isPhy){disk_factory.rmgrivity();}isPhy = !isPhy;}

4.2 Interface

增加了用户操作changeStyle

public interface IUserAction
{void Hit(Vector3 pos);int GetScore();void GameOver();void ReStart();void BeginGame();void changeStyle();
}

4.3 ActionManagerAdapter

作为插入到原有的动作管理类上层的一个文件,决定着调用哪一种动作完成请求

public class ActionManagerAdapter : MonoBehaviour, IActionManager
{public FlyActionManager action_manager;public PhysisFlyActionManager phy_action_manager;public void playDisk(GameObject disk, float angle, float power, bool isPhy){Debug.Log("phy is : !" + isPhy);if (isPhy){Debug.Log("phy");//disk.AddComponent<>phy_action_manager.UFOFly(disk, angle, power);}else{Debug.Log("not phy");action_manager.UFOFly(disk, angle, power);}}// Use this for initializationvoid Start(){action_manager = gameObject.AddComponent<FlyActionManager>() as FlyActionManager;phy_action_manager = gameObject.AddComponent<PhysisFlyActionManager>() as PhysisFlyActionManager;}}

4.4 PhsisFlyActionManager

物理动作管理类,用于管理物理动作

public class PhysisFlyActionManager : SSActionManager
{public PhysisUFOFlyAction fly;                            //飞碟飞行的动作//public FirstController scene_controller;             //当前场景的场景控制器protected void Start(){}//飞碟飞行public void UFOFly(GameObject disk, float angle, float power){fly = PhysisUFOFlyAction.GetSSAction(disk.GetComponent<DiskData>().direction, angle, power);this.RunAction(disk, fly, this);}
}

4.5 PhysisUFOFlyAction

设定飞碟物理模式下的运动,这里通过添加重力以及velocity实现

public class PhysisUFOFlyAction : SSAction
{private Vector3 start_vector;                              //初速度向量public float power;private PhysisUFOFlyAction() { }public static PhysisUFOFlyAction GetSSAction(Vector3 direction, float angle, float power){//初始化物体将要运动的初速度向量PhysisUFOFlyAction action = CreateInstance<PhysisUFOFlyAction>();if (direction.x == -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;}action.power = power;return action;}public override void FixedUpdate(){//判断是否超出范围if (this.transform.position.y < -10){this.destroy = true;this.callback.SSActionEvent(this);}}public override void Update() { }public override void Start(){//使用重力以及给一个初速度gameobject.GetComponent<Rigidbody>().velocity = power / 20 * start_vector;gameobject.GetComponent<Rigidbody>().useGravity = true;}
}

4.5 DiskFactory

工厂类中增加了rmgrivity函数,用于从物理模式切换到运动学模式时,消除物理学的刚体组件中的参数

    public void rmgrivity(){for (int i = 0; i < used.Count; i++){used[i].GetComponent<Rigidbody>().useGravity = false;used[i].GetComponent<Rigidbody>().velocity = 0*Vector3.zero;}for (int i = 0; i < free.Count; i++){free[i].GetComponent<Rigidbody>().useGravity = false;free[i].GetComponent<Rigidbody>().velocity = 0 * Vector3.zero;}}

五、效果展示

  • 物理模式:

  • 运动学模式:

射箭游戏

一、实现功能:

  • 靶对象为 5 环,按环计分;
  • 箭对象,射中后要插在靶上
    • 射中后,箭对象产生颤抖效果,持续八秒
  • 游戏仅一轮,无限 trials
    • 添加一个风向和强度标志,提高难度
  • 模拟真实射箭过程
    • 按住右键调整弓箭方向
    • 按住左键进行蓄力,松开后发射,根据蓄力时间决定力度

二、程序实现:

2.1 SceneController & interface

首先定义用户动作,并在SceneController中定义动作调用

namespace Scene
{public interface IUserAction{void getArrow();void shootArrow(Vector3 mousePos,float xuli);void changeArrowpos(Vector3 mousePos);}public interface ISceneController{void addScore(int point);//void showTips(int point);void changeWind();int getWindDirection();int getWindStrength();bool ifReadyToShoot();}public class SceneController : System.Object, IUserAction, ISceneController{private static SceneController instance;private GameStateController gameStateController;private ArrowController arrowController;public static SceneController getInstance(){if (instance == null) instance = new SceneController();return instance;}public void setGameController(GameStateController gsc){gameStateController = gsc;}public void setArrowController(ArrowController _arrowController){arrowController = _arrowController;}public void addScore(int point){gameStateController.addScore(point);}public void changeWind(){gameStateController.changeWind();}public void getArrow(){arrowController.getArrow();}public int getWindDirection(){return gameStateController.getWindDirec();}public int getWindStrength(){return gameStateController.getWindStrength();}public bool ifReadyToShoot(){return arrowController.ifReadyToShoot();}public void shootArrow(Vector3 mousePos,float xuli){arrowController.shootArrow(mousePos,xuli);}public void changeArrowpos(Vector3 mousePos){arrowController.changeArrowpos(mousePos);}}

2.2 GameStateController

这里完成积分工作和风向提示,在OnGUI中更新数据

public class GameStateController : MonoBehaviour {public int i = 0;private int score = 0, windDir = 0, windStrength = 0;GUIStyle bold_style = new GUIStyle();GUIStyle score_style = new GUIStyle();GUIStyle text_style = new GUIStyle();GUIStyle over_style = new GUIStyle();private int high_score = 0;//private const float TIPS_SHOW_TIME = 0.5f;//private GameObject canvas, scoreText, tipsText, windText;private SceneController scene;private string[] windDirectionArray;// Use this for initializationvoid Start () {scene = SceneController.getInstance();scene.setGameController(this);windDirectionArray = new string[8] { "↑", "↗", "→", "↘", "↓", "↙", "←", "↖" };changeWind();}public void changeWind(){windDir = UnityEngine.Random.Range(0,8);windStrength = UnityEngine.Random.Range(0, 8);}internal void addScore(int point){i++;if (i % 2 == 0)high_score += point;changeWind();}// Update is called once per framevoid Update () {}void OnGUI(){bold_style.normal.textColor = new Color(1, 0, 0);bold_style.fontSize = 16;text_style.normal.textColor = new Color(0, 0, 0, 1);text_style.fontSize = 16;score_style.normal.textColor = new Color(1, 0, 1, 1);score_style.fontSize = 16;over_style.normal.textColor = new Color(1, 0, 0);over_style.fontSize = 25;GUI.Label(new Rect(10, 5, 200, 50), "分数:" +high_score, text_style);GUI.Label(new Rect(10, 105, 200, 50), "Wind: " + windDirectionArray[windDir] + " x" + windStrength, text_style);}internal int getWindDirec(){return windDir;}internal int getWindStrength(){return windStrength;}}

2.3 UserInterface

检测鼠标的动作,这里定义了一个时间用于判断蓄力,并检测鼠标左右键的按下和松开,来进行角度调整和拉弓射箭,模拟真实射箭环境

public class UserInterface : MonoBehaviour {private IUserAction action;private ISceneController scene;bool gameStart = false;int timeCount = 0;bool left = false;bool right = false;bool timeflag;float xuli;// Use this for initializationvoid Start () {action = SceneController.getInstance() as IUserAction;scene = SceneController.getInstance() as ISceneController;}void Update () {if (!gameStart){action.getArrow();gameStart = true;}if (timeCount%75==0) action.getArrow();if (Input.GetMouseButtonUp(1)){right = false;}if (scene.ifReadyToShoot()){//if (Input.GetMouseButtonDown(1)){right = true;}if (right){Vector3 mousePos = Camera.main.ScreenPointToRay(Input.mousePosition).direction;action.changeArrowpos(mousePos);}if (Input.GetMouseButtonDown(0)){timeflag = true;xuli = 0;}//左键松开,射出弓箭if (Input.GetMouseButtonUp(0)){Vector3 mousePos = Camera.main.ScreenPointToRay(Input.mousePosition).direction;action.shootArrow(mousePos,xuli);timeCount = 0;timeflag = false;}if (timeflag){xuli += Time.deltaTime;}}timeCount++;}}

2.4 ArrowFactory

弓箭的工厂类,定义弓箭的产生和获取

public class ArrowFactory : System.Object
{private static ArrowFactory instance;private GameObject ArrowPrefabs;private List<GameObject> usingArrowList = new List<GameObject>();private List<GameObject> freeArrowList = new List<GameObject>();private Vector3 INITIAL_POS = new Vector3(0, 0, -19);public static ArrowFactory getInstance(){if (instance == null) instance = new ArrowFactory();return instance;}public void init(GameObject _arrowPrefabs){ArrowPrefabs = _arrowPrefabs;}internal void detectArrowsReuse(){for(int i = 0; i < usingArrowList.Count; i++){if(usingArrowList[i].transform.position.y <= -8){usingArrowList[i].GetComponent<Rigidbody>().isKinematic = true;usingArrowList[i].SetActive(false);usingArrowList[i].transform.position = INITIAL_POS;freeArrowList.Add(usingArrowList[i]);usingArrowList.Remove(usingArrowList[i]);i--;SceneController.getInstance().changeWind();}} }internal GameObject getArrow(){if(freeArrowList.Count == 0){GameObject newArrow = Camera.Instantiate(ArrowPrefabs);usingArrowList.Add(newArrow);return newArrow;}else{GameObject oldArrow = freeArrowList[0];freeArrowList.RemoveAt(0);oldArrow.SetActive(true);usingArrowList.Add(oldArrow);return oldArrow;}}
}

2.5 ArrowCollider

放在箭头上的脚本,用于判断是否碰触到板子,然后为弓箭添加颤抖组件

public class ArrowCollider : MonoBehaviour {private ISceneController scene;float radian = 0;                             // 弧度  float per_radian = 3f;                        // 每次变化的弧度  float radius = 0.01f;                         // 半径  Vector3 old_pos;                              // 开始时候的坐标  public float left_time = 8f;                 //动作持续时间void Start () {scene = SceneController.getInstance() as ISceneController;}void Update () {}[System.Obsolete]void OnTriggerEnter(Collider other){if (other.gameObject.tag == "target"){gameObject.transform.parent.gameObject.GetComponent<Rigidbody>().isKinematic = true;gameObject.SetActive(false);int points = 0;if(other.gameObject.name.ToString() == "1"){points = 1;}if (other.gameObject.name.ToString() == "2"){points = 2;}if (other.gameObject.name.ToString() == "3"){points = 3;}if (other.gameObject.name.ToString() == "4"){points = 4;}if (other.gameObject.name.ToString() == "5"){points = 5;}if (other.gameObject.name.ToString() == "6"){points = 6;}scene.addScore(points);//scene.showTips(points);gameObject.transform.parent.FindChild("Body").gameObject.AddComponent<bodytremble>();Debug.Log("pengzhuang");}}
}

2.6 ArrowController

增加风力,并控制弓箭和靶子的产生和选择

public class ArrowController : MonoBehaviour {public GameObject TargetPrefabs, ArrowPrefabs;private GameObject holdingArrow, target;private const int SPEED = 40;private SceneController scene;private Vector3[] winds = new Vector3[8]{new Vector3(0, 1, 0), new Vector3(1,1,0), new Vector3(1,0,0), new Vector3(1,-1,0), new Vector3(0,-1,0), new Vector3(-1,-1,0), new Vector3(-1,0,0), new Vector3(-1,1,0)};private void Awake(){ArrowFactory.getInstance().init(ArrowPrefabs);}// Use this for initializationvoid Start () {scene = SceneController.getInstance();scene.setArrowController(this);target = Instantiate(TargetPrefabs);}// Update is called once per framevoid Update () {ArrowFactory.getInstance().detectArrowsReuse();}public bool ifReadyToShoot(){return (holdingArrow != null);}internal void getArrow(){if (holdingArrow == null) holdingArrow = ArrowFactory.getInstance().getArrow();}internal void shootArrow(Vector3 mousePos,float xuli){holdingArrow.transform.LookAt(mousePos * 30);holdingArrow.GetComponent<Rigidbody>().isKinematic = false;addWind();  //箭在射出过程中会持续受到一个风力if(xuli <= 2){holdingArrow.GetComponent<Rigidbody>().AddForce(mousePos * 30 * xuli, ForceMode.Impulse);}else{holdingArrow.GetComponent<Rigidbody>().AddForce(mousePos * 60, ForceMode.Impulse);}holdingArrow = null;}internal void changeArrowpos(Vector3 mousePos){holdingArrow.transform.LookAt(mousePos * 30);}private void addWind(){int windDir = scene.getWindDirection();int windStrength = scene.getWindStrength();Vector3 windForce = winds[windDir]*50;holdingArrow.GetComponent<Rigidbody>().AddForce(windForce, ForceMode.Force);}
}

2.7 bodytremble

颤抖脚本,以原来位置为基础,进行7弧度的颤抖

public class bodytremble : MonoBehaviour
{float radian = 0;                             // 弧度  float per_radian = 7f;                        // 每次变化的弧度  float radius = 0.01f;                         // 半径  Vector3 old_pos;                              // 开始时候的坐标  public float left_time = 8f;                 //动作持续时间// Start is called before the first frame updatevoid Start(){old_pos = transform.position;}// Update is called once per framevoid Update(){left_time -= Time.deltaTime;if (left_time <= 0){//颤抖后回到初始位置transform.position = old_pos;}// 弧度每次增加radian += per_radian;//y轴的位置变化,上下颤抖float dy = Mathf.Cos(radian) * radius;transform.position = old_pos + new Vector3(0, dy, 0);Debug.Log("tremble");}
}

三、实现效果

  • 左上摄像机用于观察颤抖效果,右上摄像机用于观察中靶情况

  • 动画演示:右键移动瞄准,左键按住蓄力,松开发射,这里设定了颤抖8秒,所以左上一直在抖,有点鬼畜

物体碰撞和检测——Hit UFO改进版射箭游戏相关推荐

  1. 与游戏世界交互——Hit UFO

    目录 Hit UFO 一.游戏规则 二.gitee 三.程序实现 3.1 SSDirector.cs 3.2 SSAction.cs 3.3 SSActionManager.cs 3.4 Sequen ...

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

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

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

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

  4. Unity 3D学习笔记(5)物体的碰撞/触发检测

    前言 在学习了刚体组件后,我们看到了物体的物理效果,比如重力,碰撞等等,那么该如何检测他们之间的碰撞呢? 在Unity中,有碰撞检测和触发检测两种类型,他们的简单概括如下: 一.碰撞检测 1.如何使用 ...

  5. Unity 2D检测物体碰撞

    文章目录 添加物理脚本 使用脚本检测碰撞 添加物理脚本 Unity2D中,检测物体碰撞首相要给物体添加两个属性分别是: rigibody和collider,刚体和碰撞器. collider有不同的形状 ...

  6. 六、改进版(Hit UFO)

    文章目录 1.改进飞碟(Hit UFO)游戏: 游戏内容要求: 2.实现 类图 adapter(适配器)模式 改进 IActionManager PhysisActionManager RoundAc ...

  7. Unity 判断两物体碰撞方向

    Unity 判断两物体碰撞方向 问题描述:游戏玩家可以在两个平面之间不断进行跳跃,且出现玩家顶着上面平面飞着走的情况. 问题原因:玩家碰撞体与平面不断进行碰撞体检测,导致游戏玩家可以不断进行跳跃. 解 ...

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

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

  9. 【30分钟学完】canvas动画|游戏基础(7):动量守恒与多物体碰撞

    前言 一路沿着本系列教程学习的朋友可能会发现,前面教程中都尽量避免提及质量的概念,很多运动概念也时刻提醒大家这不是真实的物体运动.因为真实的物体运动其实跟质量都是密不可分的,而且质量的引入自然必须提及 ...

最新文章

  1. 记住:永远不要在 MySQL 中使用 UTF-8
  2. 基于 GraphQL 实践的一点思考
  3. Java中常见数据结构Map之HashMap
  4. linux高级运维要会的,linux高级运维必会命令
  5. 阿里云华北3超大规模数据中心开服 ECS全系列降价20%
  6. 小程序上让随机的两个点都显示在地图可视区域
  7. NTU 课程笔记:MAS 714(16) 图灵机
  8. mysql 事务日志备份_事务日志备份与恢复 5
  9. 变量不合法的表达式JAVA_Java8中lambda表达式的语法,别人都会的,你还不会吗?「一」...
  10. 深度学习笔记(47) 神经风格迁移
  11. ssm项目的maven-pom.xml
  12. 2021-10-26
  13. 深度学习 黑白图片 着色
  14. php输出26个大小写英文字母
  15. stm32wb55 flash
  16. C语言习题:编程序将”China”译成密码[C语言]
  17. Visual Paradigm在 Windows系统电脑上安装
  18. CPU不同字母的意思
  19. Android Studio 连接夜神模拟器的方法
  20. MATLAB 矢量场

热门文章

  1. 计算机编程怎样打符号,在CAD中如何输入一些特殊符号?比如乘除、符号.
  2. FLYMCU之串口下载到stm32单片机注意点
  3. Jsp的内置对象(重点)
  4. HTTP(Request)
  5. Matlab创建蕨形叶和塞平斯基三角形的图形用户界面(wzl)
  6. php中mb_str_split分割字符串为数组的函数介绍与使用以及低版本php函数实现
  7. 围观一个无限循环的奇葩代码,把电脑弄死机了
  8. windows 无效驱动器 问题
  9. 【今日数据】《中国民政统计年鉴》1949-2021(免费),70多年数据大集结!
  10. Centos7根目录扩容方法(添加一块磁盘扩容根目录)