8

まず第一に、私の英語に批判的になりすぎないでください。私はネイティブスピーカーではありません。それでも自分自身を説明できることを願っています!さらに、与えられた問題を自分で解決するために何らかの努力をしたことを示す必要があることを読みました。これを示すために、私の投稿は比較的長くなりました。

私がしたいこと:

私は JavaScript を初めて使用し (3 週間)、html5 キャンバスと JavaScript を使用してプール ビリヤード テーブルを構築しようとしています。最終的に、ユーザーは 16 個のボールをドラッグすることで、仮想プール テーブルで特定のプレイ状況を提示できるはずです。ここで、パスとドラッグ アンド ドロップに関するスタックオーバーフローに関する多くのヒントを見つけました。

すでに機能しているもの:

その間、円はほとんどビリヤードのボールのように見え、マウスで動かすことができます。ここまでは順調ですね。

問題は何ですか:

確かにビリヤードのボールは現実に衝突し、重なることはありません。衝突検出に関しては、ピタゴラスのサーム a*a + b*b = c*c を使用してこれを行うように指示された役立つ投稿を見つけました。私はこの概念を理解しています。私が絶対に理解していないのは、コード内で検出を実装する必要がある場所です。私のスクリプトには、ボールがドラッグされた場合 (dragok = true)、新しい x 座標と y 座標を計算する関数 (moveBall00(e)) があります。しかし、ドラッグされたボールの新しい座標を同時に計算しながら、ボール間の距離を計算するにはどうすればよいでしょうか? これは簡単に初心者の質問になる可能性があります。

私はこれを試しました:

  1. 新しい変数「x」</p>

    変数 x = 真;

  2. ボール間の距離を検出する新機能

    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. 10 ミリ秒ごとに「collision()」を呼び出す

    (関数 isIntersecting() { return setInterval(collision, 10); })();

  4. 「x=true」の場合のみボールをドラッグ</p>

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

その結果、円 (ボール) が停止するまで重なりました。それらは、ボールをドラッグするのが速ければ速いほど重なりました。これは最初の問題の継ぎ目ですか?!

経験豊富な開発者にとっては、公園を散歩するのが最も確実ですが、私にとってはそうではありません.

私はしつこいタイプで、javascript でこのようなことを行うことを学びますが、現時点では、言及された問題を解決する方法についての手がかりがありません。

これについて何か助けていただければ幸いです。今後の結果をここに投稿します。

これが私がこれまでにしたことです:

(単純化するために、白いボールのみが描画可能です。)

<!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>
4

1 に答える 1

5

あなたが直面している問題は、基礎となるレンダリング技術とはまったく関係ありません。これは単なる数学の問題です。

あなたの状況で基本的にやりたいことは、ドラッグしたボールとテーブル上のボールとの間の距離を計算することです。距離が短すぎると、衝突が発生しました。

2 つのオブジェクトの場合、これは単純です。3 つの値が必要です。ボールの x 座標と y 座標、およびそれらの半径です。

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) {
    // new position is valid
}

ビリヤード台には多数のボールがあるため、すべてのボールを比較するには、テーブル上の動かされていないボールごとにこのコードを 1 回呼び出す必要があります。

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;
}

最後のスニペットでは、ボール オブジェクトがボール配列に格納されていると仮定しました。これが役立つことを願っています。

于 2012-10-18T11:01:00.083 に答える