javascriptゲームの設計パターン

## もくじ

1. はじめに
2. デモ
3. どのゲームも「画像を一定間隔で描画」でOK
4. ひな形となるコード
5. 簡易フロー図
6. ポイントとなる部分
7. 最後に


## はじめに

### きっかけ

過去、javascriptでゲームを作成する機会が多々ありました。
ベースとなる部分さえ抑えてしまえばコーディングは簡単で、後はアイデア勝負な感じがします。
おおよそどのゲームも基本は同じなので、ここら辺で自分自身のためにまとめておきたいと思い、投稿します。

### 余談

今時javascriptのゲーム作成フレームワークは溢れるほど沢山あるけど、個人的にはどうも使う気にはならないです。
一番の理由は個人的に「楽しくないから」。
フレームワークを使うと、どうしてもフレームワーク自体の使い方を覚える必要があり、どうしてもこれが意味が無いと感じてしまって精神的に苦痛。
なので、大人数だったり仕事で指定でもされない限りはスクラッチで作成することにしています。


## デモ

過去に作成した作品です。

[Chunta フィッシングゲーム](http://chunta.html.xdomain.jp/chuntafishing/index.html)

[ソースコード](https://gitlab.com/RyutaKaii/chuntafishing)

子供向けの釣りゲームです。
PC専用です。

[Chunta シューティングゲーム](http://chunta.html.xdomain.jp/chuntascrollgame/index.html)

ふざけて作ったシューティングゲームです。
スマホにも対応しています。


## どのゲームも「画像を一定間隔で描画」でOK

登場するもの全てを物( = オブジェクト)としてコードにします。
一定間隔でこれらの物( = オブジェクト)の位置や状態を変更して、描画します。
一定間隔で描画することで、動画として見えます。(1枚1枚の画像を連続で描画すれば動画になるのと一緒です)
大抵のゲームはこの考え方で作成できると思っています。


## ひな形となるコード
```
// ==================================================
// ゲームを開始
// ==================================================
function start_game() {
	// 初期化処理
	init();
	
	// 一定間隔で実行
	setInterval(function(){exec_one_frame()}, 100);
}

// ==================================================
// 1フレームごとの処理
// ==================================================
function exec_one_frame() {
	// オブジェクトを更新
	update();
	
	// 描画
	view();
	
	// 終化処理
	finalize();
}
```

setInterval関数で、半永久的にexec_one_frame関数を実行します。
初期化処理では主にオブジェクトの生成処理、終化処理では主にオブジェクトの削除処理を行います。


## 簡易フロー図

分かりやすいか微妙ですが、フロー図的なものも記載しておきます。

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527168/78e92662-ca32-1358-cf37-ef5708930c46.jpeg)



## ポイントとなる部分

ポイントと思っている部分を紹介させていただきます。

### ユーザー入力値による更新

マウスクリックやキー押下で主人公を動かす際は、
onmousedownイベントの中でオブジェクトを更新するのではなく、必ずupdate関数の中で更新します。
onmousedownイベントの中で更新すると、
オブジェクトを更新する間隔よりも短い間隔でオブジェクトが更新されてしまいます。

```
// ==================================================
// クリック情報
// ==================================================
var click_info = function() {
	// クリックしたか
	this.is_click = false;
	// X座標
	this.x = 0;
	// Y座標
	this.y = 0;
	
	// 設定
	this.set_value = function(is_click, x, y) {
		this.is_click = is_click;
		this.x = x;
		this.y = y;
	}
}

// ==================================================
// クリック時の処理
// ==================================================
document.onmousedown = function(e) {
	CLICK_INFO.set_value(true, e.pageX, e.pageY);
}

// ==================================================
// 更新
// ==================================================
update() {
	// クリックによる更新
	update_by_click(CLICK_INFO);
}
```

### オブジェクトの描画

オブジェクトを描画する際は、html要素を生成もしくは更新します。

```
// ==================================================
// 指定位置に画像を表示
// ==================================================
function dispic(id, img_url, x, y, kakudo) {
	var image;
	
	if (document.getElementById(id) == null) {
		// オブジェクトが存在しない場合は新規作成
		image = document.createElement("img");
		image.setAttribute("id", id);
		image.setAttribute("src", img_url);
		image.style.position = "absolute";
		
		document.getElementById(NAME_ID_DISP).appendChild(image);
	} else {
		image = document.getElementById(id);
	}
	
	image.style.left = x + "px";
	image.style.top = y + "px";
	image.style.transform = "rotate(" + kakudo + "deg)";
}
```


## 最後に

特に個人で作成する際は機能とか効率とかよりも、やっていて「自分自身が楽しいか楽しくないか」が一番だと思います。
あわよくば、この記事が誰かのお役に立てれば幸いです。