Created
May 12, 2012 07:38
-
-
Save hecomi/2665012 to your computer and use it in GitHub Desktop.
だんまくさんぷる7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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%5 === 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(enemy) { | |
this.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; | |
} | |
}); | |
/* ------------------------------------------------------------------------- */ | |
// 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); | |
}; | |
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() {} | |
}); | |
/* ------------------------------------------------------------------------- */ | |
// 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