为了吃鸡苦练狙击,避免坑队友自己造一个狙击游戏!

在这里插入图片描述

引言

一文教会你造一个简易的狙击游戏。

说到狙击,相信大家都不陌生,无论是影视作品还是网络游戏,都经常能看到狙击枪的身影,最深刻的是它能够从百里之外,一枪爆头

本文将介绍如何在Cocos Creator中造一个简易的狙击游戏非常详细

本文源工程在文末获取,小伙伴们自行前往。

1.狙击游戏常见的元素有什么?

以下是狙击游戏中常见的一些元素

  1. 狙击枪: 各种类型的狙击枪。

  2. 瞄准镜: 玩家可以使用各种瞄准镜来提高精准度和观察敌人。

  3. 目标: 狙击目标。

那么实现狙击游戏需要哪些知识点?

2.实现狙击游戏的知识点

想要在Cocos Creator中造一个简易的狙击游戏,需要掌握以下知识点:

  1. 动画编辑:狙击游戏通常包含一些动画效果,例如打开瞄准镜的时候、子弹的运动轨迹等等都需要一些简易的动画效果,本文用到动画编辑器Tween动画。

  2. 瞄准镜效果:瞄准镜的效果通常使用RTT方法,全称RenderToTexture,通过把摄像机拍到的内容渲染到2DUI上。

  3. 碰撞检测:本文是简易狙击游戏,开枪即判断是否命中,采用的是屏幕射线检测,子弹的物理碰撞不做详细介绍。

  4. 圆形遮罩:圆形的瞄准镜,需要借助一下Mask遮罩。

  5. 3D游戏基础:例如模型的摆放、坐标的计算转换以及相机的调整

以上相关知识点笔者前面的文章都有介绍,可在文末100个Cocos实例专栏查阅。

话不多说,一起来看下如何在Cocos Creator中造一个简易的狙击游戏

3.一起来造一个简易的狙击游戏

我们根据以下的步骤一步一步来造一个简易的狙击游戏:

1.环境

引擎版本:Cocos Creator 3.8.1

编程语言:TypeScript

2.资源准备

首先从市场搞一把帅气带瞄准镜狙击枪模型,还送了个开火特效!(这回节目组可是下重本啊。)

下重本了

然后找一张简单的瞄准镜画面UI,准备做几个小按钮用作瞄准镜开镜、射击和重置复位。

与技术无关,没有他我能闭着眼爆头

给瞄准镜添加一个Mask组件形成圆形遮罩。

方便好用

为了营造一个非常好的打鸡效果,我们把熟悉的鸡朋友拉过来当靶子

给我摆高一点

添加2个摄像机,并且分别调整各自的摄像机的机位,包括原有的主摄像机瞄准镜摄像机子弹轨迹跟踪摄像机

没想到做个Demo都那么不容易

小技巧

瞄准镜摄像机可以和主摄像机一致,包括位置、旋转和设置,通过改变相机Fov实现放大效果

通过动画编辑器简单编辑一下开镜动画

有手就行

3.编写代码

首先定义一个Snipe组件,包含以下几个属性。

@ccclass('Snipe')
export class Snipe extends Component {bulletPfb: Node;         //子弹预制体animation: Animation;    //动画组件sighting: Node = null;   //瞄准UI节点bullet: Node;            //当前子弹checkerCameraNode: Node; //相机检测节点
}

然后在start方法里面初始化一下,并且监听一下开镜、射击、重置事件。

start() {this.animation = this.node.getComponent(Animation);director.getScene().on("PreShoot", this.PreShoot, this);director.getScene().on("Shoot", this.Shoot, this);director.getScene().on("Reset", this.Reset, this);this.bulletPfb = this.node.getChildByPath("qiang/Line16");this.SightingCamera();
}

开镜、射击、重置事件从UI_Joystick中的按钮发出。

const sighting = this.node.getChildByName('Sighting');
this.node.getChildByName('BtnOpen').on(NodeEventType.TOUCH_END, () => {this._scene.emit("PreShoot", sighting);
}, this);
this.node.getChildByName('BtnShoot').on(NodeEventType.TOUCH_END, () => {if (sighting.active) {this._scene.emit("Shoot", checkerCamera.node);}
}, this);
this.node.getChildByName('BtnReset').on(NodeEventType.TOUCH_END, () => {this._scene.emit("Reset");
}, this);

实现瞄准镜的核心源码

  • 创建RenderTexture
  • 设置摄像机的targetTexture为上面创建的RenderTexture
  • 创建SpriteFrame也设置它的texture为上面创建的RenderTexture
  • 最后将瞄准镜SpritespriteFrame为上面创建的SpriteFrame
SightingCamera() {const modelRtt = new RenderTexture();modelRtt.reset({width: 1024,height: 1024});const camera = find("Main Camera/SightingCamera").getComponent(Camera);camera.targetTexture = modelRtt;const spriteFrame = new SpriteFrame();spriteFrame.texture = modelRtt;find("Canvas/ui_joystick_panel/Sighting/Mask/SightingSprite").getComponent(Sprite).spriteFrame = spriteFrame;
}

PreShoot方法中实现开镜动画的播放,核心API如下。

  • 通过animation.play播放动画。
  • 通过animation.on(Animation.EventType.FINISHED监听动画播放完成。
  • 通过animation.targetOff取消监听。
PreShoot(sighting: Node, callback = null) {if (this.bullet) return;this.sighting = sighting;if (this.node.children[0].active) {this.animation.targetOff(this);this.animation.on(Animation.EventType.FINISHED, (event) => {this.sighting.active = true;this.node.children[0].active = false;}, this);this.animation.play("animation");}else {this.animation.targetOff(this);if (callback) {this.animation.on(Animation.EventType.FINISHED, (event) => {callback();}, this);}this.sighting.active = false;this.node.children[0].active = true;this.animation.play("animation2");}
}

Shoot方法中利用射线检测判断瞄准镜是否瞄准了目标核心API如下。

  • 通过camera.screenPointToRay 产生射线。
  • 通过PhysicsSystem.instance.raycast 进行射线碰撞检测并记录结果。
  • 通过PhysicsSystem.instance.raycastResults 获取射线检测结果,通过名字或者其他信息得到想要的物体。
Shoot(checkerCameraNode: Node) {this.checkerCameraNode = checkerCameraNode;var ray = new geometry.Ray();var camera = find("Main Camera").getComponent(Camera);var size = view.getViewportRect();camera.screenPointToRay(size.width / 2, size.height / 2, ray);if (PhysicsSystem.instance.raycast(ray)) {const raycastResults = PhysicsSystem.instance.raycastResults;for (let i = 0; i < raycastResults.length; i++) {const item = raycastResults[i];if (item.collider.node.name == "rooster_man_skin") {this.OnShootTarget(item.collider.node, item.hitPoint);return;}}this.OnShoot();} else {this.OnShoot();}
}

最后在OnShootTarget中通过Tween动画运行子弹并且击中目标。

OnShootTarget(hitNode: Node, hitPoint: Vec3) {this.checkerCameraNode.active = false;this.PreShoot(this.sighting, () => {this.node.children[1].active = true;const bullet = instantiate(this.bulletPfb);this.bullet = bullet;bullet.parent = this.bulletPfb.parent;bullet.children[0].active = true;// tween(bullet.children[1]).by(0.5, { eulerAngles: new Vec3(0, 360, 0) }).repeatForever().start();tween(bullet).by(3, { position: new Vec3(0, -0.5, 0) }).to(1, { worldPosition: hitPoint }).call(() => {bullet.getComponentInChildren(MeshRenderer).enabled = false;hitNode.getComponent(CharacterMovement).onJump("btn_slot_0");this.node.children[1].active = false;}).start();tween(bullet.children[0].getComponent(Camera)).to(3, { fov: 30 }).to(1, { fov: 80 }).start();})
}

4.效果演示

瞄准镜动画效果。

在这里插入图片描述

瞄准镜效果。

在这里插入图片描述

射击效果。
在这里插入图片描述

整体效果。

在这里插入图片描述

结语

本文源工程可通过阅读原文或者私信发送"Snipe"付费获取。付费不仅是知识的获取,更是对笔者的支持和认可,感谢!

我是"亿元程序员",一位有着8年游戏行业经验的主程。在游戏开发中,希望能给到您帮助, 也希望通过您能帮助到大家。

AD:笔者线上的小游戏《贪吃蛇掌机经典》《重力迷宫球》《填色之旅》大家可以自行点击搜索体验。

实不相瞒,想要个在看!请把该文章分享给你觉得有需要的其他小伙伴。谢谢!

推荐专栏:

100个Cocos实例

8年主程手把手打造Cocos独立游戏开发框架

和8年游戏主程一起学习设计模式

游戏开发的技巧、心得、资讯

从零开始开发贪吃蛇小游戏到上线系列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/279060.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axie Infinity 之后,Ronin 的潜力何在?

作者&#xff1a;stellafootprint.network 数据来源&#xff1a;Ronin Dashboard 备受欢迎的 Web3 游戏 Pixels 在 2023 年 10 月下旬从 Polygon 迁移到了专为游戏设计的区块链 Ronin。Pixels 此前作为 Polygon 上活跃用户&#xff08;钱包数量&#xff09;最多的 Web3 游戏&…

『OPEN3D』1.5.2 动手实现点云栅格/体素最近邻

本专栏地址: https://blog.csdn.net/qq_41366026/category_12186023.html?spm=1001.2014.3001.5482 NEARBY6实现的voxel可视化 一种NEARBY14实现的可视化voxel

CT成像技术—20231210

本文要说的是扇束重排&#xff0c;对于扇束及锥束直接重建公式&#xff0c;可以看我做的PDF https://github.com/leslielee619/CTRec/blob/main/重建公式.pdf 在说重排之前&#xff0c;我还想对那个文件内容补充两点&#xff1a; 1、FDK算法或Feldkamp算法&#xff0c;出自Fel…

springAop有哪五种通知类型?可根据图标查看!

Spring AOP的通知类型有以下几种&#xff08;后面是图标变化&#xff09;&#xff1a; 1.Before通知&#xff1a; 在目标方法执行前执行。 上白下红&#xff0c;方法前执行。 2.After通知&#xff1a; 在目标方法执行后&#xff08;无论是否发生异常&#xff09;执行。 图标…

实验06:VLAN配置

1.实验目的&#xff1a; VLAN&#xff08;Virtual Local Area Network&#xff09;是一种通过逻辑方式而不是物理方式划分局域网的技术&#xff0c;可以提高网络性能、安全性和管理效率。VLAN的划分方法有基于端口、基于MAC地址、基于协议和基于IP组播等。VLAN之间的通信需要路…

第十一章 React 封装自定义组件

一、专栏介绍 &#x1f30d;&#x1f30d; 欢迎加入本专栏&#xff01;本专栏将引领您快速上手React&#xff0c;让我们一起放弃放弃的念头&#xff0c;开始学习之旅吧&#xff01;我们将从搭建React项目开始&#xff0c;逐步深入讲解最核心的hooks&#xff0c;以及React路由、…

2024 年值得收藏的 10 款 iPhone 数据恢复软件评论

iPhone 让您将数字生活装在口袋里。从您所爱之人的照片和视频&#xff0c;到与学校和工作相关的文档&#xff0c;再到重要的备忘录和日历约会&#xff0c;iPhone 内的微型存储芯片可以容纳的数据量是惊人的。 唯一的问题是&#xff0c;很快就会丢失这些数据。一次错误的点击或…

320科技工作室ZEMAX培训通知

一 软件介绍 ZEMAX是一套综合性的光学设计软件。它提供先进的、且符合工业标准的分析、优化、公差分析功能&#xff0c;能够快速准确的完成光学成像及照明设计。 二 培训方式 本次培训全程线上授课, 采用一对一或者一对多方式进行, 以视频方式授课&#xff0c;工程案例讲解&…

WebGL+Three.js入门与实战——给画布换颜色、绘制一个点、三维坐标系

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

紫光展锐T820与飞桨完成I级兼容性测试 助推端侧AI融合创新

近日&#xff0c;紫光展锐高性能5G SoC T820与百度飞桨完成I级兼容性测试&#xff08;基于Paddle Lite工具&#xff09;。测试结果显示&#xff0c;双方兼容性表现良好&#xff0c;整体运行稳定。这是紫光展锐加入百度“硬件生态共创计划”后的阶段性成果。 本次I级兼容性测试完…

小程序使用Nodejs作为服务端,Nodejs与与MYSQL数据库相连

小程序使用Nodejs作为服务端,Nodejs与MYSQL数据库相连 一、搭建环境二、配置Nodejs三、与小程序交互四、跨域处理/报错处理五、nodejs连接mysql数据库六、微信小程序连接nodejs报错七、小程序成功与服务端相连,且能操作数据库一、搭建环境 新建空文件夹:Win + R进入cmd命令界…

Jenkins Pipeline 脚本优化实践:从繁琐到简洁

引言 在持续集成的过程中&#xff0c;Jenkins Pipeline 是非常关键的一环。它定义了如何自动编译、测试和部署代码。随着项目的不断发展&#xff0c;Pipeline 的复杂性也在不断上升&#xff0c;这就需要我们持续优化 Pipeline 脚本&#xff0c;以提高代码的可读性和维护性。本…