**问题描述:**在项目开发中,使用到了刚体, 在搭建地图过程中,发现两个相邻的砖块,即使贴合的再紧密,但星星人在上面走动的时候还是会有很大概率发生卡顿(被两个刚体的边界处卡住)。为了解决这个问题,我们小组对砖块进行了分类处理。
**处理过程如下:**将所有左上角的砖块(左边和上边都不是砖块的砖块)当做特殊砖块(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 刚体卡顿问题(边界会卡住)的更多相关文章

  1. iOS 14 egret 游戏卡顿问题分析和部分解决办法

    现象 总体而言,iOS 14 渲染性能变差,可以从以下三个测试看出. 测试1:简单demo,使用egret引擎显示3000个图(都是同一个100*100 png 纹理),逐帧做旋转.(博客园视频播放可 ...

  2. Cocos Creator 资源加载流程剖析【一】——cc.loader与加载管线

    这系列文章会对Cocos Creator的资源加载和管理进行深入的剖析.主要包含以下内容: cc.loader与加载管线 Download部分 Load部分 额外流程(MD5 Pipe) 从编辑器到运 ...

  3. 无需SherlockActionbar的SlidingMenu使用详解(一)——通过SlidingMenu设置容器并解决滑动卡顿的问题

    想必很多人都听过这个开源框架,一年前真的是风靡一时.只是它的配置较为繁琐,还需要sherlockActionbar的支持,我这里下载了最新的开源库,并且在实际用套用了AppCompat的官方库,这样就 ...

  4. android问题及其解决-优化listView卡顿和怎样禁用ListView的fling

    问题解决-优化listView卡顿和怎样禁用ListView的fling 前戏非常长,转载请保留出处:http://blog.csdn.net/u012123160/article/details/4 ...

  5. Cocos Creator 中 _worldMatrix 到底是什么(中)

    Cocos Creator 中 _worldMatrix 到底是什么(中) 1. 中篇摘要 在上篇中主要做了三件事 简单表述了矩阵的基本知识,以及需要涉及到的三角函数知识 推导了图形变换中 位移 .旋 ...

  6. 反复横跳的瞄准线!从向量计算说起!基于射线检测的实现!Cocos Creator!

    最近有小伙伴问我瞄准线遇到各种形状该怎么处理?如何实现反复横跳的瞄准线?最近刚好在<Cocos Creator游戏开发实战>中看到物理系统有一个射线检测,于是,基于这个射线检测,写了一个反 ...

  7. cocos creator屏幕适配的一些知识点

    一. cocos creator 提供的几种适配策略 EXACT_FIT: 整个应用程序在指定区域可见,无需尝试保留原始纵横比.可能会出现失真,应用程序会被拉伸或压缩.也就是说设计分辨率的长和宽不会等 ...

  8. 触控的手牌—Cocos Creator

    科普 Cocos Creator是触控最新一代游戏工具链的名称.如果不太清楚的,可以先看一些新闻.   新编辑器Cocos Creator发布: 对不起我来晚了! http://ol.tgbus.co ...

  9. xamarin MasterDetailPage点击Master时卡顿现象

    在很多项目中经常会使用到MasterDetailPage的布局方式,而且一般做为主页面来开发,在开发中,发现一个并不算Bug的问题,但是却发生了,以此记录下来,方便大家探讨. 现象是这样的,我开发了一 ...

随机推荐

  1. 【重磅】Spring Boot 2.0权威发布

    新版本特性 新版本值得关注的亮点有哪些: 基于 Java 8,支持 Java 9 也就是说Spring Boot2.0的最低版本要求为JDK8,据了解国内大部分的互联网公司系统都还跑在JDK1.6/7 ...

  2. 软件151 王楚博 JavaEE的配置

    一.准备以下压缩包 1.JDK1.7 文件:jdk1.7.rar 2. eclipse-jee-mars-2 文件:32位系统准备eclipse-jee-mars-2-win32.zip,64位系统准 ...

  3. C# 反射及应用

    一.什么是反射 反射(Reflection)可以在运行时获 得.NET中每一个类型(包括类.结构.委托.接口和枚举等)的成员,包括方法.属性.事件,以及构造函数等.还可以获得每个成员的名称.限定符和参 ...

  4. Judy Beta 第二天

    Intro 我们采取的code review方式是两人一组,每个人在自己的分支上完成工作后向master分支发起pull request,小组的另一人对pr进行review后merge进入原仓库.gi ...

  5. Windows操作系统下搭建Git服务器和客户端。

    本文将介绍如何在Windows操作系统下搭建Git服务器和客户端.服务器端采用的是Bonobo Git Server,一款用ASP.NET MVC开发的Git源代码管理工具,界面简洁,基于Web方式配 ...

  6. 前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    写在前面 参考答案及资源在看云平台发布,如果大家想领取资源以及查看答案,可直接前去购买.一次购买永久可看,文档长期更新!有什么意见与建议欢迎您及时联系作者或留言回复! 文档描述 本文是关注微信小程序的 ...

  7. .net公众号开发自动回复消息

    using System;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web. ...

  8. OTP gen_server

    erlang behaviour小结之gen_server OTP入门 分类: Erlang2012-08-06 18:55 867人阅读 评论(0) 收藏 举报 servererlangcallba ...

  9. APP测试报告

    招标手机APP测试总结报告     作    者: 日    期: 2016-03-10 文档编号: 002 版    本: Ver 1.0 目   录 1.测试概述 1 1.1. 编写目的 1 1. ...

  10. 自己练习的一个小的demo的时候a标签关于href链接的问题

    一.Js的几种调用方法(参考总结的) 1.a href="javascript:js_method();" 这是常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且 ...