【问题标题】:How do you calculate the radius of the smallest circle-shape that a sprite would fit in?你如何计算精灵适合的最小圆形的半径?
【发布时间】:2014-03-26 00:32:47
【问题描述】:

我正在用 HTML5 JS 制作游戏。

在游戏中,由于我的精灵在旋转,所以我通过圆形进行碰撞。

玩家拥有不同的形状,因为当它持有不同的武器时,它具有不同的精灵。

玩家的半径是精灵宽度/高度的一半。

精灵的大小从 16x16 调整为 50x50 像素(50 / 16 = 3.125,因此大 3.125 倍)

我的问题是:如何计算精灵适合的最小圆形的半径?像这样:

普通精灵:http://imgur.com/wWS1nDy

红色 = 计算半径(如何?),蓝色 = 我使用的半径(精灵宽度或高度 / 2):http://imgur.com/kytpRPz

(为了更好地查看图像,请在图像程序中打开它们或放大。)

【问题讨论】:

    标签: javascript html canvas sprite collision


    【解决方案1】:

    获得答案的几个步骤...

    演示:http://jsfiddle.net/m1erickson/hvT63/

    确定播放器像素的边界框(不包括透明像素)。

    • 使用 .getImageData 获取图像的单个像素数据。

    • 检查左侧的每个垂直列并确定第一个播放器像素出现的位置。

    • 检查右侧的每个垂直列并确定第一个播放器像素出现的位置。

    • 从顶部检查每个水平行并确定第一个播放器像素出现的位置。

    • 从底部检查每个水平行并确定第一个播放器像素出现的位置。

    现在您有了上、左、下和右边界值。

    确定边界框的半径(== 其对角线的一半):

    var dx=right-left;
    var dy=bottom-top;
    var radius=Math.sqrt(dx*dx+dy*dy)/2;
    

    所以你的包含圆具有计算出的半径。

    示例代码如下:

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; padding:20px; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        ctx.translate(.5,.5);
    
        var img=new Image();
        img.crossOrigin="anonymous";
        img.onload=start;
        img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/sprite.png";
    
        function start(){
    
            var cw=canvas.width;
            var ch=canvas.height;
    
            ctx.drawImage(img,cw/2-img.width/2,ch/2-img.height/2);
    
            var data=ctx.getImageData(0,0,cw,ch).data;
            var leftX=getLeft(data,cw,ch);
            var rightX=getRight(data,cw,ch);
            var topY=getTop(data,cw,ch);
            var bottomY=getBottom(data,cw,ch);
            var w=rightX-leftX;
            var h=bottomY-topY;
            var cx=leftX+w/2;
            var cy=topY+h/2;
            var radius=Math.sqrt(w*w+h*h)/2;
    
            ctx.beginPath();
            ctx.arc(leftX+w/2,topY+h/2,radius,0,Math.PI*2);
            ctx.closePath();
            ctx.stroke();
    
            ctx.strokeRect(leftX,topY,w,h);
    
        }
    
        function getLeft(data,width,height){
            for(var x=0;x<width;x++)
            for(var y=0;y<height;y++)
            {
                if(data[(width*y+x)*4+3]>0){ return(x); }
            }
        }
    
        function getRight(data,width,height){
            for(var x=width-1;x>=0;x--)
            for(var y=height-1;y>=0;y--)
            {
                if(data[(width*y+x)*4+3]>0){ return(x); }
            }
        }
    
        function getTop(data,width,height){
            for(var y=0;y<height;y++)
            for(var x=0;x<width;x++)
            {
                if(data[(width*y+x)*4+3]>0){ return(y); }
            }
        }
    
        function getBottom(data,width,height){
            for(var y=height-1;y>=0;y--)
            for(var x=width-1;x>=0;x--)
            {
                if(data[(width*y+x)*4+3]>0){ return(y); }
            }
        }
    
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <h4>1. Calc boundingbox of non-transparent pixels<br>2. Calc radius that contains that boundingbox</h4>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

      【解决方案2】:

      假设您有一个带有width = wheight = h 的矩形精灵。有两种选择:

      • 外圆:简单计算矩形的斜边r = sqrt(w^2 + h^2)

      • 内圆:在这种情况下,直径将是矩形的最短边。例如:r = w/2

      至于透明像素。是固定大小的透明边界吗?如果是这样,那么只需从半径计算中减去该值。如果没有,那么你可以试试这个:

      • 加载图片
      • 从最外层像素开始,检查是否有透明像素
      • 如果是,则移动到下一层
      • 等等
      • 一旦找到没有透明像素的图层,停止

      您现在知道有多少个透明像素。只需从半径计算中减去它。

      如果您不知道如何获取像素颜色,这可能会有所帮助:Get pixel color from canvas, on mouseover

      当然,每次都这样做会很慢。我建议在 Photoshop 或其他任何工具中打开您的精灵并测量适当的大小。


      听起来您正在尝试实现非圆形的像素完美碰撞。也许你应该研究一下,例如:Per-Pixel collision code

      【讨论】:

        【解决方案3】:

        您的精灵是均匀的圆形还是旋转的矩形/正方形?在正方形和矩形的情况下,您需要找到斜边(使用勾股定理),然后将其中的一半用作半径。这样,当您旋转它时,最长的对角线将始终适合该框。圈子是给定的。

        【讨论】:

        • 不,我的意思是如何让精灵内的实际“玩家”的半径适合一个圆圈
        • 播放器周围有透明的像素,不应该计算在内。
        猜你喜欢
        • 2017-04-07
        • 2018-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多