1. HOME»
  2. プログラミング・Web»
  3. JavaScript»
  4. 【JavaScript】マップでキャラを動かせるようにしよう! 小学生からのプログラミング入門

【JavaScript】マップでキャラを動かせるようにしよう! 小学生からのプログラミング入門

小学生からのプログラミング講座こうざ、今回もはじめていきましょう!

前回は、JavaScriptでのマップの作り方を紹介しょうかいしました。
しかし、まだマップを配置はいちしただけで、キャラクターの画像がぞう表示ひょうじさせていませんでした。

今回こんかいはマップ上にキャラクターの画像を表示させ、うごかせるようにしてみようと思います。
また、かべとの衝突しょうとつ判定はんていも作り、キャラクターが壁をすりけられないようにしてみようと思います。

アル

昨日きのうさ、前回おしえてもらったマップチップの表示と、りこちゃんの画像表示を自分で組み合わせて作ってみたんだ

りこ

うまくうごいた?

アル

それが全然(ぜんぜん)。一応表示(いちおうひょうじ)はされたんだけど、りこちゃんが壁(かべ)をすり抜けちゃうんだそれが全然ぜんぜん一応いちおう表示ひょうじはされたんだけど、りこちゃんがかべをすり抜けちゃうんだ

りこ

そうなんだ

山田

それが全然(ぜんぜん)。一応表示(いちおうひょうじ)はされたんだけど、りこちゃんが壁(かべ)をすり抜けちゃうんだじゃあ、今日きょうかべとの衝突しょうとつ判定はんていを作っていくべ!

りこ

山田先生! わーい!

アル

それが全然(ぜんぜん)。一応表示(いちおうひょうじ)はされたんだけど、りこちゃんが壁(かべ)をすり抜けちゃうんだはやくやろう!

目次
  1. マップにキャラクターを表示してみよう!
  2. 壁の座標とりこちゃんの座標を比べて、壁との当たり判定をする
  3. まとめ

マップにキャラクターを表示してみよう!

まずはマップにキャラクターを表示ひょうじさせるところから始めましょう!
第12回目紹介しょうかいした、HTML5とCanvasでキャラクターをうごかす方法ほうほうと、第13回目で紹介した、マップの表示方法を組み合わせて作ります。

まずはcanvasの設定せっていと、コンテキストを取得しゅとくです。

//canvasの設定(せってい)
var canvas = document.getElementById( 'canvas' );
canvas.width = 640;	//canvasの横幅(よこはば)
canvas.height = 640;	//canvasの縦幅(たてはば)
 
//コンテキストを取得(しゅとく)
var ctx = canvas.getContext( '2d' );
アル

ここまでで、Canvasをつかう準備じゅんびができたわけだね

りこ

Canvasを設定せっていして、コンテキスト(プログラムを動かすのに必要な情報)を取得しゅとく

そして今回必要ひつような、オブジェクトや変数へんすうです。
りこちゃんのオブジェクト、マップチップのImageオブジェクト、キーボードのオブジェクト、マップ配置はいち変数へんすうを作っておきます。

//りこちゃんのオブジェクトを作成
var rico = new Object();
rico.img = new Image();
rico.img.src = 'img/rico.png';
rico.x = 0;
rico.y = 0;
rico.move = 0;

//マップチップのImageオブジェクトを作る
var mapchip = new Image();
mapchip.src = 'img/map.png';

//キーボードのオブジェクトを作成
var key = new Object();
key.up = false;
key.down = false;
key.right = false;
key.left = false;
key.push = '';

//マップの作成(さくせい)
var map = [
	[0, 0, 1, 0, 1, 0, 0, 0 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 1, 1, 0, 0, 0, 1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 0, 0 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,1 ,0],
	[0, 0, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1 ,0],
	[0, 1, 1, 1, 0, 0, 0, 0 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 0, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[1, 1, 0, 1, 1, 1, 1, 1 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,1 ,1 ,0 ,1 ,1],
	[1, 0, 0, 0, 0, 0, 1, 1 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,0],
	[1, 0, 1, 1, 1, 0, 0, 0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 1, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1],
	[0, 0, 1, 0, 0, 1, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 0, 1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 0, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0],
	[1, 1, 0, 1, 0, 1, 0, 1 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 1, 1, 0, 1, 0, 0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1],
	[0, 1, 0, 0, 0, 1, 0, 1 ,1 ,1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 0, 0, 1, 0, 0, 0, 1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,0]
]
りこ

マップはたて20、よこ20で、マップチップひとつが32pxだから、縦横640pxのマップができるのね

さらに、メインループとキー入力にゅうりょくがあったときに呼ばれる関数かんすうです。
メインループでは、まず背景はいけいを黒くりつぶし、そこにマップチップを、そのあとにりこちゃんの画像がぞう表示ひょうじさせます。
あとから表示した画像ほど、上にくるので、表示の順番じゅんばんには気をつけましょう。

//メインループ
function main() {
	//塗(ぬ)りつぶす色を指定(してい)
	ctx.fillStyle = "rgb( 0, 0, 0 )";
	//塗(ぬ)りつぶす
	ctx.fillRect(0, 0, 640, 640);

	for (var y=0; y<map.length; y++) {
		for (var x=0; x<map[y].length; x++) {
			if ( map[y][x] === 0 ) ctx.drawImage( mapchip, 0, 0, 32, 32, 32*x, 32*y, 32, 32 );
			if ( map[y][x] === 1 ) ctx.drawImage( mapchip, 32, 0, 32, 32, 32*x, 32*y, 32, 32 );
		}
	}

	//画像を表示
	ctx.drawImage( rico.img, rico.x, rico.y );

	addEventListener("keydown", keydownfunc, false);
	addEventListener("keyup", keyupfunc, false);

	//方向キーが押されている場合(ばあい)は、りこちゃんが移動する
	if ( rico.move === 0 ) {
		if ( key.left === true ) {
			rico.move = 32;
			key.push = 'left';
		}
		if ( key.up === true ) {
			rico.move = 32;
			key.push = 'up';
		}
		if ( key.right === true ) {
			rico.move = 32;
			key.push = 'right';
		}
		if ( key.down === true ) {
			rico.move = 32;
			key.push = 'down';
		}
	}
	//rico.moveが0より大きい場合は、4pxずつ移動(いどう)を続ける
	if (rico.move > 0) {
		rico.move -= 4;
		if ( key.push === 'left' ) rico.x -= 4;
		if ( key.push === 'up' ) rico.y -= 4;
		if ( key.push === 'right' ) rico.x += 4;
		if ( key.push === 'down' ) rico.y += 4;
	}

	requestAnimationFrame( main );
}
//ページと依存(いぞん)している全てのデータが読み込まれたら、メインループ開始
addEventListener('load', main(), false);

//キーボードが押されたときに呼び出される関数(かんすう)
function keydownfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = true;
	if( key_code === 38 ) key.up = true;
	if( key_code === 39 ) key.right = true;
	if( key_code === 40 ) key.down = true;
	event.preventDefault();
}

//キーボードが放(はな)されたときに呼び出される関数
function keyupfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = false;
	if( key_code === 38 ) key.up = false;
	if( key_code === 39 ) key.right = false;
	if( key_code === 40 ) key.down = false;
}
アル

りこちゃんが移動いどうするためのプログラムだね

少々長いですが、全体ぜんたいはこのようになっています。

//canvasの設定(せってい)
var canvas = document.getElementById( 'canvas' );
canvas.width = 640;	//canvasの横幅(よこはば)
canvas.height = 640;	//canvasの縦幅(たてはば)
 
//コンテキストを取得(しゅとく)
var ctx = canvas.getContext( '2d' );

//りこちゃんのオブジェクトを作成
var rico = new Object();
rico.img = new Image();
rico.img.src = 'img/rico.png';
rico.x = 0;
rico.y = 0;
rico.move = 0;

//マップチップのImageオブジェクトを作る
var mapchip = new Image();
mapchip.src = 'img/map.png';

//キーボードのオブジェクトを作成
var key = new Object();
key.up = false;
key.down = false;
key.right = false;
key.left = false;
key.push = '';

//マップの作成(さくせい)
var map = [
	[0, 0, 1, 0, 1, 0, 0, 0 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 1, 1, 0, 0, 0, 1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 0, 0 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,1 ,0],
	[0, 0, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1 ,0],
	[0, 1, 1, 1, 0, 0, 0, 0 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 0, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[1, 1, 0, 1, 1, 1, 1, 1 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,1 ,1 ,0 ,1 ,1],
	[1, 0, 0, 0, 0, 0, 1, 1 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,0],
	[1, 0, 1, 1, 1, 0, 0, 0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 1, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1],
	[0, 0, 1, 0, 0, 1, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 0, 1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 0, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0],
	[1, 1, 0, 1, 0, 1, 0, 1 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 1, 1, 0, 1, 0, 0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1],
	[0, 1, 0, 0, 0, 1, 0, 1 ,1 ,1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 0, 0, 1, 0, 0, 0, 1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,0]
]

//メインループ
function main() {
	//塗(ぬ)りつぶす色を指定(してい)
	ctx.fillStyle = "rgb( 0, 0, 0 )";
	//塗(ぬ)りつぶす
	ctx.fillRect(0, 0, 640, 640);

	for (var y=0; y<map.length; y++) {
		for (var x=0; x<map[y].length; x++) {
			if ( map[y][x] === 0 ) ctx.drawImage( mapchip, 0, 0, 32, 32, 32*x, 32*y, 32, 32 );
			if ( map[y][x] === 1 ) ctx.drawImage( mapchip, 32, 0, 32, 32, 32*x, 32*y, 32, 32 );
		}
	}

	//画像を表示
	ctx.drawImage( rico.img, rico.x, rico.y );

	addEventListener("keydown", keydownfunc, false);
	addEventListener("keyup", keyupfunc, false);

	//方向キーが押されている場合(ばあい)は、りこちゃんが移動する
	if ( rico.move === 0 ) {
		if ( key.left === true ) {
			rico.move = 32;
			key.push = 'left';
		}
		if ( key.up === true ) {
			rico.move = 32;
			key.push = 'up';
		}
		if ( key.right === true ) {
			rico.move = 32;
			key.push = 'right';
		}
		if ( key.down === true ) {
			rico.move = 32;
			key.push = 'down';
		}
	}
	//rico.moveが0より大きい場合は、4pxずつ移動(いどう)を続ける
	if (rico.move > 0) {
		rico.move -= 4;
		if ( key.push === 'left' ) rico.x -= 4;
		if ( key.push === 'up' ) rico.y -= 4;
		if ( key.push === 'right' ) rico.x += 4;
		if ( key.push === 'down' ) rico.y += 4;
	}

	requestAnimationFrame( main );
}
//ページと依存(いぞん)している全てのデータが読み込まれたら、メインループ開始
addEventListener('load', main(), false);

//キーボードが押されたときに呼び出される関数(かんすう)
function keydownfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = true;
	if( key_code === 38 ) key.up = true;
	if( key_code === 39 ) key.right = true;
	if( key_code === 40 ) key.down = true;
	event.preventDefault();
}

//キーボードが放(はな)されたときに呼び出される関数
function keyupfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = false;
	if( key_code === 38 ) key.up = false;
	if( key_code === 39 ) key.right = false;
	if( key_code === 40 ) key.down = false;
}

しかしこのプログラムでは、りこちゃんがかべをすりけてしまいます。

下の枠内わくないをクリックして、方向ほうこうキーで操作そうさしてみてね!

りこ

きゃー、私がかべをすりけてる

アル

これじゃあ迷路めいろにならないね

山田

そこで今回は、かべにぶつからないように、プログラムをつくっていくべ!

壁の座標とりこちゃんの座標を比べて、壁との当たり判定をする

当たり判定はんていといえば、Scratch(スクラッチ)でシューティングゲームを作った時も敵とぶつかっているかとか、たまが当たっているかとか、やりましたね。

しかし今回の場合ばあい、「かべに当たっているか」ではなく、「壁に当たってしまうか」という判定になります。
どちらにしろ実際じっさいには当たっていないので、「この先、衝突しょうとつするかも」という予測よそく判定はんていです。

アル

予測よそくって……まほうでもつかうのかな?

りこ

そんなわけないでしょ! でも、どうやるんだろう

山田

座標ざひょうで考えればいんだべ

アル

りこちゃんの座標と、壁の座標を比べるってこと? でもどうやって……

さて、壁の座標はもうすでに取得しゅとくできています。
なぜなら、mapという配列はいれつにマップを作って、そこに合わせて壁を配置はいちしているからです。

さらに、りこちゃんの座標も取得できますね。
オブジェクトのrico.xとrico.yです。

じつはこの2つ、座標の表し方がちがいます。
りこちゃんは実際じっさいに動かすため、正確せいかくな座標をrico.xとrico.yが覚えてくれています。
しかしmapは正確な座標を覚えているわけではなく、マップチップの場所ばしょを覚えているだけなんです。

左から0番目、上から0番目の数字は0、
左から1番目、上から0番目の数字は0、
左から2番目、上から0番目の数字は1、
左から3番目、上から0番目の数字は0、

といったふうです。

だけど心配しんぱいする必要ひつようはありません。
りこちゃんの座標は、マップチップのサイズである32でわることで、mapと同じことになります。

りこ

なんで!? よく分からない!

アル

僕もさっぱり!

山田

じゃあ、れいを見るべよ!

では、れいで見ていきましょう。
りこちゃんのいる場所ばしょは、0から数えて、左から何番目の、上から何番目でしょうか?

答えは、左から3番目の、上から6番目です。

では、x座標ざひょうとy座標を正確せいかくにいうとどうなるでしょうか?
かんたんです。1マス32pxなので、32をかけ算すれば、答えがでますね。
つまりxは96px, yは192pxです。

りこ

逆にいえば、わり算すれば正確な座標から、何番目のところにいるかが出せるってことね!

山田

そうなんだべよ!

もしも右矢印が押されて、右方向にかべがある場合はすすむことができません。
壁があるということは、りこちゃんの右側が「1」になっているということです。

まず、変数xとyに、りこちゃんの座標ざひょうを32でわった数を代入だいにゅうします。
右矢印が押されたとき、x座標に1プラスしたいので、x++とすることでxに1足すことができます。

そのあと、map[y][x]とすることで、キャラが右方向へ1移動いどうしたあとのマップ上の座標をしめすことができます。
その座標が0の場合ばあいのときのみ移動できるようにします。

これをプログラムにしてみると、このようになります。

if ( key.right === true ) {
	var x = rico.x/32;
	var y = rico.y/32;
	x++;
	if ( map[y][x] === 0 ) {
		rico.move = 32;
		key.push = 'right';
	}
}

ほかのキーのときも同じです。

しかし、このプログラムでは、y座標の場合ばあい、上や下にマップからはみ出てしまうとエラーがおきてしまいます。
上下の矢印キーが押されたときのみ、移動いどう制限せいげんします。
例えば、上キーが押されたときは、このように4行目で移動を制限しています。

if ( key.up === true ) {
	var x = rico.x/32;
	var y = rico.y/32;
	if ( y > 0) {
		y--;
		if ( map[y][x] === 0 ) {
			rico.move = 32;
			key.push = 'up';
		}
	}
}

全体ぜんたいではこのようになります。

//canvasの設定(せってい)
var canvas = document.getElementById( 'canvas' );
canvas.width = 640;		//canvasの横幅(よこはば)
canvas.height = 640;	//canvasの縦幅(たてはば)
 
//コンテキストを取得(しゅとく)
var ctx = canvas.getContext( '2d' );
 
//りこちゃんのオブジェクトを作成
var rico = new Object();
rico.img = new Image();
rico.img.src = 'img/rico.png';
rico.x = 0;
rico.y = 0;
rico.move = 0;

//マップチップのImageオブジェクトを作る
var mapchip = new Image();
mapchip.src = 'img/map.png';

//キーボードのオブジェクトを作成
var key = new Object();
key.up = false;
key.down = false;
key.right = false;
key.left = false;
key.push = '';

//マップの作成(さくせい)
var map = [
	[0, 0, 1, 0, 1, 0, 0, 0 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 1, 1, 0, 0, 0, 1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 0, 0 ,0 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,1 ,0 ,1 ,0],
	[0, 0, 0, 0, 0, 1, 1, 1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1 ,0],
	[0, 1, 1, 1, 0, 0, 0, 0 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 0, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[1, 1, 0, 1, 1, 1, 1, 1 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,1 ,1 ,0 ,1 ,1],
	[1, 0, 0, 0, 0, 0, 1, 1 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,1 ,0],
	[1, 0, 1, 1, 1, 0, 0, 0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,0 ,0],
	[1, 0, 1, 0, 1, 1, 1, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,0 ,1],
	[0, 0, 1, 0, 0, 1, 0, 0 ,1 ,0 ,0 ,1 ,0 ,1 ,0 ,1 ,1 ,1 ,0 ,0],
	[0, 1, 1, 1, 0, 1, 0, 1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 0, 0 ,1 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0],
	[1, 1, 0, 1, 0, 1, 0, 1 ,1 ,0 ,0 ,1 ,0 ,1 ,1 ,0 ,1 ,1 ,1 ,0],
	[0, 0, 0, 1, 0, 1, 1, 1 ,1 ,1 ,0 ,1 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,0],
	[0, 1, 1, 1, 0, 1, 0, 0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,1],
	[0, 1, 0, 0, 0, 1, 0, 1 ,1 ,1 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,0 ,0 ,0],
	[0, 0, 0, 1, 0, 0, 0, 1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,0]
]

//メインループ
function main() {
	//塗(ぬ)りつぶす色を指定(してい)
	ctx.fillStyle = "rgb( 0, 0, 0 )";
	//塗(ぬ)りつぶす
	ctx.fillRect(0, 0, 640, 640);

	for (var y=0; y<map.length; y++) {
		for (var x=0; x<map[y].length; x++) {
			if ( map[y][x] === 0 ) ctx.drawImage( mapchip, 0, 0, 32, 32, 32*x, 32*y, 32, 32 );
			if ( map[y][x] === 1 ) ctx.drawImage( mapchip, 32, 0, 32, 32, 32*x, 32*y, 32, 32 );
		}
	}

	//画像を表示
	ctx.drawImage( rico.img, rico.x, rico.y );

	addEventListener("keydown", keydownfunc, false);
	addEventListener("keyup", keyupfunc, false);

	//方向キーが押されている場合(ばあい)は、りこちゃんが移動する
	if ( rico.move === 0 ) {
		if ( key.left === true ) {
			var x = rico.x/32;
			var y = rico.y/32;
			x--;
			if ( map[y][x] === 0 ) {
				rico.move = 32;
				key.push = 'left';
			}
		}
		if ( key.up === true ) {
			var x = rico.x/32;
			var y = rico.y/32;
			if ( y > 0) {
				y--;
				if ( map[y][x] === 0 ) {
					rico.move = 32;
					key.push = 'up';
				}
			}
		}
		if ( key.right === true ) {
			var x = rico.x/32;
			var y = rico.y/32;
			x++;
			if ( map[y][x] === 0 ) {
				rico.move = 32;
				key.push = 'right';
			}
		}
		if ( key.down === true ) {
			var x = rico.x/32;
			var y = rico.y/32;
			if ( y < 19 ) {
				y++;
				if ( map[y][x] === 0 ) {
					rico.move = 32;
					key.push = 'down';
				}
			}
		}
	}

	//rico.moveが0より大きい場合は、4pxずつ移動(いどう)を続ける
	if (rico.move > 0) {
		rico.move -= 4;
		if ( key.push === 'left' ) rico.x -= 4;
		if ( key.push === 'up' ) rico.y -= 4;
		if ( key.push === 'right' ) rico.x += 4;
		if ( key.push === 'down' ) rico.y += 4;
	}

	requestAnimationFrame( main );
}
//ページと依存(いぞん)している全てのデータが読み込まれたら、メインループ開始
addEventListener('load', main(), false);

//キーボードが押されたときに呼び出される関数(かんすう)
function keydownfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = true;
	if( key_code === 38 ) key.up = true;
	if( key_code === 39 ) key.right = true;
	if( key_code === 40 ) key.down = true;
	event.preventDefault();		//方向キーでブラウザがスクロールしないようにする
}

//キーボードが放(はな)されたときに呼び出される関数
function keyupfunc( event ) {
	var key_code = event.keyCode;
	if( key_code === 37 ) key.left = false;
	if( key_code === 38 ) key.up = false;
	if( key_code === 39 ) key.right = false;
	if( key_code === 40 ) key.down = false;
}

下の枠内わくないをクリックして、方向ほうこうキーで操作そうさしてみてね!

りこ

きゃー、迷路、まよっちゃう!

アル

すごい! ちゃんと壁で止まってるよ!

まとめ

今回は、マップ上をキャラクターが移動いどうし、かべをすりけられないように作りました。
大切なのはりこちゃんの座標ざひょうと、マップチップの座標をらし合わせることです。そのためには、りこちゃんの座標を1つのマップチップのサイズで割るというのも1つの方法です。

山田

ここまででも、一応遊べるべよ

アル

まだスタートもゴールもないけどね

りこ

でもスタートとゴールだけなら簡単かんたんにつくれそうだね

山田

ふたりとも、よくここまで頑張ったべ

りこ

へへへっ

アル

もっと頑張ればポケモンみたいなゲームだってゆめじゃないなって思えてきたよ

山田

それは良かったべ。ところでわだず、昨日ザギンで、こんなのかってきたべ

アル

ザギン……?

りこ

銀座ぎんざのことじゃない? どうやって行ったんだろう

山田

サングラスと、ジーパンだべ。どうだべ、似合にあうべか? これで人間になりすますんだべ

アル

ゴーグルと海パンだよ

りこ

ははは、海でも行くのー?

山田

あ……

山田

て……てやんでぇ、べらぼうめだべさ! 海に行ってこそ、真の男だべさ!
次回はもっとむずかしいこと教えてやるべ! 覚悟かくごするべ!

りこ

ひぃ、う……うん。先生、こわい

アル

ゆるしてー

このシリーズの一覧はこちら

  1. 小学生からのプログラミング入門。プログラミングってなぁに?
  2. Scratchの使い方と、ゲーム作りの基礎知識を学ぼう! 小学生からのプログラミング入門
  3. Scratchでじゃんけんゲームを作ろう! 小学生からのプログラミング入門
  4. Scratchでシューティングゲームを作ろう! 小学生からのプログラミング入門
  5. Scratchでピアノ鍵盤を作って音を鳴らそう! 小学生からのプログラミング入門
  6. テキストエディタ(Visual Studio Code)をインストールしてみよう! 小学生からのプログラミング入門
  7. Visual Studio Codeを日本語化してみよう! 小学生からのプログラミング入門
  8. JavaScriptでおみくじを作ろう! 小学生からのプログラミング入門
  9. JavaScriptで今月の残り日数を計算してみよう! 小学生からのプログラミング入門
  10. JavaScriptで画像を表示してみよう! 小学生からのプログラミング入門
  11. JavaScriptで画像を移動してみよう! 小学生からのプログラミング入門
  12. 【JavaScript】キー入力でキャラを動かしてみよう! 小学生からのプログラミング入門
  13. 【JavaScript】ファイルを分けて管理してみよう! 小学生からのプログラミング入門
  14. 【JavaScript】オブジェクトを使ってみよう! 小学生からのプログラミング入門
  15. 【JavaScript】ゲームのメインループを作ってみよう! 小学生からのプログラミング入門
  16. 【JavaScript】キャラを決まった間隔ずつ動かす! 小学生からのプログラミング入門
  17. HTML5とCanvasを使ってみよう! 小学生からのプログラミング入門
  18. 【JavaScript】迷路やRPGで使えるマップを作ってみよう! 小学生からのプログラミング入門
  19. 【JavaScript】マップでキャラを動かせるようにしよう! 小学生からのプログラミング入門
  20. 【JavaScript】クラスの概念をしっかりと理解しよう! 小学生からのプログラミング入門
  21. 【JavaScript】プログラム全体をクラスを使って作ってみよう! 小学生からのプログラミング入門
  22. 【JavaScript】文字を表示するクラスを作ってみよう! 小学生からのプログラミング入門
  23. 【JavaScript】改行と一文字ずつ画面に表示する方法! 小学生からのプログラミング入門
  24. 【JavaScript】ノベルゲーム風にキー入力で文字を切り替える方法! 小学生からのプログラミング入門
  25. JavaScriptでRPGを作ろう!スマホにも対応したゲームの作り方
  26. webpackを使ってゲームエンジンを作ろう!(JSライブラリの作り方)
  27. WindowsにPythonをインストールしてみよう!小学生からのPython入門
  28. MacにPythonをインストールしてみよう!小学生からのPython入門
  29. Pythonでじゃんけんゲームを作ってみよう!小学生からのPython入門
  30. Pythonのtkinterを使って、ウィンドウを表示してみよう!
  31. Pythonのtkinterで、画像つきのおみくじゲームを作ろう!
オリジナルゲーム.com