キャンバスにスプライトを反転する

私はいくつかのスプライトを表示するためにキャンバスを使用していますが、私は水平に(これは左または右に面しています)1つを反転する必要があります。しかし、私は drawImage でこれを行う方法はありません。

関連コードは次のとおりです。

this.idleSprite = new Image();
this.idleSprite.src = "/game/images/idleSprite.png";
this.idleSprite.frameWidth = 28;
this.idleSprite.frameHeight = 40;
this.idleSprite.frames = 12;
this.idleSprite.frameCount = 0;

this.draw = function() {
        if(this.state == "idle") {
            c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
            if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; }
        } else if(this.state == "running") {
            c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, 0, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight);
            if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; }
        }
    }

ご覧のとおり、私はスプラインをキャンバスに描画するために drawImage メソッドを使用しています。私が見ることができるスプライトを反転する唯一の方法は、私がやりたいことではないキャンバス全体を反転/回転させることです。

それを行う方法はありますか?それとも、新しいスプライトを逆向きにして使用する必要がありますか?

20

3 答え

Gauravは、キャンバスでスプライトを反転させる技術的な方法を示していますが...

あなたのゲームでこれをしないでください。

代わりに、擬似シートの反転版である2番目のイメージを作成します(または現在のイメージを大きくします)。 「コンテキストを反転して画像を描画する」と「画像を描画する」との性能差は大規模になる可能性があります。 OperaとSafariでキャンバスを反転させると描画が10倍遅くなり、Chromeでは2倍遅くなります。例については、このjsPerf を参照してください。

反転したスプライトの事前計算は常により高速になり、ゲームではキャンバスのパフォーマンスが重要になります。

33
追加された
ありがとう。私がやり遂げたことは、私のキャラクターが他の方法で走っている既存のスプライトに、別のスプライトを追加し、その方向に応じてそのスプライトのセットを使用するコードを追加することでした。このように: i.imgur.com/uIPvF.png
追加された 著者 James Dawson,
いいね!新しい行を並べ替えることもできますが、反転した各バージョンを縦に並べることで、反転するときに変更する必要があるのはy座標だけです。
追加された 著者 Simon Sarris,
Jeffは saverestore が不要であるが、あなたの結果はまばゆいものだったという良い点を挙げています。ブラウザーがページまたはJavaの読み込みを完了する前に、テストを開始している可能性があります(タイマーで使用されています)。私は、テストには/4 では正確ではないと主張したいと思います。なぜなら、フリップする作業には変換を元の状態に戻す作業も含まれなければならないからです。これは、少なくとも ctx.scale(-1,1)を2回呼び出したことを意味します。ここでは「公平な」テストがあり、テストするすべてのブラウザとモバイルデバイスでフリップが遅くなることがあります。 jsperf.com/ctx-flip-performance/5
追加された 著者 Simon Sarris,
うわー!あなたは本当に重要なことを示しました。 Jsperfのセットアップ機能が壊れていて、キャンバスをクリアしていません!私が明示的に何が起こるかについては、 jsperf.com/ctx-flip-performance/10 を参照してください。テスト内部をクリアし、実際に何が起こったかを jsfiddle.net/sX2jT で確認してください。 scale は常に乗算され、私たちが見ているjsperfのバグです。
追加された 著者 Simon Sarris,
Gauravの答えは、実際にはctx.save/restoreのためにコストがかかります。実際、毎回ctx.scale(...)を呼び出すだけで、フリップされたバージョンは素早く描画されます。 jsperf.com/ctx-flip-performance/3 (フリップされた場合はctx.scale(-1)を呼び出し、フリップされていない場合は何もしないでください: jsperf.com/ctx-flip-performance/4 )。
追加された 著者 Jeff Gates,
私は.scale()がそれを乗算するのではなく、変換スケールを設定したと思っていました。 multiplyは、w3.orgのドキュメント( dev。 w3.org/html5/2dcontext/#dom-context-2d-scale )、これは実際にtest/4を無効にします。 (これは、少し曖昧な 'add'という用語を使用します)。しかし、これは少なくともクロムについてはそうではないようです: jsperf.com/ctx-フリップ・パフォーマンス/ 8
追加された 著者 Jeff Gates,

キャンバス全体を反転させることなく、キャンバスの描画コンテキストを変形することができます。

c.save();
c.scale(-1, 1);

コンテキストを反映します。あなたのイメージを描画し、次に

c.restore();

and you can draw normally again. For more information, see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations

11
追加された
ありがとうございました!しかし、サイモンの答えのために、私は彼のテクニックを使用します。それは私の質問に答えるとして、私はあなたの受け入れられた答えとしてあなたの印をつける:)
追加された 著者 James Dawson,

Use this to flip your sprite sheet http://flipapicture.com/

3
追加された
残念ながら、これはPNGをサポートしていません:(
追加された 著者 Scott,
JavaScript - 日本のコミュニティ
JavaScript - 日本のコミュニティ
2 参加者の

日本人コミュニティのjavascript