CocosCreator物理引擎Demo源码分析(3)-stick-arrow

2024-09-04 09:58

本文主要是介绍CocosCreator物理引擎Demo源码分析(3)-stick-arrow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CocosCreator开发笔记(8)-读取和解析JSON数据文件
Box2D C++ 三种作用力效果 ApplyForce、ApplyLinearImpulse、SetLinearVelocity


stick-arrow示例展示了如何动态发射刚体飞往目标点。

技术点
1、触摸屏幕发射刚体,计算起点和目标点的夹角,设置刚体的线性速度。
2、在Update中不断施加一个作用力到刚体尾部,使它能一直往目标点飞去。
3、在碰撞上后,动态计算并设置WeldJoint的属性,使刚体和碰撞体按一定角度连接起来,不致于自然掉落。

源码分析
arrow.js
arrow.js代码功能是处理碰撞之后的逻辑,主要是动态计算和设置WeldJoint关节的属性。

cc.Class({
extends: cc.Component,

properties: {},// LIFE-CYCLE CALLBACKS:onLoad () {this.weldJoint = this.getComponent(cc.WeldJoint);
},// 每次处理完碰撞体接触逻辑时被调用
onPostSolve: function(contact, selfCollider, otherCollider) {// 获取冲量信息 注意:这个信息只有在 onPostSolve 回调中才能获取到var impulse = contact.getImpulse();// normalImpulses: 法线方向的冲量// PTM_RATIO: 物理单位与像素单位互相转换的比率,一般是 32。if (Math.abs(impulse.normalImpulses[0]) < cc.PhysicsManager.PTM_RATIO) return;let joint = this.weldJoint;if (joint.enabled) {joint.enabled = false;return;}if (otherCollider.node.name === 'arrow') {return;}let arrowBody = selfCollider.body;let targetBody = otherCollider.body;// 将 arrowBody 本地坐标系下的点转换为世界坐标系下的点let worldCoordsAnchorPoint = arrowBody.getWorldPoint(cc.v2(0.6, 0));joint.connectedBody = targetBody;// 将给定的世界坐标系下的点转换为 arrowBody 本地坐标系下的点joint.anchor = arrowBody.getLocalPoint(worldCoordsAnchorPoint);// 将给定的世界坐标系下的点转换为 targetBody 本地坐标系下的点joint.connectedAnchor = targetBody.getLocalPoint(worldCoordsAnchorPoint);joint.referenceAngle = targetBody.node.rotation - arrowBody.node.rotation;joint.enabled = true;
},

});

shoot-arrow.js
shoot-arrow.js代码功能是发射刚体,并在刚体飞行过程中不断计算和施加作用力。

cc.Class({
extends: cc.Component,

properties: {arrow: {type: cc.Node,default: null}
},onEnabled: function() {this.debugDrawFlags = cc.director.getPhysicsManager().debugDrawFlags;cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_jointBit |cc.PhysicsManager.DrawBits.e_shapeBit;
},onDisable: function() {cc.director.getPhysicsManager().debugDrawFlags = this.debugDrawFlags;
},// LIFE-CYCLE CALLBACKS:onLoad () {this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this);this.arrowBodies = [];
},onTouchBegan: function(event) {let touchLoc = event.touch.getLocation();let node = cc.instantiate(this.arrow);node.active = true;let vec = cc.v2(touchLoc).sub(node.position);// 通过反正切函数得到触摸点和arrow出生点之间的夹角角度// 乘以 180/3.14159 是为了把弧度转化为角度node.rotation = -Math.atan2(vec.y, vec.x) * 180 / Math.PI;cc.director.getScene().addChild(node);// 返回向量的长度let distance = vec.mag();// 返回归一化后的向量,再乘以800let velocity = vec.normalize().mulSelf(800);// 设置刚体的线性速度let arrowBody = node.getComponent(cc.RigidBody);arrowBody.linearVelocity = velocity;this.arrowBodies.push(arrowBody);
},update: function (dt) {let dragConstant = 0.1;let arrowBodies = this.arrowBodies;for (let i = 0; i < arrowBodies.length; i++) {let arrowBody = arrowBodies[i];let velocity = arrowBody.linearVelocity;let speed = velocity.mag();if (speed === 0) {continue;}let direction = velocity.normalize();// 将世界坐标系下的(1,0)向量转换为刚体本地坐标系下的向量let pointingDirection = arrowBody.getWorldVector(cc.v2(1, 0));let flightDirection = arrowBody.linearVelocity;let flightSpeed = flightDirection.mag();// 向量归一化,让这个向量的长度为 1flightDirection.normalizeSelf();// 向量之间进行点乘let dot = cc.pDot(flightDirection, pointingDirection);let dragForceMagnitude = (1 - Math.abs(dot)) * flightSpeed * flightSpeed * dragConstant * arrowBody.getMass();// 得到arrowBody尾部的世界坐标let arrowTailPosition = arrowBody.getWorldPoint(cc.v2(-80, 0));// 施加一个力到arrowBody刚体的尾部(世界坐标系)arrowBody.applyForce(flightDirection.mul(-dragForceMagnitude), arrowTailPosition, false);}
},

});

这篇关于CocosCreator物理引擎Demo源码分析(3)-stick-arrow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135704

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码