小学生からのプログラミング講座、今回もはじめていきましょう!
前回は、JavaScriptでのマップの作り方を紹介しました。
しかし、まだマップを配置しただけで、キャラクターの画像を表示させていませんでした。
今回はマップ上にキャラクターの画像を表示させ、動かせるようにしてみようと思います。
また、壁との衝突判定も作り、キャラクターが壁をすり抜けられないようにしてみようと思います。

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

うまく動いた?

それが全然。一応表示はされたんだけど、りこちゃんが壁をすり抜けちゃうんだ

そうなんだ

じゃあ、今日は壁との衝突判定を作っていくべ!

山田先生! わーい!

はやくやろう!
マップにキャラクターを表示してみよう!
まずはマップにキャラクターを表示させるところから始めましょう!
第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つの方法です。

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

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

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

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

へへへっ

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

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

ザギン……?

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

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

ゴーグルと海パンだよ

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

あ……

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

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

ゆるしてー
このシリーズの一覧はこちら
- 小学生からのプログラミング入門。プログラミングってなぁに?
- Scratchの使い方と、ゲーム作りの基礎知識を学ぼう! 小学生からのプログラミング入門
- Scratchでじゃんけんゲームを作ろう! 小学生からのプログラミング入門
- Scratchでシューティングゲームを作ろう! 小学生からのプログラミング入門
- Scratchでピアノ鍵盤を作って音を鳴らそう! 小学生からのプログラミング入門
- テキストエディタ(Visual Studio Code)をインストールしてみよう! 小学生からのプログラミング入門
- Visual Studio Codeを日本語化してみよう! 小学生からのプログラミング入門
- JavaScriptでおみくじを作ろう! 小学生からのプログラミング入門
- JavaScriptで今月の残り日数を計算してみよう! 小学生からのプログラミング入門
- JavaScriptで画像を表示してみよう! 小学生からのプログラミング入門
- JavaScriptで画像を移動してみよう! 小学生からのプログラミング入門
- 【JavaScript】キー入力でキャラを動かしてみよう! 小学生からのプログラミング入門
- 【JavaScript】ファイルを分けて管理してみよう! 小学生からのプログラミング入門
- 【JavaScript】オブジェクトを使ってみよう! 小学生からのプログラミング入門
- 【JavaScript】ゲームのメインループを作ってみよう! 小学生からのプログラミング入門
- 【JavaScript】キャラを決まった間隔ずつ動かす! 小学生からのプログラミング入門
- HTML5とCanvasを使ってみよう! 小学生からのプログラミング入門
- 【JavaScript】迷路やRPGで使えるマップを作ってみよう! 小学生からのプログラミング入門
- 【JavaScript】マップでキャラを動かせるようにしよう! 小学生からのプログラミング入門
- 【JavaScript】クラスの概念をしっかりと理解しよう! 小学生からのプログラミング入門
- 【JavaScript】プログラム全体をクラスを使って作ってみよう! 小学生からのプログラミング入門
- 【JavaScript】文字を表示するクラスを作ってみよう! 小学生からのプログラミング入門
- 【JavaScript】改行と一文字ずつ画面に表示する方法! 小学生からのプログラミング入門
- 【JavaScript】ノベルゲーム風にキー入力で文字を切り替える方法! 小学生からのプログラミング入門
- JavaScriptでRPGを作ろう!スマホにも対応したゲームの作り方
- webpackを使ってゲームエンジンを作ろう!(JSライブラリの作り方)
- WindowsにPythonをインストールしてみよう!小学生からのPython入門
- MacにPythonをインストールしてみよう!小学生からのPython入門
- Pythonでじゃんけんゲームを作ってみよう!小学生からのPython入門
- Pythonのtkinterを使って、ウィンドウを表示してみよう!
- Pythonのtkinterで、画像つきのおみくじゲームを作ろう!