HTML5のCanvas使って簡単なシューティングゲームを作ろうと思っている。JavaScript初心者だがなんとかする。それで現在はプレイヤー機を操作できるところまでいった。まずはHTML、onloadでgameを呼び出し初期化と16msec毎に描画を行うようにしている。keydownとkeyupで移動方向の指定と解除、攻撃の設定と解除を行っている。HTMLのあるフォルダにimageフォルダを作り以下の画像を保存しておく
- 操作方法
- W 上へ移動
- A 後ろへ移動
- S 下へ移動
- D 前へ移動
- Space ショット
となっている
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script type="text/javascript" src="./util/Point.js"></script> <script type="text/javascript" src="./util/Rect.js"></script> <script type="text/javascript" src="./object/Player.js"></script> <script type="text/javascript" src="./object/PlayerBullet1.js"></script> <script type="text/javascript" src="./info/GameInfo.js"></script> <script type="text/javascript" src="./view/GameView.js"></script> <script type="text/javascript"> var IMAGE_NAMES = ["Player", "Enemy"]; var IMAGE_FILES = ["./image/player.png", "./image/enemy1.png"]; var view; function game(){ var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); view = new GameView(context, 600, 400); view.loadImages(IMAGE_NAMES, IMAGE_FILES); setInterval(function(){ view.draw(); }, 16); } function keydown(event){ var code = event.keyCode; switch(code){ //'A' 後ろ case 65: view.onDirection(0x02); break; //'D' 前 case 68: view.onDirection(0x01); break; //'W' 上 case 87: view.onDirection(0x08); break; //'S' 下 case 83: view.onDirection(0x04); break; //'space' 攻撃 case 32: view.fire(true); break; } } function keyup(event){ var code = event.keyCode; switch(code){ //'A' 後ろ case 65: view.offDirection(0x02); break; //'D' 前 case 68: view.offDirection(0x01); break; //'W' 上 case 87: view.offDirection(0x08); break; //'S' 下 case 83: view.offDirection(0x04); break; //'space' 攻撃 case 32: view.fire(false); break; } } </script> </head> <body onload="game()" onkeydown="keydown(event)" onkeyup="keyup(event)"> <canvas id="canvas" width="600" height="400">Canvasをサポートしたブラウザで見てください</canvas> </body> </html>
次にJavaScript。GameView.jsから。メインはdrawメソッド。現在はプレイヤー機とプレイヤー機が放った弾を描画している。
var GameView = function(context, width, height){ var images = new Array(); var isLoadedImage = false; var player; var gameInfo; this.draw = function(){ if(!isLoadedImage){ return; } context.fillStyle = 'rgb(00, 00, 00)'; context.fillRect(0, 0, 600, 400); player.doAction(gameInfo); player.draw(context); for(i = 0; i < gameInfo.bullets.length; i++){ var bullet = gameInfo.bullets[i]; bullet.doAction(gameInfo); bullet.draw(context); } } this.loadImages = function(names, files){ var count = 0; for(i = 0; i < files.length; i++){ var image = new Image(); image.src = files[i]; images[names[i]] = image; image.onload = function(){ count++; if(count == files.length){ init(); } } } } this.onDirection = function(direction){ player.onDirection(direction); } this.offDirection = function(direction){ player.offDirection(direction); } this.fire = function(fire){ player.fire = fire; } function init(){ player = new Player(images["Player"]); gameInfo = new GameInfo(); gameInfo.player = player; gameInfo.width = width; gameInfo.height = height; isLoadedImage = true; } }
Player.js。doActionで移動をしてdrawで描画を行う。ライフや敵と衝突したときに敵に与えるダメージなどが保存される
var Player = function(image){ this.image = image; this.position = new Point(); this.rect = new Rect(); this.life = 300; this.damage = 300; this.score = 10000; this.fire = false; var direction = 0; var fireCount = 0; this.draw = function(context){ context.drawImage(this.image, this.position.x, this.position.y); } this.doAction = function(info){ this.doMove(); if(this.fire && fireCount == 0){ var bullet = new PlayerBullet1(); bullet.move(this.position.x + 60, this.position.y + 22); info.bullets.push(bullet); fireCount = 16; } if(fireCount > 0){ fireCount--; } } this.doMove = function(){ if((direction & 0x01) > 0){ this.dmove(3, 0); } if((direction & 0x02) > 0){ this.dmove(-3, 0); } if((direction & 0x04) > 0){ this.dmove(0, 3); } if((direction & 0x08) > 0){ this.dmove(0, -3); } } this.onDirection = function(input){ direction |= input; } this.offDirection = function(input){ direction &= ~input; } this.getRect = function(){ this.rect.left = this.position.x + 8; this.rect.top = this.position.y + 14; this.rect.right = this.position.x + 68; this.rect.bottom = this.position.y + 30; return this.rect; } this.move = function(x, y){ this.position.move(x, y); } this.dmove = function(dx, dy){ this.position.dmove(dx, dy); } this.applyDamage = function(damage){ this.life -= damage; this.life = this.life < 0 ? 0 : this.life; return this.life > 0; } this.intersect = function(object){ return this.getRect().intersect(object.getRect()); } }
PlayerBullet1.js。プレイヤー機の弾を表している。敵に当たったとき敵に与えるダメージなどがある
var PlayerBullet1 = function(){ this.position = new Point(); this.rect = new Rect(); this.life = 10000; this.damage = 100; this.score = 100000; this.doAction = function(info){ this.position.dmove(8, 0); } this.move = function(x, y){ this.position.move(x, y); } this.draw = function(context){ context.fillStyle = 'rgb(255, 255, 0)'; context.beginPath(); context.arc(this.position.x + 1, this.position.y + 1, 2, 0, 360, true); context.closePath(); context.fill(); } this.getRect = function(){ this.rect.left = this.position.x; this.rect.top = this.position.y; this.rect.right = this.rect.left + 2; this.rect.bottom = this.rect.top + 2; } this.applyDamage = function(damage){ this.life -= damage; this.life = this.life < 0 ? 0 : this.life; return this.life > 0; } this.intersect = function(object){ return this.getRect().intersect(object.getRect()); } }
GameInfo.js。ここに登録されている弾や敵を描画する。また、弾や敵の情報を渡す役目もある
var GameInfo = function(){ this.bullets = new Array(); this.enemies = new Array(); this.enemyBullets = new Array(); this.width = 0; this.height = 0; }
次にPoint.js。座標を格納しているだけ
var Point = function(){ this.x = 0.0; this.y = 0.0; this.move = function(x, y){ this.x = x; this.y = y; } this.dmove = function(dx, dy){ this.x += dx; this.y += dy; } }
Rect.jsは長方形を定義している。座標の他に長方形同士が交差しているかどうかを返すintersectを定義している
var Rect = function(){ this.left = 0; this.top = 0; this.right = 0; this.bottom = 0; this.set = function(left, top, right, bottom){ this.left = left; this.top = top; this.right = right; this.bottom = bottom; } this.intersect = function(rect){ if(this.left <= rect.left && rect.left <= this.right && this.top <= rect.top && rect.top <= this.bottom){ return true; } if(this.left <= rect.right && rect.right <= this.right && this.top <= rect.top && rect.top <= this.bottom){ return true; } if(this.left <= rect.left && rect.left <= this.right && this.top <= rect.bottom && rect.bottom <= this.bottom){ return true; } if(this.left <= rect.right && rect.right <= this.right && this.top <= rect.bottom && rect.bottom <= this.bottom){ return true; } return false; } }