[JS]HTML5 Canvasを使ったライフゲーム

Pocket

HTML5 で導入された要素 Canvas には自由に図形を描画でき、JavaScript と組み合わせることでリアルタイムに書き換えることができます。
そこで練習も兼ねて HTML5 + JavaScript でシンプルなライフゲームを作ってみました。

lifegame

Demo

・html 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<title>Game of Life</title>
<meta charset="utf-8">
<script src="lifegame.js"></script>
</head>
<body>
 
<div style="margin: 1em 0;">
<form>
<input type="button" value="Random" id="buttonRandom">
<input type="button" value="Start" id="buttonStart">
<input type="button" value="Reset" id="buttonReset">
</form>
</div>
 
<canvas id="lifegame" width="320" height="320"></canvas>
</body>
</html>

・スクリプト部分(lifegame.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var canvas;
var ctx;
var cellSize = 8;   // セル1マスのサイズ
var cols;
var rows;
var cells = new Array();
var buttonStart;
var buttonRandom;
var buttonReset;
var timer1;
var running = false;
 
window.onload = function()
{
    canvas = document.getElementById('lifegame');
    ctx = canvas.getContext('2d');
    cols = Math.floor(canvas.width / cellSize);
    rows = Math.floor(canvas.height / cellSize);
    initCells();
    buttonStart = document.getElementById('buttonStart');
    buttonRandom = document.getElementById('buttonRandom');
    buttonReset = document.getElementById('buttonReset');
    buttonStart.addEventListener('click', onStart, false);
    buttonRandom.addEventListener('click', randomCells, false);
    buttonReset.addEventListener('click', initCells, false);
    canvas.addEventListener('click', canvasClick, false);
};
 
// 開始
function onStart(){
    if(running){
        clearInterval(timer1);
        buttonStart.value = "Start";
        running = false;
    } else {
        nextGeneration();
        timer1 = setInterval("nextGeneration()", 100);
        buttonStart.value = "Stop";
        running = true;
    }
}
 
// 初期化
function initCells(){
    ctx.fillStyle = 'rgb(60, 60, 60)';
    ctx.fillRect(0,0, canvas.width, canvas.height);
    for(col=0;col<cols;col++){
        cells[col] = new Array();
        for(row=0;row<rows;row++){
            cells[col][row] = 0;
        }
    }
    redraw();
}
 
// ランダムに埋める
function randomCells(){
    for(col=0;col<cols;col++){
        cells[col] = new Array();
        for(row=0;row<rows;row++){
            cells[col][row] = Math.round( Math.random());
        }
    }
    redraw();
}
 
// 全体を再描画
function redraw(){
    for(col=0;col<cols;col++){
        for(row=0;row<rows;row++){
            drawCell(col, row);
        }
    }
}
 
// セルを描画
function drawCell(x, y){
    var value = cells[x][y];
    var style = value ? "rgb(156, 255,0)" : "rgb(40,40,40)";
    ctx.fillStyle = style;
    ctx.fillRect(x * cellSize, y * cellSize,
        cellSize - 1, cellSize - 1);
}
 
// 世代を進行させる
function nextGeneration(){
    var tmpCells = new Array();
    for(col=0;col<cols;col++){
        tmpCells[col] = new Array();
        for(row=0;row<rows;row++){
            var count = countAround(col, row);
            if(cells[col][row]){
                if(count == 2 || count == 3){
                    tmpCells[col][row] = 1;
                } else {
                    tmpCells[col][row] = 0;
                }
            } else {
                if(count == 3){
                    tmpCells[col][row] = 1;
                } else {
                    tmpCells[col][row] = 0;
                }
            }
        }
    }
    cells = tmpCells;
    redraw();
}
 
// 周囲の生存セルを数える
function countAround(x, y){
    var count = 0;
    for(i=-1;i<=1;i++){
        for(j=-1;j<=1;j++){
            if(
                (i != 0 || j != 0) &&
                x + i >= 0 && x + i < cols &&
                y + j >= 0 && y + j < rows
            ) {
                count += cells[x + i][y + j];
            }
        }
    }
    return count;
}
 
// Canvasクリック
function canvasClick(e){
    var x = e.clientX - canvas.offsetLeft;
    var y = e.clientY - canvas.offsetTop;
    var col = Math.floor(x / cellSize);
    var row = Math.floor(y / cellSize);
    cells[col][row] = !cells[col][row];
    drawCell(col, row);
}

ランダムボタンでランダムにセルを埋めるかマウスクリックでセルの ON/OFF を設定してスタートボタンで開始します。
セルの周囲に2~3の生存セルが隣接している場合生き残り、過疎(1以下)や過密(4以上)の場合消滅します。
死んでいるセルの周囲にちょうど3つの生存セルが隣接している場合生きているセルが発生します。


Similar Posts:




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です