HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
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.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
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.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
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.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<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>
h2 {
color: #036;
font-size: 30px;
}
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;
}
}
Also see: Tab Triggers