nzbin编译

  我正在开发一个需要再次使用碰撞检测的游戏。我通常会使用简单高效的盒模型碰撞检测。盒子模型的主要原则就是把所有的物体都抽象成正方形,如果两个正方形有重叠,就认为是一次碰撞。这通常是一个简单的游戏所需要的。但是因为这种模型我之前用过多次,我想尝试一些更深刻更准确的方法。

  我选择从像素级层面来看是否发生了碰撞。首先我要了解“像素是什么”。我测试的元素透明度都不为0,换句话说,所有的可见像素都被看做一个碰撞点。为了提高算法效率,我预先创建了一张图片的像素映射图。换句话说,就是一个数组内包含了屏幕上的所有可见像素。

 

 

  1. /* 描述像素图的伪代码 */
  2. var pixelMap = [];
  3. for( var y = 0; y < image.width; y++ ) {
  4. for( var x = 0; x < image.height; x++ ) {
  5. // 获取当前位置的元素
  6. var pixel = ctx.getImageData( x, y, 1, 1 );
  7. // 判断透明度不为0
  8. if( pixel.data[3] != 0 ) {
  9. pixelMap.push( { x:x, y:y } );
  10. }
  11. }
  12. }
  13. return pixelMap;

 

  1. /* 像素碰撞检测的伪代码 */
    • function pixelHitTest( source, target ) {
      • // 循环源图像的所有像素
        • for( var s = 0; s < source.pixelMap.length; s++ ) {
          • var sourcePixel = source.pixelMap[s];
            • // 添加位置偏移
              • var sourceArea = {
                • x: sourcePixel.x + source.x,
                  • y: sourcePixel.y + source.y,
                    • width: 1,
                      • height: 1
                        • };
                          •  
                          • // 循环目标图像的所有像素
                            • for( var t = 0; t < target.pixelMap.length; t++ ) {
                              • var targetPixel = target.pixelMap[t];
                                • // 添加位置偏移
                                  • var targetArea = {
                                    • x: targetPixel.x + target.x,
                                      • y: targetPixel.y + target.y,
                                        • width: 1,
                                          • height: 1
                                            • };
                                              •  
                                              • /* 使用之前提到的 hitbox 函数 */
                                                • if( hitBox( sourceArea, targetArea ) ) {
                                                  • return true;
                                                    • }
                                                      • }
                                                        • }
                                                          • }

 

  1. /* 描绘更大分辨率像素图的伪代码 */
    • function generateRenderMap( image, resolution ) {
      • var pixelMap = [];
        • for( var y = 0; y < image.width; y=y+resolution ) {
          • for( var x = 0; x < image.height; x=x+resolution ) {
            • // 获取当前位置的像素群
              • var pixel = ctx.getImageData( x, y, resolution, resolution );
                •  
                • // 判断像素群的透明度不为0
                  • if( pixel.data[3] != 0 ) {
                    • pixelMap.push( { x:x, y:y } );
                      • }
                        • }
                          • }
                            • return {
                              • data: pixelMap,
                                • resolution: resolution
                                  • };
                                    • }
                                      •  
                                      • /* 像素碰撞测试伪代码 */
                                        • function pixelHitTest( source, target ) {
                                          •  
                                          • // 源对象和目标对象包含两张属性
                                            • // { data: a render-map, resolution: The precision of the render-map}
                                              •  
                                              • // 循环源对象的所有像素
                                                • for( var s = 0; s < source.pixelMap.data.length; s++ ) {
                                                  • var sourcePixel = source.data.pixelMap[s];
                                                    • // 添加位置偏移
                                                      • var sourceArea = {
                                                        • x: sourcePixel.x + source.x,
                                                          • y: sourcePixel.y + source.y,
                                                            • width: target.pixelMap.resolution,
                                                              • height: target.pixelMap.resolution
                                                                • };
                                                                  •  
                                                                  • // 循环源对象的所有像素
                                                                    • for( var t = 0; t < target.pixelMap.data.length; t++ ) {
                                                                      • var targetPixel = target.pixelMap.data[t];
                                                                        • // 添加位置偏移
                                                                          • var targetArea = {
                                                                            • x: targetPixel.x + target.x,
                                                                              • y: targetPixel.y + target.y,
                                                                                • width: target.pixelMap.resolution,
                                                                                  • height: target.pixelMap.resolution
                                                                                    • };
                                                                                      •  
                                                                                      • /*使用之前提到的 hitbox 函数 */
                                                                                        • if( hitBox( sourceArea, targetArea ) ) {
                                                                                          • return true;
                                                                                            • }
                                                                                              • }
                                                                                                • }
                                                                                                  • }
复制代码
  同样的40X40的像素块如今只有100组像素点,而之前是有1600像素的图像。我们将2650000次的计算量降低到10000次的计算量,只有原始 计算量的0.39%。如果你有更多不同分辨率的渲染图,你会建立精度更高的系统,从分辨率大的像素群开始依次计算,当然系统的复杂度也会逐渐提高。在两个 40X40像素的圆形物体上使用3的分辨率(13.33X13.33),当前的方案在最差的碰撞测试中会耗时1-2ms。

  相关阅读安全开发之碰撞检测与伤害计算逻辑

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛