javascript可绘制圆之间的碰撞检测 [英] javascript collision detection between drawable circles

查看:151
本文介绍了javascript可绘制圆之间的碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




首先,请不要对我的英语太重要。我不是母语。我希望我能解释自己从来不少!更进一步,我读到,我应该显示我做了一些努力,以解决给自己的问题。



我想做什么:



我是新的周)到javascript,我尝试通过html5画布和javascript构建一个池台球桌。最终,用户应当能够通过拖动十六个球来在虚拟池桌上呈现某种游戏情况。我在这里发现了很多关于stackoverflow的提示,涉及路径和拖动&



已经有效:



能够用鼠标移动它们。到目前为止这么好。



问题是什么:



当然,池球在现实中碰撞,交叠。关于碰撞检测我发现一个有用的帖子,告诉我这样做使用毕达哥拉斯aa * a + b * b = c * c。我理解这个概念。我绝对不明白是我必须在我的代码中实现检测。在我的脚本中有一个函数(moveBall00(e)),如果球被拖动(dragok = true),计算新的x和y坐标。但是如何计算球之间的距离,同时计算拖动的球的新坐标?



我试过这个:


  1. p> new variablex



    var x = true;




  2. function collision(){
    if((Math.pow(bp [1] [0] - bp [1] ,2))+(Math.pow(bp [2] [0] -bp [2] [1],2))<= 576){
    x =
    }
    }


  3. 每10毫秒呼叫collision()



    (function isIntersecting(){
    return setInterval(collision,10);
    })();


  4. ball ifx = true



    function moveBall00(e){
    if(dragok& x){
    bp [1] [0] = e.pageX - canvas.offsetLeft;
    bp [2] [0] = e.pageY - canvas.offsetTop;
    }
    }


结果是圆圈休息。他们重叠的越多,我拖动球越快。



对于经验丰富的开发人员来说,这是最确定的步行公园,但不适合我。



我是坚持类型,并将学习在javascript中做这个东西,但是目前我没有如何解决上述问题的线索。


$ b



这是我到目前为止做的:



(为了简化,只有白色的球是可绘制的)。

 <!doctype html& 

< html>

< head>
< meta charset =UTF-8/>
< title>碰撞检测< / title>
< / head>

< body>

< canvas id =pooltablewidth =1200height =660>如果您的浏览器不支持HTML5 Canvas,则会显示此文本< / canvas&

< script>

var canvas;
var ctx;
var width = 1200;
var height = 660;
var dragok = false;

var bp = new Array();
//颜色的球ballColor
bp [0] = new Array(rgba(255,255,255,1),rgba(231,214,8,1));
// x-position of ballsxBallPosition
bp [1] = new Array(20,50);
// y-position of ballsyBallPosition
bp [2] = new Array(50,50);
//颜色的条纹条纹
bp [3] = new Array(rgba(255,255,255,0),rgba(231,214,8,1));
//条纹颜色stripeStroke
bp [4] = new Array(rgba(255,255,255,0),rgba(231,214,8,1));
//球数ballNumber
bp [5] = new Array(,1);
//球数位置positionBallNumber
bp [6] = new Array();

function init(){
canvas = document.getElementById(pooltable);
ctx = canvas.getContext(2d);
return setInterval(draw,1);
}

function clear(){
ctx.clearRect(0,0,width,height);
}

function rect(x,y,w,h){
ctx.beginPath();
ctx.rect(x,y,w,h);
ctx.closePath();
ctx.fill();
}

function ball(ballColor,xBallPosition,yBallPosition,ballRadius,angle,stripe,stripeStroke,circleRadius,ballNumber,positionBallNumber){

ctx.fillStyle = ballColor ;
ctx.shadowBlur = 5;
ctx.shadowColor =rgba(0,0,0,1);
ctx.beginPath();
ctx.arc(xBallPosition,yBallPosition,ballRadius,angle,Math.PI * 2,true);
ctx.closePath();
ctx.fill();

ctx.fillStyle = stripe;
ctx.strokeStyle = stripeStroke;
ctx.shadowColor =rgba(0,0,0,0);
ctx.beginPath();
ctx.moveTo(xBallPosition - 7,yBallPosition - 8);
ctx.bezierCurveTo(xBallPosition - 8,yBallPosition - 13,xBallPosition + 8,yBallPosition - 13,xBallPosition + 7,yBallPosition - 8);
ctx.lineTo(xBallPosition + 7,yBallPosition + 8);
ctx.bezierCurveTo(xBallPosition + 8,yBallPosition + 13,xBallPosition - 8,yBallPosition + 13,xBallPosition - 7,yBallPosition + 8);
ctx.closePath();
ctx.stroke();
ctx.fill();

ctx.fillStyle =rgba(255,255,255,1);
ctx.shadowColor =rgba(0,0,0,0);
ctx.beginPath();
ctx.arc(xBallPosition,yBallPosition,circleRadius,angle,Math.PI * 2,true);
ctx.closePath();
ctx.fill();

ctx.fillStyle =rgba(0,0,0,1);
ctx.font =normal normal lighter 7px Helvetica;
ctx.textBaseline =middle;
ctx.fillText(ballNumber,xBallPosition - positionBallNumber,yBallPosition + 1);

var gradient = ctx.createRadialGradient(xBallPosition,yBallPosition,1,xBallPosition + 3,yBallPosition + 3,12);
gradient.addColorStop(0,rgba(255,255,55,0.6));
gradient.addColorStop(1,rgba(0,0,0,0.2));
ctx.fillStyle = gradient;
ctx.strokeStyle =rgba(0,0,0,0.4);
ctx.shadowColor =rgba(0,0,0,0);
ctx.beginPath();
ctx.arc(xBallPosition,yBallPosition,ballRadius,angle,Math.PI * 2,true);
ctx.closePath();
ctx.stroke();
ctx.fill();

}

function draw(){

clear();

table = new rect(0,0,width,height);

ball00 = new ball(bp [0] [0],bp [1] [0],bp [2] [0],12,0,bp [3] [4] [0],6,bp [5] [0],0);
ball01 = new ball(bp [0] [1],bp [1] [1],bp [2] [1],12,0bp [3] [0] 1],6,bp [5] [1],2);

}

function myDown(e){
if(e.pageX bp [1] [0] = e.pageX - canvas.offsetLeft;
bp [2] [0] = e.pageY - canvas.offsetTop;
dragok = true;
canvas.onmousemove = moveBall00;
}
else {
dragok = false;
}
}

function myUp(){
dragok = false;
canvas.onmousemove = null;
}

function moveBall00(e){
if(dragok){
bp [1] [0] = e.pageX - canvas.offsetLeft;
bp [2] [0] = e.pageY - canvas.offsetTop;
}
}

init();

canvas.onmousedown = myDown;
canvas.onmouseup = myUp;

< / script>

< / body>

< / html>


解决方案

您面对的问题与底层渲染技术。这只是一个数学问题。



你基本上想要做的事情是计算你拖动的球和桌上的任何球之间的距离。如果距离太短,碰撞发生。



对于两个对象,这很简单,你需要三个值:球的x和y坐标及其半径。 / p>

  var ball = {
x:100,
y:100
r:10
};

要计算您的距离:

  var squareX = Math.pow(Math.abs(ballA.x-ballB.x),2); 
var squareY = Math.pow(Math.abs(ballA.y - ballB.y),2);
var hypothenuse = Math.sqrt(squareX + squareY);
var distance = hypothenuse - ballA.r - ballB.r;

if(distance> = 0){
//新位置有效
}

因为你有一个球在一个台球桌上,你需要调用这个代码一次,每个球的桌子上,没有移动比较所有的球。

  function canMove(ballA,ballB){
var squareX = Math.pow(Math.abs(ballA.x - ballB.x) ,2);
var squareY = Math.pow(Math.abs(ballA.y - ballB.y),2);
var hypothenuse = Math.sqrt(squareX + squareY);
var distance = hypothenuse - ballA.r - ballB.r;

if(distance> = 0){
return true;
}
return false;
}


函数canDrag(ball,balls){
var isMovable = true;
for(var i = balls.length-1; i> = 0; i--){
isMovable = canMove(ball,balls [i]);
if(!isMovable){
return false;
}
}
return true;
}

在上一个代码段中,我假设你的球对象存储在球数组。我希望这有助于。



First of all please don't be too critical with my English. I'm not a native speaker. I hope I can explain myself never the less! Further more, I read that I should show I made some efforts to solve the given problem myself. To show this my post became relatively long.

What I want to do:

I am new (three weeks) to javascript and I try to build a pool billiard table via html5 canvas and javascript. In the end a user should be able to present a certain playing situation on the virtual pool tabe by dragging the sixteen balls around. I found a lot of hints here on stackoverflow concerning paths and drag & drop.

What already works:

By the while the circles almost look like pool balls and I'm able to move them around with the mouse. So far so good.

What the problem is:

Certainly pool balls collide in reality and don't overlap. Concerning the collision detection I found a helpful post which told me to do this using the Pythagorean therm a*a + b*b = c*c. I understand this concept. What I definitely don't understand is where I have to implement the detection within my code. In my script there is a function (moveBall00(e)) which calculates the new x- and y-coordinates if the balls are dragged around (dragok = true). But how can a calculation of the distance between the balls be made while the new coordinates of the dragged ball are calculated at the same time? This could easily be newbie-question!

I tried this:

  1. new variable "x"

    var x = true;

  2. new function to detect the distance between the balls

    function collision() { if((Math.pow(bp[1][0] - bp[1][1], 2)) + (Math.pow(bp[2][0] - bp[2][1], 2)) <= 576 ) { x = false; } }

  3. call "collision()" every 10 millisecounds

    (function isIntersecting() { return setInterval(collision, 10); })();

  4. only drag the ball if "x=true"

    function moveBall00(e) { if (dragok && x) { bp[1][0] = e.pageX - canvas.offsetLeft; bp[2][0] = e.pageY - canvas.offsetTop; } }

The result is that the circles (balls) overlaped until they came to a rest. They overlaped the more the quicker I dragged the ball. This seams to be a first-after-problem?!

For experienced developers it is most certain a walk through the park but not for me.

I'm the insistent type and will learn to do this stuff in javascript but at the moment I have no clue on how to solve the mentioned problem.

I would appreciate any help with this an will post the future result here!

Here is what I did so far:

(To simplify it only the white ball is drawable.)

<!doctype html>

<html>

    <head>
    <meta charset="UTF-8" />
            <title>Collision detection</title>
    </head>

    <body>

            <canvas id="pooltable" width="1200" height="660">This text is displayed if your browser does not support HTML5 Canvas</canvas>

        <script>

            var canvas;
            var ctx;
            var width = 1200;
            var height = 660;
            var dragok = false;

            var bp = new Array();
                // color of balls "ballColor"
                bp[0] = new Array("rgba(255,255,255,1)","rgba(231,214,8,1)");
                // x-position of balls "xBallPosition"
                bp[1] = new Array(20,50);
                // y-position of balls "yBallPosition"
                bp[2] = new Array(50,50);
                // color of stripes "stripe"
                bp[3] = new Array("rgba(255,255,255,0)","rgba(231,214,8,1)");
                // color of stripe strokes "stripeStroke"
                bp[4] = new Array("rgba(255,255,255,0)","rgba(231,214,8,1)");
                // ball numbers "ballNumber"
                bp[5] = new Array(" ","1");
                // position of ball numbers "positionBallNumber"
                bp[6] = new Array();

            function init() {
                canvas = document.getElementById("pooltable");
                ctx = canvas.getContext("2d");
                return setInterval(draw, 1);
            }

            function clear() {
                ctx.clearRect(0, 0, width, height);
            }

            function rect(x,y,w,h) {
                ctx.beginPath();
                ctx.rect(x,y,w,h);
                ctx.closePath();
                ctx.fill();
            }

            function ball(ballColor, xBallPosition, yBallPosition, ballRadius, angle, stripe, stripeStroke, circleRadius, ballNumber, positionBallNumber) {

                ctx.fillStyle = ballColor;
                ctx.shadowBlur = 5;
                ctx.shadowColor = "rgba(0,0,0,1)";
                ctx.beginPath();
                ctx.arc(xBallPosition, yBallPosition, ballRadius, angle, Math.PI * 2, true);
                ctx.closePath();
                ctx.fill();

                ctx.fillStyle = stripe;
                ctx.strokeStyle = stripeStroke;
                ctx.shadowColor = "rgba(0,0,0,0)";
                ctx.beginPath();
                ctx.moveTo(xBallPosition - 7, yBallPosition - 8);
                ctx.bezierCurveTo(xBallPosition - 8, yBallPosition - 13, xBallPosition + 8, yBallPosition - 13, xBallPosition + 7, yBallPosition - 8);
                ctx.lineTo(xBallPosition + 7, yBallPosition + 8);
                ctx.bezierCurveTo(xBallPosition + 8, yBallPosition + 13, xBallPosition - 8, yBallPosition + 13, xBallPosition - 7, yBallPosition + 8);
                ctx.closePath();
                ctx.stroke();
                ctx.fill();

                ctx.fillStyle =  "rgba(255,255,255,1)";
                ctx.shadowColor = "rgba(0,0,0,0)";
                ctx.beginPath();
                ctx.arc(xBallPosition, yBallPosition, circleRadius, angle, Math.PI * 2, true);
                ctx.closePath();
                ctx.fill();

                ctx.fillStyle = "rgba(0,0,0,1)";
                ctx.font = "normal normal lighter 7px Helvetica";
                ctx.textBaseline = "middle";
                ctx.fillText(ballNumber, xBallPosition - positionBallNumber, yBallPosition + 1);

                var gradient = ctx.createRadialGradient(xBallPosition, yBallPosition, 1, xBallPosition + 3, yBallPosition + 3, 12);
                gradient.addColorStop(0, "rgba(255,255,255,0.6)");
                gradient.addColorStop(1, "rgba(0,0,0,0.2)");
                ctx.fillStyle = gradient;
                ctx.strokeStyle = "rgba(0,0,0,0.4)";
                ctx.shadowColor = "rgba(0,0,0,0)";
                ctx.beginPath();
                ctx.arc(xBallPosition, yBallPosition, ballRadius, angle, Math.PI * 2, true);
                ctx.closePath();
                ctx.stroke();
                ctx.fill();

            }

            function draw() {

                clear();

                table = new rect(0,0,width,height);

                ball00 = new ball(bp[0][0], bp[1][0], bp[2][0], 12, 0, bp[3][0], bp[4][0], 6, bp[5][0], 0);
                ball01 = new ball(bp[0][1], bp[1][1], bp[2][1], 12, 0, bp[3][0], bp[4][1], 6, bp[5][1], 2);

            }

            function myDown(e) {
                if (e.pageX < bp[1][0] + 6 + canvas.offsetLeft && e.pageX > bp[1][0] - 6 + canvas.offsetLeft && e.pageY < bp[2][0] + 6 + canvas.offsetTop && e.pageY > bp[2][0] - 6 + canvas.offsetTop) {
                    bp[1][0] = e.pageX - canvas.offsetLeft;
                    bp[2][0] = e.pageY - canvas.offsetTop;
                    dragok = true;
                    canvas.onmousemove = moveBall00;
                }
                else {
                    dragok = false;
                }
            }

            function myUp() {
                dragok = false;
                canvas.onmousemove = null;
            }

            function moveBall00(e) {
                if (dragok) {
                    bp[1][0] = e.pageX - canvas.offsetLeft;
                    bp[2][0] = e.pageY - canvas.offsetTop;
                }
            }

            init();

            canvas.onmousedown = myDown;
            canvas.onmouseup = myUp;

        </script>

    </body>

</html>

解决方案

The problem you are facing is totally unrelated to the underlying rendering techinique. This is just a math problem.

What you basically want to do for your situation is calculate the distance between the ball you drag and any ball on the table. If the distance is too short a collision happened.

For two objects this is simple, you need three values: The x and y coordinates of the balls and their radii.

var ball = {
    x: 100,
    y: 100
    r: 10
};

To calculate the distance you do this:

var squareX = Math.pow(Math.abs(ballA.x - ballB.x), 2);
var squareY = Math.pow(Math.abs(ballA.y - ballB.y), 2);
var hypothenuse = Math.sqrt(squareX + squareY);
var distance = hypothenuse - ballA.r - ballB.r;

if (distance >= 0) {
    // new position is valid
}

Since you have a number of balls on a pool table you need to call this code once for each ball on the table that is not moved to compare all of them.

function canMove(ballA, ballB) {
    var squareX = Math.pow(Math.abs(ballA.x - ballB.x), 2);
    var squareY = Math.pow(Math.abs(ballA.y - ballB.y), 2);
    var hypothenuse = Math.sqrt(squareX + squareY);
    var distance = hypothenuse - ballA.r - ballB.r;

    if (distance >= 0) {
        return true;
    }
    return false;
}


function canDrag(ball, balls) {
    var isMovable = true;
    for (var i = balls.length-1; i >= 0; i--) {
        isMovable = canMove(ball, balls[i]);
        if (!isMovable) {
            return false;
        }
    }
    return true;
}

In the last snippet I assumed that your ball objects are stored in the balls array. I hope this helps.

这篇关于javascript可绘制圆之间的碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆