Cocos2d.JSでゲームを作ってみた

#Cocos2d.JSで簡単なゲームを作ってみました
JavaScriptベースのゲームエンジンであるCocos2d.JSを使用した簡単なゲームを作ってみましたので、その作成手順をステップバイステップで説明します。　なお、Windows10の環境において Microsoft Edge (Ver. 11.0.17763.379), Firefox (Ver. 65.0.2/64 bit) 及び Google Chrome (Ver. 73.0.3683.86/64 bit) で動作を確認しました。　しかしながら、タッチ・イベントは未実装ですのでAndroidやiOSでは動作しませんので悪しからず。
また、ここで使用しているグラフィックの一部に「[​どらぴか様](https://dorapika.wixsite.com/pikasgame)」ならびに「[ぴぽや様](http://blog.pipoya.net/)」作成の素材をサウンドエフェクトには「[効果音ラボ様](https://soundeffect-lab.info/)」作成の素材を使用させていただきました。　フリー素材を提供して下さった各位に感謝いたします。
##ファイル構成
ここで説明する内容に関するファイルは全て「[GitHub Cocos2d_Sample_games](https://github.com/To-Fujita/Cocos2d_Sample_games)」からダウンロード可能です。　また、そのファイル構成は次の通りです。
・ frameworks: Cocos2d.JSからダウンロードしたものでゲームエンジン本体を含むフォルダーです。
・ res: ゲームで使用するグラフィックやサウンド・エフェクトを収納するフォルダーです。
・ Cocos2dJS_Sample_01 ～ Cocos2dJS_Sample_07: 各ステップ用のフォルダーです。
　- Cocos2d_Sample_xx.html: 各ステップでのGame開始用HTMLファイルです。（xxは、各ステップの番号です／以下同様）
　- main_xx.js: 最初に読み込まれるJSファイルです。（Cocos2d.JSからダウンロードしたものを修正しました）
　- project.json: 読込むゲームファイルを指定するJSONファイルです。
　- src: ゲーム・プログラム本体や設定ファイルを収容するフォルダーです。
　　+ app_xx.js: ゲーム本体のJSファイルです。
　　+ loading.js: ゲーム開始までのローディング画面用JSファイルです。（Cocos2d.JSからダウンロードしたもの）
　　+ resource_xx.js: グラフィックやサウンド・エフェクトを設定するためのJSファイルです。
##ゲーム作成の説明
以下にゲーム作成の手順をステップバイステップで説明します。
###Step-1：　静止画グラフィックスを表示させる
始めにHTMLファイルを示します。　画面のキャンバス・サイズや背景色の設定等を行い全てのステップでほぼ同一ですが、各ステップ毎にタイトルと「src="main_01.js"」の部分を各ステップ番号に変更しています。
[Step-1のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_01/Cocos2d_Sample_01.html)

```html:Cocos2d_Sample_01.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Cocos2d-html5 Sample_01: Set a static character image by T. Fujita on 2019/9/10</title>
    <link rel="icon" type="image/GIF" href="../res/favicon.ico"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="full-screen" content="yes"/>
    <meta name="screen-orientation" content="portrait"/>
    <meta name="x5-fullscreen" content="true"/>
    <meta name="360-fullscreen" content="true"/>
    <style>
        body, canvas, div {
            -moz-user-select: none;
            -webkit-user-select: none;
            -ms-user-select: none;
            -khtml-user-select: none;
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        }
    </style>
</head>
<body style="padding:0; margin: 0; background: #000;">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script src="./src/loading.js"></script>
<script src="../frameworks/cocos2d-html5/CCBoot.js"></script>
<script src="main_01.js"></script>
</body>
</html>
```

次に「main_01.js」を示します。　ゲーム画面サイズ等を設定しますが、これは各ステップで内容は同一です。

```javascript:main_01.js
cc.game.onStart = function(){
    if(!cc.sys.isNative && document.getElementById("cocosLoading")) //If referenced loading.js, please remove it
        document.body.removeChild(document.getElementById("cocosLoading"));
    cc.view.setDesignResolutionSize(800, 600, cc.ResolutionPolicy.SHOW_ALL);
	cc.view.resizeWithBrowserSize(true);
    //load resources
    cc.LoaderScene.preload(g_resources, function () {
        cc.director.runScene(new GameScene());
    }, this);
};
cc.game.run();
```

「project.json」ファイルの内容を示します。　各ステップ毎に読み込むファイルを指定します。

```text:project.json
{
    "project_type": "javascript",

    "debugMode" : 1,
    "showFPS" : true,
    "frameRate" : 60,
    "id" : "gameCanvas",
    "renderMode" : 0,
    "engineDir":"../frameworks/cocos2d-html5",

    "modules" : ["cocos2d"],

    "jsList" : [
        "src/resource_01.js",
        "src/app_01.js"
    ]
}
```

メイン・プログラムである「app_01.js」を示します。　Step-1では、背景画像とグラフィックス（player）を表示させています。

```javascript:app_01.js
// Sample for Cocos2d.js by T. Fujita on 2019/9/10

var GameLayer = cc.Layer.extend({
    sprite:null,
    ctor:function () {

// Initialize
        this._super();

// Get windows size
        var size = cc.director.getWinSize();
	var temp_x = size.width / 2;
	var temp_y = size.height / 2;
	var MS_x = 0;
	var MS_y = 0;
	var Speed = 1;
	var act1, act2, acts;

// Create the background image
        this.back_img = cc.Sprite.create(res.Back_jpg);
        this.back_img.x = temp_x;
        this.back_img.y = temp_y;
        this.addChild(this.back_img, 0);

// Create the sprite for player
	this.player = new cc.Sprite.create(res.PLAYER_png, cc.rect(48, 0, 48, 48));
	this.player.x = temp_x;
	this.player.y = temp_y;
	this.addChild(this.player, 1);
    }
});

var GameScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new GameLayer();
        this.addChild(layer);
    }
});
```

「resource_01.js」では、ゲーム内で使用する背景およびグラフィックスを指定します。

```javascript:resource_01.js
var res = {
	Back_jpg : "../res/bg.jpg",
	PLAYER_png : "../res/20190405_1372448.png",
};

var g_resources = [
//image
    res.Back_jpg,
    res.PLAYER_png,

//plist

//fnt

//tmx

//bgm

//effect
];
```

###Step-2：　静止画グラフィックスを移動させてみる
前述の「app_01.js」にマウスをクリックした位置あるいはキー入力の検知を追加し、それに合わせてplayerを移動（x方向用のact1及びy方向用のact2）させるものが「app_02.js」です。　追加個所を以下に示します。
[Step-2のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_02/Cocos2d_Sample_02.html)

```javascript:app_02.js（追加部分）
// Get the mouse's position at push down the bottun
	cc.eventManager.addListener({
	    event: cc.EventListener.MOUSE,
	    onMouseDown: function(e) {
		MS_x = Math.floor(e.getLocationX());
		MS_y = Math.floor(e.getLocationY());
		Move_set();
		acts = cc.Sequence.create(act1, act2);
		Player.runAction(cc.Sequence.create(acts));
	    }
	}, this);

// Get the pressed key on keyboard 
	cc.eventManager.addListener({
	    event: cc.EventListener.KEYBOARD,
	    onKeyPressed: function(keyCode, event) {
                if (keyCode == cc.KEY.left) {
                    MS_x = Player.x - P_size;
		    MS_y = Player.y;
                }
                if (keyCode == cc.KEY.right) {
                    MS_x = Player.x + P_size;
		    MS_y = Player.y;
                }
                if (keyCode == cc.KEY.up) {
		    MS_x = Player.x;
                    MS_y = Player.y + P_size;
                }
                if (keyCode == cc.KEY.down) {
		    MS_x = Player.x;
                    MS_y = Player.y - P_size;
                }
		Move_set();
		acts = cc.Sequence.create(act1, act2);
		Player.runAction(cc.Sequence.create(acts));
	    }
	}, this);
        return true;

// Set the action for the Player
	function Move_set() {
		Speed = Math.floor(Math.abs(Player.x - MS_x)) / 100;
		act1 = cc.MoveTo.create(Speed, cc.p(MS_x, Player.y));
		Speed = Math.floor(Math.abs(Player.y - MS_y)) / 100;
		act2 = cc.MoveTo.create(Speed, cc.p(MS_x, MS_y));
		return true;
	}
```

###Step-3：　アニメーション・グラフィックスを表示させる
「app_01.js」を元にplayerをアニメーションさせる「app_03.js」を作成します。　変更部分を次に示します。　Cocos2d.JSでは、RPGツクール等の歩行グラフィックスが使用できます。
[Step-3のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_03/Cocos2d_Sample_03.html)

```javascript:app_03.js（追加分）
// Create the sprite for player
	var frames = [];
	for (i = 0; i < 3; i++) {
		var frame = new cc.SpriteFrame(res.PLAYER_png, cc.rect( i * 48, 0, 48, 48));
		frames.push(frame);
	}
	var animation_walk = new cc.Animation.create(frames);
	animation_walk.setDelayPerUnit(15 / 60);
	animation_walk.setRestoreOriginalFrame(false);
	var action_walk = new cc.Animate(animation_walk, 1);
	this.player = new cc.Sprite.create();
	this.player.x = temp_x;
	this.player.y = temp_y;
	this.player.runAction(cc.RepeatForever.create(action_walk));
	this.addChild(this.player, 1);
```

###Step-4：　アニメーション・グラフィックスを移動させてみる
前述の「app_02.js」と「app_03.js」を組み合わせると共に前後（上下）左右それぞれの歩行グラフィックスを追加したものが「app_04.js」です。　追加分の一部として右側歩行分を以下に示します。
[Step-4のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_04/Cocos2d_Sample_04.html)

```javascript:app_04.js（追加の一部分）
var Player = cc.Layer.extend({
    ctor: function() {
	this._super();
    },
    initializedParam: function() {
	direction = "stay";
    },
    walkRight: function() {
	var frames = [];
	for (i = 0; i < 3; i++) {
		var frame = new cc.SpriteFrame(res.PLAYER_png, cc.rect( i * 48, 96, 48, 48));
		frames.push(frame);
	}
	    var animation_right = new cc.Animation.create(frames);
	    animation_right.setDelayPerUnit(15 / 60);
	    animation_right.setRestoreOriginalFrame(false);
	    var action_right = new cc.Animate(animation_right, 1);
	    if(flag == 0) {
		player = new cc.Sprite.create();
		player.setScale(Scale, Scale);
		var act = cc.MoveTo.create(0.1, cc.p(PS_x, PS_y));
		player.runAction(cc.Sequence.create(act));
	    }
	    var act_right = cc.MoveTo.create(Speed, cc.p(player.x + P_size, player.y));
	    player.runAction(cc.Sequence.create(act_right));
	    player.runAction(cc.RepeatForever.create(action_right));
	    this.addChild(player, 1);
	flag = 1;
	PC_x = player.x + P_size;
	PC_y = player.y;
    },
```

###Step-5：　壁等を表示させ、移動を制限する
「app_04.js」に「stages_01.js」で設定する各ステージを読み込みタイルデータを表示させたものが「app_05.js」です。　ここでは、壁を通り抜け出来ない設定とゴール、再度実行（Aタイル）のみ対応するようにしています。
[Step-5のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_05/Cocos2d_Sample_05.html)

```javascript:app_05.js（タイルデータ表示部分）
	for (i=0; i<ROOM.length; i++) {
	    temp[i] = [];
	    for (j=0; j<ROOM[i].length; j++) {
		temp[i][j] = ROOM[i].substr(j,1);
		if(ROOM[i].substr(j,1) == "P") { 
		    this.PLAYER = new Player();
		    this.PLAYER.x = 0;
		    this.PLAYER.y = 0;
		    this.addChild(this.PLAYER, 10);
		    PS_x = j * P_size + P_size/2;
		    PS_y = (ROOM.length - i - 1) * P_size + P_size/2;
		}
		 if(ROOM[i].substr(j,1) == "A") { 
		    this.again = cc.Sprite.create(res.AGAIN_png);
		    this.again.setScale(Scale, Scale);
		    this.again.x = j * P_size + P_size/2;
		    this.again.y = (ROOM.length - i - 1) * P_size + P_size/2;
		    this.addChild(this.again, 1);
		}
		 if(ROOM[i].substr(j,1) == "G") { 
		    this.goal = cc.Sprite.create(res.GOAL_png);
		    this.goal.setScale(Scale, Scale);
		    this.goal.x = j * P_size + P_size/2;
		    this.goal.y = (ROOM.length - i - 1) * P_size + P_size/2;
		    this.addChild(this.goal, 1);
		}
		else if(ROOM[i].substr(j,1) == "B") { 
		    this.block = cc.Sprite.create(res.BLOCK_png);
		    this.block.setScale(Scale, Scale);
		    this.block.x = j * P_size + P_size/2;
		    this.block.y = (ROOM.length - i - 1) * P_size + P_size/2;
		    this.addChild(this.block, 2);
		    BLOCK[BL_counter] = this.block;
		}
		else if(ROOM[i].substr(j,1) == "w") { 
		    this.wall_0 = cc.Sprite.create(res.WALL_00_png);
		    this.wall_0.setScale(Scale, Scale);
		    this.wall_0.x = j * P_size + P_size/2;
		    this.wall_0.y = (ROOM.length - i - 1) * P_size + P_size/2;
		    this.addChild(this.wall_0, 3);
		}
		else if(ROOM[i].substr(j,1) == "W") { 
		    this.wall_1 = cc.Sprite.create(res.WALL_01_png);
		    this.wall_1.setScale(Scale, Scale);
		    this.wall_1.x = j * P_size + P_size/2;
		    this.wall_1.y = (ROOM.length - i - 1) * P_size + P_size/2;
		    this.addChild(this.wall_1, 4);
		}
	    }
	}
```

```javascript:app_05.js（左側の壁対応部分）
	function Move_set() {
	    px = Math.round((PC_x - P_size/2) / P_size);
	    py = ROOM.length - 1 - Math.round((PC_y - P_size/2) / P_size);
	    if(px < 1) {px = 1;}
	    if(py < 1) {py = 1;}
		if(direction == "left") {
		    if(flag != 0) {
			PLAYER1.actionManager.removeAllActions();
		    }
		    if((pos[px - 1][py] =="w") ||(pos[px - 1][py] =="W")) {
			PLAYER1.walkStay();
			var act = cc.MoveTo.create(Speed, cc.p(px * P_size + P_size/2, PC_y));
			player.runAction(cc.Sequence.create(act));
		    } else {
			PLAYER1.walkLeft();
		    }
		} else if(direction == "right") {
```

```javascript:app_05.js（ゴール対応部分と再度実行部分）
// Process for reaching the goal
	function Check_Goal() {
		if(pos[p_x][p_y] == "G") {
			alert("Goal ! \n ここで使用しているキャラクターの一部に「どらぴか」様 \n URL: https://dorapika.wixsite.com/pikasgame \n作成の素材を使用しております。");
			counter = counter + 1;
		        var layer = new GameLayer();
			cc.director.runScene(layer);
		}
	}

// Process for again the same room
	function Check_Again() {
		if(pos[MS_x][ROOM.length - 1 - MS_y] == "A") {
			alert("Again ! \n ここで使用しているキャラクターの一部に「どらぴか」様 \n URL: https://dorapika.wixsite.com/pikasgame \n作成の素材を使用しております。");
		        var layer = new GameLayer();
			cc.director.runScene(layer);
		}
	}
```

各ステージを構成する「stage_01.js」の一部を以下に示します。　メモ帳等のエディターで修正・追加してみてください。

```javascript:stage_01.js
// All the rooms are here. 
// by T. Fujita
// 
// A: Again
// B: Block(Movable)
// F: Floor
// G: Goal
// P: Player
// W: Wall

var room = [];
    room[0] = [ "WwwwwGwW",
		"WFFFFFFW",
		"WFFFFFFW",
		"WFPFFFFW",
		"WFFFFFFW",
		"WwwwwwwA"]

    room[1] = [ "WwwwwGwW",
		"WFFFFBFW",
		"WFFFFFFW",
		"WFPFFFFW",
		"WFFFFFFW",
		"WwwwwwwA"]

    room[2] = [ "WwwwwwwwwwwwwGwW",
		"WFFFFFFFFFFFFFFW",
		"WBBBBBBBBBBBBBBW",
		"WFFFFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WFFPFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WFFFFFFFFFFFFFFW",
		"WwwwwwwwwwwwwwwA"]
```

###Step-6：　ボックスを押して移動可能にさせる
「app_06.js」でplayerがBoxを押して移動できるようにしました。　これでゲームの基本部分は完成です。
[Step-6のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_06/Cocos2d_Sample_06.html)

```javascript:app_06.js（左側の壁対応にBOX移動を追加した部分）
	function Move_set() {
	    px = Math.round((PC_x - P_size/2) / P_size);
	    py = ROOM.length - 1 - Math.round((PC_y - P_size/2) / P_size);
	    b_x = 0;
	    b_y = 0;
		if(direction == "left") {
		    if(flag != 0) {
			PLAYER1.actionManager.removeAllActions();
		    }
		    if((pos[px - 1][py] =="w") ||(pos[px - 1][py] =="W")) {
			PLAYER1.walkStay_L();
			var act = cc.MoveTo.create(Speed, cc.p(px * P_size + P_size/2, PC_y));
			player.runAction(cc.Sequence.create(act));
		    } else if((pos[px - 1][py] =="B") && (pos[px - 2][py] =="F")) {
			pos[px][py] = "F";
			pos[px - 1][py] = "P";
			pos[px - 2][py] = "B";
			for(i=0; i<BLOCK.length; i++) {
			    if((Math.floor(BLOCK[i].x / P_size) == (px - 1)) && ((ROOM.length - 1 - Math.floor(BLOCK[i].y / P_size)) == py)) {
				BL_counter = i;
				b_x = -1;
				b_y = 0;
			    }
			}
			act_b = cc.MoveBy.create(Speed, cc.p(P_size * b_x, P_size * b_y));
			if(BL_temp != 0) {
			    BLOCK[BL_counter].runAction(new cc.Sequence.create(act_b));
			}
			PLAYER1.walkLeft();
		    } else if ((pos[px - 1][py] =="B") && (pos[px - 2][py] !="F")) {
			PLAYER1.walkStay_L();
		    } else {
			if(pos[px - 1][py] != "G") {
			    pos[px][py] = "F";
			    pos[px - 1][py] = "P";
			}
			PLAYER1.walkLeft();
		    }
		} else if(direction == "right") {
```

さらにゴール時の効果音を追加しました。　「resource_06_WSE.js」で効果音のファイルを追加した他、「app_06_WSE.js」でゴール時に効果音を作動させます。
[Step-6効果音付きのデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_06_with_Sound_Effect/Cocos2d_Sample_06_WSE.html)

```javascript:app_06_WSE.js（ゴール時の効果音を追加した部分）
// Process for reaching the goal
	function Check_Goal() {
		if(pos[p_x][p_y] == "G") {
			cc.audioEngine.playEffect(res.GOAL_mp3);
			alert("Goal! \n ここで使用しているキャラクターの一部に「どらぴか」様 \n URL: https://dorapika.wixsite.com/pikasgame 作成の素材を\nまた、サウンドは「soundeffect-lab　https://soundeffect-lab.info/ 」様作成の素材を使用しております。");
			counter = counter + 1;
		        var layer = new GameLayer();
			cc.director.runScene(layer);
		}
	}
```

###Step-7：　迷路を作成しアニメーション・グラフィックスを移動させてみる
「app_06_WSE.js」を若干変更し、「maze_02.js」で作成した迷路を表示させたものが「app_07.js」です。　各グラフィックスのサイズは縦横共に1/2に設定しています。　迷路は、「[Algoful : Algorithm for making a maze](http://algoful.com/Archive/Algorithm/MazeDig)」のアルゴリズムを使用させていただきました。
[Step-7のデモ実行](https://to-fujita.github.io/Cocos2d_Sample_games/Cocos2dJS_Sample_07/Cocos2d_Sample_07.html)

```javascript:maze_02.js
// This program is based on "http://algoful.com/Archive/Algorithm/MazeDig" by Algoful.
// by T. Fujita

var maze = [];
var startCells = [];

var Maze = function(X, Y) 
{
    var w = X;									// 幅（奇数）
    var h = Y;									// 高さ（奇数）
    if(w < 11) {w = 11;}
    if(h < 11) {h = 11;}
    if(w % 2 == 0) {w = w - 1;}
    if(h % 2 == 0) {h = h - 1;}

    var x;
    var y;
    var results = [];

    var currentCells = [];

    for (x = 0; x < w; x++) {
	maze[x] = new Array();
	for (y = 0; y < h; y++) {
            if (x == 0 || y == 0 || x == w - 1 || y == h - 1) {
                maze[x][y] = "F";						// 外周を通路に設定
            } else {
		maze[x][y] = "W";						// 残りを壁に設定
	    }
	}
    }

    startCells[0] = [];
    startCells[0][0] = (Math.floor(Math.random() * (w / 2 - 2))) * 2 + 1;
    startCells[0][1] = (Math.floor(Math.random() * (h / 2 - 2))) * 2 + 1;

    Dig(startCells[0][0], startCells[0][1]);

    for (x = 0; x < w; x++)
    {
	for (y = 0; y < h; y++)
	{
	    if (x == 0 || y == 0 || x == w - 1 || y == h - 1)
	    {
		maze[x][y] = "W";						// 外周を壁に戻す
	    }
	}
    }
    let i = 0;
    while (maze[i][1] == "W") {
	if(maze[i + 1][1] == "F") {
	    maze[i + 1][1] = "P";
	    break;
	}
	i = i + 1;
    }
    i = maze.length - 2;
    let j = maze[0].length - 1;
    while(maze[i][j] == "W") {
	if(maze[i - 1][j - 1] == "F") {
	    maze[i - 1][j] = "G";
	    break;
	}
	i = i - 1;
    }
    for (y = 0; y < h; y++) {
	results[y] = [];
	for (x = 0; x < w; x++) {
	    results[y] = results[y] + maze[x][y];
	}
    }
// alert(results[0] + "\n" + results[1]);
    return results;
}


function Dig(x, y) 
{
  while (true) {
    var directions = [];
    if(maze[x][y-1] == "W" && maze[x][y-2] =="W") {directions.push("UP");}
    if(maze[x][y+1] == "W" && maze[x][y+2] =="W") {directions.push("DOWN");}
    if(maze[x-1][y] == "W" && maze[x-2][y] =="W") {directions.push("LEFT");}
    if(maze[x+1][y] == "W" && maze[x+2][y] =="W") {directions.push("RIGHT");}
    if(directions.length == 0) {break;}
    var rnd = Math.floor(Math.random() * directions.length);
    switch (directions[rnd])
    {
	case 'UP':
	    SetPath(x, --y);
            SetPath(x, --y);
            break;
        case 'DOWN':
            SetPath(x, ++y);
            SetPath(x, ++y);
            break;
        case 'LEFT':
            SetPath(--x, y);
            SetPath(--x, y);
            break;
        case 'RIGHT':
            SetPath(++x, y);
            SetPath(++x, y);
            break;
    }
// console.log(maze[0] + "\n" + maze[1] + "\n" + maze[2] + "\n" + maze[3] + "\n" + maze[4] + "\n" + maze[5]);
    var cell = GetStartCell();
    if(cell != null)
    {
	Dig(cell[0], cell[1]);
    }
  }
}


function SetPath(x, y) 
{
    maze[x][y] = "F";
    if((x % 2 == 1) && (y % 2 == 1))
    {
	var Temp = [x, y];
	startCells.push(Temp);
    }
}


function GetStartCell()
{
    if(startCells.length == 0) {return null;}
    var rnd = Math.floor(Math.random() * startCells.length);
    var cell = startCells[rnd];
    startCells.splice(rnd, 1);
    return cell;
}
```

##Reference
1. [github Cocos2d_Sample_games](https://github.com/To-Fujita/Cocos2d_Sample_games)
2. [Home Page of Cocos2d-x](https://www.cocos.com/en/)
3. [Download page for Cocos2d-JS](https://cocos2d-x.org/filecenter/jsbuilder/)
4. [Home Page of PIKA's GAME](https://dorapika.wixsite.com/pikasgame)
5. [Home Page of Pipoya](http://blog.pipoya.net/)
6. [Algoful : Algorithm for making a maze](http://algoful.com/Archive/Algorithm/MazeDig)
7. [Home Page of soundeffect-lab](https://soundeffect-lab.info/)

##おまけ
JavaScriptベースのゲームエンジンは他にも多数ありますが、その内の幾つかで同様のゲームを作成してみました。　ソースファイルを覘くとゲームエンジン別の特徴がうかがえるかと思います。

- Cocos2d.JSでゲームを作ってみた（本記事です）
- [Phaser3.JSでゲームを作ってみた](https://qiita.com/halboujp/items/7f6cfcd73a1c95023511)
- [Phina.JSでゲームを作ってみた](https://qiita.com/halboujp/items/1cae099645d7a4e1bf2f)
- [Babylon.jsで3Dゲームを作成してみた（その１：迷路編）](https://qiita.com/halboujp/items/8b4b07136420c5defb13)　　
- [Babylon.jsで3Dゲームを作成してみた（その２：脱出パズル編）](https://qiita.com/halboujp/items/751c42f3bda10adb7674)　

以上