• 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. 大大减少了刚体精灵的绘制数量,对性能有一定的提升

  • 相关阅读:
    P2832 行路难
    P2634 [国家集训队]聪聪可可
    模拟退火算法
    洛谷 P2986 [USACO10MAR]Great Cow Gat…(树形dp+容斥原理)
    bzoj1040: [ZJOI2008]骑士(基环树dp)
    洛谷P2014 选课(树形dp)
    洛谷P3047 [USACO12FEB]Nearby Cows(树形dp)
    bzoj1026: [SCOI2009]windy数(数位dp)
    hdu3555Bomb(数位dp)
    hdu3652B-number(数位dp)
  • 原文地址:https://www.cnblogs.com/ldy520/p/9803898.html
Copyright © 2020-2023  润新知