交互入门2——射击打靶游戏
文章目录
- 射箭游戏设计与实现
- 游戏要求:
- 具体实现代码
- 动作部分
- 碰撞检测
- 工厂类生产箭
- Controller类
- UI类
- 游戏效果
射箭游戏设计与实现
游戏要求:
游戏内容要求:
靶对象为 5 环,按环计分;
箭对象,射中后要插在靶上
增强要求:射中后,箭对象产生颤抖效果,到下一次射击 或 1秒以后
游戏仅一轮,无限 trials;
增强要求:添加一个风向和强度标志,提高难度
具体实现思路:
- 设计扁平圆柱体作为靶标,多个不同大小的圆柱体叠加形成不同的环,并利用颜色区分,由于叠加会影响正常显示,所以每个圆柱体的宽度(高)需要不一致,或者利用位置不同实现一个层级的效果,小的在前,大的在后就能显示出一个个环的效果。
- 由于对游戏轮次没有太大的要求,所以这里设置为游戏开始时拥有一定数量的箭,箭用完就算结束,显示得分,由用户决定是否再来一次(对于无限trails的规则不太清楚)。
- 风向则可是使用一个持续添加在箭上的力来实现。
具体实现代码
首先用到之前几个游戏的一些基类:Director、SSAction、SSActionManager、Singleton等,这几个类由于只是基类,真正的逻辑实现都在子类中,所以直接重用。
动作部分
public class ArrowAction : SSAction{public Vector3 force;public Vector3 affect;public static ArrowAction GetSSAction(Vector3 f, Vector3 wind) {ArrowAction action = ScriptableObject.CreateInstance<ArrowAction>();action.force = f;action.affect = wind;return action;}public override void FixedUpdate() {this.gameObject.GetComponent<Rigidbody>().AddForce(affect, ForceMode.Acceleration);if (this.transform.position.z > 3 || Mathf.Abs(this.transform.position.y) > 7 || Mathf.Abs(this.transform.position.x) > 10 || this.gameObject.tag == "ontarget") {this.destroy = true;if (this.gameObject.tag != "ontarget")this.callBack.SSActionEvent(this);}}public override void Update(){}public override void Start() {this.gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;this.gameObject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);}
}
动作管理器类也就是简单的包装一下动作类,并且使其执行,并且实现回调函数,这里的回调就是用弓箭工厂的方法将箭的对象释放掉(加入到free的队列去,以便重新使用):
ArrowActionManager
public class ArrowActionManager : SSActionManager, ISSActionCallback {ArrowAction arrowAction;Controller controller;private void Start(){controller = Director.getInstance().currentSceneController as Controller;controller.actionManager = this;}public void arrowFly(GameObject arrow, Vector3 target, Vector3 wind) {arrowAction = ArrowAction.GetSSAction(target, wind);if (arrow.GetComponent<Rigidbody>() == null)arrow.AddComponent<Rigidbody>();else arrow.GetComponent<Rigidbody>().isKinematic = false;this.RunAction(arrow, arrowAction, this);}public void SSActionEvent(SSAction action){Singleton<ArrowFactory>.Instance.freeArrow(action.gameObject);if (controller.arrow.name == "arrow")controller.getArrow();}
}
碰撞检测
public class CollisionRev : MonoBehaviour {private void OnTriggerEnter(Collider other){ GameObject arrow = other.gameObject;if (arrow.name == "arrow") {string str = this.name;arrow.GetComponent<Rigidbody>().velocity = Vector3.zero;arrow.GetComponent<Rigidbody>().isKinematic = true;Singleton<Judger>.Instance.addScore(str);arrow.transform.position += Vector3.forward * 0.001f;arrow.name = "ontarget";Controller controller = Director.getInstance().currentSceneController as Controller;controller.hit(arrow);// if (controller.arrow == null)controller.getArrow();}}
}
工厂类生产箭
与前一个实验的飞碟工厂很像,而且不需要添加属性什么的,更加简单。
只需要将空闲的或者刚创建的箭,初始化位置等就可以了。还有一个Free的方法,也是跟之前类似。
public class ArrowFactory : MonoBehaviour {public GameObject arrow = null;private List<GameObject> activeList = new List<GameObject>();private List<GameObject> freeList = new List<GameObject>();public GameObject getArrow() {if (freeList.Count > 0) {arrow = freeList[0].gameObject;freeList.Remove(freeList[0]);arrow.GetComponent<Rigidbody>().isKinematic = true;}else {arrow = Instantiate(Resources.Load("Prefabs/arrow", typeof(GameObject))) as GameObject;}arrow.transform.rotation = Quaternion.Euler(0,0,0);arrow.transform.position = new Vector3(-0.1f, 0.85f, -9.7f);arrow.SetActive(true);arrow.name = "ready";activeList.Add(arrow);return arrow;}public void freeArrow(GameObject a) {for (int i = 0; i < activeList.Count; i ++) {if (a.GetInstanceID() == activeList[i].gameObject.GetInstanceID()) {activeList[i].gameObject.SetActive(false);freeList.Add(activeList[i]);activeList.Remove(activeList[i]);break;}}}
}
Controller类
public class Controller : MonoBehaviour, SceneController, Interaction
{public ArrowActionManager actionManager;public ArrowFactory factory;public GameObject bow;public GameObject target;public GameObject arrow;public Judger judger;public Vector3 direction;public UI ui;public int state = 0;private int arrowNumber = 0;private Queue<GameObject> hit_arrow = new Queue<GameObject>();public Vector3 wind = Vector3.zero; private int[] direc = {1,-1,0};private void Start() {Director director = Director.getInstance();director.currentSceneController = this;factory = this.gameObject.AddComponent<ArrowFactory>();actionManager = this.gameObject.AddComponent<ArrowActionManager>() as ArrowActionManager;ui = this.gameObject.AddComponent<UI>();judger = this.gameObject.AddComponent<Judger>();// factory = Singleton<ArrowFactory>.Instance;loadResources();int x = Random.Range(0,3);int y = Random.Range(0,3);x = direc[x];y = direc[y];int level = Random.Range(1,5);wind = new Vector3(x, y, 0) * level;}public void loadResources() {bow = Instantiate(Resources.Load("Prefabs/bow", typeof(GameObject))) as GameObject;target = Instantiate(Resources.Load("Prefabs/target", typeof(GameObject))) as GameObject;arrow = factory.getArrow();}private void Update(){}public void moveArrowDirection(Vector3 to) {if (state <= 0) {return;}arrow.transform.rotation = Quaternion.LookRotation(to);bow.transform.rotation = Quaternion.LookRotation(to);direction = to;}public void reuse() {int tmp = hit_arrow.Count;for (int i = 0; i < tmp; i ++) {factory.freeArrow(hit_arrow.Dequeue());}arrowNumber = 0;}public void shoot(Vector3 force) {if (state > 0 && arrow != null) {// arrow = factory.getArrow();arrow.name = "arrow";actionManager.arrowFly(arrow, direction * 15, wind);arrowNumber ++;}}public void hit(GameObject arrow) {hit_arrow.Enqueue(arrow);}public void getArrow() {int x = Random.Range(0,3);int y = Random.Range(0,3);x = direc[x];y = direc[y];int level = Random.Range(1,5);wind = new Vector3(x, y, 0) * level;if (state == 1) {if (arrowNumber > 7) {setState(-1);}}arrow = factory.getArrow();}public void setState(int s) {state = s;}public void restart() {state = 0;arrowNumber = 0;}public int getState() {return state;}public string arrowState() {return arrow != null ? arrow.name : null;}public Vector3 getWind() {return wind;}
}
UI类
UI主要是负责用户的交互,所以需要获取Controller的一些状态来判断用户操作是否合法或者限制用户的操作。
public class UI : MonoBehaviour {Interaction interaction;bool flag = true;GUIStyle style1;GUIStyle style2;GUIStyle style3;float time = 0;private void Start() {interaction = Director.getInstance().currentSceneController as Interaction;style1 = new GUIStyle("button");style1.fontSize = 25;style2 = new GUIStyle();style2.fontSize = 35;style2.alignment = TextAnchor.MiddleLeft;style3 = new GUIStyle();style3.fontSize = 15;style3.alignment = TextAnchor.MiddleLeft;}private void OnGUI(){ if (interaction.getState() == -1) {if (time < 2) {time += Time.deltaTime;GUI.Label(new Rect(Screen.width/2-70, Screen.height/2-135, 200, 30), "Preparing Arrow...", style2);} else {GUI.Label(new Rect(Screen.width/2-70, Screen.height/2-135, 200, 30), "Your Score:" + Singleton<Judger>.Instance.getScore().ToString(), style2);if (GUI.Button(new Rect(Screen.width/2-70, Screen.height/2 - 20, 180, 70), "Play again", style1)) {interaction.reuse();interaction.setState(1);Singleton<Judger>.Instance.restart();time = 0;}}}GUI.Label(new Rect(5, 5, 100, 30), "Score: " + Singleton<Judger>.Instance.getScore().ToString(), style3);Vector3 wind = interaction.getWind();int x = (int)wind.x;int y = (int)wind.y;string str1, str2, level;if (x < 0) str1 = "West";else if (x > 0)str1 = "East";else str1 = "";if (y < 0) str2 = "South";else if (y > 0)str2 = "North";else str2 = "";if (x == 0 && y == 0) {str1 = "No wind";}if (x != 0) {int tmp = x > 0 ? x : -x;level = tmp.ToString();} else if (y != 0) {int tmp = y > 0 ? y : -y;level = tmp.ToString();} else {level = "0";}GUI.Label(new Rect(5, 35, 200, 30), "Wind Direction: " + str1 + str2, style3);GUI.Label(new Rect(5, 65, 100, 30), "Wind Level: " + level , style3);if (flag) {GUI.Label(new Rect(Screen.width/2-60, Screen.height/2-135, 100, 50), "ShootArrow!", style2);if(GUI.Button(new Rect(Screen.width/2-70, Screen.height/2 - 20, 150, 70), "Play", style1)) {flag = false;interaction.setState(1);}}}private void Update(){if (interaction.getState() > 0) {Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (interaction.arrowState() == "ready") {interaction.moveArrowDirection(ray.direction);if (Input.GetButtonDown("Fire1")) {interaction.shoot(ray.direction);}}}}
}
游戏效果
交互入门2——射击打靶游戏相关推荐
- unity 开发射击打靶vr_【好玩微信小游戏大全】香肠派对:点开既玩的射击小游戏!正版授权...
沐沐带你发现好游戏! 沐沐今天推荐这款游戏叫<香肠派对>, 你以为是这款吃鸡的APP游戏吗? 大错特错! 沐沐我怎么会这么俗呢? 要推荐就推荐你没玩过的! 今天推荐这款<香肠派对&g ...
- python3小游戏源代码_Python入门塔防小游戏,开发步骤和源码,带你轻松学python...
在上一篇文章中,我介绍了有关python入门塔防小游戏的一些功能,下面我继续讲解有关这个小游戏的大致开发步骤. 开发工具还是: Python版本:3.6.4 相关的模块有:pygame模块,以及一些p ...
- 游戏开发入门(五)游戏动画系统
视频链接:游戏开发入门(五)游戏动画系统(8节课 时常:约2小时30分钟) PPT比视频要块一些 第二节与PPT对不上 视频中杂音太大,如果带耳机还听不清的话,建议直接看内容即可 笔记与总结(请先学习 ...
- Java面向对象(6) —— 射击小游戏
这里做一个射击小游戏,作为对前面Java学习的一个小结. 1.设计 2.知识点总结 主要是在主程序ShootGame.java中引入了一些新知识,swing画图.定时器.鼠标事件处理.其他程序则主要体 ...
- 【青少年编程】陈晓光:打靶游戏
「青少年编程竞赛交流群」已成立(适合6至18周岁的青少年),公众号后台回复[Scratch]或[Python],即可进入.如果加入了之前的社群不需要重复加入. 微信后台回复"资料下载&quo ...
- C#游戏开发快速入门2.2改变游戏对象的状态
C#游戏开发快速入门2.2改变游戏对象的状态 改变游戏对象的状态,就是要改变游戏对象的位置.朝向和大小.那么,为什么要改变游戏对象的状态呢?当然是因为游戏对象的状态不合适了.在具体说明之前,读者应该先 ...
- C#游戏开发快速入门 2.1 构建游戏场景
C#游戏开发快速入门 2.1 构建游戏场景 如果已经计划好了要编写什么样的游戏,在打开Unity以后,要做的第一件事情就是构建游戏场景(Scene).游戏场景就是玩家游戏时,在游戏视图中看到的一切, ...
- 基于pygame的射击小游戏制作(一)让飞船动起来
基于pygame的射击小游戏制作(一)让飞船动起来 一.文件结构 alien_invasion.py 是整个系统的主文件,用来创建游戏中的一系列对象,ai_settings存储设置.screen存储显 ...
- 非常强大的射击动作游戏源码完整版
一款横版射击动作游戏.左下方有一个摇杆,可以控制物体作前进和跳跃,点击屏幕的左边,可以进行射击.游戏采用的是2D动画,可玩性还是不错的.使用ios4,ios5,ios6模拟器运行都没问题,但是在本人的 ...
最新文章
- 2021 年 NLP 重要国际会议时间
- css中font-family的中文字体
- c#链接操作mysql数据库代码_c#连接mysql数据库 代码
- 「LOJ 2289」「THUWC 2017」在美妙的数学王国中畅游——LCT泰勒展开
- Python二级笔记(9)
- java nextlong_Java Random nextLong()方法与示例
- 【转】const int *p和int * const p的区别(常量指针与指向常量的指针)
- Linux——查看系统的日志的一些实用操作
- solaris中如何新建一个用户登录
- MySQL自动生成Oracle建表语句脚本
- sg90舵机c语言编程,浅谈用单片机控制SG90舵机(原理+编程)
- REST Assured 系列汇总
- wei.getA()
- python3.7程序实例_生信编程实战第7题(python)
- Excel操作:制作to do list
- 抖音爱心c语言程序,抖音上用记事本编写爱心小程序教程
- SAP中物料历史标准成本清单
- Ubuntu20.04更换软件源之后apt-get update报错
- Maven发布轻量二方包
- cmnet 和 cmwap 收费等区别