Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h2>GINTORI GAME</h2>
<canvas id="game2" width="270" height="400"></canvas>
<ul>
  <li>The player (blue ball) moves in the direction of the mouse drag.</li> 
  <li>It is also possible to move with the arrow key on the keyboard.</li>
  <li>If the path in motion is the enemy or yourself, the player dies. </li>
  <li>Once you move the ball and secure the position more than 80% it is stage clear.</li>
  <li>If you lock down the enemy, you can defeat the enemy and get bonus points.</li>
</ul>
              
            
!

CSS

              
                h2 {
  color: #036;
  font-size: 30px;
}
              
            
!

JS

              
                var canvas = document.getElementById("game2");
var ctx = canvas.getContext("2d");

var w,p,f,pa,tm,e,st,t,l,score,game,area_anime,enemy_del_anime;
var c_w = canvas.width;
var c_h = canvas.height;
var e = [];

//Life用の画像
var img_heart = new Image();
img_heart.src = 'http://endoyuta.com/wp-content/uploads/2011/07/heart_48.png';

//初期化メソッド
function init(){
	enemy_del_anime = [];
	area_anime = [];
	game = new Game();
	w = new Waku();
	t = new Timer();
	st = new Stage();
	l = new Life();
	s = new Status();
	s.init();
	p = new Player();
	pa = new Path();
	f = new Fix_path();
	f.init();
	e = new AllEnemy();
	e.init();
	score = new Score();
}

init();

tm = setInterval(main,10);

function main(){
	ctx.clearRect(0,0,c_w,c_h); //画面のクリア
	w.view_waku(); //外枠の表示
	//start画面
	if(game.game_start){
		game.game_start_animation();
		return;
	}
	w.view_waku_fill();
	f.view_paths(); //枠パスの表示
	s.main();
	//ラウンド(ステージ)開始画面
	if(game.round_start && !game.game_over){
		game.round_start_animation();
		return;
	}
	//プレイヤーがしんだとき
	if(game.player_death){
		//敵は動かずに表示だけされる
		e.all_enemys_view();
		//プレイヤーのですあにめ
		p.death_animation();
		if(p.size == 0){
			game.player_death = false;
			//初期化
			st.dead_init();
		}
	}else if(game.game_over){
		//敵は動かずに表示だけされる
		e.all_enemys_view();
		//GameOverあにめ
		if(game.game_over_anim_sec>0){
			game.game_over_animation();
		}else if(game.game_score_sec>0){
			//スコア・ランキングページ
			game.game_score_animation();
		}else{
			//初期化
			init();
		}
	}else if(game.game_clear){
		//Clear!あにめ
		if(game.game_clear_finish_sec>0){
			game.clear_animation();
		}else if(game.game_score_sec>0){
			//スコアページ
			game.game_clear_score_animation();
		}else{
			game.init();
			st.next_stage_init();
		}
		//エリアスコアアニメあれば実施
		for(var i=0;i<area_anime.length;i++){
			area_anime[i].main();
		}
		//敵スコアアニメあれば実施
		for(var i=0;i<enemy_del_anime.length;i++){
			enemy_del_anime[i].main();
		}
	}else{
		p.main();
		e.main_all();
		t.main();
		//エリアスコアアニメあれば実施
		for(var i=0;i<area_anime.length;i++){
			area_anime[i].main();
		}
		//敵スコアアニメあれば実施
		for(var i=0;i<enemy_del_anime.length;i++){
			enemy_del_anime[i].main();
		}
	}
}

//ゲームクラス
function Game(){
	var obj = this;
	obj.font = 'verdana';
	obj.game_start = true;
	obj.round_start =false;
	obj.player_death = false;
	obj.game_over = false;
	obj.game_over_anim_sec = 100;
	obj.game_score_sec = 200;
	obj.game_clear = false;
	obj.game_clear_normal_sec = 100;
	obj.score_stage_bounus = 0;
	obj.game_clear_finish_sec = 150;
	obj.round_sec = 150;
	obj.area_make = false;

	//init
	obj.init = function(){
		obj.player_death = false;
		obj.game_over_anim_sec = 150;
		obj.game_score_sec = 200;
		obj.game_clear = false;
		obj.game_clear_normal_sec = 150;
		obj.score_stage_bounus = 0;
		obj.game_clear_finish_sec = 150;
		obj.round_sec = 150;
	}

	//ラウンドスタート
	obj.round_start_animation = function(){
		if(obj.round_sec>0){
			//背景表示
			ctx.beginPath();
			ctx.fillStyle = "rgba(0,153,204, 0.3)";
			ctx.moveTo(w.z[0][0],w.z[0][1]); //左上
			ctx.lineTo(w.z[1][0],w.z[1][1]); //右上
			ctx.lineTo(w.z[2][0],w.z[2][1]); //右下
			ctx.lineTo(w.z[3][0],w.z[3][1]); //左下
			ctx.closePath();
			ctx.fill();
			//文字表示
			ctx.beginPath();
			ctx.fillStyle = "#000000";
			ctx.font = "30px "+obj.font;
			ctx.fillText('Round '+st.big_num+'-'+st.small_num,60, 200);
			ctx.font = "16px "+obj.font;
			ctx.fillText('Get 80% Area.',60, 250);
			ctx.fill();
			obj.round_sec--;
		}else{
			obj.round_start =false;
		}
	}

	var c_r_a_no = 0;
	var blank_time = 5;
	var vec = 1;
	//スタートあにめ用色あにめ(色返すメソッド)
	obj.color_red_animation = function(){
		var color_arr = ['#ff0000','#ff1111','#ff2222','#ff3333','#ff4444','#ff5555','#ff6666','#ff7777','#ff8888','#ff9999'];
		if(blank_time<0){
			if(vec == 1){
				if(c_r_a_no == color_arr.length-1){
					vec = -1;
					c_r_a_no--;
				}else c_r_a_no++;
			}else{
				if(c_r_a_no == 0){
					vec = 1;
					c_r_a_no++;
				}else c_r_a_no--;
			}
			blank_time=5;
		}
		blank_time--;
		return color_arr[c_r_a_no];
	}

	//スタートあにめ
	obj.game_start_animation = function(){
		//クリックされたらアクション(スタート)
		if(m.d_x>=95&&m.d_x<=160&&m.d_y>=230&&m.d_y<=258){
			obj.game_start = false;
			obj.round_start = true;
			obj.init();
		}
		//クリックされたらアクション(ランク)

		//クリックされたらアクション(ハウツー)

		//マウスがのったら色あにめ
		//$('#hoge').text(m.m[0]+','+m.m[1]);
		if(m.m[0]>=95&&m.m[0]<=160&&m.m[1]>=230&&m.m[1]<=258){
			var color_start = obj.color_red_animation(c_r_a_no);
		}else{
			var color_start = '#ffffff';
		}
		if(m.m[0]>=95&&m.m[0]<=160&&m.m[1]>=270&&m.m[1]<=298){
			var color_rank = obj.color_red_animation(c_r_a_no);
		}else{
			var color_rank = '#ffffff';
		}
		if(m.m[0]>=73&&m.m[0]<=185&&m.m[1]>=310&&m.m[1]<=338){
			var color_how = obj.color_red_animation(c_r_a_no);
		}else{
			var color_how = '#ffffff';
		}
		//背景表示
		ctx.beginPath();
		ctx.fillStyle = "#0099cc";
		ctx.moveTo(w.z[0][0],w.z[0][1]); //左上
		ctx.lineTo(w.z[1][0],w.z[1][1]); //右上
		ctx.lineTo(w.z[2][0],w.z[2][1]); //右下
		ctx.lineTo(w.z[3][0],w.z[3][1]); //左下
		ctx.closePath();
		ctx.fill();
		//文字表示
		ctx.beginPath();
		ctx.fillStyle = "#ffffff";
		ctx.font = "40px "+obj.font;
		ctx.fillText('GinTori',60, 200);
		ctx.font = "20px "+obj.font;
		ctx.fillStyle = color_start;
		ctx.fillText('Start',100, 250);
		ctx.fillStyle = color_rank;
		ctx.fillText('Rank',100, 290);
		ctx.font = "16px "+obj.font;
		ctx.fillStyle = color_how;
		ctx.fillText('How to Play?',75, 330);
		ctx.fill();
	}

	//Game Overあにめ
	obj.game_over_animation = function(){
		ctx.beginPath();
		ctx.fillStyle = "#000000";
		ctx.font = "16px "+obj.font;
		ctx.fillText('Game Over...', 90, 240);
		ctx.fill();
		obj.game_over_anim_sec--;
	}

	//スコアランキングページ(GameOver時用)
	obj.game_score_animation = function(){
		//黒いページ
		obj.black_page_view();
		//スコア表示
		ctx.beginPath();
		ctx.fillStyle = "#ffffff";
		ctx.font = "16px "+obj.font;
		ctx.fillText('Score: '+s.score, 90, 240);
		ctx.fill();
		obj.game_score_sec--;
	}

	//クリア時のアニメーション
	obj.clear_animation = function(){
		ctx.beginPath();
		ctx.fillStyle = "#000000";
		ctx.font = "16px "+obj.font;
		ctx.fillText('Clear!!!', 90, 240);
		ctx.fill();
		obj.game_clear_finish_sec --;
	}

	//スコアページ(クリア時用)
	obj.game_clear_score_animation  =function(){
		//黒いページ表示
		obj.black_page_view();
		if(obj.game_clear_normal_sec>0){
			//ステージボーナス(難しい程稼いだ点に応じてボーナスがもらえる)
			var stage_sc = score.stage_score_bounus();
			obj.clear_base_method(stage_sc);
			obj.game_clear_normal_sec--;
		//タイムボーナスあにめ
		}else if(t.min>0||t.sec>0){
			if(t.sec == 0){
				t.min--;
				t.sec = 59;
			}else{
				t.sec--;
			}
			s.score += 100;
			score.this_stage_score += 100;
			//ステージボーナス(難しい程稼いだ点に応じてボーナスがもらえる)
			var stage_sc = score.stage_score_bounus();
			obj.score_stage_bounus = stage_sc;
			obj.clear_base_method(stage_sc);
		//ステージボーナスあにめ
		}else{
			if(obj.score_stage_bounus>0){
				s.score += 100;
				obj.score_stage_bounus -=100;
			}else{
				obj.game_score_sec --;
			}
			obj.clear_base_method(obj.score_stage_bounus);
		}
	}

	//クリア時スコアページ用の標準動作
	obj.clear_base_method = function(stage_sc){
		//secの表示調整
		var sec_t = s.sec_text();
		//現在のスコア表示
		ctx.beginPath();
		ctx.fillStyle = "#ffffff";
		ctx.font = "16px "+obj.font;
		ctx.fillText('Score: '+s.score, 50, 240);
		ctx.fillText('Time Bounus: '+t.min+':'+sec_t, 50, 270);
		ctx.fillText('Stage Bounus: '+stage_sc, 50, 300);
		ctx.fill();
	}

	//黒いページ表示するメソッド
	obj.black_page_view = function(){
		ctx.beginPath();
		ctx.fillStyle = "black";
		ctx.moveTo(w.z[0][0],w.z[0][1]); //左上
		ctx.lineTo(w.z[1][0],w.z[1][1]); //右上
		ctx.lineTo(w.z[2][0],w.z[2][1]); //右下
		ctx.lineTo(w.z[3][0],w.z[3][1]); //左下
		ctx.closePath();
		ctx.fill();
	}
}


//ステータスクラス
function Status(){
	var obj = this;
	var x = 0;
	var y = 0;
	var h = 40;
	var w = c_w;
	obj.score = 0;
	obj.sum = 0;

	obj.init = function(){

	}

	obj.main = function(){
		obj.waku_view();
		obj.status_view();
		//面積クリアした場合
		if(obj.check_area()){
			st.clear();
		}

	}

	//ステータスバーを表示
	obj.waku_view = function(){
		ctx.beginPath();
		ctx.fillStyle = "#ffffff";
		ctx.moveTo(x,y); //左上
		ctx.lineTo(c_w,y); //右上
		ctx.lineTo(c_w,h); //右下
		ctx.lineTo(x,h); //左下
		ctx.closePath();
		ctx.fill();
	}

	//scoreを10桁のテキストにするメソッド
	obj.score_text = function(){
		var st = '' + obj.score;
		var zero_count = 10-st.length;
		var zero = '';
		for(var i=0;i<zero_count;i++){zero += '0';}
		return zero + st;
	}

	//secを2桁のテキストにするメソッド
	obj.sec_text = function(){
		var sec = ''+t.sec;
		var zero_count = 2 - sec.length;
		var zero = '';
		for(var i=0; i<zero_count;i++){zero += 0;}
		return zero + sec;
	}

	//ステータスの中身表示
	obj.status_view = function(){
		var s = obj.score_text();
		var sec = obj.sec_text();
		ctx.beginPath();
		ctx.fillStyle = "#000000";
		ctx.font = "12px "+game.font;
		ctx.fillText('Score: '+s, 140, 10);
		ctx.fillText('Area: '+obj.sum+'%', 140, 30);
		ctx.fillText(st.big_num+'-'+st.small_num, 10, 10);
		ctx.fillText('Time: '+t.min+':'+sec, 10, 30);
		ctx.drawImage(img_heart,50,-3,16,16);
		ctx.fillText('x '+l.count, 68, 10);
		ctx.fill();
	}

	//取得した面積の割合を出すメソッド
	obj.get_sum = function(){
		obj.sum = Math.floor((f.start_sum-f.now_sum)/f.start_sum*100);
	}

	//Areaチェク
	obj.check_area = function(){
		if(obj.sum >= st.area) return true;
	}
}

//Stageクラス
function Stage(){
	var obj = this;
	obj.big_num =1;
	obj.small_num = 1;
	obj.enemy_cnt = 1;
	obj.enemy_v = 0.5;
	obj.area = 80; //何%でクリアか?

	//clear時に実施するメソッド
	obj.clear = function(){
		game.game_clear = true;
	}

	//next stage用初期化
	obj.next_stage_init = function(){
		obj.small_num ++;
		if(obj.small_num == 6){
			obj.small_num = 1;
			obj.big_num ++;
			obj.enemy_v += 0.1;
		}
		obj.enemy_cnt = obj.small_num;
		e.init(); //敵の初期化
		t.init(); //timerの初期化
		f.init(); //pathの初期化
		s.sum = 0; //エリアの初期化
		p = new Player(); //プレイヤーの初期化
		pa = new Path(); //パスの初期化
		score.this_stage_score = 0; //ステージスコアの初期化
		game.round_start = true;
		game.init();
		area_anime = [];
		enemy_del_anime = [];
	}

	//dead時の実施メソッド
	obj.dead = function(){
		game.player_death = true;
	}

	//dead時の初期化メソッド
	obj.dead_init = function(){
		l.count --;
		if(l.count == -1){
			//Game Over
			game.game_over = true;
			l.count = 0;
		}
		e.init(); //敵の初期化
		t.init(); //timerの初期化
		f.init(); //pathの初期化
		s.sum = 0; //エリアの初期化
		p = new Player(); //プレイヤーの初期化
		pa = new Path(); //パスの初期化
		game.round_start = true;
		game.init();
		area_anime = [];
		enemy_del_anime = [];
	}
}

//Scoreクラス
function Score(){
	var obj = this;
	obj.this_stage_score = 0;

	//path(エリア)作ったときのスコア算出(sumは割合%)
	obj.area_score = function(sum){
		 return sum*100*1.2^(sum/10);
	}

	//timer残数に応じたスコア算出
	obj.timer_score = function(sec){
		return 100*sec;
	}

	//敵をたおしたときのスコア算出
	obj.enemy_score = function(death_enemy_cnt,alive_enemy_cnt){
		var score = 0;
		score += 4000*Math.pow(death_enemy_cnt,2);
		if(alive_enemy_cnt == 0&&death_enemy_cnt>0) score += 20000;
		return score;
	}

	//ステージボーナスの算出
	obj.stage_score_bounus = function(){
		//ステージの算出
		var k = st.big_num + 0.1*st.small_num;
		return 10000*k;
	}

}

//Lifeクラス
function Life(){
	var obj = this;
	obj.count = 3;
}

//Timerクラス
function Timer(){
	var obj = this;
	obj.min = 2;
	obj.sec = 0;
	obj.msec = 0;

	obj.init = function(){
		obj.min = 2;
		obj.sec = 0;
		obj.msec = 0;
	}

	//タイマーのメインメソッド
	obj.main = function(){
		//時間切れの場合
		if(obj.min==0 && obj.sec==0){
			st.dead();
			return;
		}
		obj.msec += 10;
		if(obj.msec==1000){
			obj.msec = 0;
			obj.sec--;
			if(obj.sec==-1){
				obj.min--;
				obj.sec = 59;
			}
		}
	}
}

//外枠クラス
function Waku(){
	var obj = this;
	obj.w = c_w-10; //プレイヤーの大きさにあわせましょう
	obj.h = c_h-50; //-50はステータスの高さ+プレイヤの大きさにあわせましょう
	obj.x = (c_w-obj.w)/2;
	obj.y = (c_h-obj.h)-5; //-5はプレイヤーの大きさ÷2にあわせましょう
	obj.z = [[obj.x,obj.y],[obj.x+obj.w,obj.y],[obj.x+obj.w,obj.y+obj.h],[obj.x,obj.y+obj.h]]; //枠の座標4点の配列

	//Waku表示メソッド(fill)
	obj.view_waku_fill = function(){
		ctx.beginPath();
		ctx.fillStyle = "white";
		ctx.moveTo(obj.z[0][0],obj.z[0][1]); //左上
		ctx.lineTo(obj.z[1][0],obj.z[1][1]); //右上
		ctx.lineTo(obj.z[2][0],obj.z[2][1]); //右下
		ctx.lineTo(obj.z[3][0],obj.z[3][1]); //左下
		ctx.closePath();
		ctx.fill();
	}
	//Waku表示メソッド(storke)
	obj.view_waku = function(){
		ctx.beginPath();
		ctx.strokeStyle = "white";
		ctx.moveTo(obj.z[0][0],obj.z[0][1]); //左上
		ctx.lineTo(obj.z[1][0],obj.z[1][1]); //右上
		ctx.lineTo(obj.z[2][0],obj.z[2][1]); //右下
		ctx.lineTo(obj.z[3][0],obj.z[3][1]); //左下
		ctx.closePath();
		ctx.stroke();
	}
}

//確定パス保存クラス
function Fix_path(){
	var obj = this;
	obj.path_count = 0;
	obj.before_sum = 0;
	obj.now_sum = 0;
	obj.start_sum = 0;
	obj.paths =[];

	//pathsを表示するメソッド
	obj.view_paths = function(){
		ctx.strokeStyle = '#4682B4';
		ctx.beginPath();
		ctx.moveTo(obj.paths[0][0],obj.paths[0][1]);
		for(var i=1; i<obj.paths.length; i++){
			ctx.lineTo(obj.paths[i][0],obj.paths[i][1]);
		}
		ctx.closePath();
		//ctx.fill();
		ctx.stroke();
	}

	//pathを登録するメソッド
	obj.put_path = function(path,sum){
		obj.paths = path;
		obj.path_count ++;
		obj.before_sum = obj.now_sum;
		obj.now_sum = sum;
		s.get_sum();
		//スコア加算(エリア)
		obj.add_score_area();
		//エリア消したときのアニメーション
		area_anime.push(new Area_animation(score.area_score((obj.before_sum -obj.now_sum)/obj.start_sum*100),[p.x,p.y]));
		//敵を倒しているかチェック
		e.check_hit_path_all_enemys();
	}

	/*
	 * 初期化メソッド
	 * 枠をpathsに登録する
	 * 枠の面積をstart_sumに登録する
	 */
	obj.init = function(){
		obj.paths = [w.z[0],w.z[1],w.z[2],w.z[3]];
		obj.start_sum = pa.area(obj.paths);
		obj.now_sum = obj.start_sum;
		obj.before_sum = 0;
		obj.path_count = 0;
	}

	//点と点が作る辺にボールが存在するか否かを返すメソッド(汎用)
	//存在したらtrueを返す
	obj.is_ball_line =function(a,b,ball){
		x1 = a[0];
		y1 = a[1];
		x2 = b[0];
		y2 = b[1];
		if(x1 == x2){
			if(y1<y2){
				if(y1<=ball[1] && y2>=ball[1] && x1 == ball[0]) return true;
			}else{
				if(y1>=ball[1] && y2<=ball[1] && x1 == ball[0]) return true;
			}
		}else if(y1 == y2){
			if(x1<x2){
				if(x1<=ball[0] && x2>=ball[0] && y1 == ball[1]) return true;
			}else{
				if(x1>=ball[0] && x2<=ball[0] && y1 == ball[1]) return true;
			}
		}else{
			alert('ずれてます');
		}
		return false;
	}

	//点が多角形の中に存在するかをチェックするメソッド
	obj.check_in_path = function(dot){
		var k,counter = 0;
		//敵用dotの小数点を切り上げる
		dot[0] = Math.ceil(dot[0]);
		dot[1] = Math.ceil(dot[1]);
		while(dot[1] < w.z[2][1]+1){
			for(var i=0; i<obj.paths.length; i++){
				k = i+1;
				if(i == obj.paths.length-1) k = 0;
				if(obj.is_ball_line(obj.paths[i],obj.paths[k],dot)) counter++;
			}
			dot[1]++;
		}
		//counterが奇数であれば中、counterが偶数あるいは0であれば外
		if(counter % 2 != 0) return true;
		else return false;
	}

	//エリア分のスコア追加
	obj.add_score_area = function(){
		var sc = score.area_score((obj.before_sum -obj.now_sum)/obj.start_sum*100);
		s.score += sc;
		score.this_stage_score += sc;
	}
}

//エリア消したときのアニメーションクラス
function Area_animation(num,xy){
	var obj = this;
	obj.x = xy[0];
	obj.y = xy[1];
	obj.num = num;
	obj.view_sec = 100;

	//場所によって位置調整
	if(obj.x<w.w/2) obj.x += 25;
	if(obj.x>w.w/2) obj.x -= 40;
	if(obj.y<w.h/2) obj.y += 30;
	if(obj.y>w.h/2) obj.y -= 30;

	obj.main = function(){
		if(obj.view_sec>0){
			//文字表示
			ctx.beginPath();
			ctx.fillStyle = "rgba(0,102,190,"+obj.view_sec/100+")";
			ctx.font = "14px "+game.font;
			ctx.fillText(obj.num,obj.x, obj.y);
			ctx.fill();
			obj.view_sec--;
		}
	}

}

//敵を消したときのアニメーションクラス
function Enemy_animation(score,hit_count,xy){
	var obj = this;
	obj.x = xy[0];
	obj.y = xy[1];
	obj.num = score;
	obj.hc = hit_count;
	obj.view_sec = 100;

	//場所によって位置調整
	if(obj.x<w.w/2){obj.x += 10; obj.x2 = obj.x+10;}
	if(obj.x>w.w/2){obj.x -= 10; obj.x2 = obj.x-10;}
	if(obj.y<w.h/2){obj.y += 10; obj.y2 = obj.y+10;}
	if(obj.y>w.h/2){obj.y -= 10; obj.y2 = obj.y-10;}

	obj.main = function(){
		if(obj.view_sec>0){
			//文字表示
			ctx.beginPath();
			ctx.fillStyle = "rgba(255,0,0,"+obj.view_sec/100+")";
			ctx.font = "14px "+game.font;
			ctx.fillText(obj.num,obj.x, obj.y);
			ctx.fillText('x'+obj.hc,obj.x2, obj.y2);
			ctx.fill();
			obj.view_sec--;
		}
	}

}

//敵グループクラス
function AllEnemy(){
	var obj = this;
	obj.v = 0; //enemyの速度
	obj.cnt = 0; // enemyの数
	obj.enemy = [];
	obj.enemy_cnt = 0;
	obj.dead_enemys = [];

	//初期化メソッド
	obj.init = function(){
		obj.v = st.enemy_v;
		obj.cnt = st.enemy_cnt;
		obj.enemy = [];
		obj.make_enemys();
		obj.enemy_cnt = obj.enemy.length;
		obj.dead_enemys = [];
	}

	//敵の配列作成メソッド
	obj.make_enemys = function(){
		for(var i=0;i<obj.cnt;i++){
			obj.enemy[i] = new Enemy();
			obj.enemy[i].init(obj.v);
		}
	}

	//全ての敵のメインメソッド実施
	obj.main_all = function(){
		for(var i=0;i<obj.enemy.length;i++){
			obj.enemy[i].main();
		}
	}

	//全ての敵のcheck_hit_action_pathメソッド実施
	obj.check_hit_action_path = function(){
		for(var i=0;i<obj.enemy.length;i++){
			if(obj.enemy[i].check_hit_action_path()) return true;
		}
	}

	//全ての敵がパス内にいるか調べる。いない場合はですあにめ
	obj.check_hit_path_all_enemys = function(){
		var hit_enemys = [];
		for(i=0;i<obj.enemy.length;i++){
			if(!f.check_in_path([obj.enemy[i].x,obj.enemy[i].y])){
				var flag = false;
				for(var j=0;j<obj.dead_enemys.length;j++){
					if(i==obj.dead_enemys[j]){flag = true;}
				}
				if(!flag){
					hit_enemys.push([i]);
					//ですあにめ
					obj.enemy[i].death_animation();
				}
			}
		}
		obj.enemy_cnt -= hit_enemys.length;
		//スコア加算(敵倒し用)
		var sc = score.enemy_score(hit_enemys.length,obj.enemy_cnt);
		s.score += sc;
		score.this_stage_score += sc; //ステージスコアも加算

		//敵スコアアニメ
		if(hit_enemys.length>0){
			var idx = hit_enemys[0];
			enemy_del_anime.push(new Enemy_animation(sc,hit_enemys.length,[obj.enemy[idx].x,obj.enemy[idx].y]));
		}
		[].push.apply(obj.dead_enemys, hit_enemys);
	}

	//全ての敵を表示するだけのメソッド
	obj.all_enemys_view = function(){
		for(var i=0;i<obj.enemy.length;i++){
			obj.enemy[i].view();
		}
	}
}

//敵単体クラス
function Enemy(){
	var obj = this;
	obj.size = 7;
	obj.x = 0;
	obj.y = 0;
	obj.vec = [];
	obj.death_flag = false;

	//初期化メソッド
	obj.init = function(total_v){
		obj.x = Math.floor(Math.random()*(w.w-obj.size))+w.x;
		obj.y = Math.floor(Math.random()*(w.h-obj.size))+w.y;
		obj.vec = obj.make_vec(total_v);
	}

	//mainメソッド
	obj.main = function(){
		if(obj.death_flag){
			obj.death_animation();
			return;
		}
		obj.view();
		//1進む
		obj.x += obj.vec[0];
		obj.y += obj.vec[1];
		//衝突チェック
		obj.check_hit_path();
	}

	//enemyを表示するメソッド
	obj.view = function(){
		ctx.beginPath();
		ctx.fillStyle = "red";
		ctx.moveTo(obj.x,obj.y); //左上
		ctx.lineTo(obj.x+obj.size,obj.y); //右上
		ctx.lineTo(obj.x+obj.size,obj.y+obj.size); //右下
		ctx.lineTo(obj.x,obj.y+obj.size); //左下
		ctx.closePath();
		ctx.fill();
	}

	//パスとの衝突判定メソッド
	obj.check_hit_path = function(){
		var a1x,a1y,a2x,a2y,j,tmp=0;
		var x = obj.x;
		var y = obj.y;
		var s = obj.size;
		for(var i=0; i<f.paths.length; i++){
			a1x = f.paths[i][0];
			a1y = f.paths[i][1];
			if(i==f.paths.length-1) j=0;
			else j= i+1;
			a2x = f.paths[j][0];
			a2y = f.paths[j][1];
			if(a1x==a2x&&a2y<a1y){tmp=a1y; a1y=a2y; a2y=tmp;}
			if(a1y==a2y&&a2x<a1x){tmp=a1x; a1x=a2x; a2x=tmp;}
			if(x<=a2x && a1x<=x+s && y<=a2y && a1y<=y+s){
				//衝突したのがxに垂直なのか、yに垂直なのか?
				if(a1y==a2y){
					//上からなのか、下からなのか?
					if(obj.vec[1]<0) obj.y = a1y; //位置の調整
					else obj.y = a1y-s; //位置の調整
					obj.vec[1] = -obj.vec[1]; //向きを変える
				}else if(a1x==a2x){
					//右からか、左からか?
					if(obj.vec[0]<0) obj.x = a1x;
					else obj.x = a1x-s;
					obj.vec[0] = -obj.vec[0];
				}
			}
		}
	}

	//向きと速さを決めるメソッド
	obj.make_vec = function(total_v){
		var x = Math.random()*total_v;
		if(Math.random()<0.5) x = -x;
		var y = total_v-x;
		if(Math.random()<0.5) y = -y;
		return [x,y];
	}

	//アクション中のパスとの衝突判定メソッド
	obj.check_hit_action_path = function(){
		var a1x,a1y,a2x,a2y,tmp=0;
		var x = obj.x;
		var y = obj.y;
		var s = obj.size;
		for(var i=0; i<pa.path.length; i++){
			a1x = pa.path[i][0];
			a1y = pa.path[i][1];
			if(i==pa.path.length-1){
				a2x = p.x;
				a2y = p.y;
			}else{
				a2x = pa.path[i+1][0];
				a2y = pa.path[i+1][1];
			}
			if(a1x==a2x&&a2y<a1y){tmp=a1y; a1y=a2y; a2y=tmp;}
			if(a1y==a2y&&a2x<a1x){tmp=a1x; a1x=a2x; a2x=tmp;}
			if(x<=a2x && a1x<=x+s && y<=a2y && a1y<=y+s){
				return true;
			}
		}
		return false;
	}

	//ですあにめ メソッド
	obj.death_animation =function(){
		var color = 'gray';
		if(!obj.death_flag) obj.death_flag = 1;
		if(obj.death_flag < 25)obj.size = obj.size *1.1;
		if(obj.death_flag == 25){
			obj.size = 3;
		}
		ctx.beginPath();
		ctx.fillStyle = color;
		ctx.moveTo(obj.x,obj.y); //左上
		ctx.lineTo(obj.x+obj.size,obj.y); //右上
		ctx.lineTo(obj.x+obj.size,obj.y+obj.size); //右下
		ctx.lineTo(obj.x,obj.y+obj.size); //左下
		ctx.closePath();
		ctx.fill();
		if(obj.death_flag == 25){
			obj.size = 0;
		}
		obj.death_flag ++;
	}
}

function Player(){
	var obj = this;
	obj.size = 10;
	obj.x = w.z[3][0]; //円中心のx座標
	obj.y = w.z[3][1]; //円中心のy座標
	obj.mouseX = false;
	obj.mouseY = false;
	obj.action_mode = false; //action中(クリック座標に向かっている状態)(フラグ)
	var becs = [[0,-1],[1,0],[0,1],[-1,0]] //上右下左
	obj.bec = becs[0];
	obj.key_down = false;

	//main(最初に起動するメソッド)
	obj.main = function(){
		obj.view_ball();

		//actionモード時
		if(obj.action_mode){
			obj.action();
			return;
		}

		//mouseイベント発生時
		if((obj.mouseX && obj.mouseY)|| obj.key_down) {
			if(obj.mouse_bec()){
				pa.path.push([obj.x,obj.y]); //パスの追加
				obj.action_mode = true;
			}
			obj.key_down = false;
			obj.go();
			return;
		}

		//ノーマルアクションを実行
		obj.normal_action();
	}

	//actionモード
	obj.action = function(){
		//パスの軌跡を表示
		obj.view_path_stroke();
		//アクションパスに衝突している場合
		if(obj.check_hit_pass()){
			st.dead();
			return;
		}

		//アクションパスに敵が衝突している場合
		if(e.check_hit_action_path()){
			st.dead();
			return;
		}

		//枠パスに到着した場合
		if(obj.check_on_paths()){
			obj.action_mode = false;
			obj.go();
			pa.path.push([obj.x,obj.y]); //パスの追加
			obj.fix_path();
			pa.path = []; //パスのクリア
			return;
		}
		//マウスイベント時
		if((obj.mouseX && obj.mouseY) || obj.key_down){
			if(obj.mouse_bec()) pa.path.push([obj.x,obj.y]); //パスの追加
			obj.key_down = false;
		}
		obj.go();
	}

	/*
	 * パスのFIX
	 * 登録されたパスから枠パスの頂点を追加することでエリアが完成されるが、
	 * 作成しうるエリアは2通りある。どちらが大きいかを確認し、大きい方の
	 * エリアを作成するパスをFIXとし、枠パスを更新する
	 */
	obj.fix_path = function(){
		var temp_path = [];
		var x = obj.x;
		var y = obj.y;
		var v = obj.bec;
		var counter_temp = 0;
		temp_path = make_area(x,y,v,'r'); //右に進んでエリアをつくる
		pa.sum = pa.area(pa.path.concat(temp_path)); //右に行った場合の面積を求める
		//面積が大きいか確認
		if(pa.sum > f.now_sum/2){
			f.put_path(pa.path.concat(temp_path),pa.sum); //パスをFIX
		}else{
			temp_path = make_area(x,y,v,'l'); //小さい場合は、左に進んでエリアをつくる
			pa.sum = pa.area(pa.path.concat(temp_path)); //左に行った場合の面積を求める
			f.put_path(pa.path.concat(temp_path),pa.sum); //パスをFIX
		}
	}

	//エリアを作成するメソッド(x,y,向き,右か左か)
	//追加パスを返す
	var make_area = function(x,y,v,rl){
		var temp_path = [];
		if(rl == 'r') obj.bec_next_r();
		else obj.bec_next_l();
		while(!array_compare([obj.x,obj.y],pa.path[0])){
			//1進んだ場合枠からはみ出さないか確認
			if(!obj.check_on_paths()){
				temp_path.push([obj.x,obj.y]); //temp_pathに登録
				obj.right_or_left();
			}
			obj.go();
		}
		obj.x = x; obj.y = y; obj.bec = v; //位置・向きを元に戻す
		return temp_path;
	}

	//mouseX,mouseYをbecに変換
	//有効なドラッグであれば向きを変更しtrueを返す。無効ならfalseを返す。
	obj.mouse_bec = function(){
		if(obj.mouseX>0 && obj.bec[0] == 0 && f.check_in_path([obj.x+1,obj.y])){
			obj.bec = [1,0];
		}else if(obj.mouseX<0 && obj.bec[0] == 0 && f.check_in_path([obj.x-1,obj.y])){
			obj.bec = [-1,0];
		}else if(obj.mouseY>0 && obj.bec[1] == 0 && f.check_in_path([obj.x,obj.y+1])){
			obj.bec = [0,1];
		}else if(obj.mouseY<0 && obj.bec[1] == 0 && f.check_in_path([obj.x,obj.y-1])){
			obj.bec = [0,-1];
		}else{
			obj.del_mouse();
			return false;
		}
		obj.del_mouse();
		return true;
	}

	//normal action
	obj.normal_action = function(){
		//1進んだときにパスから出ないか調べる
		if(!obj.check_on_paths()) obj.right_or_left();
		obj.go();
	}

	//1進んだ場合にパスからはみ出さないか調べるメソッド
	//登録されているすべてのパス(f.paths)を調べる
	obj.check_on_paths = function(){
		var x1 = obj.x + obj.bec[0];
		var y1 = obj.y + obj.bec[1];
		var k;
		for(var i=0;i<f.paths.length;i++){
			if(i==f.paths.length-1) k=0;
			else k = i+1;
			if(f.is_ball_line(f.paths[i],f.paths[k],[x1,y1])) return true;
		}
		return false;
	}

	//右に向きを変えてpathがなければ左に向きを変えるメソッド
	obj.right_or_left = function(){
		//右に向きを変える
		obj.bec_next_r();
		//1進んだ場合に衝突中のパスからはみ出すか確認
		if(!obj.check_on_paths()){
			//右ではみ出すなら、左にする
			obj.bec_next_l();
			obj.bec_next_l();
		}
	}
	//mouseX,mouseYの消去メソッド
	obj.del_mouse = function(){
		obj.mouseX = false;
		obj.mouseY = false;
	}

	//ボールを表示するメソッド
	obj.view_ball = function(){
		ctx.beginPath()
		ctx.fillStyle = '#191970';
		ctx.arc(obj.x, obj.y, obj.size/2, 0, 360,false);
		ctx.fill();
	}

	//obj.becの次を決めるメソッド(右回り)
	obj.bec_next_r = function(){
		for(var i=0; i<becs.length; i++){
			if(array_compare(becs[i],obj.bec)){
				if(i==becs.length-1) obj.bec = becs[0];
				else obj.bec = becs[i+1];
				break;
			}
		}
	}

	//obj.becの次を決めるメソッド(左回り)
	obj.bec_next_l = function(){
		for(var i=0; i<becs.length; i++){
			if(array_compare(becs[i],obj.bec)){
				if(i==0) obj.bec = becs[becs.length-1];
				else obj.bec = becs[i-1];
				break;
			}
		}
	}

	//ボールを向きに1進めるメソッド
	obj.go = function(){
		obj.x += obj.bec[0];
		obj.y += obj.bec[1];
	}

	//アクション中にボールがパスの軌跡に衝突していないか確認するメソッド
	obj.check_hit_pass = function(){
		for(var i=0; i<pa.path.length-1; i++){
			if(f.is_ball_line(pa.path[i],pa.path[i+1],[obj.x,obj.y])) return true;
		}
		return false;
	}

	//パスを軌跡を表示するメソッド
	obj.view_path_stroke = function(){
		ctx.beginPath();
		ctx.moveTo(pa.path[0][0],pa.path[0][1]);
		for(var i=0; i < pa.path.length; i++){
			ctx.lineTo(pa.path[i][0],pa.path[i][1]);
		}
		ctx.lineTo(obj.x,obj.y);
		ctx.strokeStyle = 'red';
		ctx.stroke();
	}

	//プレイヤーのですあにめ
	obj.death_animation = function(){
		var color = 'gray';
		if(!obj.death_flag) obj.death_flag = 1;
		if(obj.death_flag < 25)obj.size = obj.size *1.1;
		if(obj.death_flag == 25){
			obj.size = 3;
		}
		ctx.beginPath();
		ctx.fillStyle = color;
		ctx.moveTo(obj.x,obj.y); //左上
		ctx.lineTo(obj.x+obj.size,obj.y); //右上
		ctx.lineTo(obj.x+obj.size,obj.y+obj.size); //右下
		ctx.lineTo(obj.x,obj.y+obj.size); //左下
		ctx.closePath();
		ctx.fill();
		if(obj.death_flag == 25){
			obj.size = 0;
		}
		obj.death_flag ++;
	}
}

/*
アクション中に曲がった点の集まり
1アクションが終了したら完成させる
*/
function Path(){
	var obj = this;
	obj.path = [];
	obj.sum; //パスが作成する図形の面積

	//面積を求めるメソッド
	obj.area = function(paths){
		var num = 0;
		//座標法で求める
		for(var i=0; i < paths.length; i++){
			if(i+1 == paths.length){
				num = num + paths[i][0]*paths[0][1]-paths[0][0]*paths[i][1];
			}else{
				num = num + paths[i][0]*paths[i+1][1]-paths[i+1][0]*paths[i][1];
			}
		}
		return 0.5*Math.abs(num);
	}
}

var m = new Mouse();

//マウスイベント感知関連
function Mouse(){
	var obj = this;
	obj.d_x = false;
	obj.d_y = false;
	obj.u_x = false;
	obj.u_y = false;
	obj.m = [];
	obj.vector = function(){
		//d_x,d_yがfalseじゃないか確認
		if(obj.d_x && obj.d_y){
			p.mouseX = obj.u_x - obj.d_x;
			p.mouseY = obj.u_y - obj.d_y;
		}
	}
	obj.d_init = function(){
		obj.d_x = false;
		obj.d_y = false;
	}
}

//イベントリスナーの登録
canvas.addEventListener("mousedown", mouseDownHandler, false);
canvas.addEventListener("mouseup", mouseUpHandler, false);
canvas.addEventListener("mouseover", mouseOverHandler, false);
canvas.addEventListener("mousemove", mouseMoveHandler, false);

function mouseDownHandler(e) {
	var rect = e.target.getBoundingClientRect();
	m.d_x =  Math.floor(e.clientX - rect.left);
	m.d_y =  Math.floor(e.clientY - rect.top);
}

function mouseUpHandler(e) {
	var rect = e.target.getBoundingClientRect();
	m.u_x =  Math.floor(e.clientX - rect.left);
	m.u_y =  Math.floor(e.clientY - rect.top);
	m.vector();
	m.d_init();
}

function mouseOverHandler(e) {
	var rect = e.target.getBoundingClientRect();
	//m.o[0] =  Math.floor(e.clientX - rect.left);
	//m.o[1] =  Math.floor(e.clientY - rect.top);
	//alert(2343);
}

function mouseMoveHandler(e) {
	var rect = e.target.getBoundingClientRect();
	m.m[0] =  Math.floor(e.clientX - rect.left);
	m.m[1] =  Math.floor(e.clientY - rect.top);
	//alert(2343);
}

//キーコード
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_UP = 38;
var KEY_DOWN = 40;
var KEY_SPACE = 32;
var KEY_ENTER = 13;
var KEY_ESC = 27;
var KEY_A = 65;

//キー入力検出
$(window).keydown(function(e){
	//スペースか上を押したら...
	if(e.keyCode == KEY_UP){
		p.key_down = true;
		p.mouseX = 0;
		p.mouseY = -1;
		m.d_init();
		return false;
	//左を押したら...
	}else if(e.keyCode == KEY_LEFT){
		p.key_down = true;
		p.mouseX = -1;
		p.mouseY = 0;
		m.d_init();
		return false;
	//右を押したら...
	}else if(e.keyCode == KEY_RIGHT){
		p.key_down = true;
		p.mouseX = 1;
		p.mouseY = 0;
		m.d_init();
		return false;
	//下を押したら...
	}else if(e.keyCode == KEY_DOWN){
		p.key_down = true;
		p.mouseX = 0;
		p.mouseY = 1;
		m.d_init();
		return false;
	//Aを押したら...
	}else if(e.keyCode == KEY_A){
		return false;
	}
});

//配列を比較する関数
function array_compare(a1,a2){
	if(a1.length != a2.length) return false;
	else{
		for(var i=0; i<a1.length; i++){
			if(a1[i] != a2[i]) return false;
		}
		return true;
	}
}
              
            
!
999px

Console