cocos creator 刚体卡顿问题(边界会卡住)
**问题描述:**在项目开发中,使用到了刚体, 在搭建地图过程中,发现两个相邻的砖块,即使贴合的再紧密,但星星人在上面走动的时候还是会有很大概率发生卡顿(被两个刚体的边界处卡住)。为了解决这个问题,我们小组对砖块进行了分类处理。
**处理过程如下:**将所有左上角的砖块(左边和上边都不是砖块的砖块)当做特殊砖块(specialBlock),其余的砖块是普通砖块(normalBlock),对特殊砖块进行特殊操作,使其的碰撞框范围覆盖所有的相邻砖块,特殊砖块的定义如下:


被圈起来的砖块就属于特殊砖块,参与碰撞范围的绘制,其他的砖块则只是普通精灵,没有刚体组件(RigidBody)和碰撞体组件(collider)
实现代码如下:
## 正确绘制特殊砖块的碰撞范围,并将points所需要的点存入到this.blockColliderItemArr 中,以备使用
```
/**
* 正确绘制特殊砖块的碰撞范围,并将points所需要的点存入到this.blockColliderItemArr 中,以备使用
* @param element 特殊砖块本体
* @param i 特殊砖块的横坐标
* @param j 特殊砖块的纵坐标
* @param type 是朝哪个方向遍历 1 下 2 右 3 上 4左
* this.blockArr = []; // 这个数组用来放置被绘制过的砖块
* this.blockColliderItemArr = []; // 一个完整的碰撞盒的坐标点
*/
setColliderRange: function (element, i, j, type) {
var temp = [i, j];
if (type !== 1 && type !== 2 && this.nowBlock[0] === i && this.nowBlock[1] === j) {
// 又回到了起点,那么就结束
// console.log("回到结束点了");
if (type === 3 && j + 1 !== constants.mapEditProperties.column && (this.mapData[i][j + 1].type === constants.elementValue.BLOCK ||
this.mapData[i][j + 1].type === constants.elementValue.BUTTONM)) {
// console.log("经过起始点去了右边");
this.calculateColliderPoints(i, j, 3);
this.setColliderRange(element, i, j + 1, 2);
}
if (type === 3) {
this.blockColliderItemArr.push(cc.p(constants.itemSize.blockColliderSize.x / 2, constants.itemSize.blockColliderSize.y / 2));
}
return;
}
switch (type) {
case 1:
// 下
if (j !== 0 && (this.mapData[i][j - 1].type === constants.elementValue.BLOCK || this.mapData[i][j - 1].type === constants.elementValue.BUTTONM)) {
// 计算要存储的点坐标
this.calculateColliderPoints(i, j, 1);
// 左
this.setColliderRange(element, i, j - 1, 4);
} else if (i + 1 !== constants.mapEditProperties.row && (this.mapData[i + 1][j].type === constants.elementValue.BLOCK ||
this.mapData[i + 1][j].type === constants.elementValue.BUTTONM)) {
// 下
this.setColliderRange(element, i + 1, j, 1);
} else if (j + 1 !== constants.mapEditProperties.column && (this.mapData[i][j + 1].type === constants.elementValue.BLOCK ||
this.mapData[i][j + 1].type === constants.elementValue.BUTTONM)) {
// 右
this.calculateColliderPoints(i, j, 2);
this.setColliderRange(element, i, j + 1, 2);
} else {
// 返回 上
this.calculateColliderPoints(i, j, 2);
this.calculateColliderPoints(i, j, 3);
this.setColliderRange(element, i - 1, j, 3);
}
break;
case 2:
// 右
if (i + 1 !== constants.mapEditProperties.row && (this.mapData[i + 1][j].type === constants.elementValue.BLOCK ||
this.mapData[i + 1][j].type === constants.elementValue.BUTTONM)) {
// 下
this.calculateColliderPoints(i, j, 2);
this.setColliderRange(element, i + 1, j, 1);
} else if (j + 1 !== constants.mapEditProperties.column && (this.mapData[i][j + 1].type === constants.elementValue.BLOCK ||
this.mapData[i][j + 1].type === constants.elementValue.BUTTONM)) {
// 右
this.setColliderRange(element, i, j + 1, 2);
} else if (i !== 0 && (this.mapData[i - 1][j].type === constants.elementValue.BLOCK || this.mapData[i - 1][j].type === constants.elementValue.BUTTONM)) {
// 上
this.calculateColliderPoints(i, j, 3);
this.setColliderRange(element, i - 1, j, 3);
} else {
// 返回 左
this.calculateColliderPoints(i, j, 3);
this.calculateColliderPoints(i, j, 4);
this.setColliderRange(element, i, j - 1, 4);
}
break;
case 3:
// 上
if (j + 1 !== constants.mapEditProperties.column && (this.mapData[i][j + 1].type === constants.elementValue.BLOCK || this.mapData[i][j + 1].type === constants.elementValue.BUTTONM)) {
this.calculateColliderPoints(i, j, 3);
// 右
this.setColliderRange(element, i, j + 1, 2);
} else if (i !== 0 && (this.mapData[i - 1][j].type === constants.elementValue.BLOCK || this.mapData[i - 1][j].type === constants.elementValue.BUTTONM)) {
// 上
this.setColliderRange(element, i - 1, j, 3);
} else if (j !== 0 && (this.mapData[i][j - 1].type === constants.elementValue.BLOCK || this.mapData[i][j - 1].type === constants.elementValue.BUTTONM)) {
// 左
this.calculateColliderPoints(i, j, 4);
this.setColliderRange(element, i, j - 1, 4);
} else {
// 返回 下
this.calculateColliderPoints(i, j, 4);
this.calculateColliderPoints(i, j, 1);
this.setColliderRange(element, i + 1, j, 1);
}
break;
case 4:
// 左
if (i !== 0 && (this.mapData[i - 1][j].type === constants.elementValue.BLOCK || this.mapData[i - 1][j].type === constants.elementValue.BUTTONM)) {
this.calculateColliderPoints(i, j, 4);
// 上
this.setColliderRange(element, i - 1, j, 3);
} else if (j !== 0 && (this.mapData[i][j - 1].type === constants.elementValue.BLOCK || this.mapData[i][j - 1].type === constants.elementValue.BUTTONM)) {
// 左
this.setColliderRange(element, i, j - 1, 4);
} else if (i + 1 !== constants.mapEditProperties.row && (this.mapData[i + 1][j].type === constants.elementValue.BLOCK || this.mapData[i + 1][j].type === constants.elementValue.BUTTONM)) {
// 下
this.calculateColliderPoints(i, j, 1);
// 特殊处理,如果是做下的话,把这个点放入到blockArr中
if (!this.blockArr.includes(temp)) {
this.blockArr.push(temp);
}
this.setColliderRange(element, i + 1, j, 1);
} else {
// 返回 右
// 特殊处理,如果是做下的话,把这个点放入到blockArr中
if (!this.blockArr.includes(temp)) {
this.blockArr.push(temp);
}
this.calculateColliderPoints(i, j, 1);
this.calculateColliderPoints(i, j, 2);
this.setColliderRange(element, i, j + 1, 2);
}
break;
default:
break;
}
},
```
###### calculateColliderPoints()方法用来计算单个碰撞体的点坐标,并将得到的点坐标添加到this.blockColliderItemArr数组中
```
/**
* 计算单个碰撞体的点坐标,并将其添加到this.blockColliderItemArr中
* @param i 当前点的横坐标
* @param j 当前坐标的纵坐标
* @param type 要取的点的类型 1:左上 2:左下 3:右下 4:右上
* this.nowblock 存储的特殊砖块的相对坐标
*/
calculateColliderPoints: function (x, y, type) {
var temp = cc.p();
switch (type) {
case 1:
if (y >= this.nowBlock[1]) {
temp.x = (Math.abs(y - this.nowBlock[1]) - (1 / 2)) * constants.itemSize.blockColliderSize.x;
} else {
temp.x = (-Math.abs(y - this.nowBlock[1]) - (1 / 2)) * constants.itemSize.blockColliderSize.x;
}
if (x > this.nowBlock[0]) {
temp.y = (-Math.abs(this.nowBlock[0] - x) + (1 / 2)) * constants.itemSize.blockColliderSize.y;
} else {
temp.y = (Math.abs(this.nowBlock[0] - x) + (1 / 2)) * constants.itemSize.blockColliderSize.y;
}
break;
case 2:
if (y >= this.nowBlock[1]) {
temp.x = (Math.abs(y - this.nowBlock[1]) - (1 / 2)) * constants.itemSize.blockColliderSize.x;
} else {
temp.x = (-Math.abs(y - this.nowBlock[1]) - (1 / 2)) * constants.itemSize.blockColliderSize.x;
}
if (x > this.nowBlock[0]) {
temp.y = (-Math.abs(this.nowBlock[0] - x) - (1 / 2)) * constants.itemSize.blockColliderSize.y;
} else {
temp.y = (Math.abs(this.nowBlock[0] - x) - (1 / 2)) * constants.itemSize.blockColliderSize.y;
}
break;
case 3:
if (y >= this.nowBlock[1]) {
temp.x = (Math.abs(y - this.nowBlock[1]) + (1 / 2)) * constants.itemSize.blockColliderSize.x;
} else {
temp.x = (-Math.abs(y - this.nowBlock[1]) + (1 / 2)) * constants.itemSize.blockColliderSize.x;
}
if (x > this.nowBlock[0]) {
temp.y = (-Math.abs(this.nowBlock[0] - x) - (1 / 2)) * constants.itemSize.blockColliderSize.y;
} else {
temp.y = (Math.abs(this.nowBlock[0] - x) - (1 / 2)) * constants.itemSize.blockColliderSize.y;
}
break;
case 4:
if (y >= this.nowBlock[1]) {
temp.x = (Math.abs(y - this.nowBlock[1]) + (1 / 2)) * constants.itemSize.blockColliderSize.x;
} else {
temp.x = (-Math.abs(y - this.nowBlock[1]) + (1 / 2)) * constants.itemSize.blockColliderSize.x;
}
if (x > this.nowBlock[0]) {
temp.y = (-Math.abs(this.nowBlock[0] - x) + (1 / 2)) * constants.itemSize.blockColliderSize.y;
} else {
temp.y = (Math.abs(this.nowBlock[0] - x) + (1 / 2)) * constants.itemSize.blockColliderSize.y;
}
break;
default:
break;
}
temp.x = parseFloat(temp.x.toFixed(1));
temp.y = parseFloat(temp.y.toFixed(1));
var i = 0;
for (; i < this.blockColliderItemArr.length; i++) {
if (this.blockColliderItemArr[i].x === temp.x && this.blockColliderItemArr[i].y === temp.y) {
console.log("这个点阵中已经存在这个点了");
return;
}
}
this.blockColliderItemArr.push(temp);
},
```
最后,将计算出来的结果赋值给碰撞框的points属性:
上图中的points数组,这个数组决定了你的碰撞体的碰撞范围,将计算出的顶点数组赋值给这个属性。
代码如下:
##### 带来的收益:
1. 完美解决了星星人在砖块上发生卡顿的问题
2. 大大减少了刚体精灵的绘制数量,对性能有一定的提升
cocos creator 刚体卡顿问题(边界会卡住)的更多相关文章
- iOS 14 egret 游戏卡顿问题分析和部分解决办法
现象 总体而言,iOS 14 渲染性能变差,可以从以下三个测试看出. 测试1:简单demo,使用egret引擎显示3000个图(都是同一个100*100 png 纹理),逐帧做旋转.(博客园视频播放可 ...
- Cocos Creator 资源加载流程剖析【一】——cc.loader与加载管线
这系列文章会对Cocos Creator的资源加载和管理进行深入的剖析.主要包含以下内容: cc.loader与加载管线 Download部分 Load部分 额外流程(MD5 Pipe) 从编辑器到运 ...
- 无需SherlockActionbar的SlidingMenu使用详解(一)——通过SlidingMenu设置容器并解决滑动卡顿的问题
想必很多人都听过这个开源框架,一年前真的是风靡一时.只是它的配置较为繁琐,还需要sherlockActionbar的支持,我这里下载了最新的开源库,并且在实际用套用了AppCompat的官方库,这样就 ...
- android问题及其解决-优化listView卡顿和怎样禁用ListView的fling
问题解决-优化listView卡顿和怎样禁用ListView的fling 前戏非常长,转载请保留出处:http://blog.csdn.net/u012123160/article/details/4 ...
- Cocos Creator 中 _worldMatrix 到底是什么(中)
Cocos Creator 中 _worldMatrix 到底是什么(中) 1. 中篇摘要 在上篇中主要做了三件事 简单表述了矩阵的基本知识,以及需要涉及到的三角函数知识 推导了图形变换中 位移 .旋 ...
- 反复横跳的瞄准线!从向量计算说起!基于射线检测的实现!Cocos Creator!
最近有小伙伴问我瞄准线遇到各种形状该怎么处理?如何实现反复横跳的瞄准线?最近刚好在<Cocos Creator游戏开发实战>中看到物理系统有一个射线检测,于是,基于这个射线检测,写了一个反 ...
- cocos creator屏幕适配的一些知识点
一. cocos creator 提供的几种适配策略 EXACT_FIT: 整个应用程序在指定区域可见,无需尝试保留原始纵横比.可能会出现失真,应用程序会被拉伸或压缩.也就是说设计分辨率的长和宽不会等 ...
- 触控的手牌—Cocos Creator
科普 Cocos Creator是触控最新一代游戏工具链的名称.如果不太清楚的,可以先看一些新闻. 新编辑器Cocos Creator发布: 对不起我来晚了! http://ol.tgbus.co ...
- xamarin MasterDetailPage点击Master时卡顿现象
在很多项目中经常会使用到MasterDetailPage的布局方式,而且一般做为主页面来开发,在开发中,发现一个并不算Bug的问题,但是却发生了,以此记录下来,方便大家探讨. 现象是这样的,我开发了一 ...
随机推荐
- fpread for asp.net 应用技术点滴
单元格的相对性应用 //收支计算平衡 RC[-1]当前行的前一列;R[1]C下一行的同一列 R[-2]C[2]当前行的前2行,当前列的后2列 this.FpSpread1.Sheets[0].Ref ...
- 《Python量化交易教程》第一部分新手入门 第1天:谁来给我讲讲Python?
一.量化投资视频学习课程 二.Python手把手教学 第1天:谁来给我讲讲Python? PS: 1.注意使用方法,这个以后都有大用 2.注意符号的使用方式 3.尽量用英文表达 4.本日学习内容以及其 ...
- win10电脑安装win7
1.进入BIOS,关闭“Secure Boot”功能,启用传统的“Legacy Boot”.预装WIN8的系统想要更换WIN7系统首先需要修改BIOS设置.BIOS设置方法:F2进入BIOS,选择se ...
- rebar3自动编译
功能:修改完代码可以自动编译加载到VM中 必须安装的软件: Linux: inotify 链接https://github.com/rvoicilas/inotify-tools/wiki 配置: ...
- validation-api各注解的用法
入参用@Valid,要不下面实体类中的注解不生效 @AssertFalse 被注解的元素必须为false@AssertTrue 被注解的元素必须为True@DecimalMax(value) 被注解的 ...
- Java中的静态和枚举
一.静态成员 对静态成员最简单的解释,静态成员属于整个类而不属于某个对象,所以又叫做类变量.一个类不管创建多少个实例对象,静态变量在内存中有且只有一个(调用方法用类名调用). 通常的非静态变量称为实例 ...
- myBatis xml if、where、if-else?、foreach 心得
MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦.例如拼接时要确保不能忘记添加必要的空格,还要注意去掉 ...
- Django 安装配置
1-安装Python3.6.1 Python2.x 与3.x的版本在语法上稍有不同,区别在于输出语句的不同,这个可以看相关的文档. Python3.6.1,可以在Python的官网上下载:https: ...
- 201671010142 2017-2 《java第十二十三章学习感悟》
Swing编程第一步,需要导入Swing相关包,即javax.swing.*. 接下里需要设置界面外观风格,使用到UIManager类. 设置完外观之后一定要调用 SwingUtilities.upd ...
- SQL-59 按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推。
题目描述 按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推. 具体结果如下Demo展示..CREATE TABLE `s ...