JavaScriptでゲーム作成 - その1
仕事でちらっとJavaScriptを使ったので、興味がわいて来て現在勉強中です。
JavaScriptはプロトタイプベースのオブジェクト指向言語ということで、Javaなどの普通のオブジェクト指向言語とは毛色の違うものです。
また、手続き型言語と同じような書き方の関数でありながら、実はオブジェクトっていうような、今まで使ってきた言語と違う仕様に、苦戦しつつも、なんとか理解出来てきたように思います。
どれだけ理解出来たかを試すなら、実際にコーディングしてみるしかない→ゲームを作ろう!ということで、簡単なゲームを作ってみました。
作ったのは一番簡単なシューティングゲームであるインベーダーです。
[実行]ボタンを押すとスタートします。
カーソルキーで移動、Zキーでショットです。
(動かない場合は画面を一回クリックしてください。)
にとよんさんのところの記事を読んでいたので、はてなダイアリー上でJavaScriptを動かせるってことは知っていたのですが、今回作ったゲームみたいなのをどうやって動かせばいいのかわからず、色々試したんですけど結局、動かなくて、
もうダメ元で
document.write('<body bgcolor="#000000" text="#ffffff" onKeyDown="input(event)">'); document.write('<script type="text/javascript"src="invader.js"></script>');
というように外部ファイル読み込みタグとBodyタグをdocument.writeで出力してみたら、無事に動きました。ちゃんとキー入力も受け付けてくれています。
この方法を使えば、ブラウザ上で手軽に遊んでもらえるゲームを作ることが出来ますねー。今度はもっと本格的なゲームを…って、これ普通にFlashで出来ちゃうことですよね……。
JavaScriptはゲームを作りづらいですし、今時Flashが動作しないブラウザなんてものもないですから、JavaScriptで作られたゲーム、というのは需要がなさそうです。
何か残念だなぁ。
大した処理は行っていませんが、ソースコードの全文を以下に載せておきます。
(何かおかしな書き方などしてあったらツッコミをお願いします!)
長めなので、続きを読む記法を使ってみます↓
var SC_WIDTH = 400; var SC_HEIGHT = 400; var PATH = "images/"; function Base(){} Base.prototype = { isHit : function(obj) { if((this.x < obj.x + obj.width) && (this.x + this.width > obj.x) && (this.y < obj.y + obj.height) && (this.y + this.height > obj.y)) return true; return false; }, update: function() { document.getElementById(this.id).style.left = this.x; document.getElementById(this.id).style.top = this.y; document.getElementById(this.id).style.visibility = (this.visible ? 'visible':'hidden'); }, setPos: function(x,y) { this.x = x; this.y = y; }, out: function() { this.visible = false; document.getElementById(this.id).style.visibility = 'hidden'; }, draw : function() { document.write( '<img src="'+this.path+'" ID="'+this.id+'" STYLE="position:absolute;top:'+this.y+';left:'+this.x+';visibility:'+(this.visible?'visible':'hidden')+'">' ); } } var Player = function() { this.id = "player"; this.path = PATH+"plane.gif"; this.width = 25; this.height = 18; this.x = SC_WIDTH / 2 - this.width / 2; this.y = 300; this.speed = 8; this.visible = true; } Player.prototype = new Base(); Player.prototype.move = function(event) { switch(event.keyCode) { case 37:this.x += -this.speed; break; case 38:this.y += -this.speed; break; case 39:this.x += this.speed; break; case 40:this.y += this.speed; break; case 90:return true; } this.update(); return false; } var Bullet = function(id) { this.x = 0; this.y = 0; this.id = "bullet"+id; this.path = PATH+"stary.gif"; this.width = 8; this.height = 8; this.visible = false; this.shotRad = 0; this.speed = 5; } Bullet.prototype = new Base(); Bullet.prototype.shot = function(x,y,rad) { if( this.visible ) return false; this.x = x; this.y = y; this.shotRad = rad; this.visible = true; return true; } Bullet.prototype.move = function(){ if( !this.visible ) return; this.x += Math.cos(this.shotRad) * this.speed; this.y += Math.sin(this.shotRad) * this.speed; if( this.y < -20 ){ this.visible = false; } this.update(); } var Enemy = function(id,i) { this.id = "enemy"+id; this.path = PATH+"inve"+i+".gif"; this.width = 24; this.height = 17 this.x = SC_WIDTH / 2 - this.width / 2; this.y = 300; this.speed = 0.5; this.score = i*10; this.visible = true; } Enemy.prototype = new Base(); Enemy.prototype.move = function() { if( !this.visible ) return 3 this.x += this.speed; if(this.x < 0){ this.x = 0; return 1; } if(this.x+this.width > SC_WIDTH){ this.x = SC_WIDTH - this.width; return 2; } this.update(); return 0; } Enemy.prototype.turn = function() { this.speed = -this.speed; } Enemy.prototype.forward = function() { this.y += this.height/2; } var Score = function() { this.score = 0; this.add = function(num){ this.score += num; document.getElementById("score").innerHTML = "SCORE:"+this.score; } this.draw = function() { document.write( '<div id="score">SCORE:'+this.score+'</div>' ); } } var player = new Player(); var bullets = new Array(3*4); for (var i = 0; i < bullets.length; ++i){ bullets[i] = new Bullet(i); } var ENEMYS_X = 12; var ENEMYS_Y = 4; var enemys = new Array(ENEMYS_X*ENEMYS_Y); var kind = new Array(3,3,2,1); for(var i = 0; i < ENEMYS_Y; ++i){ for(var j = 0; j < ENEMYS_X; ++j){ var k = i*ENEMYS_X+j; enemys[k] = new Enemy(k,kind[i]); enemys[k].setPos(20+j*30,50+i*20); } } var score = new Score(); function input(event){ if( player.move(event) ){ for (var i in bullets){ var center = player.x + player.width / 2 - bullets[i].width / 2; if( bullets[i].shot(center, player.y,-Math.PI/2) ) break; } } } var timerID = setInterval(update,16*3); function update() { for (var i in bullets){ bullets[i].move(); } for (var i in enemys){ switch( enemys[i].move() ){ case 2: for (var j in enemys){ enemys[j].forward(); } case 1: for (var j in enemys){ enemys[j].turn(); } break; case 0: for (var j in bullets){ if( !bullets[j].visible ) continue; if( bullets[j].isHit(enemys[i]) ){ enemys[i].out(); bullets[j].out(); score.add(enemys[i].score); } } break; } } } for (var i in bullets){ bullets[i].draw(); } for (var i in enemys){ enemys[i].draw(); } player.draw(); score.draw();