0

JavaScriptコードに問題があります。それぞれの円が独自の属性を持つ、動く円のセットを作成しようとしています。これまでのところ、必要なすべての値を配列に入力することができましたが、キャンバスに描画するためにそれらを適切に使用する方法がわかりません。

これがjavascriptです:

var radius = 10;
var step = x = y = 0;
var r = g = b = 255;
var circleHolder = [];
var loop = setInterval(function(){update();}, 30);

function Circle(x, y, radius, r, g, b)
{
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.r = r;
    this.g = g;
    this.b = b;
    circleHolder.push(this);
}

Circle.prototype.draw = function()
{
    Circle.prototype.ctx = document.getElementById("MyCanvas").getContext("2d");
    Circle.prototype.ctx.clearRect(0,0,720,720); // clear canvas
    Circle.prototype.ctx.beginPath();
    Circle.prototype.ctx.strokeStyle = "rgb("+ this.r +", "+ this.g +", "+ this.b +")";
    Circle.prototype.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    Circle.prototype.ctx.stroke();
}

Circle.prototype.update = function ()
{
    step += .02;
    step %= 2 * Math.PI;
    this.x = parseInt((Math.sin(step)) * 150) + 360;
    this.y = parseInt((Math.cos(step)) * 150) + 360;
    this.radius += 16;
    if (this.radius > 200)
    {
        for (i in circleHolder)
        {
            if (circleHolder[i]==this)
            {
                circleHolder.splice(i, 1);
            }
        }
    }
}

function update()
{
    var ci = new Circle(x, y, radius, r, g, b);
    for (i in circleHolder)
    {
        ci = circleHolder[i];
        ci.update();
        ci.draw();
    }
}

私の問題はupdate(){}にあると確信していますが、それを正しく行う方法がわかりません。


編集:さて、私はそれをいくつかの変更で動作させました!このフィドルをチェックしてください!ただし、コンソールで「ci not defined」エラーが発生し、奇妙なバグがあります。「if(this.radius> 128)」をより高い整数に変更すると、円の回転が速くなります。わかりません。どうして。必要に応じて、256に変更して、何が起こるかを確認できます。

for (var i=0; i < allCircles; i++)
        {
            ci = circleHolder[i]; <----- This is causing the error
            ci.update();
            ci.draw();
        }
4

2 に答える 2

1

あなたが何をしようとしているのかは100%明確ではありませんが、私は主な問題を解決しようとしました

1つの問題は、forループです。for in配列には使用しないでください。代わりに次のようにしてください。

for (var i=0 ; i<circleHolder.length ; i++)
{
    ci = circleHolder[i];
    ci.update();
    ci.draw();
}

このフィドルを参照してください

また、getコンテキストや、一度だけ発生するはずのその他のことを、update関数ではなく、コンストラクターに移動しました。

また、各描画の前にキャンバスをクリアしているため、フレームごとに最後に描画された円のみが表示されます。(削除するclearRectと、古いスピログラフの1つのように見えます)。

また、(白)で円を描いていた(255,255,255)ので、色が変わるまで表示されませんでした。

編集:

実際、このコードにはいくつかの問題があります。

それらの多くを持つことを計画している場合、コンテキストはサークルクラス内にあるべきではありません。

キャンバス/コンテキストとすべての円の配列を含むオブジェクトが必要です。

次に、そのオブジェクトに更新/描画を管理させます。

于 2012-09-27T18:37:13.357 に答える
1

手始めに、このコードの外で何か他のことが起こっていない限り、次のようになります。

配列で使用for ... in ...しています。for-inはオブジェクト用です。配列で使用する場合、ほとんどのブラウザには、数値インデックスだけでなく、.spliceやなどのメソッドが含まれます。.forEach0...n

function splice () {}.draw();うまく終わらない。

また、ページの背景の色は何ですか?各円のRGBカラーを100%白に設定しています。また、キャンバスをクリアしています... ...これは、全体が透明であることを意味している可能性があります。したがって、透明なキャンバス、白い円、白い背景がある場合、エラーを吐き出さずに機能していれば、何も表示されない可能性が高くなります。

何が起こっているのかを追跡できるようにロジックを移動する方がはるかに理にかなっているかもしれません。

サークルコンストラクターを作成する場合は、新しいサークルを作成する以外に何もしないでください。

アップデート内にサークルを作成します。
次に、それをサークルコレクション内に配置します(サークルコンストラクター内ではありません)。

大規模なアプリケーションでは、通常、一度に1つずつ更新して描画するのではなく、すべてのオブジェクトに対してupdateを呼び出してから、すべてオブジェクトに対してdrawを呼び出します。たとえば、あなたを引き寄せて動かせるようにする前に、あなたが弾丸に当たったかどうかをわざわざチェックしなかったゲームを想像してみてください。

したがって、ループ内には、updateとが必要drawです。の中で、updateサークルを作成してリストに追加し、それらの位置を更新します。の中にdraw、円を描きます。

将来的には、これにより、フレームごとに複数回、すべてを再描画することなく、衝突検出などの利点が得られるようになります。

また、何度も呼び出される関数内でDOMアクセスを行わないでください(Circle.draw)。それは将来あなたのフレームレートを破壊するでしょう。

代わりに、関数に依存関係(キャンバス)を渡します。

// inside of the main game's scope
var screen = document.getElementById(...).getContext("2d");


// inside of your new draw function, in the animation/game loop
var i = 0, allCircles = circleHolder.length, currentCircle;

for (; i < allCircles; i += 1) {
    currentCircle = circleHolder[i];
    currentCircle.draw(screen);
}
于 2012-09-27T18:49:59.233 に答える