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的问题,但是却发生了,以此记录下来,方便大家探讨. 现象是这样的,我开发了一 ...
随机推荐
- spark优化整理
- Android中的Context(一)
Android中的Context(一) 在Android开发中,Context可以说是我们接触地非常多的一个概念了,也译作"上下文",但是这个上下文到底是什么却并不好理解. 通俗的 ...
- Haxe东游记(上)part1.5:roadmap
part1.6 = 常用API参考 1.5.7 -> 官方手册目录/总结/中文化 1.8 -> 官方示例/讲解/总结 1.5.6-> haxe整体结构/解析/综述 part2 = 中 ...
- java -jar启动java项目时,引用不同配置文件命令
java -jar eureka-server.jar --spring.profiles.active=peer1
- Windows操作系统下搭建Git服务器和客户端。
本文将介绍如何在Windows操作系统下搭建Git服务器和客户端.服务器端采用的是Bonobo Git Server,一款用ASP.NET MVC开发的Git源代码管理工具,界面简洁,基于Web方式配 ...
- ABP-DDD学习
有一个比较大的项目,打算使用 DDD +ABP +微服务 开发: 1.涉及到社交: 业务场景比较复杂:会多变: 2.采用前后端分离,netcore+vue; 3.部署采用K8S +docker 进行部 ...
- 基于react的MQ管理系统遇到的问题以及解决办法
跟一般的管理系统差不多 一.需求 1.新增申请和修改的弹窗里面的部门跟应用组改成下拉框,并调取后台接口获取到相应的值.1.1相应的代码 // 获取部门 getDepartment = () => ...
- sql在所有存储过程中查询包含某字符串的执行语句
直接在查询分析器中执行以下代码就行: 方法一) select name from sysobjects o, syscomments s where o.id = s.id and text like ...
- JavaWeb项目三要素
- [Paper][Link note]
http://ieeexplore.ieee.org/document/6974670/