3

私は、練習のためだけに、初めて小さなゲームに取り組んでいます。そして、私のフィドルでわかるように、画面にたくさんの弾丸や敵がいると、しばらくするとフレームドロップが始まります。どういうわけかそれをキャッシュすることによってこれを減らす方法はありますか?

事前レンダリングについて何か読んだことがあります。しかし、私はKineticライブラリを使用しているので、これができることではないと思います。フレームドロップを減らすためのヒントとコツはありますか?または、KineticJSを使用して事前レンダリングする方法はありますか?

これが私のフィドルです:http://jsfiddle.net/3nEUv/3/

弾丸の描画は本当の取引破りだと思います:(フィドルの713行目)

function Enemybullet(destinationX, destinationY, enemySprite) {
    this.id = 'enemyBullet';
    this.x = enemySprite.getX()+(enemySprite.getWidth()/2);
    this.y = enemySprite.getY()+(enemySprite.getHeight()/2);

    this.damage = enemy.damage;

    //The targetX and Y are compensated by the player width and height. Subtract or add the halve of the player accordingly
    if (this.x > player.sprite.x) {
        var targetX = (destinationX - this.x)-(player.sprite.getWidth()/2);
        targetY = (destinationY - this.y)-(player.sprite.getHeight()/2);
    } else {
        var targetX = (destinationX - this.x)+(player.sprite.getWidth()/2);
        targetY = (destinationY - this.y)+(player.sprite.getHeight()/2);
    }


    var distance = Math.sqrt(targetX * targetX + targetY * targetY);

    this.velX = (targetX / distance) * enemyAttackSpeed;
    this.velY = (targetY / distance) * enemyAttackSpeed;

    this.finished = false;

    this.sprite = new Kinetic.Circle({
        x: this.x,
        y: this.y, 
        radius: 2,
        fill: 'black',
        name: 'enemyProjectile'
    });

    this.draw = function(indexEnemy, indexBullet) {

        var mayDelete = false;

        this.x += this.velX;
        this.y += this.velY;

        this.sprite.setAbsolutePosition(this.x, this.y);
        //console.log(this.sprite.getX());


        if(collisionDetection(this, player) == true) {
            player.collide(this);
            mayDelete = true;
        }

        if (bulletLeftField(this.sprite) == true) {
            mayDelete = true;
        }

        if (mayDelete == true) {
            delete this;
            this.sprite.remove();
            //console.log(enemies[indexEnemy].bullets);
            if (enemies[indexEnemy]) {
                enemies[indexEnemy].bullets.splice(indexBullet, 1);
            }
        }

        ammoLayer.draw();
    }

}

前もって感謝します!

4

2 に答える 2

1

答えのレベルに実際には上がらないいくつかの考え

あなたが5発の弾丸を発射しているのに気づきました。弾丸は非常に速いので、5発の弾丸すべてがターゲットに向かってほぼ直線で移動します。私の提案は、主要な弾丸のみを衝突テストすることです。先頭の弾丸が当たった場合、後続の弾丸は最終的に静止したターゲットに当たります。

KineticJSシェイプは非常にスマートであるため、プロセッサを非常に集中的に使用します。したがって、スマートな弾丸を作成する代わりに、キャッシュされた弾丸の画像を使用できます。Eric Drowell(KineticJSの作成者)は、「スマート」な形状よりも「ダム」の画像を使用することで、パフォーマンスが4倍向上すると述べています。5つの弾丸の画像パターン(1-弾丸、2-弾丸、3-弾丸、4-弾丸、5-弾丸)をキャッシュできます。発射時に、5発の弾丸に到達するまで、1〜5発の弾丸の画像を繰り返します。次に、発射線の傾斜に沿って5つの弾丸の画像を移動します。

そして最後に、画面外のバッファキャンバスからブリットすることは本当に役に立ちますが、KineticJSがそのキャンバスへの書き込み可能な参照を放棄することを拒否するため、不可能です。Eric Drowlell、あなたが聞いているなら…あなたの仕事が大好きですが、私たちにバッファキャンバスを与えてはどうでしょうか!

于 2013-03-25T18:44:11.780 に答える
1

私が考えることができるいくつかのことが違いを生むでしょう。


1/オブジェクトプーリング

これは、オブジェクトをリサイクルする手法です。新しいものを作成する(そしてガベージコレクションによって古いものを削除する)のは無駄です。

これは、たとえば、弾丸が不要になったときに一時配列に移動することで実行されます。画面から消えたり、敵にぶつかったりしたときのように。次に、新しい箇条書きが必要になったときに、一時配列からオブジェクトを取得して、箇条書きを再初期化します。

このリンクをチェックしてください(「魚のリサイクル」という見出しを検索してください)


2/四分木衝突検出

これは、優れた衝突最適化手法です。弾丸がすべてのティックですべての敵と衝突したかどうかを確認する代わりに、弾丸と同じ「クワッド」にある敵のみを確認します。

これが良いチュートリアルです。


3/バッファリング

オフスクリーンキャンバスを使用します。背景、UI、プレイヤー/敵/弾丸用に1つ持っています。これにはいくつかのバリエーションがありますが、私の経験から、最も効率的なのはすべての要素をオフスクリーンレイヤーに描画することです。次に、ティックごとに、そのレイヤーが変更された場合にのみ、画像を(オフスクリーンレイヤーに)再描画します。それが完了したら、各オフスクリーンレイヤーを1つの表示レイヤーにコンパイルします。私は、iPhone4sで60 fpsで実行され、一度に画面上に90を超えるオブジェクトが表示されるモバイルゲームで、この手法をうまく使用しました。


編集:Kineticを含む3つの異なるフレームワークのパフォーマンスを示すこの興味深いデモを見たところです。キネティックは、デスクトップとモバイルの両方で私にとって最も魅力的でした。

ここでインタラクティブなデモ

于 2013-03-25T20:21:14.980 に答える