【HTML5・javascript】ライフゲームより簡単なサンプルを作る
【今回の紹介】
以下のサイトでHTML5とjavascriptでできるライフゲームに興味を持った。
今回は、そのライフゲームで行っている処理のうち、以下のような部分を切り出して
サンプルを作ったので紹介。
①キャンパス内にセルを敷き詰める考え方をする
②セルごとに描くかどうかの判定する値を設定すること
③②で設定した値をもとにセルごとに描くかどうか判定、描画すること
ざっくりですが、実際のライフゲームのソースをみる限り、以下のようなことを行っているようです。
①初期設定
・キャンパスのサイズ設定
・キャンバスのobjを取得
・キャンバス内に敷き詰める総セル分の配列を作成
・配列に初期値を設定
②更新処理
・現在の総セル野配列を取得
・対象セルに対し、以下の生か死の判定処理
・8方向のセルの情報を取得(異なる行・列を取得できるようなfor文)
・縦と横の壁判定
・自分は対象にならない判定
・総セルに対して、生か死の判定処理が終わったら描画処理にわたす
・更新処理と描画処理の再起処理
③描画処理
・②でセットされた値を描画する
【内容】
上でも紹介しているが、実際には以下のようなことを行い、ライフゲームより簡単な
キャンパス内をまだら模様に着色するサンプルを作成しました。
①キャンパス内にセルを敷き詰める考え方をする
②セルごとに描くかどうかの判定する値を設定すること
③②で設定した値をもとにセルごとに描くかどうか判定、セルごとに描くこと
【メモ】
①ある領域に着色したいときの考えがおもしろい
きっと当たり前なのかもしれないけど、
ある領域に
①配列を敷き詰める
②それぞれの添字に値を持たせる
③値をもとに着色するかを判定、着色
という処理が学べておもしろかった。この考え方は汎用的で他の部分でもつかわれているんだろうなと、
ちなみにライフゲームになると
・再起処理
・着色判定が複雑になる(周りのセルの値を取得し、判定する)
なる印象。
②複雑にしている部分を削ぎ落として、シンプルなサンプルを作ること
・コピーペですれば、動く
・処理の流れが追えばわかる(なにもみないでかけるではなく、なんとなくやっていることはわかる程度)
では、やはり理解不足だし、応用が利かない気がする
複雑にしている部分を削ぎ落として、シンプルなサンプルを自分で作ってみることで、
・この1行はなんためにやっているか理解がすすむ
・この部分を変更したら、こういう変化が起きるということをつかめるようになるし、
この部分を変更してこうしたいというのも出てきやすい気がする。
③ロジックを考える部分がおもしろい
自分はまだまだ未熟だし、参考ソースのロジックを考えるのにも考えてしまうが、ロジックを考えているのは楽しい。
同じようなロジックを参考のライフゲームサイトで実装しているが今回はなるべくみないように作った。
「まだらにするには」、「セル座標とその着色面積は」とか考え、ロジックにおとして、思い通りになる瞬間は
気持ちよい。
【参考ソース】
<html> <head> <meta charset='utf-8'> </head> <title>HTML5</title> <body> <h1>キャンバス</h1> <canvas id='canvas'></canvas> <script> var SCREEN_SIZE = 600; // キャンバスの幅 var SIDE_CELLS = 30; // 一辺のセルの数 var CELL_SIZE = SCREEN_SIZE / SIDE_CELLS; // セルの幅 var canvas; //= document.getElementById('world'); var context; //= canvas.getContext('2d'); //読み込み後、行う処理 window.onload = function() { canvas=$("canvas"); canvas.width = canvas.height = SCREEN_SIZE; // キャンバスのサイズを設定 default_set(); } //キャンパス内の配列に初期値を設定する// //まだら模様にするために1行ごとに初期設定が変える// function default_set(){ var sum_cell= new Array(CELL_SIZE*CELL_SIZE); for(var i=0;i<sum_cell.length;i++){ if(Math.floor(i/CELL_SIZE)%2==0){ if(i%2==1){ sum_cell[i]=1;} else{ sum_cell[i]=0; } } else{ if(i%2==0){ sum_cell[i]=1;} else{ sum_cell[i]=0; } } } draw(sum_cell); } //描画処理 function draw(sum_cell) { context=canvas.getContext('2d'); context.fillStyle='#FFF000'; //1セルごとに座標を取得し、着色判定 for(var i=0;i<sum_cell.length;i++){ var x=i%CELL_SIZE*CELL_SIZE; var y=Math.floor(i/CELL_SIZE)*CELL_SIZE; if(sum_cell[i]==1){ context.fillRect(x,y,CELL_SIZE,CELL_SIZE); } } } //DOMobjを取得する処理 function $(id){ return document.getElementById(id); } </script> </body> </html>