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

  • 相关阅读:
    比较完整的HIS系统解释(转载记录)
    ajax读取XML文本(如读取城市)
    js实现自定义右键菜单--兼容IE、Firefox、Chrome
    元素间距属性(scrollLeft,scrollWidth,clientWidth,offsetWidth,padding,margin)
    Js控制iFrame切换加载网址
    比较两个数据库表table结构不同之处
    SQL Server 查询、搜索命令、语句
    Jquery简单瀑布流代码示例
    jQuery中添加自定义或函数方法
    Jmeter脚本增强之参数化(关联数据库)(7)
  • 原文地址:https://www.cnblogs.com/ldy520/p/9803898.html
Copyright © 2011-2022 走看看