1. HOME
  2. »
  3. プログラミング・Web
  4. »
  5. JavaScript
  6. »
  7. 小学生からのJavaScript。プログラム全体をクラスを使って作ってみよう!

小学生からのJavaScript。プログラム全体をクラスを使って作ってみよう!

小学生からのプログラミング講座(こうざ)、第13弾です。

前回はプログラミングにおける、クラスの使い方を学びました。
しかし、まだクラスをどうやって使えばいいのか、ピンときていないかもしれません。

そこで今回は、これまで作成してきたゲームを、クラスを使ったものに書き換えていきたいと思います。

山田

山田

クラスを使うと、プログラムがとても見やすいものになるんだべ

りこ

りこ

どうプログラムが変わっていくんだろう? 楽しみ!

目次
  1. スプライトクラスを作ろう!
  2. ゲームクラスを作ろう!
  3. 入力(Input)クラスを作ろう!
  4. プログラム全体をクラスを使って書いてみよう!
  5. まとめ

スプライトクラスを作ろう!

スプライトは「動かしたい画像」のことです。
Scratch(スクラッチ)にもあったスプライトと同じです。ではスプライトのためのクラスを作ってみましょう。

class Sprite {
	constructor( img, left, top ) {
		this.left = left || 0;
    		this.top = top || 0;
		this.img = new Image();
		this.img.src = img;
		this.width = 32;
		this.height = 32;
	}
}

2行目、コンストラクタ(constructor)の部分に、img、left、topというふうに書かれています。
これは「どの画像」の「左から何px」「上から何px」の部分かを指定するものです。

では次の画像を使うとします。

りこちゃん、山田先生、アル君が、1つの画像のなかにあります。
この中から、アル君のスプライトを作りたいとします。

するとアル君は左から65px、上から0pxの場所にありますので、その場所を指定してあげます。

山田

山田

スプライトを作りたいと思ったら、さっき作ったスプライトクラスのメンバーに入れてあげれば、スプライトになるんだべ

アル

アル

どうやってやるんだっけ?

山田

山田

こんなふうにすればいいべ!

let aru = new Sprite( 'img/character.png', 65, 0 );

letというのは ES6から使えるようになった、変数(へんすう)を使うよと宣言(せんげん)するためのコマンドです。
使い方はvarと同じですが、変数の有効範囲(ゆうこうはんい)が異(こと)なります。

letでaruを宣言し、aruをSprite(スプライト)クラスのメンバーに入れてあげます。
Sprite(スプライト)の後ろには、()をつけて、画像のパスと画像のどの部分をスプライトにするかを指定します。
そうすることで、アル君のスプライトが作られるのです。

今回は1つの画像を縦横32pxの大きさにあらかじめ決めてあるので、左と上のpx数だけ指定すればその画像が表示されます。

りこ

りこ

でもこれだとまだスプライトは表示されないよ

山田

山田

じつはそうなんだべ。そこでゲームクラスを作って、スプライトをゲーム上に表示できるようにするべ

ゲームクラスを作ろう!

さて、スプライトクラスには、ゲーム上にスプライトを表示させる機能をつけていません。
スプライトの表示はゲームクラスに作っていきます。

class Game {
	constructor( width, height ) {
		this.width = width || 320;
		this.height = height || 320;
 
		canvas = document.getElementById( 'canvas' );
		canvas.width = this.width;		//canvasの横幅(よこはば)
		canvas.height = this.height;		//canvasの縦幅(たてはば
 
		ctx = canvas.getContext( '2d' );
	}
	add( sprite, x, y ) {
		if ( typeof x === "undefined" ) sprite.x = 0;
		else sprite.x = x;
		if ( typeof y === "undefined" ) sprite.y = 0;
		else sprite.y = y;
		ctx.drawImage( sprite.img, sprite.left, sprite.top, sprite.width, sprite.height, sprite.x, sprite.y ,sprite.width, sprite.height );
	}
}

ゲームクラスでは、実際のゲームで使うcanvasの表示や設定などを行います。
また、14〜20行目で、add()を使ってスプライトをゲーム上に表示できるようにしています。

以下のようにすると縦横640pxのゲームの画面をつくることができます。

let game = new Game( 640, 640 );

りこちゃん、山田先生、アル君のオブジェクトを作成し、さきほどゲームクラスで作成したadd()を使って、メインループ内でスプライトを呼び出します。

〜省略(さきほど作ったクラスや、グローバル変数)〜
 
let game = new Game( 640, 640 );
 
let rico = new Sprite( 'img/character.png' );
let yamada = new Sprite( 'img/character.png', 33, 0 );
let aru = new Sprite( 'img/character.png', 65, 0 );
 
function main() {
	//キャラクターのスプライトを表示
	game.add( rico, 0, 0 );
	game.add( aru, 32, 64 )
	game.add( yamada, 96, 96 );
 
	requestAnimationFrame( main );
}
addEventListener('load', main(), false);

りこ

りこ

あらかじめクラスを作っておけば、こんなに簡単にゲームの画面やスプライトを表示できるようになるのね!

山田

山田

ブラウザで確認すると、こんなふうになるべ

アル

アル

わー、僕たち3人が表示されてる!

入力(Input)クラスを作ろう!

続いて、Inputクラスを作ってみます。
Inputは「入力する」という意味で、キー入力のためのクラスとします。

class Input {
	constructor() {
		this.up = false;
		this.left = false;
		this.down = false;
		this.right = false;
	}
	push_key() {
		addEventListener( "keydown", () => {
			const key_code = event.keyCode;
			if( key_code === 37 ) this.left = true;
			if( key_code === 38 ) this.up = true;
			if( key_code === 39 ) this.right = true;
			if( key_code === 40 ) this.down = true;
			event.preventDefault();		//方向キーでブラウザがスクロールしないようにする
		}, false);
		addEventListener( "keyup", () => {
			const key_code = event.keyCode;
			if( key_code === 37 ) this.left = false;
			if( key_code === 38 ) this.up = false;
			if( key_code === 39 ) this.right = false;
			if( key_code === 40 ) this.down = false;
		}, false);
	}
}

このInputクラスは、あらかじめよく使うと思うボタンを設定(せってい)しておいて、そのボタンが押されているかどうかを判断(はんだん)するものです。

今回はそれぞれの方向キーが押されているかどうかを判断(はんだん)できるようにしました。

inputオブジェクトを作ります。

let input = new Input();

あとは、push_key()を呼び出し、条件分岐でキーが入力されたときにどうしたいのかを書いていきます。
例えばこのようにすると、左キーが押されている間xから6ずつ引いていくというプログラムになります。

function main() {
	input.push_key();
	if ( input.left === true ) x-=6;
	requestAnimationFrame( main );
}
addEventListener('load', main(), false);

りこ

りこ

これでキャラ移動もつくれそうだね!

プログラム全体をクラスを使って書いてみよう!

では、プログラム全体をクラスを使って書いてみます。

'use strict';
 
//グローバル変数の定義
let canvas;
let ctx;
 
//マップの作成(さくせい)
let 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]
]
 
 
//スプライトクラス
//img : スプライトに使う画像
//left : 画像の左から何ピクセルの部分を使うか
//top : 画像の上から何ピクセルの部分を使うか
class Sprite {
	constructor( img, left, top ) {
		this.left = left || 0;
    		this.top = top || 0;
		this.img = new Image();
		this.img.src = img;
		this.width = 32;
		this.height = 32;
	}
}
 
//ゲームクラス
//width : ゲーム全体の横幅
//height : ゲーム全体の縦幅
//
//add() : ゲームにスプライトを表示
class Game {
	constructor( width, height ) {
		this.width = width || 320;
		this.height = height || 320;
 
		canvas = document.getElementById( 'canvas' );
		canvas.width = this.width;		//canvasの横幅(よこはば)
		canvas.height = this.height;		//canvasの縦幅(たてはば
 
		ctx = canvas.getContext( '2d' );
	}
	add( sprite, x, y ) {
		if ( typeof x === "undefined" ) sprite.x = 0;
		else sprite.x = x;
		if ( typeof y === "undefined" ) sprite.y = 0;
		else sprite.y = y;
		ctx.drawImage( sprite.img, sprite.left, sprite.top, sprite.width, sprite.height, sprite.x, sprite.y ,sprite.width, sprite.height );
	}
}
 
//入力(Input)クラス
//up : 上キー
//left : 左キー
//down : 下キー
//right : 右キー
class Input {
	constructor() {
		this.up = false;
		this.left = false;
		this.down = false;
		this.right = false;
	}
	push_key() {
		addEventListener( "keydown", () => {
			const key_code = event.keyCode;
			if( key_code === 37 ) this.left = true;
			if( key_code === 38 ) this.up = true;
			if( key_code === 39 ) this.right = true;
			if( key_code === 40 ) this.down = true;
			event.preventDefault();		//方向キーでブラウザがスクロールしないようにする
		}, false);
		addEventListener( "keyup", () => {
			const key_code = event.keyCode;
			if( key_code === 37 ) this.left = false;
			if( key_code === 38 ) this.up = false;
			if( key_code === 39 ) this.right = false;
			if( key_code === 40 ) this.down = false;
		}, false);
	}
}
 
//inputオブジェクトの作成
let input = new Input();
 
//プレイヤークラス
//x : プレイヤーのx座標
//y : プレイヤーのy座標
//move : プレイヤーをうまく動かすためのもの
//
//move_sp() : プレイヤーのスプライトを動かす
class Player {
	constructor(x, y) {
		this.sprite = new Sprite( 'img/character.png' );
		this.x = x;
		this.y = y;
		this.move = 0;
	}
	move_sp() {
		input.push_key();
		game.add( this.sprite, this.x, this.y );
		if ( this.move === 0 ) {
			if ( input.left === true ) {
				var x = this.x/32;
				var y = this.y/32;
				x--;
				if ( map[y][x] === 0 ) {
					this.move = 32;
					input.push = 'left';
				}
			}
			if ( input.up === true ) {
				var x = this.x/32;
				var y = this.y/32;
				if ( y > 0) {
					y--;
					if ( map[y][x] === 0 ) {
						this.move = 32;
						input.push = 'up';
					}
				}
			}
			if ( input.right === true ) {
				var x = this.x/32;
				var y = this.y/32;
				x++;
				if ( map[y][x] === 0 ) {
					this.move = 32;
					input.push = 'right';
				}
			}
			if ( input.down === true ) {
				var x = this.x/32;
				var y = this.y/32;
				if ( y < 19 ) {
					y++;
					if ( map[y][x] === 0 ) {
						this.move = 32;
						input.push = 'down';
					}
				}
			}
		}
 
		//this.moveが0より大きい場合は、4pxずつ移動(いどう)を続ける
		if (this.move > 0) {
			this.move -= 4;
			if ( input.push === 'left' ) this.x -= 4;
			if ( input.push === 'up' ) this.y -= 4;
			if ( input.push === 'right' ) this.x += 4;
			if ( input.push === 'down' ) this.y += 4;
		}
	}
}
 
//ゲームオブジェクトの作成
let game = new Game( 640, 640 );
 
//プレイヤーのオブジェクトを作成
let player = new Player( 0, 0 );
 
//キャラクターのオブジェクトを作成
let yamada = new Sprite( 'img/character.png', 33, 0 );
let aru = new Sprite( 'img/character.png', 65, 0 );
 
//床、壁のマップチップのオブジェクトを作成
let floor = new Sprite( 'img/map.png', 0, 0 );
let wall = new Sprite( 'img/map.png', 33, 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 ) game.add( floor, 32*x, 32*y );
			if ( map[y][x] === 1 ) game.add( wall, 32*x, 32*y );
		}
	}
 
	//キャラクターのスプライトを表示
	player.move_sp();
	game.add( aru, 32, 64 );
	game.add( yamada, 96, 96 );
 
	requestAnimationFrame( main );
}
addEventListener('load', main(), false);

まとめ

今回はプログラム全体を、クラスを使ったものに書き換えてみました。

クラスを使うことで、ソースコードが綺麗(きれい)に整理(せいり)され、後からみたときも分かりやすくなります。
ぜひクラス使い方をマスターしましょう!

山田

山田

スプライトクラスを作っておくと、簡単にスプライトをつくることができるべ。 クラスの便利さはわかってもらえたべか?

アル

アル

うん、クラスって便利(べんり)なんだね

りこ

りこ

どこに何が書いてあったか悩(なや)むのも少なくなるね

山田

山田

今回はわだずやアル君のスプライトも表示したべけど、まだ突っ立っているだけなんだべよ

りこ

りこ

なにか喋(しゃべ)ったりとかさせたいよね

山田

山田

みんなで一緒(いっしょ)に冒険(ぼうけん)にでかけるのもいいべ。 どんどんゲームらしくなるから、今後の記事を楽しみにするべよ

りこ

りこ

はーい!

アル

アル

はーい!

この企画の一覧はこちら

  1. 小学生からのプログラミング入門。JavaScriptでおみくじを作ろう!
  2. 小学生からのJavaScript入門。今月の残り日数を計算してみよう!
  3. 小学生からのJavaScript入門。画像の表示と移動をしてみよう!
  4. 小学生からのJavaScript入門。キー入力でキャラを動かしてみよう!
  5. 小学生からのJavaScript入門。ファイルを分けて管理してみよう!
  6. 小学生からのJavaScript入門。オブジェクトを使ってみよう!
  7. 小学生からのJavaScript入門。ゲームのメインループを作ってみよう!
  8. 小学生からのJavaScript入門。キャラを決まった間隔ずつ動かす!
  9. 小学生からのJavaScript。HTML5とCanvasを使ってみよう!
  10. 小学生からのJavaScript。迷路やRPGで使えるマップを作ってみよう!
  11. 小学生からのJavaScript。マップでキャラを動かせるようにしよう!
  12. 小学生からのJavaScript。クラスの概念をしっかりと理解しよう!
  13. 小学生からのJavaScript。プログラム全体をクラスを使って作ってみよう!
  14. 小学生からのJavaScript。文字を表示するクラスを作ってみよう!
  15. 小学生からのJavaScript。改行と一文字ずつ画面に表示する方法!
  16. JavaScript|ノベルゲーム風にキー入力で文字を切り替える方法!

スポンサードリンク

関連コンテンツ

オススメ記事

リセットCSS は何を使う? まとめ8選と2019年版ランキング

Web開発でブラウザごとの表示の違いをリセットしてくれる リセットCSS というものがあります。 しかし、何を使っていいのかと感じている人もいると思います。 今回はこの リセットCSS につい

java

【Java】スーパクラス、サブクラスとは?継承について。

猿も木から落ちますが、Rは木から落ちません。だって登らないから。 @It_is_R です。いや、登ろうと思っても登れません。 Javaを使っていると継承という言葉をよく耳にしますよね。どういうも

WordPress テーマ自作 | Pug ( Jade ) で記事一覧ページを作る方法!

愛と勇気だけが友達の@It_is_Rです。 今回はPugでWordPressテーマを作る方法を少し紹介します。 詳しいテーマの作り方はこちらをご覧ください。 WordPressのテーマを自作

Docker Composeで自分のWordPressサイトをローカル開発環境に反映!

ローカルにWordPress開発環境を整えてテーマを作成することがあるのですが、単にローカルに環境を作っただけでは記事がなく、テーマのイメージが分かりません。@It_is_Rです。 かといって、te

メインループを作ってみよう!

小学生からのJavaScript入門。ゲームのメインループを作ってみよう!

小学生からのJavaScript入門講座(にゅうもんこうざ)、第7弾です。 突然(とつぜん)ですが、ゲーム開発(かいはつ)の基本として大切なことってなんだったか覚えていますか? そうです。「変

wordpress

【WordPress】パンくずリストをプラグイン無しで自作する方法

※追記(2018/2/12) もっと高機能になるように、改良修正しました。 人生で3回ほど死にそうになったことがある@It_is_Rです。 WordPressのパンくずリストを作

MacでのAndroid Studioインストール手順

今回は Android Studio 3.4 をインストールする手順を解説します。 Android Studio のダウンロード Android Studio そのページから

bootstrap3

Bootstrap3でサイトのレイアウト。グリッドシステムの使い方と裏技。

開発中のゲームはサイト制作に入っております。@It_is_Rです。 前回に引き続き、Bootstrap3の記事です。 サイトを作るとき、CSSなどを使ってサイトのレイアウトを調節したりしますが

文字を一文字ずつ表示してみよう!

小学生からのJavaScript。改行と一文字ずつ画面に表示する方法!

小学生からのJavaScript講座です。 このシリーズでは、ゲームをつくりながらJavaScriptの使い方を学んでいきます。 前回、画面に文字を表示するためのクラスを作ったのですが、それを

文字を表示するクラスを作ろう!

小学生からのJavaScript。文字を表示するクラスを作ってみよう!

小学生からのJavaScript講座です。 このシリーズでは、ゲームをつくりながらJavaScriptの使い方を学んでいきます。 シリーズの一覧はこちらをご覧ください。 さて、ゲーム作成で重

コメントをどうぞ!

メールアドレスが公開されることはありません。