はてなハイク STAR FIGHTERS
by
lieutar
2010-12-30 [2010/12/30 15:12:55]
はてなハイクで実行すると、星を打ちあう簡単な対戦型シューティングが初まる。カーソルキーで移動、Zで星発射。ESCで終了
@@ -8,6 +8,16 @@
(function(){
+ var STARS = [
+ 'http://s.hatena.ne.jp/images/star.gif',
+ 'http://s.hatena.ne.jp/images/star-green.gif',
+ 'http://s.hatena.ne.jp/images/star-red.gif',
+ 'http://s.hatena.ne.jp/images/star-blue.gif',
+ 'http://s.hatena.ne.jp/images/star-purple.gif'
+ ];
+
+ ////////////////////////////////////////////////////////////
+
if(! 'forEach' in Array.prototype){
Array.prototype.forEach = function(cb){
for(var i=0,l=this.length;i<l;i++){
@@ -329,7 +339,6 @@
if(l < 1) continue;
var chslot = (checked[f] || (checked[f] = {}));
for(i=0,l=tclasses.length;i<l;i++){
-//debugger;
var edslot = elemDic[tclasses[i]];
for(ff in edslot){
if(chslot[ff]) continue;
@@ -364,7 +373,6 @@
var genImage = function(url , container){
var img = document.createElement('img');
- (container || document.body).appendChild(img);
img.src = url;
return img;
};
@@ -410,12 +418,29 @@
this._speed = s;
};
+ this.setPosition = function(x,y){
+ this._x = x;
+ this._y = y;
+ };
+
this.getPosition = function(){
return {
x: this._x ,
y: this._y
};
};
+
+ this.getSize = function(){
+ var elem = this._elem;
+ return {
+ width: elem.clientWidth,
+ height: elem.clientHeight
+ };
+ };
+
+ this.getHitAreaSize = function(){
+ return this.getSize();
+ };
this.getSpeed = function(){
return this._speed;
@@ -439,7 +464,6 @@
return { x:this._pdx, y:this._pdy };
};
- // ステップごとの自己状態の変更
this.step = function(){
this._pre_x = this._x;
this._pre_y = this._y;
@@ -465,15 +489,15 @@
// フレームごとの計算結果を元に
this.redraw = function(){
- var img = this._elem;
if(this._dispose){
this.dispose();
return;
}
var sx = this._x;
var sy = this._y;
- img.style.top = (sy - img.clientHeight / 2) + 'px';
- img.style.left = (sx - img.clientWidth / 2) + 'px';
+ var elem = this._elem;
+ elem.style.top = (sy - elem.clientHeight / 2) + 'px';
+ elem.style.left = (sx - elem.clientWidth / 2) + 'px';
};
// 当たり判定の対象となるクラス群
@@ -481,17 +505,11 @@
return [];
};
- // 自身のフレームごとの軌跡
- this.getTrack = function(){
- var R = 0;
- return R;
- };
- // 当たり判定
this.getHitRectangle = function(){
- var img = this._elem;
- var w = img.clientWidth;
- var h = img.clientHeight;
+ var size = this.getHitAreaSize();
+ var w = size.width;
+ var h = size.height;
var sx = this._x;
var sy = this._y;
var x0 = sx - w / 2;
@@ -547,6 +565,11 @@
}
};
+ this.pacmanWarp = function(){
+ var sx = this._x;
+ var sy = this._y;
+ };
+
}
);
@@ -567,14 +590,15 @@
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
- var img = genImage('http://s.hatena.ne.jp/images/star-red.gif', div);
- img.style.position = 'absolute';
- var imgs = [ img ];
- this.stars = imgs;
- for(var i =0; i < 15; i++){
- var clone = img.cloneNode(true);
- imgs.push( clone );
- div.appendChild( clone );
+ var stars = [];
+ this.stars = stars;
+ for(var i =0; i < 16; i++){
+ var img = genImage(STARS[i % STARS.length]);
+ img.style.position = 'absolute';
+ img.width = 24;
+ img.height = 24;
+ stars.push(img);
+ div.appendChild( img );
}
return div;
};
@@ -671,10 +695,28 @@
this.makeElem = function(){
var name = this.name;
- return genImage(
+ var div = document.createElement('div');
+ var img = genImage(
'http://www.st-hatena.com/users/' + name.substring(0,2) +
'/' + name + '/profile.gif'
);
+ div.appendChild(img);
+ var label = document.createElement('div');
+ div.appendChild(label);
+ label.innerHTML = 'id:' + name;
+ label.style.backgroundColor = '#EEE';
+ label.style.color = '#339';
+ label.style.fontSize = '12px';
+ label.style.MozBorderRadius = '5px';
+ return div;
+ };
+
+ this.getHitAreaSize = function(){
+ var size = this.getSize();
+ return {
+ width: Math.floor(size.width / 3),
+ height: Math.floor(size.height / 3)
+ };
};
this.explode = function(){
@@ -816,50 +858,76 @@
this._changeDir();
};
+ this.getPlayersDirection = function(){
+ var elem = this.elem;
+ var player = (Game.getElementsByClass(Player) || [])[0] || null;
+ if(!player) return this.getRandomDirection();
+ var dx = player._x - elem._x;
+ var dy = player._y - elem._y;
+ var ddx, ddy;
+ if(Math.abs(dx) > Math.abs(dy)){
+ ddx = dx < 0 ? -1 : 1;
+ if(dy == 0){
+ ddy = 0;
+ } else {
+ ddy = dy / Math.abs(dx);
+ }
+ }else{
+ ddy = dy < 0 ? -1 : 1;
+ if(dx == 0){
+ ddx = 0;
+ } else{
+ ddx = dx / Math.abs(dy);
+ }
+ }
+ return {x:ddx, y:ddy};
+ };
+
+ this.getRandomDirection = function(){
+ return { x: Math.random() * 2 - 1,
+ y: Math.random() * 2 - 1 };
+ };
+
this._changeDir = function(){
this._turn_at = 50;
var elem = this.elem;
- var player = null;
- if(this._iter++ > 3 &&
- Math.random() * 3 < 1){
- player = (Game.getElementsByClass(Player) || [])[0] || null;
- }
- this._iter++;
- if(player){
- var dx = player._x - elem._x;
- var dy = player._y - elem._y;
- var ddx, ddy;
- if(Math.abs(dx) > Math.abs(dy)){
- ddx = dx < 0 ? -1 : 1;
- if(dy == 0){
- ddy = 0;
- } else {
- ddy = dy / Math.abs(dx);
- }
- }else{
- ddy = dy < 0 ? -1 : 1;
- if(dx == 0){
- ddx = 0;
- } else{
- ddx = dx / Math.abs(dy);
- }
- }
- elem.setDirection(ddx, ddy);
- } else {
- elem.setDirection(Math.random() * 2 - 1,
- Math.random() * 2 - 1);
- }
+ var dir = ((this._iter++ > 3 &&
+ Math.random() * 3 < 1)
+ ? this.getPlayersDirection()
+ : this.getRandomDirection());
+ elem.setDirection(dir.x, dir.y);
elem.setSpeed(Math.random() * 10);
};
this.step = function(){
- switch(this._turn_at){
+ if(this._iter > 10){
+ switch(this._turn_at){
+ case 40:
+ this.shot(this.getPlayersDirection(), 10);
+ break;
+ case 30:
+ this.shot(this.getRandomDirection(), 10);
+ break;
+ case 20:
+ this.shot(this.getPlayersDirection(), 10);
+ break;
+ case 10:
+ this.shot(this.getRandomDirection(), 10);
+ break;
+ case 0:
+ this.shot(this.elem.getDirection(), this.elem.getSpeed() + 10);
+ break;
+ }
+ } else {
+ switch(this._turn_at){
case 40:
case 30:
case 20:
case 10:
case 0:
- this.shot();
+ this.shot(this.elem.getDirection(), this.elem.getSpeed() + 10);
+ break;
+ }
}
if(this._turn_at-- < 0){
this._changeDir();
@@ -867,12 +935,11 @@
};
- this.shot = function(){
+ this.shot = function(dir, speed){
var pos = this.elem.getPosition();
var bullet = new EBullet(pos.x, pos.y);
- var dir = this.elem.getDirection();
bullet.setDirection(dir.x, dir.y);
- bullet.setSpeed(this.elem.getSpeed() + 5);
+ bullet.setSpeed(speed);
};
}
/*
* @title haiku-shoot
* @description はてなハイクで星を撃つ
* @include http://h.hatena.ne.jp/*
* @license MIT License
* @require
*/
(function(){
var STARS = [
'http://s.hatena.ne.jp/images/star.gif',
'http://s.hatena.ne.jp/images/star-green.gif',
'http://s.hatena.ne.jp/images/star-red.gif',
'http://s.hatena.ne.jp/images/star-blue.gif',
'http://s.hatena.ne.jp/images/star-purple.gif'
];
////////////////////////////////////////////////////////////
if(! 'forEach' in Array.prototype){
Array.prototype.forEach = function(cb){
for(var i=0,l=this.length;i<l;i++){
cb(this[i],i);
}
};
}
if(! 'map' in Array.prototype){
Array.prototype.map = function(cb){
var R = [];
for(var i=0,l=this.length;i<l;i++){
R.push(cb(this[i],i));
}
return R;
};
}
////////////////////////////////////////////////////////////
var defclass = function(spec, initializer){
var base = spec.base;
var klass = function(){};
klass.prototype = base.prototype;
var proto = new klass;
if(!('initialize' in proto)) proto.initialize = function(){};
var R = function(){
this.constructor = arguments.callee;
this.initialize.apply(this,arguments);
};
R.prototype = proto;
R.name = spec.name;
R.base = base;
R.getBaseClasses = function(){
var R = [this];
if('getBaseClasses' in base){
R.push.apply(R, base.getBaseClasses());
} else {
R.push(base);
}
return R;
};
initializer.apply(
proto,
[
base.prototype,
R
]
);
return R;
};
////////////////////////////////////////////////////////////
var AbstractKeyManager = defclass(
{
name: 'AbstractKeyManager',
base: Object
},
function(SUPER, Class){
this.initialize = function(){
this._hooks = [];
this._lastKey = null;
this._lastEvent = null;
};
this.addHook = function(hook){
this._hooks.push(hook);
};
this.deleteHook = function(hook){
var hooks = this._hooks;
var found = null;
for(var i=0,l=hooks.length;i<l;i++){
if(hook === hooks[i]){
found = i;
break;
}
}
if( found !== null ){
hooks.splice( found, 1 );
}
};
this._runHooks = function(){
var self = this;
this._hooks.forEach(
function(hook){
hook.apply(self, []);
}
);
};
this.pushKey = function(k){
this._lastKey = k;
this._lastEvent = 'push';
};
this.releaseKey = function(k){
this._lastKey = k;
this._lastEvent = 'release';
};
}
);
var ShotKeyManager = defclass(
{
name: 'ShotKeyManager',
base: AbstractKeyManager
},
function(SUPER, Class){
this.releaseKey = function(k){
SUPER.releaseKey.apply(this, [k]);
this._runHooks();
};
}
);
var ArrowKeyManager = defclass(
{
name: 'ArrowKeyManager',
base: AbstractKeyManager
},
function(SUPER, Class){
this.initialize = function(){
SUPER.initialize.apply(this,[]);
this.pressed = {n:0,s:0,w:0,e:0};
};
this.pushKey = function(k){
var pressed = this.pressed;
switch(k){
case 'n':
pressed.n = (pressed.s > 0) ? 2 : 1;
break;
case 's':
pressed.s = (pressed.n > 0) ? 2 : 1;
break;
case 'w':
pressed.w = (pressed.e > 0) ? 2 : 1;
break;
case 'e':
pressed.e = (pressed.w > 0) ? 2 : 1;
break;
}
this._runHooks();
};
this.releaseKey = (
function(){
var timer = null;
return function(k){
var pressed = this.pressed;
switch(k){
case 'n':
pressed.n = 0;
break;
case 's':
pressed.s = 0;
break;
case 'w':
pressed.w = 0;
break;
case 'e':
pressed.e = 0;
}
var self = this;
if(timer){
clearTimeout(timer);
timer = null;
}
timer = setTimeout(
function(){
self._runHooks();
timer = null;
},
50
);
};
}
)();
this.getCurrentDirection = function(){
var pressed = this.pressed;
var x = 0;
var y = 0;
if(pressed.s != pressed.n) y = pressed.s > pressed.n ? 1 : -1;
if(pressed.w != pressed.e) x = pressed.e > pressed.w ? 1 : -1;
return {x:x, y:y};
};
}
);
////////////////////////////////////////////////////////////
var Game = new (
defclass(
{
base: Object,
name: 'Game'
},
function(SUPER, Class){
this.initialize = function(){
this.allElems = {};
this.elemDic = {};
var akman = new ArrowKeyManager();
var skman = new ShotKeyManager();
document.addEventListener(
'keypress',
function(e){ e.preventDefault();},
false
);
window.addEventListener(
'keydown', function(e){
e.stopPropagation();
e.preventDefault();
// console.log(e.keyCode);
switch(e.keyCode){
case 37: //LEFT
akman.pushKey('w');
break;
case 38: //UP
akman.pushKey('n');
break;
case 39: //RIGHT
akman.pushKey('e');
break;
case 40: //DOWN
akman.pushKey('s');
break;
case 90:
skman.pushKey(1);
}
}, true
);
window.addEventListener(
'keyup', function(e){
e.stopPropagation();
e.preventDefault();
switch(e.keyCode){
case 37: //LEFT
akman.releaseKey('w');
break;
case 38: //UP
akman.releaseKey('n');
break;
case 39: //RIGHT
akman.releaseKey('e');
break;
case 40: //DOWN
akman.releaseKey('s');
break;
case 90: // Z
skman.releaseKey(1);
}
}, true
);
this.arrowKeyManager = akman;
this.shotKeyManager = skman;
};
this.getElementsByClass = function(cls){
var elemDic = this.elemDic;
var slot = elemDic[cls.name || ''] || {};
var R = [];
for(var f in slot) R.push(slot[f]);
return R;
};
this.registerElement = function(elem){
var self = this;
var elemDic = this.elemDic;
this.allElems[elem.key] = elem;
elem.constructor.getBaseClasses().forEach(
function(cl){
if(!cl.name) return;
(elemDic[cl.name] || (elemDic[cl.name] = {}))[elem.key] = elem;
}
);
};
this.unregisterElement = function(elem){
delete this.allElems[elem.key];
var elemDic = this.elemDic;
elem.constructor.getBaseClasses().forEach(
function(cl){
if(!(cl.name && elemDic[cl.name])) return;
delete elemDic[cl.name][elem.key];
}
);
};
this.iter = function(){
var allElems = this.allElems;
var elemDic = this.elemDic;
var i,l, ff;
var elem;
for(f in allElems){
allElems[f].step();
}
var checked = {};
for(f in allElems){
elem = allElems[f];
var tclasses = elem.getTargetClasses();
l = tclasses.length;
if(l < 1) continue;
var chslot = (checked[f] || (checked[f] = {}));
for(i=0,l=tclasses.length;i<l;i++){
var edslot = elemDic[tclasses[i]];
for(ff in edslot){
if(chslot[ff]) continue;
chslot[ff] = true;
var target = edslot[ff];
if(!elem.checkHit(target)) continue;
(checked[target.key] ||
(checked[target.key] = {}))[f] = true;
elem.onHit(target);
target.onHit(elem);
}
}
}
for(f in allElems){
allElems[f].redraw();
}
};
this.start = function(){
var self = this;
(function(){
self.iter();
setTimeout(arguments.callee, 10);
})();
};
}) // end of defclass
); // end of new
////////////////////////////////////////////////////////////
var genImage = function(url , container){
var img = document.createElement('img');
img.src = url;
return img;
};
var GameElement = defclass(
{
base: Object,
name: 'GameElement'
},
function(SUPER, Class){
var counter = 0;
this.initialize = function(x,y){
this.key = 'elem_'+ counter++;
this._x = x;
this._y = y;
this._pre_x = NaN;
this._pre_y = NaN;
this._speed = 1;
this._dx = 0;
this._dy = 0;
this._pdx = 0;
this._pdy = -1;
this._elem = this.makeElem();
this.initElem(this._elem);
Game.registerElement(this);
this.redraw();
};
this.makeElem = function(){
var div = document.createElement('div');
div.style.border = 'solid black 2px';
return div;
};
this.initElem = function(elem){
document.body.appendChild(elem);
elem.style.zIndex = 65536;
elem.style.position = 'fixed';
};
this.setSpeed = function(s){
this._speed = s;
};
this.setPosition = function(x,y){
this._x = x;
this._y = y;
};
this.getPosition = function(){
return {
x: this._x ,
y: this._y
};
};
this.getSize = function(){
var elem = this._elem;
return {
width: elem.clientWidth,
height: elem.clientHeight
};
};
this.getHitAreaSize = function(){
return this.getSize();
};
this.getSpeed = function(){
return this._speed;
};
this.setDirection = function(x, y){
this._dx = x;
this._dy = y;
};
this.getDirection = function(){
return { x:this._dx, y:this._dy };
};
this.setShotDirection = function(x,y){
this._pdx = x;
this._pdy = y;
};
this.getShotDirection = function(){
return { x:this._pdx, y:this._pdy };
};
this.step = function(){
this._pre_x = this._x;
this._pre_y = this._y;
this._x = this._x + this._dx * this._speed;
this._y = this._y + this._dy * this._speed;
};
//
this.dispose = function(){
this.disposeElements();
Game.unregisterElement(this);
for(var f in this){
if('function' == typeof this[f]){
this[f] = function(){};
}
}
};
this.disposeElements = function(){
var img = this._elem;
if(img.parentNode) img.parentNode.removeChild(img);
};
// フレームごとの計算結果を元に
this.redraw = function(){
if(this._dispose){
this.dispose();
return;
}
var sx = this._x;
var sy = this._y;
var elem = this._elem;
elem.style.top = (sy - elem.clientHeight / 2) + 'px';
elem.style.left = (sx - elem.clientWidth / 2) + 'px';
};
// 当たり判定の対象となるクラス群
this.getTargetClasses = function(){
return [];
};
this.getHitRectangle = function(){
var size = this.getHitAreaSize();
var w = size.width;
var h = size.height;
var sx = this._x;
var sy = this._y;
var x0 = sx - w / 2;
var y0 = sy - h / 2;
return {
x1: x0,
y1: y0,
x2: x0 + w,
y2: y0 + h
};
};
// elem との当り判定を書く
// TODO すりぬけない方法について学習する
this.checkHit = function(elem){
var sr = this.getHitRectangle();
var er = elem.getHitRectangle();
var x0 = sr.x1;
var x1 = sr.x2;
var x2 = er.x1;
var x3 = er.x2;
var y0 = sr.y1;
var y1 = sr.y2;
var y2 = er.y1;
var y3 = er.y2;
return (x0 < x3 && x2 < x1 && y0 < y3 && y2 < y1);
};
// elem 衝突時の振舞い
this.onHit = function(elem){
};
this.onScreen = function(){
var sx = this._x;
var sy = this._y;
return (sx >= 0 && sx < window.innerWidth &&
sy >= 0 && sy < window.innerHeight);
};
this.backToScreen = function(){
var sx = this._x;
var sy = this._y;
if(sx < 0){
this._x = 0;
} else if (sx >= window.innerWidth){
this._x = window.innerWidth - 1;
}
if(sy < 0){
this._y = 0;
} else if (sy >= window.innerHeight){
this.y = window.innerHeight - 1;
}
};
this.pacmanWarp = function(){
var sx = this._x;
var sy = this._y;
};
}
);
var Explode = defclass(
{
base: GameElement,
name: 'Explode'
},
function(SUPER, Class){
this.initialize = function(x, y){
SUPER.initialize.apply(this, [x, y]);
this._frame = 0;
this._stars = null;
};
this.makeElem = function(){
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '100px';
var stars = [];
this.stars = stars;
for(var i =0; i < 16; i++){
var img = genImage(STARS[i % STARS.length]);
img.style.position = 'absolute';
img.width = 24;
img.height = 24;
stars.push(img);
div.appendChild( img );
}
return div;
};
this.step = function(){
this._frame++;
if(this._frame > 40){
this.dispose();
}
};
this.redraw = function(){
SUPER.redraw.apply(this, []);
var imgs = this.stars;
var frame = this._frame;
var sx = this._x;
var sy = this._y;
for(var i = 0;i<16;i++){
var rad = i / 16 * 2 * Math.PI;
var x = (Math.cos(rad)) * frame;
var y = (Math.sin(rad)) * frame;;
imgs[i].style.top = (50 + y) + 'px';
imgs[i].style.left = (50 + x) + 'px';
}
};
}
);
////////////////////////////////////////////////////////////
var Bullet = defclass(
{
base: GameElement,
name: 'Bullet'
},
function(SUPER, Class){
this.initialize = function(x,y){
SUPER.initialize.apply(this,[x, y]);
this.setDirection(0,-1);
this.setSpeed(10);
};
this.step = function(){
SUPER.step.apply(this, []);
if(!this.onScreen()) this._dispose = true;
};
}
);
var EBullet = defclass(
{
base: Bullet,
name: 'EBullet'
},
function(SUPER, Class){
this.makeElem = function(){
return genImage('http://s.hatena.ne.jp/images/star.gif');
};
}
);
var PBullet = defclass(
{
base: Bullet,
name: 'PBullet'
},
function(SUPER, Class){
this.makeElem = function(){
return genImage('http://s.hatena.ne.jp/images/star-green.gif');
};
}
);
////////////////////////////////////////////////////////////
var Motion;
var RandomMotion;
var User = defclass(
{
base: GameElement,
name: 'User'
}, function(SUPER,Class){
this.initialize = function(name){
this.name = name;
SUPER.initialize.apply(this,[0,0]);
this._defaultSpeed = 5;
this.setDirection(0, -1);
this.setSpeed(0);
};
this.makeElem = function(){
var name = this.name;
var div = document.createElement('div');
var img = genImage(
'http://www.st-hatena.com/users/' + name.substring(0,2) +
'/' + name + '/profile.gif'
);
div.appendChild(img);
var label = document.createElement('div');
div.appendChild(label);
label.innerHTML = 'id:' + name;
label.style.backgroundColor = '#EEE';
label.style.color = '#339';
label.style.fontSize = '12px';
label.style.MozBorderRadius = '5px';
return div;
};
this.getHitAreaSize = function(){
var size = this.getSize();
return {
width: Math.floor(size.width / 3),
height: Math.floor(size.height / 3)
};
};
this.explode = function(){
new Explode(this._x, this._y);
this.dispose();
};
}
);
var Enemy = defclass(
{
base: User,
name: 'Enemy'
},
function(SUPER, Class){
this.initialize = function(name){
SUPER.initialize.apply(this,[name]);
var img = this._elem;
this._x = Math.floor((window.innerWidth - img.clientWidth ) / 2
);
this._y = img.clientHeight;
this._motion = new RandomMotion( this );
};
this.setMotion = function(motion){
this._motion = motion;
};
this.step = function(){
this._motion.step();
SUPER.step.apply(this, []);
if(!this.onScreen()){
this.backToScreen();
}
};
this.getTargetClasses = function(){
return ['PBullet'];
};
this.onHit = function(elem){
if(elem instanceof PBullet){
this.explode();
}
};
}
);
var Player = defclass(
{
base: User,
name: 'Player'
}, function(SUPER, Class){
this.initialize = function(name){
SUPER.initialize.apply(this,[name]);
var self = this;
var img = this._elem;
this._arrowHook = function(){
var dir = this.getCurrentDirection();
self.setDirection(dir.x, dir.y);
};
Game.arrowKeyManager.addHook( this._arrowHook );
this._shotHook = function(){ self.shot(); };
Game.shotKeyManager.addHook( this._shotHook );
this._x =
Math.floor((window.innerWidth - img.clientWidth ) / 2
);
this._y =
(window.innerHeight - img.clientHeight - 10);
};
this.dispose = function(){
Game.arrowKeyManager.deleteHook( this._arrowHook );
Game.shotKeyManager.deleteHook( this._shothook );
SUPER.dispose.apply(this, []);
};
this.getTargetClasses = function(){
return ['Enemy', 'EBullet'];
};
this.onHit = function(elem){
if(elem instanceof Enemy){
this.explode();
elem.explode();
}
if(elem instanceof EBullet){
this.explode();
}
};
this.shot = function(){
var pos = this.getPosition();
var bullet = new PBullet(pos.x, pos.y);
var dir = this.getDirection();
bullet.setDirection(dir.x, dir.y);
bullet.setSpeed(this._defaultSpeed + 2);
};
this.setDirection = function(x, y){
if(x == 0 && y == 0){
this.setSpeed(0);
} else {
this.setSpeed(this._defaultSpeed);
SUPER.setDirection.apply(this, [x,y]);
}
};
}
);
////////////////////////////////////////////////////////////
Motion = defclass(
{
base: Object,
name: 'Motion'
},
function(SUPER, Class){
this.initialize = function(elem){
this.elem = elem;
};
this.step = function(){
};
}
);
RandomMotion = defclass(
{
base: Motion,
name: 'RandomMotion'
},
function(SUPER, Class){
this.initialize = function(elem){
SUPER.initialize.apply(this, [elem]);
this._turn_at = null;
this._iter = 0;
this._changeDir();
};
this.getPlayersDirection = function(){
var elem = this.elem;
var player = (Game.getElementsByClass(Player) || [])[0] || null;
if(!player) return this.getRandomDirection();
var dx = player._x - elem._x;
var dy = player._y - elem._y;
var ddx, ddy;
if(Math.abs(dx) > Math.abs(dy)){
ddx = dx < 0 ? -1 : 1;
if(dy == 0){
ddy = 0;
} else {
ddy = dy / Math.abs(dx);
}
}else{
ddy = dy < 0 ? -1 : 1;
if(dx == 0){
ddx = 0;
} else{
ddx = dx / Math.abs(dy);
}
}
return {x:ddx, y:ddy};
};
this.getRandomDirection = function(){
return { x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1 };
};
this._changeDir = function(){
this._turn_at = 50;
var elem = this.elem;
var dir = ((this._iter++ > 3 &&
Math.random() * 3 < 1)
? this.getPlayersDirection()
: this.getRandomDirection());
elem.setDirection(dir.x, dir.y);
elem.setSpeed(Math.random() * 10);
};
this.step = function(){
if(this._iter > 10){
switch(this._turn_at){
case 40:
this.shot(this.getPlayersDirection(), 10);
break;
case 30:
this.shot(this.getRandomDirection(), 10);
break;
case 20:
this.shot(this.getPlayersDirection(), 10);
break;
case 10:
this.shot(this.getRandomDirection(), 10);
break;
case 0:
this.shot(this.elem.getDirection(), this.elem.getSpeed() + 10);
break;
}
} else {
switch(this._turn_at){
case 40:
case 30:
case 20:
case 10:
case 0:
this.shot(this.elem.getDirection(), this.elem.getSpeed() + 10);
break;
}
}
if(this._turn_at-- < 0){
this._changeDir();
}
};
this.shot = function(dir, speed){
var pos = this.elem.getPosition();
var bullet = new EBullet(pos.x, pos.y);
bullet.setDirection(dir.x, dir.y);
bullet.setSpeed(speed);
};
}
);
////////////////////////////////////////////////////////////
var name = document.evaluate(
'.//p[@class="username"]/a/text()',
document.body,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null).snapshotItem(0).data;
var user = new Player(name);
var enemy = new Enemy('default');
Game.start();
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。