はてなハイク STAR FIGHTERS

    @@ -16,6 +16,30 @@ 'http://s.hatena.ne.jp/images/star-purple.gif' ]; + var CSS_DIALOG = [ + 'z-index: 131072', + 'opacity: 0.9', + 'display: table', + 'padding: 20px',, + 'font-size: 40px', + 'font-weight: 900', + 'background: #C99', + 'color: #FFF', + '-moz-border-radius: 20px', + '-webkit-border-radius: 20px', + 'border-radius: 20px', + 'position: fixed' + ].join(";\n"); + + var CSS_NAMEPLATE= [ + 'background: #EEE', + 'color: #339', + 'font-size: 12px', + '-moz-border-radius: 5px', + '-webkit-border-radius: 5px', + 'border-radius: 5px' + ].join(";\n"); + //////////////////////////////////////////////////////////// if(! 'forEach' in Array.prototype){ @@ -50,8 +74,9 @@ }; R.prototype = proto; - R.name = spec.name; - R.base = base; + R._name = spec.name; + R._base = base; + R.getName = function(){ return this._name; }; R.getBaseClasses = function(){ var R = [this]; @@ -233,6 +258,7 @@ this.elemDic = {}; this.timer = null; this.runnning = false; + this._initializer = null; var akman = new ArrowKeyManager(); var skman = new ShotKeyManager(); @@ -291,6 +317,10 @@ this.initEventListeners(); }; + this.setInitializer = function(cb){ + this._initializer = cb; + }; + this.initEventListeners = function(){ this.listeners.forEach( function(spec){ @@ -309,7 +339,7 @@ this.getElementsByClass = function(cls){ var elemDic = this.elemDic; - var slot = elemDic[cls.name || ''] || {}; + var slot = elemDic[cls._name || ''] || {}; var R = []; for(var f in slot) R.push(slot[f]); return R; @@ -321,8 +351,8 @@ this.allElems[elem.key] = elem; elem.constructor.getBaseClasses().forEach( function(cl){ - if(!cl.name) return; - (elemDic[cl.name] || (elemDic[cl.name] = {}))[elem.key] = elem; + if(!cl._name) return; + (elemDic[cl._name] || (elemDic[cl._name] = {}))[elem.key] = elem; } ); }; @@ -332,8 +362,8 @@ var elemDic = this.elemDic; elem.constructor.getBaseClasses().forEach( function(cl){ - if(!(cl.name && elemDic[cl.name])) return; - delete elemDic[cl.name][elem.key]; + if(!(cl._name && elemDic[cl._name])) return; + delete elemDic[cl._name][elem.key]; } ); }; @@ -383,8 +413,18 @@ } }; + this.reset = function(){ + var allElems = this.allElems; + for(var f in allElems){ + allElems[f].dispose(); + } + if(this.timer) clearTimeout(this.timer); + this.start(); + }; + this.start = function(){ var self = this; + this._initializer(); this.runnning = true; (function(){ if(!self.runnning) return; @@ -395,24 +435,46 @@ }) // end of defclass ); // end of new - var endgame = function(msg){ + var dialog = function(msg){ var div = document.createElement('div'); div.appendChild(document.createTextNode(msg)); - div.style.display = 'table'; - div.style.padding = '20px'; - div.style.fontSize = '40px'; - div.style.fontWeight = '900'; - div.style.background = '#C99'; - div.style.color = '#FFF'; - div.style.MozBorderRadius = '20px'; - div.style.position = 'fixed'; + div.style.cssText = CSS_DIALOG; document.body.appendChild(div); div.style.left = (( window.innerWidth - div.clientWidth ) / 2 )+'px'; div.style.top = (( window.innerHeight - div.clientHeight ) / 2 )+'px'; - setTimeout(function(){ - div.parentNode.removeChild(div); - Game.end(); - }, 3000); + return div; + }; + + + var StateLock = false; + + var endgame = function(msg){ + if(StateLock) return; + StateLock = true; + var div = dialog(msg); + setTimeout( + function(){ + div.parentNode.removeChild(div); + Game.end(); + var gameover = dialog('GAME OVER'); + setTimeout( + function(){ + gameover.parentNode.removeChild(gameover); + }, 3000 + ); + }, 3000); + }; + + var nextgame = function(msg){ + if(StateLock) return; + StateLock = true; + var div = dialog(msg); + setTimeout( + function(){ + div.parentNode.removeChild(div); + StateLock = false; + Game.reset(); + }, 3000); }; @@ -800,10 +862,7 @@ 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'; + label.style.cssText = CSS_NAMEPLATE; return div; }; @@ -861,7 +920,7 @@ this.onHit = function(elem){ if(elem instanceof PBullet){ this.explode(); - endgame('You Win!!'); + nextgame('You Win!!'); } }; } @@ -1049,36 +1108,39 @@ ); //////////////////////////////////////////////////////////// - - var name = document.evaluate( - './/p[@class="username"]/a/text()', - document.body, - null, - XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, - null).snapshotItem(0).data; - - var enemies = document.evaluate( - './/*[@id="leftbar"]//img[@class="profile-image"]/@alt', - document.body, - null, - XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, - null - ); - var enemy_id = enemies.snapshotItem( - Math.floor( - enemies.snapshotLength * Math.random() - ) - ).value; + var newgame = function(){ + var name = document.evaluate( + './/p[@class="username"]/a/text()', + document.body, + null, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null).snapshotItem(0).data; + + var enemies = document.evaluate( + './/*[@id="leftbar"]//img[@class="profile-image"]/@alt', + document.body, + null, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null + ); + var enemy_id = enemies.snapshotItem( + Math.floor( + enemies.snapshotLength * Math.random() + ) + ).value; + + for(var i=0; i < 10; i++){ + var x = 30 + Math.random() * (window.innerWidth - 60); + var y = 30 + Math.random() * (window.innerHeight - 60); + new Rock(x,y); + } - for(var i=0; i < 10; i++){ - var x = 30 + Math.random() * (window.innerWidth - 60); - var y = 30 + Math.random() * (window.innerHeight - 60); - new Rock(x,y); - } + new Player(name); + new Enemy(enemy_id); + }; - var user = new Player(name); - var enemy = new Enemy(enemy_id); + Game.setInitializer(newgame); Game.start(); })();
  • /*
     * @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'
       ];
    
       var CSS_DIALOG = [
         'z-index: 131072',
         'opacity: 0.9',
         'display: table',
         'padding: 20px',,
         'font-size: 40px',
         'font-weight: 900',
         'background: #C99',
         'color: #FFF',
         '-moz-border-radius: 20px',
         '-webkit-border-radius: 20px',
         'border-radius: 20px',
         'position: fixed'
       ].join(";\n");
    
       var CSS_NAMEPLATE= [
         'background: #EEE',
         'color: #339',
         'font-size: 12px',
         '-moz-border-radius: 5px',
         '-webkit-border-radius: 5px',
         'border-radius: 5px'
       ].join(";\n");
    
       ////////////////////////////////////////////////////////////
    
       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.getName    = function(){  return this._name;  };
    
         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   = {};
               this.timer     = null;
               this.runnning  = false;
               this._initializer = null;
    
               var akman = new ArrowKeyManager();
               var skman  = new ShotKeyManager();
    
               this.listeners = [
                 [ document,
                   'keypress',
                   function(e){ e.preventDefault();},
                   false ],
                 [ window,
                   '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,
                   '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.initEventListeners();
             };
    
             this.setInitializer = function(cb){
               this._initializer = cb;
             };
    
             this.initEventListeners = function(){
               this.listeners.forEach(
                 function(spec){
                   spec[0].addEventListener(spec[1],spec[2],spec[3]);
                 }
               );
             };
    
             this.removeEventListeners = function(){
               this.listeners.forEach(
                 function(spec){
                   spec[0].removeEventListener(spec[1],spec[2],spec[3]);
                 }
               );
             };
    
             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.end = function(){
               this.runnnig = false;
               this.removeEventListeners();
               var allElems = this.allElems;
               for(var f in allElems){
                 allElems[f].dispose();
               }
             };
    
             this.reset = function(){
               var allElems = this.allElems;
               for(var f in allElems){
                 allElems[f].dispose();
               }
               if(this.timer) clearTimeout(this.timer);
               this.start();
             };
    
             this.start = function(){
               var self = this;
               this._initializer();
               this.runnning = true;
               (function(){
                  if(!self.runnning) return;
                  self.iter();
                  self.timer = setTimeout(arguments.callee, 10);
                })();
             };
           }) // end of defclass
       ); // end of new
    
       var dialog = function(msg){
         var div = document.createElement('div');
         div.appendChild(document.createTextNode(msg));
         div.style.cssText = CSS_DIALOG;
         document.body.appendChild(div);
         div.style.left = (( window.innerWidth  - div.clientWidth  ) / 2 )+'px';
         div.style.top  = (( window.innerHeight - div.clientHeight ) / 2 )+'px';
         return div;
       };
    
    
       var StateLock = false;
    
       var endgame = function(msg){
         if(StateLock) return;
         StateLock = true;
         var div = dialog(msg);
         setTimeout(
           function(){
             div.parentNode.removeChild(div);
             Game.end();
             var gameover = dialog('GAME OVER');
             setTimeout(
               function(){
                 gameover.parentNode.removeChild(gameover);
               }, 3000
             );
           }, 3000);
       };
    
       var nextgame = function(msg){
         if(StateLock) return;
         StateLock = true;
         var div = dialog(msg);
         setTimeout(
           function(){
             div.parentNode.removeChild(div);
             StateLock = false;
             Game.reset();
           }, 3000);
       };
    
    
       ////////////////////////////////////////////////////////////
    
       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.getPreviousPosition = function(){
             return {
               x: this._pre_x,
               y: this._pre_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 Rock = defclass(
         {
           base: GameElement,
           name: 'Rock'
         },
         function(SUPER, Class){
           this.makeElem = function(){
             var img = genImage('http://h.hatena.ne.jp/favicon.ico');
             img.width = 32;
             img.height = 32;
             return img;
           };
    
           this.getTargetClasses = function(){
             return ['Bullet'];
           };
    
           this.onHit = function(elem){
             if(elem instanceof Bullet){
               var dir = elem.getDirection();
               var dx  = dir.x;
               var dy  = dir.y;
               var pp  = elem.getPreviousPosition();
               var sp  = this.getPosition();
               var w   = sp.x - pp.x;
               var h   = sp.y - pp.y;
               var r   = w == 0 ? (h < 0 ? -Infinity : Infinity) : h / w;
               if      ((w > 0 && r >  1) || (w < 0 && r <  -1)){// from north
                 dy = - dy;
               } else if(w > 0 && r < 1 && r >= -1){             // from west
                 dx = -dx;
               } else if((w > 0 && r < -1) || (w < 0 && r >= 1)){// from sourh
                 dy = -dy;
               } else {                                          // from east
                 dx = -dx;
               }
               elem.setDirection(dx, dy);
             }
           };
         }
       );
       ////////////////////////////////////////////////////////////
       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.cssText = CSS_NAMEPLATE;
             return div;
           };
    
           this.getHitAreaSize = function(){
             var size = this.getSize();
             return {
               width: Math.floor(size.width / 3),
               height: Math.floor(size.height / 3)
             };
           };
    
           this.step = function(){
             SUPER.step.apply(this, []);
             if(!this.onScreen()){
               this.backToScreen();
             }
           };
    
           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, []);
           };
    
           this.getTargetClasses = function(){
             return ['PBullet'];
           };
    
           this.onHit = function(elem){
             if(elem instanceof PBullet){
               this.explode();
               nextgame('You Win!!');
             }
           };
         }
       );
    
       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', 'Rock'];
           };
    
           this.onHit = function(elem){
             if(elem instanceof Enemy){
               this.explode();
               elem.explode();
               endgame('Draw');
             }
             if(elem instanceof EBullet){
               this.explode();
               endgame('You Lose');
             }
           };
    
           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 newgame = function(){   
         var name = document.evaluate(
           './/p[@class="username"]/a/text()',
           document.body,
           null,
           XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
           null).snapshotItem(0).data;
         
         var enemies = document.evaluate(
           './/*[@id="leftbar"]//img[@class="profile-image"]/@alt',
           document.body,
           null,
           XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
           null
         );
         var enemy_id = enemies.snapshotItem(
           Math.floor(
             enemies.snapshotLength * Math.random()
           )
         ).value;
    
         for(var i=0; i < 10; i++){
           var x = 30 + Math.random() * (window.innerWidth - 60);
           var y = 30 + Math.random() * (window.innerHeight - 60);
           new Rock(x,y);
         }
    
         new Player(name);
         new Enemy(enemy_id);
       };
    
       Game.setInitializer(newgame);
       Game.start();
       
     })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2010/12/30 15:12:55 - 2010-12-30
  2. 2010/12/18 15:13:34 - 2010-12-18
  3. 2010/12/18 15:11:50 - 2010-12-18
  4. 2010/12/18 05:40:03 - 2010-12-18
  5. 2010/12/18 03:58:19 - 2010-12-18
  6. 2010/12/18 03:47:07 - 2010-12-18
  7. 2010/12/18 02:09:19 - 2010-12-18
  8. 2010/12/18 00:16:28 - 2010-12-18
  9. 2010/12/16 23:55:19 - 2010-12-16
  10. 2010/12/16 22:56:54 - 2010-12-16
  11. 2010/12/15 21:59:33 - 2010-12-15
  12. 2010/12/15 04:50:59 - 2010-12-15
  13. 2010/12/14 23:45:13 - 2010-12-14
  14. 2010/12/14 23:27:59 - 2010-12-14
  15. 2010/12/14 23:18:54 - 2010-12-14