打靶游戏:

    1.靶对象为 5 环,按环计分;
    2.箭对象,射中后要插在靶上;
    3.游戏仅一轮,无限 trials;

增强要求:

 添加一个风向和强度标志,提高难度


游戏成品图:

UML图:


游戏设计思路&大致过程&核心代码
游戏对象主要由三个,靶、弓和箭,射出去的箭可以复用(利用简单工厂),将箭从弓的位置加上常力向某个方向射出。最后实现增强功能——添加常力作为风向并且在界面中显示出风向(只设置了界面上的左右两个不同方向)以及风力(0~50)。

1.首先设置游戏对象——靶子、弓和箭。
    为了实现识别不同的环,通过五个共圆心的圆柱体(高度不同——通过设置Transform)来识别箭首先碰到的环(小环厚度较大)。

游戏的弓和箭——刚开始用圆柱体(箭身)+胶囊(箭头)实现箭,在后来进行界面优化时下载了模型。将模型直接作为预制即可。

2.大致明确类——建立在之前实验的基础上

2.1复用之前的类:不需要修改

SSDirector,Singleton,动作类——CCSequenceAction,SSAction,SSActionEvetType,SSActionManager

2.2需要修改的类:CCActionManager,FirstController,SceneController,UserGUI

3.设计基本UML图,调试好基本代码,只有空函数——不具体实现。

4.根据课堂实验5实现自由移动弓

在Bow的预制对象上挂上下述代码即可。利用方向控制键(键盘)可以控制弓的移动。

5.实现UI界面

6.实现箭的工厂类

7.实现射出箭的动作

8.实现箭插在靶上和分数识别计算

9.添加风力和风的方向

关键设置——在上述的第8点算是这次实验的一大难点,其余的基本在之前的实验都已经实现过类似的操作。


详细代码:

SSDirector.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Mygame;public class SSDirector : System.Object {private static SSDirector _instance;public ISceneController currentSceneController { get; set; }public bool running{ get; set; }public static SSDirector getInstance() {if (_instance == null) {_instance = new SSDirector ();}return _instance;}public int getFPS() {return Application.targetFrameRate;}public void setFPS(int fps) {Application.targetFrameRate = fps;}
}

FirstController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Com.Mygame;public class FirstController : MonoBehaviour, ISceneController, IUserAction {public IshootArrow actionManager {get; set;}public ArrowFactory arrowfactory {get; set;}public GameObject Arrow;public GameObject Bow;public Text ScoreText;  // 显示得分public int score;void Awake() {SSDirector director = SSDirector.getInstance ();director.setFPS (60);director.currentSceneController = this;director.currentSceneController.LoadResources ();actionManager = gameObject.AddComponent<CCActionManager>();arrowfactory = gameObject.AddComponent<ArrowFactory>();}public void hit(Vector3 dir) {actionManager.playArrow(Bow.transform.position);}void Update() {ScoreText.text = "Score:" + score.ToString();}public float getWindforce() {return actionManager.getforce();}public void StartGame() {//
        }public void ShowDetail() {GUI.Label(new Rect(220, 50, 350, 250), "you can controll the bow and click mouse to emit arrow"); }// 接口具体实现--------------------------------------------------------------------public void LoadResources() {Debug.Log ("load...\n");Instantiate(Resources.Load("prefabs/Target"));Bow = Instantiate(Resources.Load("prefabs/Bow")) as GameObject; Arrow.transform.position = Bow.transform.position;}public void Pause(){}public void Resume(){}}

SceneController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Mygame;namespace Com.Mygame {public interface ISceneController {void LoadResources ();float getWindforce();}public interface IUserAction {void ShowDetail();void StartGame();void hit(Vector3 dir);}}

UserGUI.cs

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Com.Mygame;public class UserGUI : MonoBehaviour {private IUserAction action;     // 用户动作接口private ISceneController queryInt;   // 场景接口public bool isButtonDown = false;public Camera camera;public Text WindForce;public Text WindDirection;void Start() {// 实例化对象action = SSDirector.getInstance().currentSceneController as IUserAction;queryInt = SSDirector.getInstance().currentSceneController as ISceneController;}void Update() {float force = queryInt.getWindforce ();if (force < 0) {WindDirection.text = "Wind Direction : Left";} else if (force > 0) {WindDirection.text = "Wind Direction : Right";} else {WindDirection.text = "Wind Direction : No Wind";}WindForce.text = "Wind Force : " + queryInt.getWindforce(); //显示风力
    }void OnGUI() {GUIStyle fontstyle1 = new GUIStyle();fontstyle1.fontSize = 50;fontstyle1.normal.textColor = new Color(255, 255, 255);if (GUI.RepeatButton(new Rect(0, 0, 120, 40), "Rule")) {action.ShowDetail();}if (GUI.Button(new Rect(0, 60, 120, 40), "Start")) {  action.StartGame();}if (Input.GetMouseButtonDown(0) && !isButtonDown) {Ray mouseRay = camera.ScreenPointToRay (Input.mousePosition);Debug.Log("RayDir = " + mouseRay.direction);action.hit(mouseRay.direction);isButtonDown = true;}else if(Input.GetMouseButtonDown(0) && isButtonDown) {  isButtonDown = false;}}
}

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("Cant find instance of "+typeof(T));}}return instance;}}
}

Data.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Data : MonoBehaviour {public Vector3 size;public Color color = Color.red;public float speed = 5f;public Vector3 director;public play Action;public bool hit;
}

ArrowFactory.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ArrowFactory : MonoBehaviour {private static ArrowFactory _instance;private List<GameObject> freeArrow; // 空闲的箭头private List<GameObject> usedArrow;private GameObject arrowTemplate;public FirstController sceneControler { get; set; }void Awake() {if (_instance == null) {_instance = Singleton<ArrowFactory>.Instance;_instance.usedArrow = new List<GameObject>();_instance.freeArrow = new List<GameObject>();}}public GameObject GetArrow1() {  GameObject newArrow;  if (freeArrow.Count == 0) {newArrow = GameObject.Instantiate(Resources.Load("Prefabs/arrow")) as GameObject;  } else {newArrow = freeArrow[0];freeArrow.Remove(freeArrow[0]);}newArrow.transform.position = arrowTemplate.transform.position;newArrow.transform.localEulerAngles = new Vector3(90, 0, 0);usedArrow.Add(newArrow);return newArrow;}  public void FreeArrow1(GameObject arrow1) {for (int i = 0; i < usedArrow.Count; i++) {if (usedArrow[i] == arrow1) {usedArrow.Remove(arrow1);arrow1.SetActive(true);freeArrow.Add(arrow1);}}return;}// Use this for initializationvoid Start () {sceneControler = (FirstController)SSDirector.getInstance().currentSceneController;  sceneControler.arrowfactory = this;  arrowTemplate = Instantiate(Resources.Load("prefabs/arrow")) as GameObject;arrowTemplate.SetActive (false);//arrowTemplate.transform.parent = sceneControler.Bow.transform;  arrowTemplate.transform.localEulerAngles = new Vector3(90, 0, 0);  freeArrow.Add(sceneControler.Arrow);  }// Update is called once per framevoid Update () {}
}

joystick.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class joystick : MonoBehaviour {public float speedY = 10.0F;public float speedX = 10.0F;//public GameObject cam;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//Debug.Log("p");float translationY = Input.GetAxis("Vertical")*speedY;float translationX = Input.GetAxis("Horizontal")*speedX;translationY *= Time.deltaTime;translationX *= Time.deltaTime;transform.Translate(0, translationY, 0);transform.Translate(translationX, 0, 0);/*if (Input.GetButtonDown("Fire1")) {Debug.Log("Fired Pressed");Debug.Log(Input.mousePosition);Vector3 mp = Input.mousePosition;//Camera ca = cam.GetComponent<Camera>();Ray ray = ca.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit)) {print(hit.transform.gameObject.name);if (hit.collider.gameObject.tag.Contains("Finish")) {Debug.Log("hit "+hit.collider.gameObject.name+"!");}}}*/}
}

target.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Target : MonoBehaviour {public int num;//每个靶都有特定的分数public play EmitDisk;public FirstController sceneController;//场记//private ScoreRecorder recorder;public void Start() {Debug.Log("target");sceneController = (FirstController)SSDirector.getInstance().currentSceneController;}void OnTriggerEnter(Collider other) {Debug.Log("jizhong");Debug.Log(other.gameObject);if (other.gameObject.tag == "Arrow") {if (!other.gameObject.GetComponent<Data>().hit) {other.gameObject.GetComponent<Data>().hit = true;Debug.Log(num);sceneController.score += num;//加分
            }EmitDisk = (play)other.gameObject.GetComponent<Data>().Action;other.gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;//插在箭靶上  EmitDisk.Destory();//动作完成
        }}
}

Aciton(动作类代码)

CCActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Mygame;
public class CCActionManager : SSActionManager, ISSActionCallback, IshootArrow {public FirstController sceneController;public ArrowFactory arrowFactory;public play EmitArrow;public GameObject Arrow;public float force = 0f;int count = 0;//public CCMoveToAction moveToA, moveToB, moveToC, moveToD;// Use this for initializationprotected new void Start () {sceneController = (FirstController)SSDirector.getInstance().currentSceneController;sceneController.actionManager = this;arrowFactory = sceneController.arrowfactory;}// Update is called once per frameprotected new void Update () {base.Update();}public float getforce() {return force;}public void playArrow(Vector3 dir) {force = Random.Range(-50,50); //获取随机的风力EmitArrow = play.GetSSAction();//force = play.getWindForce();//Debug.Log("play");Arrow = arrowFactory.GetArrow1();//Arrow.transform.position = new Vector3(0, 2, 0);Arrow.transform.position = dir;Arrow.GetComponent<Rigidbody>().AddForce(new Vector3(force, 0.3f, 2), ForceMode.Impulse);this.RunAction(Arrow, EmitArrow, this);Arrow.GetComponent<Data>().Action = EmitArrow;}//
    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null) {arrowFactory.FreeArrow1(source.gameobject);  Debug.Log("free");source.gameobject.GetComponent<Data>().hit = false;}
}

CCSequenceAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCSequenceAction : SSAction, ISSActionCallback {public List<SSAction> sequence;public int repeat = -1;public int start = 0;public static CCSequenceAction GetSSAction(int repeat, int start, List<SSAction> sequence) {CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();action.repeat = repeat;action.sequence = sequence;action.start = start;return action;}public override void Update() {if (sequence.Count == 0) return;if (start < sequence.Count) {sequence [start].Update();}}// Use this for initializationpublic override void Start () {foreach (SSAction action in sequence) {action.gameobject = this.gameobject;action.transform = this.transform;action.callback = this;action.Start();}}void OnDestory() {//
    }public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null) {source.destroy = false;this.start++;if (this.start >= sequence.Count) {this.start = 0;if (repeat > 0) repeat--;if (repeat == 0) {this.destroy = true;this.callback.SSActionEvent(this);}}} }

IshootArrow.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Mygame;
public interface IshootArrow {void playArrow(Vector3 dir);float getforce();
}

play.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class play : SSAction {  int count = 0;  bool enableEmit = true;  Vector3 force;public FirstController sceneControler = (FirstController)SSDirector.getInstance().currentSceneController;  public static play GetSSAction() {play action = ScriptableObject.CreateInstance<play>();  return action;  }// Use this for initialization  public override void Start() {force = new Vector3(0, 0.3f, 2);}// Update is called once per frame  public override void Update() {gameobject.GetComponent<Rigidbody>().velocity = Vector3.zero;  gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);}public void Destory() {  this.destroy = true;this.callback.SSActionEvent(this);Destroy(gameobject.GetComponent<BoxCollider>());}
}

SSAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSAction : ScriptableObject {public bool enable = true;public bool destroy = false;public GameObject gameobject { get; set; }public Transform transform {get; set;}public ISSActionCallback callback {get; set;}protected SSAction() {}public virtual void Start() {throw new System.NotImplementedException();}public virtual void Update() {  throw new System.NotImplementedException();}public virtual void FixedUpdate() {throw new System.NotImplementedException();}
}

SSActionEventType.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SSActionEventType:int {Started, Competeted}
public interface ISSActionCallback {void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted, int intParam = 0, string strParam = null, Object objectParam = null);
}

SSActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSActionManager : MonoBehaviour {private Dictionary <int, SSAction> actions = new Dictionary <int, SSAction>();private List<SSAction> waitingAdd = new List<SSAction>();private List<int> waitingDelete = new List<int> ();// Use this for initializationprotected void Start () {}// Update is called once per frameprotected void Update () {foreach (SSAction ac in waitingAdd) actions [ac.GetInstanceID()] = ac;waitingAdd.Clear();foreach (KeyValuePair <int, SSAction> kv in actions) {SSAction ac = kv.Value;if (ac.destroy) {waitingDelete.Add(ac.GetInstanceID());} else if (ac.enable) {ac.Update();}}foreach (int key in waitingDelete) {SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {action.gameobject = gameobject;action.transform = gameobject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}
}

转载于:https://www.cnblogs.com/xieyuanzhen-Feather/p/6666586.html

【Unity3D】射箭打靶游戏(简单工厂+物理引擎编程)相关推荐

  1. PhysX物理引擎(编程入门)

    PhysX物理引擎(编程入门) --PhysX,Hello World! Author: 华文广   E-MAIL: huawenguang@sina.com  DATE:06/7/20 Hi,大家好 ...

  2. Unity3D学习(7)之物理引擎的应用与代码复用

    Unity3D的物理引擎做得很不错,让物体的运动更加贴近现实了.没有人喜欢高深的数学,去计算复杂的运动曲线和力学.使用物理引擎,而你仅需要高中的物理(牛顿!三定律, F = m * a). 物理引擎( ...

  3. Unity3D学习:射箭打靶游戏

    这次做一个有点类似飞碟射击的游戏,射箭游戏 规则:靶有五环,射中不同的靶会相应加不同的分数(从红心到最外环分别加100,70,50,40,30,20),射出靶外会扣分200,中靶10次会有一次神箭效果 ...

  4. Unity3D射箭小游戏

    游戏说明如下: 1.首先我制作了靶对象,利用五个不同半径和不同高度的圆柱体制作成一个靶子,圆柱的不同高度,可以让碰撞的时候碰撞到不同的环数,然后根据此进行计分: 2.制作了箭对象,挺简陋的,就是一个空 ...

  5. 【Unity】FPS游戏中的物理引擎——角色控制器(CharacterController)和刚体(Rigidbody)初解

    今天会谈到角色控制器和刚体主要是为了做一个游戏人物的控制器,角色控制器和刚体各有各的优点. 首先说一下刚体吧,刚体这个组件可以说是做一些真是物理游戏的开发者的福音,只要你给物体加上刚体基本可以算是给它 ...

  6. Unity3D游戏开发初探—3.初步了解U3D物理引擎

    一.什么是物理引擎? 四个世纪前,物理学家牛顿发现了万有引力,并延伸出三大牛顿定理,为之后的物理学界的发展奠定了强大的理论基础.牛顿有句话是这么说的:"如果说我看得比较远的话,那是因为我站在 ...

  7. Havok物理引擎与Unity3D游戏的结合

    背景 在重度手游的研发过程当中,游戏中的车辆模拟,场景互动,特效展示等功能很多时候需要物理引擎的介入,以提供丰富的交互体验.目前3D手游的开发主要工具是使用Unity3D引擎,于是,如何在Unity3 ...

  8. Havok物理引擎与Unity3D的结合

    背景 在重度手游的研发过程当中,游戏中的车辆模拟,场景互动,特效展示等功能很多时候需要物理引擎的介入,以提供丰富的交互体验.目前3D手游的开发主要工具是使用Unity3D引擎,于是,如何在Unity3 ...

  9. 不使用物理引擎,自己动手做真实物理的模拟投篮游戏

    最近打算做一个2D投篮游戏,由于对于BOX2D等物理引擎并不熟悉,加之一开始低估了游戏所需要的碰撞检测复杂度,认为仅仅涉及4面墙,篮球,篮板,篮筐,篮网的碰撞检测并不复杂.因此决定自己实现所需要的碰撞 ...

最新文章

  1. 在vs里不重启模拟器进行Symbian调试
  2. python读写csv时中文乱码问题解决办法
  3. ABAP实现农历转成公历
  4. Hadoop: MapReduce2的几个基本示例
  5. 简述使用REST API 的最佳实践
  6. mybatis思维导图,让mybatis不再难懂(二)
  7. 德州2021高考考试成绩查询,德州高考成绩查询系统2021
  8. python使用json序列化datetime类型问题处理
  9. Android 的安全性岌岌可危!
  10. preg_match 参数获取两个_「死磕 Spring」—– IOC 之 获取 Document 对象
  11. Java static静态关键字 有啥用
  12. ansible-handlers
  13. 【ANDROID游戏开发二十六】追加简述SURFACEVIEW 与 GLSURFACEVIEW效率!
  14. Oracle12c错误01017,ORACLE12.2中用户无法登陆报ORA-01017的解决办法
  15. MySQL手册chm格式文档
  16. JavaScript:分支流程控制switch语句详解
  17. Lua基础入门—— 写出自己的魔兽世界插件
  18. 苹果/Mac电脑软件卸载不了怎么办?
  19. 网页中的th/th是什么意思
  20. 男朋友是一名程序员,他都好久没有交作业了

热门文章

  1. 为什么ping不通网站 但是却可以访问该网站?
  2. JWT Claims
  3. 苏杭计算机发展,“英才计划”计算机学科大师报告走进苏杭
  4. 【学习笔记】设计模式-原型模式/克隆模式(Prototype)
  5. 真悲剧:中国宽带资费是韩国124倍 严重影响新技术应用
  6. 负载、集群功能Beetle Agent简介
  7. 【渗透测试笔记】之【内网渗透——域渗透信息收集神器BloodHound安装方法】
  8. 方法值传递和引用传递的过程重难点剖析
  9. 名帖137 沈尹默 楷书《祝寿十屏》
  10. 苹果AirPower迟迟不见发布 或因商标被抢注