小学生からのプログラミング講座、今回もはじめていきましょう!
前回は、JavaScriptでのマップの作り方を紹介しました。
しかし、まだマップを配置しただけで、キャラクターの画像を表示させていませんでした。
今回はマップ上にキャラクターの画像を表示させ、動かせるようにしてみようと思います。
また、壁との衝突判定も作り、キャラクターが壁をすり抜けられないようにしてみようと思います。
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
昨日さ、前回教えてもらったマップチップの表示と、りこちゃんの画像表示を自分で組み合わせて作ってみたんだ
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
うまく動いた?
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
それが全然。一応表示はされたんだけど、りこちゃんが壁をすり抜けちゃうんだ
![](https://original-game.com/wp-content/uploads/2020/09/sad-1.jpg)
そうなんだ
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
じゃあ、今日は壁との衝突判定を作っていくべ!
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
山田先生! わーい!
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
はやくやろう!
マップにキャラクターを表示してみよう!
まずはマップにキャラクターを表示させるところから始めましょう!
第12回目で紹介した、HTML5とCanvasでキャラクターを動かす方法と、第13回目で紹介した、マップの表示方法を組み合わせて作ります。
まずはcanvasの設定と、コンテキストを取得です。
//canvasの設定(せってい)
var canvas = document.getElementById( 'canvas' );
canvas.width = 640; //canvasの横幅(よこはば)
canvas.height = 640; //canvasの縦幅(たてはば)
//コンテキストを取得(しゅとく)
var ctx = canvas.getContext( '2d' );
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
ここまでで、Canvasをつかう準備ができたわけだね
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
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]
]
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
マップは縦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;
}
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
りこちゃんが移動するためのプログラムだね
少々長いですが、全体はこのようになっています。
//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;
}
しかしこのプログラムでは、りこちゃんが壁をすり抜けてしまいます。
下の枠内をクリックして、方向キーで操作してみてね!
![](https://original-game.com/wp-content/uploads/2020/09/surprise-1.jpg)
きゃー、私が壁をすり抜けてる
![](https://original-game.com/wp-content/uploads/2020/09/sad-2.jpg)
これじゃあ迷路にならないね
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
そこで今回は、壁にぶつからないように、プログラムをつくっていくべ!
壁の座標とりこちゃんの座標を比べて、壁との当たり判定をする
当たり判定といえば、Scratch(スクラッチ)でシューティングゲームを作った時も敵とぶつかっているかとか、弾が当たっているかとか、やりましたね。
しかし今回の場合、「壁に当たっているか」ではなく、「壁に当たってしまうか」という判定になります。
どちらにしろ実際には当たっていないので、「この先、衝突するかも」という予測の判定です。
![](https://original-game.com/wp-content/uploads/2020/09/sad-2.jpg)
予測って……まほうでもつかうのかな?
![](https://original-game.com/wp-content/uploads/2020/09/angry-1.jpg)
そんなわけないでしょ! でも、どうやるんだろう
![](https://original-game.com/wp-content/uploads/2020/09/angry.jpg)
座標で考えればいんだべ
![](https://original-game.com/wp-content/uploads/2020/09/sad-2.jpg)
りこちゃんの座標と、壁の座標を比べるってこと? でもどうやって……
さて、壁の座標はもうすでに取得できています。
なぜなら、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と同じことになります。
![](https://original-game.com/wp-content/uploads/2020/09/surprise-1.jpg)
なんで!? よく分からない!
![](https://original-game.com/wp-content/uploads/2020/09/sad-2.jpg)
僕もさっぱり!
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
じゃあ、例を見るべよ!
では、例で見ていきましょう。
りこちゃんのいる場所は、0から数えて、左から何番目の、上から何番目でしょうか?
答えは、左から3番目の、上から6番目です。
では、x座標とy座標を正確にいうとどうなるでしょうか?
かんたんです。1マス32pxなので、32をかけ算すれば、答えがでますね。
つまりxは96px, yは192pxです。
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
逆にいえば、わり算すれば正確な座標から、何番目のところにいるかが出せるってことね!
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
そうなんだべよ!
もしも右矢印が押されて、右方向に壁がある場合は進むことができません。
壁があるということは、りこちゃんの右側が「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;
}
下の枠内をクリックして、方向キーで操作してみてね!
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
きゃー、迷路、まよっちゃう!
![](https://original-game.com/wp-content/uploads/2020/09/surprise-2.jpg)
すごい! ちゃんと壁で止まってるよ!
まとめ
今回は、マップ上をキャラクターが移動し、壁をすり抜けられないように作りました。
大切なのはりこちゃんの座標と、マップチップの座標を照らし合わせることです。そのためには、りこちゃんの座標を1つのマップチップのサイズで割るというのも1つの方法です。
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
ここまででも、一応遊べるべよ
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
まだスタートもゴールもないけどね
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
でもスタートとゴールだけなら簡単につくれそうだね
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
ふたりとも、よくここまで頑張ったべ
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
へへへっ
![](https://original-game.com/wp-content/uploads/2020/09/normal-2.jpg)
もっと頑張ればポケモンみたいなゲームだって夢じゃないなって思えてきたよ
![](https://original-game.com/wp-content/uploads/2020/09/angry.jpg)
それは良かったべ。ところでわだず、昨日ザギンで、こんなのかってきたべ
![](https://original-game.com/wp-content/uploads/2020/09/angry-2.jpg)
ザギン……?
![](https://original-game.com/wp-content/uploads/2020/09/sad-1.jpg)
銀座のことじゃない? どうやって行ったんだろう
![](https://original-game.com/wp-content/uploads/2020/09/normal.jpg)
サングラスと、ジーパンだべ。どうだべ、似合うべか? これで人間になりすますんだべ
![](https://original-game.com/wp-content/uploads/2020/09/angry-2.jpg)
ゴーグルと海パンだよ
![](https://original-game.com/wp-content/uploads/2020/09/normal-1.jpg)
ははは、海でも行くのー?
![](https://original-game.com/wp-content/uploads/2020/09/surprise.jpg)
あ……
![](https://original-game.com/wp-content/uploads/2020/09/angry.jpg)
て……てやんでぇ、べらぼうめだべさ! 海に行ってこそ、真の男だべさ!
次回はもっと難しいこと教えてやるべ! 覚悟するべ!
![](https://original-game.com/wp-content/uploads/2020/09/sad-1.jpg)
ひぃ、う……うん。先生、こわい
![](https://original-game.com/wp-content/uploads/2020/09/sad-2.jpg)
ゆるしてー
このシリーズの一覧はこちら
- 小学生からのプログラミング入門。プログラミングってなぁに?
- 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で、画像つきのおみくじゲームを作ろう!