infinite-world示例展示了小球顺着山坡凹凸做左右滚动的效果。

技术点

1、山坡由数量不等动态生成的的竖条状方块组成。
2、每个方块动态添加RigidBody组件和PolygonCollider组件,使小球和山坡产生物理碰撞效果。
3、摄像机根据山坡的凹凸高度做动态缩放。
4、通过键盘或触摸来控制小球的左右滚动。

源码分析

camera-control.js

该源文件功能是根据小球在屏幕上的位置高度来控制摄像机的缩放。

cc.Class({extends: cc.Component,properties: {target: {default: null,type: cc.Node}},// LIFE-CYCLE CALLBACKS:onLoad () {this.camera = this.getComponent(cc.Camera);},onEnable: function() {// 将物理系统的调试绘制信息附加到指定摄像机上。// 使用摄像机时,如果使用到了物理系统或碰撞系统等内置渲染节点的系统,// 那么需要将它们的渲染节点也添加摄像机上。cc.director.getPhysicsManager().attachDebugDrawToCamera(this.camera);},onDisable: function() {// 将物理系统的调试绘制信息从指定摄像机上移除cc.director.getPhysicsManager().attachDebugDrawFromCamera(this.camera);},lateUpdate: function(dt) {// 此例中,this.target指小球,即将小球中心点转换为世界空间坐标系let targetPos = this.target.convertToWorldSpaceAR(cc.Vec2.ZERO);// 再转换为游戏Scene的(局部)空间坐标系,并调整摄像机到相应位置this.node.position = this.node.parent.convertToNodeSpaceAR(targetPos);// ratio的值区间将为 0 < ratio < 1let ratio = targetPos.y / cc.winSize.height;// 如小球位于屏幕中部,则摄像机缩放比例不变(即保持1),如屏幕上半部则缩小,如屏幕下半部则放大。// 极端情况下,如小球位于屏幕顶部,则缩小25%,如果小球位于屏幕底部,则放大25%。this.camera.zoomRatio = 1 + (0.5 - ratio) * 0.5;},// update (dt) {},
});

ball-control.js

该源文件功能是根据输入事件控制小球的运动方向和速度。

const MOVE_LEFT = 1; // 向左移动标志位
const MOVE_RIGHT = 2; // 向右移动标志位cc.Class({extends: cc.Component,properties: {maxSpeed: 1200},// LIFE-CYCLE CALLBACKS:onLoad () {// 注册键盘按下和释放事件的回调cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this);// 注册触摸事件的回调var canvas = cc.find('/Canvas');canvas.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);canvas.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);this.moveFlags = 0;},start () {// start 在 onLoad 之后,此时RigidBody组件已经被加载进来this.body = this.getComponent(cc.RigidBody);        },onKeyDown(event) {switch(event.keyCode) {case cc.KEY.a:case cc.KEY.left:this.moveFlags |= MOVE_LEFT; // 添加向左移动的标志位this.updateMotorSpeed();break;case cc.KEY.d:case cc.KEY.right:this.moveFlags |= MOVE_RIGHT; // 添加向右移动的标志位this.updateMotorSpeed();break;}},onKeyUp (event) {switch(event.keyCode) {case cc.KEY.a:case cc.KEY.left:this.moveFlags &= ~MOVE_LEFT; // 清除向左移动标志break;case cc.KEY.d:case cc.KEY.right:this.moveFlags &= ~MOVE_RIGHT; // 清除向右移动标志break;}},onTouchStart: function(event) {let touchLoc = event.touch.getLocation();if (touchLoc.x < cc.winSize.width/2) {this.moveFlags |= MOVE_LEFT; // 添加向左移动的标志位} else {this.moveFlags |= MOVE_RIGHT; // 添加向右移动的标志位}this.updateMotorSpeed();},onTouchEnd: function(event) {let touchLoc = event.touch.getLocation();if (touchLoc.x < cc.winSize.width/2) {this.moveFlags &= ~MOVE_LEFT; // 清除向左移动标志} else {this.moveFlags &= ~MOVE_RIGHT; // 清除向右移动标志}},updateMotorSpeed() {// 判断this.body是否可用if (!this.body) {return;}var desiredSpeed = 0;if ((this.moveFlags & MOVE_LEFT) == MOVE_LEFT) {desiredSpeed = -this.maxSpeed;} else if ((this.moveFlags & MOVE_RIGHT) == MOVE_RIGHT) {desiredSpeed = this.maxSpeed;}// 设置小球刚体角速度来控制小球的运动方向和速度this.body.angularVelocity = desiredSpeed;},update (dt) {// 判断标志位是否为空(避免在没有事件触发时也去改变小球运动)if (this.moveFlags) {this.updateMotorSpeed();}},
});

infinite-world.js

该源文件功能是随着小球方向动态生成N个高度不等的方块,从而组成凹凸不平的山坡,每个方块都动态添加了物理组件,每个方块宽度的粒度越小,则山坡越平滑。方块的颜色默认为青色,由物理引擎的调试绘制标志位决定。


cc.Class({extends: cc.Component,properties: {pixelStep: 10, // 每个矩形的宽度(N个矩形组成一个山坡)xOffset: 0, // 当前最新创建矩形的x坐标yOffset: 240, // 山坡的最低高度target: {default: null,type: cc.Node}},// LIFE-CYCLE CALLBACKS:onLoad: function () {this.hills = [];this.pools = [];while (this.xOffset < 1200) {this.generateHill(10);}},// 生成一个竖条状矩形generateHillPiece(xOffset, points) {let hills = this.hills;let first = hills[0];// 若小球离第一个块的距离超过1000,则不再创建新的node,直接复用原有数组的第一个元素if (first && ((this.target.x - first.node.x) > 1000)) {first.node.x = xOffset;first.collider.points = points;first.collider.apply();hills.push(hills.shift());return;}let node = new cc.Node();node.x = xOffset;let body = node.addComponent(cc.RigidBody);body.type = cc.RigidBodyType.Static;let collider = node.addComponent(cc.PhysicsPolygonCollider);collider.points = points;collider.friction = 1;node.parent = this.node;hills.push({node:node, collider:collider});},// 生成山坡// 每座山坡由N个竖条状矩形组成,// 每座山坡的绘制都分成2步:第1步绘制上坡,第2步绘制下坡generateHill () {let pixelStep = this.pixelStep;let xOffset = this.xOffset;let yOffset = this.yOffset;// 山坡宽度,值区间 120-640let hillWidth = 120 + Math.ceil(Math.random()*26)*20;// 计算山坡由多少个矩形组成let numberOfSlices = hillWidth / pixelStep;let j;let points = [];// first steplet randomHeight;if (xOffset === 0) {randomHeight = 0;} else {// make sure yOffset < 600randomHeight = Math.min(Math.random() * hillWidth / 7.5, 600 - yOffset);}yOffset += randomHeight;for (j = 0; j < numberOfSlices/2; j++) {points.length = 0;points.push(cc.v2(0, 0));// 计算弧度let rad = Math.cos(2*Math.PI/numberOfSlices*j);points.push(cc.v2(0, yOffset-randomHeight*rad));rad = Math.cos(2*Math.PI/numberOfSlices*(j+1));points.push(cc.v2(pixelStep, yOffset-randomHeight*rad));points.push(cc.v2(pixelStep, 0));this.generateHillPiece(xOffset + j*pixelStep, points);}yOffset += randomHeight;// second stepif (xOffset === 0) {randomHeight = 0;} else {// make sure yOffset>240randomHeight = Math.min(Math.random() * hillWidth / 5, yOffset - 240);}yOffset -= randomHeight;for (j = numberOfSlices/2; j < numberOfSlices; j++) {points.length = 0;points.push(cc.v2(0, 0));// 计算弧度let rad = Math.cos(2*Math.PI/numberOfSlices*j);points.push(cc.v2(0, yOffset-randomHeight*rad));rad = Math.cos(2*Math.PI/numberOfSlices*(j+1));points.push(cc.v2(pixelStep, yOffset-randomHeight*rad));points.push(cc.v2(pixelStep, 0));this.generateHillPiece(xOffset + j*pixelStep, points);}yOffset -= randomHeight;this.xOffset += hillWidth;this.yOffset = yOffset;},update: function (dt) {if (!this.target) return;// 如果小球离x轴边界不足1200,则创建新的hillwhile ((this.target.x + 1200) > this.xOffset) {this.generateHill();}},
});

CocosCreator物理引擎Demo源码分析(1)-infinite-world相关推荐

  1. 【Overload游戏引擎】源码分析之十三:OvRendering函数库(十一)

    2021SC@SDUSC 目录 1.Driver 1.1构造函数 1.2InitGlew 1.3GLDebugMessageCallback 2.Renderer 2.1Draw 2.2FetchGL ...

  2. threejs 源码解析_ThreeJS 物理材质shader源码分析(顶点着色器)

    ThreeJS 物理材质shader源码分析(顶点着色器) Threejs将shader代码分为ShaderLib和ShaderChunk两部分,ShaderLib通过组合ShaderChunk的代码 ...

  3. 【我的渲染技术进阶之旅】Google开源的基于物理的实时渲染引擎Filament源码分析:Android版本的Filament第一个示例:sample-hello-triangle

    文章目录 一.效果展示 二.之前的博客 三.示例工程sample-hello-triangle源码分析 3.1 项目源码路径 3.2 分析源码 3.2.1 分析AndroidManifest.xml ...

  4. Pytorch Mobile 之Android Demo源码分析

    现如今,在边缘设备上运行机器学习/深度学习变得越来越流行,它需要更低的时延. 而从Pytorch 1.3开始,我们就可以使用Pytorch将模型部署到Android或者ios设备中. Pytorch官 ...

  5. vitamio官方demo源码分析(1)——MediaPlayerDemo_Video.java分析

    最近在做一个视频监控项目的android客户端,要求用rtsp协议完成视频流的传输,但苦于找到不合适的库.之前考虑过用live555或ffmpeg,但涉及到jni调用,加之不熟悉函数调用顺序,开发难度 ...

  6. 源码解析2-GUI-绘制引擎(QPainter源码分析 )

    Qt源码解析 索引 Qt图形用户界面 应用程序窗口 Qt GUI 模块中最重要的类是QGuiApplication和QWindow.想要在屏幕上显示内容的 Qt 应用程序需要使用这些.QGuiAppl ...

  7. Integer的取值范围(跳坑demo+源码分析)

    首先都知道Integer是Int的包装类型,那么理所当然的: Integer类取值和 int 类型取值范围一样,从-2147483648 至 2147483647(-231至 231-1) ,包括-2 ...

  8. 【我的渲染技术进阶之旅】Google开源的基于物理的实时渲染引擎Filament源码分析:在android中如何使用filamesh命令将.obj或者.fbx文件转换为.filamesh文件?

    文章目录 一.需求描述 1.1 为啥要学习`filamesh`命令 1.2 从android项目的build.gradle看起 1.3 查看FilamentToolsPlugin插件源代码 1.3.1 ...

  9. 【我的渲染技术进阶之旅】Google开源的基于物理的实时渲染引擎Filament源码分析:在android中如何使用cmgen命令自动将.hdr文件转换为.ktx文件或者.rgb32文件等?

    文章目录 一.需求描述 1.1 为啥要学习cmgen命令 1.1 bug描述 1.1.1 运行错误描述:java.io.FileNotFoundException: envs/flower_road_ ...

  10. Threejs 官网镜子demo源码分析

    效果如下: 这个功能其实跟webgl 编程指南中的纹理demo一样的思路 思路是把相机放在镜子的位置,所形成材质,贴在镜子上面,这个有区别的是,它还计算了相机的位置,通过相机位置拿到与镜子镜像的相机位 ...

最新文章

  1. js截屏 video_canvas与html5实现视频截图功能
  2. linux系统怎么清理,linux系统怎么清理废物清理
  3. 云炬Android开发笔记 10主界面-首页UI与数据解析器开发(RecyclerView)
  4. linux shell之awk
  5. fanuc机器人与示教器配对_看FANUC机器人在重力浇铸行业,都是又累又重的活儿啊!...
  6. CISCO ASA防火墙ASDM配置
  7. javassist修炼笔记
  8. Canceled future for execute_request message before replies were done The Kernel crashed while execut
  9. 《点满舔狗相关技能以后,不知为何就转码了》之YOLOP,YOLOPV2推理入门教学
  10. 微信 speex 高清语音文件转MP3
  11. python爬取拉钩网招聘信息分析
  12. eclipse配置tomcat9.0
  13. 对方启用和留言是什么意思_美国人老说“How so”?到底啥意思?“怎么这样”吗?...
  14. 将汉字转换为拼音:pypinyin.pinyin()
  15. Sizzle揭秘—Sizzle选择器引擎的入口
  16. 【软件推荐系列第 3 篇】如何下载、设置时钟屏保
  17. sql数据库去重语法_sql数据库查询语句去重
  18. 安卓AccountManager数据库存储位置
  19. highcharts legend图例禁止点击事件以及鼠标移入样式保持不变
  20. iOS App 上架流程

热门文章

  1. python 直方图匹配_直方图匹配原理与python、matlab实现
  2. MatLab绘制直方图
  3. IP防护等级标准及规定
  4. 使用 laravel-admin 配置后台管理系统
  5. 前期观看郝斌老师Java学习视频整理的部分笔记
  6. 计算机sense服务无法启动,workstation服务无法启动解决办法
  7. 大话企业IT安全解决方案
  8. 爬取国家统计局数据正式篇
  9. Mysql 2018国家统计局区划和城乡划分数据库(包含经纬度数据,以及数据来源,提供大家参考)
  10. Mysql压缩包版的安装教程