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 | |
}); | |
}, | |
hit : function() { | |
this.flag = 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.hit(100); | |
for (var i=0; i<30; ++i) { | |
Effects.add(new DisappearEffect({ | |
x : this.x, | |
y : this.y, | |
vx : 25 * (0.5 - Math.random()), | |
vy : 25 * (0.5 - Math.random()), | |
key : 'effect.hit', | |
color : (Math.random()*6)|0, | |
delCnt : 10 | |
})); | |
} | |
} | |
}); | |
/* ------------------------------------------------------------------------- */ | |
// 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; | |
if (this.hp < 0) { | |
this.flag = false; | |
} | |
for (var i=0; i<10; ++i) { | |
Effects.add(new DisappearEffect({ | |
x : this.x, | |
y : this.y, | |
vx : 5 * (0.5 - Math.random()), | |
vy : 5 * (0.5 - Math.random()), | |
key : 'effect.hit', | |
delCnt : 10 | |
})); | |
} | |
} | |
}); | |
/* ------------------------------------------------------------------------- */ | |
// 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() {} | |
}; | |
/* ------------------------------------------------------------------------- */ | |
// Effect | |
/* ------------------------------------------------------------------------- */ | |
var Effect = function(effect) { | |
Mover.call(this, effect); | |
}; | |
Effect.prototype = $.extend({}, Mover.prototype); | |
var DisappearEffect = function(effect) { | |
Effect.call(this, effect); | |
this.delCnt = ('delCnt' in effect) ? effect.delCnt : 10000000; | |
}; | |
DisappearEffect.prototype = $.extend({}, Effect.prototype, { | |
move : function() { | |
Effect.prototype.move.apply(this); | |
if (this.cnt >= this.delCnt) { | |
this.flag = false; | |
} | |
} | |
}); | |
/* ------------------------------------------------------------------------- */ | |
// 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(); | |
var Effects = 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 : 'http://jsrun.it/assets/f/N/1/n/fN1n7.png', | |
width : 32, | |
height : 32, | |
cd : 1 | |
}); | |
Materials.add({ | |
key : 'shot.normal', | |
path : 'http://jsrun.it/assets/5/5/K/k/55Kkx.png', | |
width : 13, | |
height : 56, | |
cd : 10 | |
}); | |
Materials.add({ | |
key : 'effect.hit', | |
path : 'http://jsrun.it/assets/c/9/X/7/c9X7X.png', | |
// http://dixq.net/rp/ からお借りしています | |
width : 6, | |
height : 6, | |
cd : 0 | |
}); | |
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, Effects]; | |
Canvas.clear(); | |
for (var i in containers) { | |
containers[i].move(); | |
containers[i].draw(); | |
} | |
Players.collision(Bullets); | |
Players.collision(Enemies); | |
Shots.collision(Enemies); | |
++frame; | |
}, 1000/FPS); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment