イニシャルッ E~ タンタンタン!
どうもNSZ山本です。
突然ですがいきなりゲーム作ってみました。
プレイ時間は30秒。クソゲーですが最小限の時間の浪費
やってみたかった
PHP+HTML+JSでレスポンシブ対応のロールプレイングゲーム作ってみた – Qiita
これを読んでしまった。すっげえかっけえ。
僕も作りたい!(中学生並みの感想)!
ブラウザゲームでこれ程できるのか。
unityとかぜったい触りたくないし(ボタン多すぎ)
というわけで作ってみました。
これがタイトル画面です。

遊び方
ここへアクセス。
ブラウザゲームなのでアクセスするだけです。
左右キー←→とエンターだけで動かせます。

車は見ればわかりますが私の手書きです。
車を選んでスタート。

制限時間は30秒
いらすとやさんの絵がポップです。
ルールは特に説明していませんが
おそらく「道に現れる歩行者や自転車を出来るだけREKI-SATSUすればハイスコア」だと思います。
あくまで暗黙のルールなので、よけるゲームとしてご利用いただいてもOK。
そんな物騒なの明言するわけにはいかんでしょ(すっとぼけ)
ほんとにどっちとしても遊べますからね?!

爆破音の効果音もつけました。

リザルト画面。
スコアを反映してあなたの運転レベルが出ます。ゴールドから免許返納レベルのステータスが与えられます。
更に上に隠しステータスもあります。
実装方法
ほぼjqueryなどのjs系で作ってます。
画面が3つ
- タイトル
 - ゲーム
 - リザルト
 
で構成しています。それぞれ使った技術を紹介します。まあこれをみてこれを作ろうなんて思う人は居ないと思うので、軽く書いておきます。
1タイトル
車の選択は実はスリックデス。
とりあえずスリック。みんな大好きSlick.jsを導入しておきます。
| 
					 1 2 3 4 5 6 7 8 9 10  | 
						$(window).keydown(function(e){						 	if(e.keyCode == 37){$('.slick-prev').trigger('click')}					 	if(e.keyCode == 39){$('.slick-next').trigger('click')}					 	if(e.keyCode == 13){					 		var imgname = $('.slick-current').find('img').attr('src');				 		$("#formtext").val(imgname);				 		$('button').trigger('click');				 	}					 });  | 
					
キーダウンイベントでキーコード判定して左右に動かす。37が左で39が右。
Enterでクリックイベントにバインド。
| 
					 1 2 3  | 
						form{						   display: none;						 }  | 
					
画面遷移を起こして2のゲーム画面に移動するのですが、画像自体にA hrefしてません。
cssでhiddenでフォームをこっそり隠して、そこにエンター押した瞬間、真ん中にある要素の画像名を取得してドーン
初心者丸出しの実装だな。
2.ゲーム
Velocity.jsの出番です。
ヴェロシティじぇーえすは、jqueryのアニメーションよりも大幅に軽く、きれいなアニメーションを実現するとのこと。
構文も直感的で書きやすいと感じました。
敵
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40  | 
						var images = [						   'iy/cardgame_man.png'						 // <只の画像の羅列なので省略>						  ];						 function img(){						 	var a = Math.floor( Math.random() * 1801 ) ;					 	if(a<901){					 		$('.iy').css({'margin-left':a});				 	}else{					 		$('.iy').css({'margin-right':a-900});				 	}					 	$('.iy').velocity(					 		{ 				 			top: 1000 			 		},{				 			duration:1500, 			 			delay:0,			 			easing:'swing',			 			complete: function(){			 				if (time < 1){		 					var fscore = $('h1').text()	 					var fkill = $('h3').text()	 					$("#fkill").val(fkill);	 					$("#fscore").val(fscore);	 					$("#fexext").val('gameend');	 					$('button').trigger('click');	 				} else {		 					$('.iy').remove();	 					var rndImg = images[Math.floor(Math.random() * images.length)];	 					$('.dummy').after("<div class = 'iy'><img  class='img'  src='"+rndImg+"'></div>");	 					img()	 				}		 			}			 		}				 	);					 }  | 
					
敵の出現位置は左右のみで管理。
乱数(1800の範囲)で数字を出し、margin-leftまたはmargin-rightのcssを上書きして左右に変化を付けて出現させます。
あとは.velocityでtop属性を、1.5秒間の間に1000px変化させることで下に落ちてくるようなアニメーションを表現。
自機
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34  | 
						var clf = true;						 $(window).keydown(function(e){						 	if(clf){					 		var carp = parseInt($('.cary').css('margin-left'), 10);				 		if(e.keyCode == 37){				 			clf = false;			 			carp = carp -200;			 			$('.cary').velocity(			 			{ 			 				'margin-left':carp		 			},{			 				duration:500, 		 				easing:'swing',		 				complete:function(){		 					clf = true;	 				}		 			});			 		}				 		if(e.keyCode == 39){				 			clf = false;			 			carp = carp +200;			 			$('.cary').velocity(			 			{ 			 				'margin-left':carp		 			},{			 				duration:500, 		 				easing:'swing',		 				complete:function(){		 					clf = true;	 				}		 			});			 		}				 	}					 });						  | 
					
自機フリウスは、現在の位置を取得、margin-left属性を変化。
右を押したらmargin-leftをプラス
左を押したらmargin-leftをマイナス
当たり判定
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47  | 
						var score = 0;						 var kill = 0;						 $(function () {						 	setInterval(function(){					 	  var iyp = $('.iy>img').offset();					 	  var iytop = iyp.top;					 	  var iyleft = iyp.left;					 	  var caryp = $('.cary>img').offset();					 	  var carlmax = caryp.left -200;					 	  var carrmax = caryp.left +200;					 	  var cartmax = caryp.top +100;					 	  var carbmax = caryp.top -100;					 	if (carlmax < iyleft && iyleft < carrmax && cartmax > iytop && iytop > carbmax){					         var src = $('.iy').children('img').attr('src');						         //役人だったらgameover						         if(src =='iy/bad2.png' || src =='iy/bad.png' ){						 			var fscore = $('h1').text()			 			var fkill = $('h3').text()			 			$("#fkill").val(fkill);			 			$("#fscore").val(fscore);			 			$("#fexext").val('bad');			 			$('button').trigger('click');			         }						 	  	score+=100;				 	  	kill+=1;				 	  	if(kill==10){				 	  		//BOUNOUS POINTS			 	  		score+=10000;			 	  		$('h4').text('CONGRATULATION! U KILLED 10 FUTURE TAXPAYER!');			 	  	}else if(kill==20){				 	  		score+=100000;			 	  		$('h4').text('R U CRAZY? SERIAL KILLER LAH.');			 	  	}				 	  	$( '#sound' ).get(0).play();				 	  	$('h1').text('score:'+score);				 	  	$('h3').text('kill:'+kill);				 	  	$('body').css('background','red');				 	  	setTimeout(function(){				      		$('body').css('background','black');				 		},100);				 	  }					       },200);						 });						  | 
					
当たり判定は0.2秒(200mmsec)おきに敵画像とフリウスの座標を取得して、その数字が範囲以内だったらtrue
条件に入ったら、上級市民かどうか判定
①上級市民だったらゲームオーバー、リザルト画面に飛ばす(フォームに点数、kill数、上級市民フラグを詰めて、submitを押したことにする)
②庶民だったら、爆破音を鳴らす。画面を赤くする。.delayで遅らせて黒画面に戻す。
リザルト画面に飛ばす(タイトル画面と同様hiddenフォームに点数、kill数、上級市民フラグを詰めて、submitを押したことにする)
初心者丸出しの実装だな。
3.リザルト
フォームから受け取った点数、kill数、上級市民フラグを取得してエコーしてるだけ。
ここは単にphpです。あとは適当です。
問題点
①クオリティが低い:うるさい
②当たり判定が雑:敵の画像のwidthがフリウスの画像と異なるので、座標の基準値が異なり、当たり判定が雑。
クソゲーだしまあいいか。
おわりに
ブラウザでもこうした縦シューくらいなら簡単に出来るなあと思いました。
肝になる技術は、
- 自機と敵をなめらかにに動かす(velocity.js)
 - 当たり判定の常時計算
 
で、あとはまあオマケみたいなもんだ。
ほんとはajaxで遷移無し読み込みしたいんですがめんどいので普通に画面遷移。僕は向上心の無いsiなのでこれくらいでいいよね。
スペシャルサンクス
参考URL
jquery – What’s the difference between keyup, keydown, keypress and input events? – Stack Overflow
jQuery キーボードによって要素を操作する方法 – キーの取得とその活用に関して | Stronghold Archive
Velocity.js のドキュメントを勝手に日本語にする – 1日ひとつ、強くなる。
CSS3のtransformで要素を斜めにしたり平行四辺形に画像をトリミング | CREATIVELOG【ホームページ制作・Web製作のクリエイティブ・ウェブ】
辺り判定
jQuery: 要素の表示位置を取得/設定するには?(offset) – Build Insider
jQueryのoffset() で表示位置の取得と要素の移動
jQueryでsetIntervalを使って特定の間隔でfunction処理を繰り返し行う(タイマー処理)方法 | BlackFlag
乱数
bgm
htmlのaudioを使用してサイト上でBGM音楽を流す – chocolat
【jQuery】遅延実行 – 数秒後にイベントを発生させる | じゆうだむ
爆破・爆発19
効果音 爆発・衝撃<『 戦闘系音 』 by On-Jin ~音人~
https://www.nxworld.net/tips/jquery-random-snippets.html
https://www.nxworld.net/tips/jquery-plugin-slick-current-class-examples.html
velocity.jsの使い方 記述方法とオプション機能 | un-Tech
javascript – Loop animation with velocity.js – Stack Overflow
javascript – Velocity.js animation delay – Stack Overflow
アニメーション最強のVelocity.jsの使い方 – Qiita
jQueryでつくる100秒タイマー | 福岡のホームページ制作会社・株式会社マグネッツ
jQuery でテキストボックスの値を設定/取得/追記/削除を行う方法
本当はこれくらい強くなりたい(ムリ)
PHP+HTML+JSでレスポンシブ対応のロールプレイングゲーム作ってみた – Qiita
//改修
JavaScript:連続クリック対応方法 | 覚え書き.com
jQueryでクリック(click)での、連打を防止して アニメーションが終わるまでクリックボタン無効にする | 9ineBB