Skip to content

Instantly share code, notes, and snippets.

@hecomi

hecomi/shooting.js

Created May 12, 2012
Embed
What would you like to do?
だんまくさんぷる7
/* Shooting Sample
* created by @hecomi
* web: http://d.hatena.ne.jp/hecomi/
*/
$(function(){
/* ------------------------------------------------------------------------- */
// Global Parameters
/* ------------------------------------------------------------------------- */
const FPS = 30;
const MARGIN = 50;
const WIDTH = 640;
const HEIGHT = 480;
// color
const COLOR = {
RED : 0,
GREEN : 1,
BLUE : 2,
YELLOW : 3,
PURPLE : 4,
PINK : 5,
ORANGE : 6,
SKYBLUE : 7,
BLACK : 8,
WHITE : 9
};
// direction
const DIRECTION = {
LEFT : 0,
LEFT_FRONT : 1,
FRONT : 2,
RIGHT_FRONT : 3,
RIGHT : 4
};
/* ------------------------------------------------------------------------- */
// Image Loader
/* ------------------------------------------------------------------------- */
var ImageLoader = function(imgPath) {
this.loaded = false;
this.img = new Image();
this.path = imgPath + "?" + new Date().getTime();
};
ImageLoader.prototype = {
load : function() {
this.img.onload = function(_this) {
return function() {
_this.loaded = true;
};
}(this);
this.img.src = this.path;
}
};
/* ------------------------------------------------------------------------- */
// Materials Container
/* ------------------------------------------------------------------------- */
var Materials = {
map : {},
add : function(material) {
var key = material.key;
this.map[key] = {
instance : new ImageLoader(material.path),
path : material.path,
width : material.width,
height : material.height,
cd : material.cd
};
this.map[key].instance.load();
},
loaded : function() {
for (var key in this.map) {
if (!this.map[key].instance.loaded) return false;
}
return true;
},
img : function(key) {
return this.map[key].instance.img;
},
path : function(key) {
return this.map[key].path;
},
width : function(key) {
return this.map[key].width;
},
height : function(key) {
return this.map[key].height;
},
cd : function(key) {
return this.map[key].cd;
}
};
/* ------------------------------------------------------------------------- */
// Container
/* ------------------------------------------------------------------------- */
var Container = function() {
this.array = [];
};
Container.prototype = {
add : function(instance) {
this.array.push(instance);
},
move : function() {
var n = 0;
for (var i in this.array) {
this.array[i].move();
if (!this.array[i].flag) {
this.array.splice(n, 1);
}
++n;
}
},
draw : function() {
for (var i in this.array) {
this.array[i].draw();
}
},
collision : function(container) {
for (var i in this.array) {
for (var j in container.array) {
if (this.array[i].collision(container.array[j])) {
this.array[i].hit(container.array[j]);
}
}
}
}
};
/* ------------------------------------------------------------------------- */
// Mover
/* ------------------------------------------------------------------------- */
var Mover = function(mover) {
this.x = ('x' in mover) ? mover.x : 0;
this.y = ('y' in mover) ? mover.y : 0;
this.vx = ('vx' in mover) ? mover.vx : 0;
this.vy = ('vy' in mover) ? mover.vy : 0;
this.color = ('color' in mover) ? mover.color : 0;
this.key = ('key' in mover) ? mover.key : null;
this.w = ('key' in mover) ? Materials.width(mover.key) : 0;
this.h = ('key' in mover) ? Materials.height(mover.key) : 0;
this.cd = ('key' in mover) ? Materials.cd(mover.key) : 0;
this.sx = this.w * this.color;
this.sy = 0;
this.cnt = 0;
this.flag = true;
};
Mover.prototype = {
move : function() {
this.x += this.vx;
this.y += this.vy;
this.chkBoundary();
++this.cnt;
},
draw : function() {
$('#canvas').drawImage({
source : Materials.path(this.key),
x : this.x,
y : this.y,
width : this.w,
height : this.h,
sWidth : this.w,
sHeight : this.h,
sx : this.sx,
sy : this.sy,
cropFromCenter: false
});
},
collision : function(mover) {
var dx = mover.x - this.x;
var dy = mover.y - this.y;
var dr = this.cd + mover.cd;
return (dx*dx + dy*dy < dr*dr);
},
chkBoundary : function() {
if (this.x < -this.w - MARGIN || this.x > WIDTH + this.w + MARGIN ||
this.y < -this.h - MARGIN || this.y > HEIGHT + this.h + MARGIN) {
this.flag = false;
}
}
};
/* ------------------------------------------------------------------------- */
// Player
/* ------------------------------------------------------------------------- */
var Player = function(player) {
Mover.call(this, {
x : ('x' in player) ? player.x : WIDTH/2,
y : ('y' in player) ? player.y : HEIGHT - 60,
key : ('key' in player) ? player.key : 'player.reimu'
});
};
Player.prototype = $.extend({}, Mover.prototype, {
move: function() {
Mover.prototype.move.apply(this);
this.shot();
},
draw: function() {
this.sx = this.w * (((this.cnt/5)|0) % 3);
Mover.prototype.draw.call(this);
},
shot: function() {
if (this.cnt%3 === 0) {
for (var i=-1; i<=1; ++i) {
Shots.add(new Shot({
x : this.x,
y : this.y,
vx : 5*i,
vy : -30,
key : 'shot.normal',
atk : 10,
}));
}
}
},
hit : function(mover) {
this.flag = false;
mover.flag = false;
}
});
/* ------------------------------------------------------------------------- */
// Shot
/* ------------------------------------------------------------------------- */
var Shot = function(shot) {
Mover.call(this, shot);
this.atk = ('atk' in shot) ? shot.atk : 10;
}
Shot.prototype = $.extend({}, Mover.prototype, {
hit : function(enemy) {
this.flag = false;
enemy.hit(this.atk);
}
});
/* ------------------------------------------------------------------------- */
// Bullet
/* ------------------------------------------------------------------------- */
var Bullet = function(bullet) {
Mover.call(this, bullet);
};
Bullet.prototype = $.extend({}, Mover.prototype);
/* ------------------------------------------------------------------------- */
// Bullet Variations
/* ------------------------------------------------------------------------- */
// Radian based Bullet
var RadianBullet = function(bullet) {
this.v = ('v' in bullet) ? bullet.v : 0;
this.ang = ('ang' in bullet) ? bullet.ang : 0;
Mover.call(this, bullet);
};
RadianBullet.prototype = $.extend({}, Bullet.prototype, {
move : function() {
this.x += this.v * Math.cos(this.ang);
this.y += this.v * Math.sin(this.ang);
this.chkBoundary();
++this.cnt;
}
});
/* ------------------------------------------------------------------------- */
// Enemy
/* ------------------------------------------------------------------------- */
var Enemy = function(enemy) {
Mover.call(this, enemy);
this.hp = ('hp' in enemy) ? enemy.hp : 100;
};
Enemy.prototype = $.extend({}, Mover.prototype, {
move : function() {
Mover.prototype.move.apply(this);
this.shot();
},
draw : function() {
// direction
var vx = this.vx, vy = Math.abs(this.vy);
if ( vx/vy < -2 ) this.sy = this.h * DIRECTION.LEFT;
else if ( vx/vy < -0.5 ) this.sy = this.h * DIRECTION.LEFT_FRONT;
else if ( vx/vy > 2 ) this.sy = this.h * DIRECTION.RIGHT;
else if ( vx/vy > 0.5 ) this.sy = this.h * DIRECTION.RIGHT_FRONT;
else this.sy = this.h * DIRECTION.FRONT;
// animation
this.sx = this.w * (((this.cnt/5)|0) % 3);
Mover.prototype.draw.apply(this);
},
shot : function() {},
hit : function(damage) {
this.hp -= damage;
console.log(this.hp);
if (this.hp < 0) {
this.flag = false;
}
}
});
/* ------------------------------------------------------------------------- */
// Enemy Variations
/* ------------------------------------------------------------------------- */
// shooting 3-way bullets curtain
var Enemy3Way = function(enemy) {
Enemy.call(this, enemy);
};
Enemy3Way.prototype = $.extend({}, Enemy.prototype, {
move : function() {
this.vx = 5*Math.sin(Math.PI/30 * this.cnt);
Enemy.prototype.move.call(this);
},
shot : function() {
var cnt = this.cnt%120;
if (cnt < 60 && cnt%5 === 0) {
BulletCurtains.add(
new BC_NWay({
nway : 3,
x : this.x,
y : this.y,
v : 5,
ang0 : Math.PI/2,
dang : Math.PI/10,
num : 1,
period : 0,
color : COLOR.RED,
key : 'bullet.normal'
})
);
}
}
});
/* ------------------------------------------------------------------------- */
// Bullet Curtain
/* ------------------------------------------------------------------------- */
var BulletCurtain = function() {
this.cnt = 0;
this.flag = true;
};
/* ------------------------------------------------------------------------- */
// Bullet Curtain Variations
/* ------------------------------------------------------------------------- */
// N-Way Pattern
var BC_NWay = function(bc) {
BulletCurtain.call(this);
for (var x in bc) {
this[x] = bc[x];
}
};
BC_NWay.prototype = {
move : function() {
for (var i = 0; i < this.num; ++i) {
if (this.cnt === this.period*i) {
for (var n = 0; n < this.nway; ++n) {
Bullets.add(new RadianBullet({
x : this.x,
y : this.y,
v : this.v,
ang : this.ang0 - this.dang*(this.nway-1)/2 + this.dang*n,
key : this.key,
color : 'color' in this ? this.color : COLOR.RED
}));
}
}
}
++this.cnt;
if (this.cnt > this.period*this.num) {
this.flag = false;
}
},
draw : function() {}
};
/* ------------------------------------------------------------------------- */
// Canvas
/* ------------------------------------------------------------------------- */
var Canvas = {
resize : function() {
var wRate = $(window).width() / WIDTH;
var hRate = $(window).height() / HEIGHT;
var rate = Math.min(wRate, hRate);
$('#canvas').css({
width : WIDTH * rate,
height : HEIGHT * rate
});
},
clear : function() {
$('#canvas').clearCanvas();
},
calcPosFromPageXY : function(x0, y0) {
var x = (x0 - $('#canvas').position().left) * WIDTH / $('#canvas').width();
var y = (y0 - $('#canvas').position().top ) * HEIGHT / $('#canvas').height() - 30;
return {x: x, y: y};
}
};
/* ------------------------------------------------------------------------- */
// OnLoad
/* ------------------------------------------------------------------------- */
$(window).bind({
resize : Canvas.resize
});
Canvas.resize();
/* ------------------------------------------------------------------------- */
// Containers
/* ------------------------------------------------------------------------- */
var Bullets = new Container();
var BulletCurtains = new Container();
var Enemies = new Container();
var Players = new Container();
var Shots = new Container();
/* ------------------------------------------------------------------------- */
// Resource
/* ------------------------------------------------------------------------- */
Materials.add({
key : 'bullet.normal',
path : 'http://jsrun.it/assets/6/7/g/6/67g6E.png',
width : 20,
height : 20,
cd : 5
});
Materials.add({
key : 'enemy.red',
path : 'http://jsrun.it/assets/5/x/q/h/5xqhn.png',
width : 32,
height : 32,
cd : 10
});
Materials.add({
key : 'player.reimu',
path : 'img/char/yukkuri_reimu.png',
width : 32,
height : 32,
cd : 1
});
Materials.add({
key : 'shot.normal',
path : 'img/char/reimu_bullet.png',
width : 13,
height : 56,
cd : 10,
});
var loadTimer = setInterval(function(){
if (Materials.loaded()) {
clearInterval(loadTimer);
main();
}
}, 100);
/* ------------------------------------------------------------------------- */
// Control
/* ------------------------------------------------------------------------- */
var Mouse = {
down : function(e) {
if (Players.array.length === 0) {
var pos = Canvas.calcPosFromPageXY(e.pageX, e.pageY);
Players.add(new Player({x: pos.x, y: pos.y}));
}
},
move : function(e) {
e.preventDefault();
if (Players.array.length === 0) return;
var player = Players.array[0];
var pos = Canvas.calcPosFromPageXY(e.pageX, e.pageY);
player.x = pos.x;
player.y = pos.y;
}
};
$('#canvas').bind({
mousedown : Mouse.down,
mousemove : Mouse.move
});
/* ------------------------------------------------------------------------- */
// Main
/* ------------------------------------------------------------------------- */
function main() {
var frame = 0;
Players.add(new Player({}));
console.log(Players);
setInterval(function(){
if (frame%60 === 0) {
Enemies.add(
new Enemy3Way({
x : (Math.random() + 0.5)*WIDTH/2,
y : -MARGIN,
vx : (Math.random() - 0.5)*5,
vy : 2,
key : 'enemy.red'
})
);
}
var containers = [Players, BulletCurtains, Enemies, Shots, Bullets];
Canvas.clear();
for (var i in containers) {
containers[i].move();
containers[i].draw();
}
Players.collision(Bullets);
Shots.collision(Enemies);
++frame;
}, 1000/FPS);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment