私はキャンバスタグを使用した簡単なJavaScriptベースのゲームに取り組んでいます。ゲームの一環として、スクリーン上のキャラクターに関連するアニメーションを含むいくつかの大きなスプライトシート(例:2816x768と4096x4864)があります。ゲームが始まると、ゲームは単にキャラクターのアイドルアニメーションを再生します。ユーザーがスペースを押すと、私はまったく違うシートから別のアニメーションを再生し始めます。ここでChromeで初めて大きな画像を描画する際の遅延が小さい
は、スプライトを描画するコードです:
Sprite.prototype.drawFrame = function(x, y)
{
ctx.drawImage(this.image,
x*this.width, y*this.height,
this.width, this.height,
this.position[0], this.position[1],
this.width, this.height);
};
そしてここでは、画像をロードするコードです:
Stage.prototype.loadImage = function(src)
{
var image = new Image();
this.incAssets();
var stage = this;
image.onload = function()
{
stage.decAssets();
}
image.src = src;
return image;
}
問題はときに、ユーザーから1.5秒の遅延があることがあります新しいスプライトシートからのフレームが実際に描画されるときにスペースを押します。これは1回のみであり、次のアニメーションの滑らかさには影響しません。私はすでにnew Image
を使ってスプライトシートをプリロードしてあり、対応するすべてのimage.onloadイベントが発生するまでゲームが開始されないので、ブラウザがロードを待っていないことがわかります。 Chrome 17.0でデバッガを使用してJavaScriptを使いこなし、コンテキスト上でdrawImage
コールの遅延を絞り込んだ。最も困惑していることは、Firefox 10.0.2ではこの遅延が存在しないため、Chrome固有の問題です。それは非常にゲームに混乱している。
私はここで間違っていますか?とにかくChromeでこの遅延を減らすことはできますか?
編集:私はPeter Wishartが提案したように読み込まれるとすぐに次のフレーム全体を描画しようとしましたが、それは最小限の効果しかありませんでした。私もloadImage
を次のように修正しようとしました:
Stage.prototype.loadImage = function(src)
{
var image = new Image();
this.incAssets();
var stage = this;
image.onload = function()
{
ctx.drawImage(image, 0, 0);
stage.decAssets();
}
image.src = src;
return image;
};
このこともあまり効果がありませんでした。
実際、私は解決策を見つけましたが、それはひどく非効率です。デモ後にChromeが画像メモリでスマートなことをしようとしている可能性があります。画像が十分に長く使用されておらず、やはりこれは単なる推測である場合、Chromeはデコードされたデータをメモリから削除し、必要に応じて再度取り込みます。通常、デコード処理には目に見えない時間がかかりますが、私が使用する大きな画像は非常に劇的なパフォーマンスの低下を招きます。これを使用して描画ループを変更しました:
function draw()
{
var currentTime = new Date().getTime();
var deltaTime = currentTime - lastTime;
lastTime = currentTime;
var dt = deltaTime/1000.0;
// The hack that keeps all decoded image data in memory is as following.
if (this.stage.nextStage != undefined)
this.stage.nextStage.draw(0); // The 0 here means the animations advance by 0 milliseconds, thereby keeping the state static.
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
if (stage != undefined && stage.loaded)
{
stage.draw(dt);
}
}
この解決策は機能しますが、私が言ったように、ひどい廃棄物のようです。デコードされたデータがChromeで古くなるのを防ぐため、次の一連のアニメーションのフレーム全体を描画する必要があります。
この戦略には、無駄が少なく、ハックの少ない代替品がありますか?