久々にenchant.jsを弄ってみました。
HTML5らしく、Canvasを使った何かを作ってみようと砂が上から落ちてきて下に落ちるだけのプログラムを作成して
問題点にあたりました。


まず基本的な仕様として

  • 300*300の画面領域のCanvasを用意する
  • 画面上部から砂(茶色のドット)が毎フレーム生成される
  • Canvasを左下から走査し、現在位置がなにもなくて、上に砂がある場合砂が下に移動する
  • 現在位置がブロック(黒のドット)の場合左右の領域が空白か調べる
  • 空白の場合、その場所に砂が移動する。空白でない場合は砂はそこで止まる
  • 空白の場所をクリックしてドラッグすることで、そこに線を書くことができる

という仕様で作成しました。
そして、現在の位置が空白か否かをチェックするのにgetPixelで1ドットずつ調べていたのですが・・・すごく遅いです。
というのも、getPixelの中身を見ていると、一回実行する毎に、getImageDataでCanvasにアクセスしてるのですね。
つまり毎フレーム300*300で9万回Canvasにアクセス。さすがにこれは重そうです。
そこで、getPixelでは1px毎に取り出していましたが、getImageDataで1ライン毎に取り出すことにしました。

 var linepx = sand.context.getImageData(0,yy-1,map_x,1).data;

と、linpxに1ライン分のデータを読み込んでから、その読み込んだのをチェックすることでCanvasへのアクセスは毎フレーム300回まで軽減されてかなり改善されました。
注意点としてはgetPixelでは1px分なので返り値はR G B Aの4つだけでしたが、1ライン分読み込んだことにより、返り値はR G B A R G B A R G B A…と、4つずつ繰り返しになっています。
取り出すときはそこを注意して扱ってください。
実験でJsdoを使ってみましたのでそれも表示してみます。

Enchant.Js 上から砂が降ってくる – jsdo.it – share JavaScript, HTML5 and CSS