見出し画像

JavaScript+html+Canvas でゲーム作成(効果音出力)

「キーボード入力(トリガ)」を使って効果音を出してみました。

SPACEキーでジャンプ時に指定した音が鳴ります。

音のファイルは、<音ファイル名>を自由に設定してください。
ファイルフォーマットは、mp3, wav, mp4, flac, m4aが使えるようです。

例:
 音ファイルがhtmlと同じフォルダにある時、
 se_jump.src = "./sound_effect.mp3";

音出力の際、.play()の前に.load()を入れています。
.load()を入れないと前の音出力が終了しないと次の音が出ないため、
連続で音を出そうとした時に音が出なくなるのを防いでいます。

以下、プログラム。(音出力追加部分には[#sound#]で括ってます。)

<html>
<head>
<style type="text/css">
<!-- canvas { background: #000  ; } -->
</style>
</head>
<body>
<canvas id="myCanvas" width="512" height="512"></canvas>
<script language="JavaScript">
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//-----<#### JavaScript+html+Canvas でゲーム作成 ####>

//音出力サンプル

	//[#sound#]------------------------------------------------------------
	// 音出力準備
	const se_jump = document.createElement("audio");
	se_jump.src = <音ファイル名>;		// <音ファイル名>を指定★
	se_jump.preload = "auto";			// 事前に音声データを読み込む
	//[#sound#]------------------------------------------------------------

	//[#key input#]------------------------------------------------------------
	// キーボード入力を取得する
	document.addEventListener("keydown", keyDownHandler, false);
	document.addEventListener("keyup", keyUpHandler, false);
	//[#key input#]------------------------------------------------------------

	// パラメータ
	var RADIUS = 2;			// 点の半径
	var DDOT = 2;			// 隣り合う点の間隔 x2(0以外の偶数)

	// 変数
	var XSIZE = canvas.width / DDOT;	// Xサイズ(描画サイズは、XSIZE * DDOT)
	var YSIZE = canvas.height / DDOT;	// Yサイズ(描画サイズは、YSIZE * DDOT)

	// インベーダーキャラクタ
	//  0 1 2 3 4 5 6 7 8 9 a b c d 
	//0:□□□□□■■■■□□□□□
	//1:□□■■■■■■■■■■□□
	//2:□■■■■■■■■■■■■□
	//3:□■■■□□■■□□■■■□
	//4:□■■■■■■■■■■■■□
	//5:□□□■■■□□■■■□□□
	//6:□□■■□□■■□□■■□□
	//7:□□□■■□□□□■■□□□
	var dottbl_0 = new Array(0x7e);
	// ■の座標:xpos, ypos,,,,
	dottbl_0 = [
		0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,
		0x02,0x01,0x03,0x01,0x04,0x01,0x05,0x01,0x06,0x01,0x07,0x01,0x08,0x01,0x09,0x01,0x0a,0x01,0x0b,0x01,
		0x01,0x02,0x02,0x02,0x03,0x02,0x04,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x08,0x02,0x09,0x02,0x0a,0x02,0x0b,0x02,0x0c,0x02,
		0x01,0x03,0x02,0x03,0x03,0x03,0x06,0x03,0x07,0x03,0x0a,0x03,0x0b,0x03,0x0c,0x03,
		0x01,0x04,0x02,0x04,0x03,0x04,0x04,0x04,0x05,0x04,0x06,0x04,0x07,0x04,0x08,0x04,0x09,0x04,0x0a,0x04,0x0b,0x04,0x0c,0x04,
		0x03,0x05,0x04,0x05,0x05,0x05,0x08,0x05,0x09,0x05,0x0a,0x05,
		0x02,0x06,0x03,0x06,0x06,0x06,0x07,0x06,0x0a,0x06,0x0b,0x06,
		0x03,0x07,0x04,0x07,0x09,0x07,0x0a,0x07,
		0xff,0xff];		// 終端

	//  0 1 2 3 4 5 6 7 8 9 a b c d 
	//0:□□□□□■■■■□□□□□
	//1:□□■■■■■■■■■■□□
	//2:□■■■■■■■■■■■■□
	//3:□■■■□□■■□□■■■□
	//4:□■■■■■■■■■■■■□
	//5:□□□□■■□□■■□□□□
	//6:□□□■■□■■□■■□□□
	//7:□■■□□□□□□□□■■□

	var dottbl_1 = new Array(0x7c);
	// ■の座標:xpos, ypos,,,,
	dottbl_1 = [
		0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,
		0x02,0x01,0x03,0x01,0x04,0x01,0x05,0x01,0x06,0x01,0x07,0x01,0x08,0x01,0x09,0x01,0x0a,0x01,0x0b,0x01,0x01,0x02,
		0x02,0x02,0x03,0x02,0x04,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x08,0x02,0x09,0x02,0x0a,0x02,0x0b,0x02,0x0c,0x02,
		0x01,0x03,0x02,0x03,0x03,0x03,0x06,0x03,0x07,0x03,0x0a,0x03,0x0b,0x03,0x0c,0x03,
		0x01,0x04,0x02,0x04,0x03,0x04,0x04,0x04,0x05,0x04,0x06,0x04,0x07,0x04,0x08,0x04,0x09,0x04,0x0a,0x04,0x0b,0x04,0x0c,0x04,
		0x04,0x05,0x05,0x05,0x08,0x05,0x09,0x05,
		0x03,0x06,0x04,0x06,0x06,0x06,0x07,0x06,0x09,0x06,0x0a,0x06,
		0x01,0x07,0x02,0x07,0x0b,0x07,0x0c,0x07,
		0xff,0xff];		// 終端

	var pos = new Array( XSIZE * YSIZE );			// 画面座標

	const COLOR_BLACK = 0;		// 黒
	const COLOR_WHITE = 1;		// 白

	// 点描画
	// xp : x座標
	// yp : y座標
	// colnum : 色番号(0:black, 1:white)
	function draw_point( xp, yp, colnum ) {
		var offset = yp * XSIZE + xp;
		ctx.beginPath();
		if( colnum == 0 ) {
			ctx.fillStyle = "rgb(" + (~~0x00) + ", " + (~~0x00) + ", " + (~~0x00) + ")";
		} else {
			ctx.fillStyle = "rgb(" + (~~0xFF) + ", " + (~~0xFF) + ", " + (~~0xFF) + ")";
		}
		ctx.fillRect( pos[offset][0], pos[offset][1], RADIUS, RADIUS);
		ctx.closePath();
	}

	// 指定された位置のパターンを描画
	// dx : x座標
	// dy : y座標
	// dn : パターン番号
	// dc : 色番号(0:black, 1:white)
	function dot_pattern_put( dx, dy, dn, dc )
	{
		var i = 0;
		if( dn == 0 ){
			while (dottbl_0[i*2] != 0xff){
				draw_point( dx + dottbl_0[i*2+0], dy + dottbl_0[i*2+1], dc);
				i++;
			}
		} else {
			while (dottbl_1[i*2] != 0xff){
				draw_point( dx + dottbl_1[i*2+0], dy + dottbl_1[i*2+1], dc);
				i++;
			}
		}
	}

	// 初期化
	// 画面座標セット
	for( var y = 0; y < YSIZE; y++ ){
		for (var x = 0; x < XSIZE; x++) {
			pos[y * XSIZE + x]  = new Array(2); // x,y
			pos[y * XSIZE + x][0] = x * ( DDOT & 0xfe ); // xpos
			pos[y * XSIZE + x][1] = y * ( DDOT & 0xfe ); // ypos
		}
	}
	
	const anim_time_max = 40;		// アニメーションスピード  40/60 sec
	var anim_time = anim_time_max;	// アニメーション時間カウンタ
	var anim_pattern = 0;			// アニメーションパターン
	var xpos = 0x20;				// x座標
	var ypos = 0x20;				// y座標
	
	//[#jump#]------------------------------------------------------------
	var ypos_offset = 0;			// y座標加算値
	var jump_switch = 0;			// ジャンプ中判定
	var jump_counter = 0;			// ジャンプテーブルカウンタ
	var jumptbl = new Array(19);
	jumptbl = [ -4,-4,-3,-3,-2,-2,-1,-1,0,0,1,1,2,2,3,3,4,4,0xFF ];
	//[#jump#]------------------------------------------------------------
	
	function draw() {

		// 前回のアニメーションパターンを削除
		dot_pattern_put( xpos, ypos, anim_pattern, COLOR_BLACK );

		// アニメーションタイミング
		if( anim_time < anim_time_max ){
			anim_time++;
		}else{
			anim_time = 0;

			// 次のパターン番号セット
			anim_pattern = ( anim_pattern + 1 ) & 1;
		}

		//[#key input#]------------------------------------------------------------
		// 入力取得
		getKey = get_input();
		
		if( getPressRIGHT() ) {			// 右移動
			// キー入力後の位置を更新
			xpos = xpos + 1;
		} else if( getPressLEFT() ) {	// 左移動
			// キー入力後の位置を更新
			xpos = xpos - 1;
		}
		//[#key input#]------------------------------------------------------------
		//[#jump#]------------------------------------------------------------

		// ジャンプ加算値クリア
		ypos_offset = 0;

		// ジャンプ中でない時にSPACEキーをチェック
		if( ( jump_switch == 0 ) && getInputSPACE() ) {
			// ジャンプ中セット
			jump_switch = 1;
			jump_counter = 0;
			//[#sound#]------------------------------------------------------------
			se_jump.load();		//ロード
			se_jump.play();		//音出力
			//[#sound#]------------------------------------------------------------
		}

		// ジャンプ中の時
		if( jump_switch == 1 ) {
			ypos_offset = jumptbl[jump_counter];
			jump_counter++;
			if( jumptbl[jump_counter] == 0xff ) {
				// 次でジャンプ終了ならジャンプ中クリア
				jump_switch = 0;
			}
		}
		// ジャンプ実行
		ypos = ypos + ypos_offset;
		//[#jump#]------------------------------------------------------------

		// 今回のアニメーションパターンを描画
		dot_pattern_put( xpos, ypos,anim_pattern, COLOR_WHITE);
	}

	//[#key input#]------------------------------------------------------------
	// 入力

	// 定数
	const KEY_LEFT  = 0;
	const KEY_RIGHT = 1;
	const KEY_SPACE = 2;
	// 変数
	var getKey = 0;
	var trgKey = 0;
	var keypress_R = 0;
	var keypress_L = 0;
	var keypress_SPACE = 0;

	const KEYCODE_SPACE  = 32;		// SPACEキーコード

	// キーON
	function keyDownHandler(e) {
		if( e.key == "Right" || e.key == "ArrowRight" ) {
			keypress_R = 1;
		} else if( e.key == "Left" || e.key == "ArrowLeft" ) {
			keypress_L = 1;
		} else if( e.keyCode == KEYCODE_SPACE ) {
			keypress_SPACE = 1;
		}
	}
	
	// キーOFF
	function keyUpHandler(e) {
		if( e.key == "Right" || e.key == "ArrowRight" ) {
			keypress_R = 0;
		} else if( e.key == "Left" || e.key == "ArrowLeft" ) {
			keypress_L = 0;
		} else if( e.keyCode == KEYCODE_SPACE ) {
			keypress_SPACE = 0;
		}
	}

	// キーボード入力を取得する
	function get_input() {
		var keypress = 0;
		if( 1 == keypress_R ) { keypress |= 1 << KEY_RIGHT; }	else { keypress &= ~(1 << KEY_RIGHT); }
		if( 1 == keypress_L ) { keypress |= 1 << KEY_LEFT;  }	else { keypress &= ~(1 << KEY_LEFT);  }	
		if( 1 == keypress_SPACE ) { keypress |= 1 << KEY_SPACE; } else { keypress &= ~(1 << KEY_SPACE); }
		return (keypress);
	}
	
	// SPACEキートリガ
	function getInputSPACE()  { 
		if( getKey & ( 1 << KEY_SPACE  ) ) { 
			if( trgKey & ( 1 << KEY_SPACE      ) ) {
				return 0;
			} else {
				trgKey |= ( 1 << KEY_SPACE      );
				return 1; 
			}
		} else { 
			trgKey &= ~( 1 << KEY_SPACE      );
			return 0; 
		} 
	}

	// カーソル左押下
	function getPressLEFT()   { 
		if( getKey & ( 1 << KEY_LEFT   ) ) { 
			return 1; 
		} else { 
			return 0; 
		} 
	}
	// カーソル右押下
	function getPressRIGHT()  { 
		if( getKey & ( 1 << KEY_RIGHT  ) ) { 
			return 1; 
		} else { 
			return 0; 
		} 
	}
	//[#key input#]------------------------------------------------------------

//-----<#### JavaScript+html+Canvas でゲーム作成 s####>
/* draw()関数がsetIntervalの中で16ミリ秒おきに実行 */
setInterval(draw, 16);

</script>
</body>
</html>

この記事が気に入ったらサポートをしてみませんか?