<html>
<head>
<style>canvas {border: 1px solid gray;}</style>
</head>
<body>
<canvas id="screen"></canvas>
<p id="info"></p>
</body>
</html>
// - 変数 - //
var Canvas;
var info;
// 第6回で追加した箇所⓪ //
var score = 0;
// 第6回で追加した箇所⓪ //
var ctx;
var Run = true;
var mouse = new Point();
var fire = false;
var Chara_Shot_Count = 10;
var Enemy_Count = 10;
var Enemy_Shot_Count = 100;
var counter = 0;
var position = new Point();
var i;
var j;
// - クラス - //
// Character
function Chara(){
this.position = new Point();
this.size = 0;
}
Chara.prototype = {
init:function(size){
//サイズ設定
this.size = size;
}
}
// Point
function Point(){
this.x = 0;
this.y = 0;
}
Point.prototype.distance = function(p){
var q = new Point();
q.x = p.x - this.x;
q.y = p.y - this.y;
return q;
};
Point.prototype.length = function(){
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Point.prototype.normalize = function(){
var i = this.length();
if(i > 0){
var j = 1 / i;
this.x *= j;
this.y *= j;
}
};
function Chara_Shot(){
this.position = new Point();
this.size = 0;
this.speed = 0;
this.alive = false;
}
Chara_Shot.prototype = {
set:function(position,size,speed){
//座標
this.position.x = position.x
this.position.y = position.y
//サイズ
this.size = size;
//スピード
this.speed = speed;
// 生存フラグを立てる
this.alive = true;
},
move:function(){
// 座標を真上にspeed分だけ移動
this.position.y -= this.speed;
// 一定以上の座標に到達⇒false
if(this.position.y < -this.size){
this.alive = false;
}
}
};
// Enemy
function Enemy(){
this.position = new Point();
this.size = 0;
this.type = 0;
this.param = 0;
this.alive = false;
}
Enemy.prototype = {
//setメソッド
set:function(position,size,type){
// 座標
this.position.x = position.x;
this.position.y = position.y;
// サイズ
this.size = size;
// 生存フラグを立てる
this.alive = true;
// タイプ
this.type = type;
// パラメーター
this.param = 0;
},
//moveメソッド
move:function(){
// パラメータ インクリメント
this.param++;
// タイプに応じて分岐
switch(this.type){
case 0:
// X方向 に進む
this.position.x += 2;
// 画面右端~左端に到達⇒生存フラグを降ろす
if(this.position.x > this.size + Canvas.width){
this.alive = false;
}
break;
case 1:
// マイナスX方向 に進む
this.position.x -= 2;
// 画面左端~右端に到達⇒生存フラグを降ろす
if(this.position.x < -this.size){
this.alive = false;
}
break;
}
}
};
function EnemyShot(){
this.position = new Point();
this.vector = new Point();
this.size = 0;
this.speed = 0;
this.alive = false;
}
EnemyShot.prototype.set = function(p, vector, size, speed){
// 座標
this.position.x = p.x;
this.position.y = p.y;
// ベクトル
this.vector.x = vector.x;
this.vector.y = vector.y;
// サイズ
this.size = size;
//スピード
this.speed = speed;
// 生存フラグを立てる
this.alive = true;
};
EnemyShot.prototype.move = function(){
// 座標をベクトルに応じてspeed分だけ移動させる
this.position.x += this.vector.x * this.speed;
this.position.y += this.vector.y * this.speed;
// 上下左右の端に到達したら生存フラグを降ろす
if(
this.position.x < -this.size ||
this.position.y < -this.size ||
this.position.x > this.size + Canvas.width ||
this.position.y > this.size + Canvas.height
){
this.alive = false;
}
};
// - メイン - //
window.onload = function(){
// スクリーンの初期化
Canvas = document.getElementById('screen');
Canvas.width = 256;
Canvas.height = 256;
// 2dコンテキスト
ctx = Canvas.getContext('2d');
// イベントの登録
Canvas.addEventListener('mousemove', mouseMove);
window.addEventListener('keydown', keyDown);
Canvas.addEventListener('mousedown', mouseDown);
// その他のエレメント関連
info = document.getElementById('info');
// 自機 初期化
var chara = new Chara();
chara.init(10);
//自機ショット 初期化
var charaShot = new Array(Chara_Shot);
for(i = 0; i < Chara_Shot_Count; i++){
charaShot[i] = new Chara_Shot();
}
// 敵機 初期化
var enemy = new Array(Enemy_Count);
for(i = 0; i < Enemy_Count; i++){
enemy[i] = new Enemy();
}
// 敵機ショット 初期化
var enemyShot = new Array(Enemy_Shot_Count);
for(i = 0; i < Enemy_Shot_Count; i++){
enemyShot[i] = new EnemyShot();
}
// 画面を繰り返し呼び出す
(function(){
// カウンタをインクリメント
counter++;
// HTMLを更新
info.innerHTML = mouse.x + ' : ' + mouse.y;
// screenクリア
ctx.clearRect(0, 0, Canvas.width, Canvas.height);
// パスの設定を開始
ctx.beginPath();
// 自機の位置を設定
chara.position.x = mouse.x;
chara.position.y = mouse.y;
// 自機を描くパスを設定
ctx.rect(chara.position.x, chara.position.y,30,30);
// 自機の色を設定する
ctx.fillStyle = "black";
// 自機を描く
ctx.fill();
// fireフラグ trueなら処理が進む
if(fire===true){
// すべての自機ショットを調査する
for(i = 0; i < Chara_Shot_Count; i++){
// 自機ショットが既に発射されているかチェック
if(charaShot[i].alive === false){
// 自機ショットを新しくセット
charaShot[i].set(chara.position, 5, 10);
// ループ抜ける
break;
}
}
// フラグをfalseにする
fire = false;
}
// パスの設定を開始
ctx.beginPath();
// すべての自機ショット(=10)を調べる
for(i = 0; i < Chara_Shot_Count; i++){
// 自機ショットが既に発射されているかチェック
if(charaShot[i].alive===true){
// 自機ショットを動かす
charaShot[i].move();
// 自機ショットを描くパスを設定
ctx.arc(
charaShot[i].position.x,
charaShot[i].position.y,
charaShot[i].size,
0, Math.PI * 2, false
);
// パスをセーブ
ctx.closePath();
}
}
// 自機ショットの色を設定する
ctx.fillStyle = "red";
// 自機ショットを描く
ctx.fill();
// 100フレームに1度敵機を出現
if(counter % 100 === 0){
// すべてのエネミー(=10)を調べる
for(i = 0; i < Enemy_Count; i++){
// エネミーが既に10体出現したかチェック
if(!enemy[i].alive){
// タイプを決定する
j = (counter % 200) / 100;
// タイプから初期位置を決める
var enemySize = 15;
position.x = -enemySize + (Canvas.width + enemySize * 2) * j;
position.y = Canvas.height / 2;
// エネミーを新規作成
enemy[i].set(position, enemySize, j);
// 1体出現したのでループ抜ける
break;
}
}
}
// 第6回で追加した箇所① //
// カウンターの値でシーン分岐
switch(true){
// カウンターが70より小さい
case counter < 70:
message = 'READY...';
break;
// カウンターが100より小さい
case counter < 100:
message = 'GO!!';
break;
// カウンターが100以上
default:
message = '';
// 第6回で追加した箇所① //
// パスの設定を開始
ctx.beginPath();
// すべての敵機(=10)を調べる
for(i = 0; i < Enemy_Count; i++){
// 敵機が既に10機出現したかチェック
if(enemy[i].alive){
// 敵機を移動
enemy[i].move();
// 敵機(=○)を描くパスを設定
ctx.arc(
enemy[i].position.x,
enemy[i].position.y,
enemy[i].size,
0, Math.PI * 2, false
);
// ショットを打つかどうかパラメータの値からチェック
if(enemy[i].param % 30 === 0){
// エネミーショットを調査する
for(j = 0; j < 100; j++){
if(enemyShot[j].alive === false){
// エネミーショットを新規にセットする
position = enemy[i].position.distance(chara.position);
position.normalize();
enemyShot[j].set(enemy[i].position, position, 5, 5);
// 1個出現させたのでループを抜ける
break;
}
}
}
// パスを閉じる
ctx.closePath();
}
}
// 敵機の色を設定する
ctx.fillStyle = "green";
// 敵機を描く
ctx.fill();
// パスの設定を開始
ctx.beginPath();
// すべてのエネミーショットを調査する
for(i = 0; i < Enemy_Shot_Count; i++){
// エネミーショットが既に発射されているかチェック
if(enemyShot[i].alive){
// エネミーショットを動かす
enemyShot[i].move();
// エネミーショットを描くパスを設定
ctx.arc(
enemyShot[i].position.x,
enemyShot[i].position.y,
enemyShot[i].size,
0, Math.PI * 2, false
);
// パスをいったん閉じる
ctx.closePath();
}
}
// エネミーショットの色を設定する
ctx.fillStyle = "red";
// エネミーショットを描く
ctx.fill();
// 衝突判定
// すべての自機ショットを調査する
for(i = 0; i < Chara_Shot_Count; i++){
// 自機ショットの生存フラグをチェック
if(charaShot[i].alive){
// 自機ショットと敵機との衝突判定
for(j = 0; j < Enemy_Count; j++){
// 敵機の生存フラグをチェック
if(enemy[j].alive){
// 敵機と自機ショットとの距離を計算
p = enemy[j].position.distance(charaShot[i].position);
if(p.length() < enemy[j].size){
// 弾がめり込んでいる(距離が敵機サイズより小さい)場合、生存フラグを降ろす
enemy[j].alive = false;
charaShot[i].alive = false;
// 第6回で追加した箇所② //
// スコアを1加算
score++;
// 第6回で追加した箇所② //
// 衝突があったのでループを抜ける
break;
}
}
}
}
}
// 自機と敵機ショットとの衝突判定
for(i = 0; i < Enemy_Shot_Count; i++){
// エネミーショットの生存フラグをチェック
if(enemyShot[i].alive){
// 自機とエネミーショットとの距離を計測
p = chara.position.distance(enemyShot[i].position);
if(p.length() < chara.size){
// 衝突していたら生存フラグを降ろす
chara.alive = false;
// 衝突があったのでパラメータを変更してループを抜ける
Run = false;
// 第6回で追加した箇所③ //
message = 'GAME OVER !!';
// 第6回で追加した箇所③ //
break;
}
}
}
// 第6回で追加した箇所④ //
break;
}
// 第6回で追加した箇所④ //
// 第6回で追加した箇所⑤ //
info.innerHTML = 'SCORE: ' + (score * 100) + ' ' + message;
// 第6回で追加した箇所⑤ //
// フラグにより再帰呼び出し
if(Run){setTimeout(arguments.callee, 1000/30);}
})();
};
// 関数
function mouseMove(event){
// マウスカーソル座標の更新
mouse.x = event.clientX;
mouse.y = event.clientY;
}
function keyDown(event){
// キーコード取得
var ck = event.key;
// spaceKeyで画面が止まる
if(ck === " "){Run = false;}
}
function mouseDown(event){
// フラグを立てる
fire = true;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.