topical media & game development

talk show tell print

mobile-game-present-lib-quintus-touch.js / js



  /*global Quintus:false */
  
  Quintus.Touch = function(Q) {
  
    var hasTouch =  !!('ontouchstart' in window);
  
    var touchStage = [0];
    var touchType = 0;
  
    Q.Evented.extend("TouchSystem",{
  
      init: function() {
        var touchSystem = this;
  
        this.boundTouch = function(e) { touchSystem.touch(e); };
        this.boundDrag = function(e) { touchSystem.drag(e); };
        this.boundEnd = function(e) { touchSystem.touchEnd(e); };
  
        Q.el.addEventListener('touchstart',this.boundTouch);
        Q.el.addEventListener('mousedown',this.boundTouch);
  
        Q.el.addEventListener('touchmove',this.boundDrag);
        Q.el.addEventListener('mousemove',this.boundDrag);
  
        Q.el.addEventListener('touchend',this.boundEnd);
        Q.el.addEventListener('mouseup',this.boundEnd);
        Q.el.addEventListener('touchcancel',this.boundEnd);
  
        this.touchPos = new Q.Evented();
        this.touchPos.grid = {};
        this.touchPos.p = { w:6, h:6, cx: 3, cy: 3 };
        this.activeTouches = {};
        this.touchedObjects = {};
      },
  
      destroy: function() {
        Q.el.removeEventListener('touchstart',this.boundTouch);
        Q.el.removeEventListener('mousedown',this.boundTouch);
  
        Q.el.removeEventListener('touchmove',this.boundDrag);
        Q.el.removeEventListener('mousemove',this.boundDrag);
  
        Q.el.removeEventListener('touchend',this.boundEnd);
        Q.el.removeEventListener('mouseup',this.boundEnd);
        Q.el.removeEventListener('touchcancel',this.boundEnd);
      },
  
      normalizeTouch: function(touch,stage) {
        var canvasPosX = touch.offsetX,
            canvasPosY = touch.offsetY;
           
        if(Q._isUndefined(canvasPosX) || Q._isUndefined(canvasPosY)) {
          canvasPosX = touch.layerX;
          canvasPosY = touch.layerY;
        }
  
        if(Q._isUndefined(canvasPosX) || Q._isUndefined(canvasPosY)) {
          canvasPosX = touch.clientX - Q.el.offsetLeft - Q.wrapper.offsetLeft;
          canvasPosY = touch.clientY - Q.el.offsetTop - Q.wrapper.offsetTop;
        }
  
        this.touchPos.p.ox = this.touchPos.p.px = canvasPosX / Q.cssWidth * Q.width;
        this.touchPos.p.oy = this.touchPos.p.py = canvasPosY / Q.cssHeight * Q.height;
        
        
        if(stage.viewport) {
          this.touchPos.p.px /= stage.viewport.scale;
          this.touchPos.p.py /= stage.viewport.scale;
          this.touchPos.p.px += stage.viewport.x;
          this.touchPos.p.py += stage.viewport.y;
        }
  
        this.touchPos.p.x = this.touchPos.p.px - 3;
        this.touchPos.p.y = this.touchPos.p.py - 3;
        this.touchPos.obj = null;
  
        return this.touchPos;
      },
  
      touch: function(e) {
        var touches = e.changedTouches || [ e ];
  
        for(var i=0;i<touches.length;i++) {
  
          for(var stageIdx=0;stageIdx < touchStage.length;stageIdx++) {
            var touch = touches[i],
                stage = Q.stage(touchStage[stageIdx]);
  
            if(!stage) { continue; }
  
            touch.identifier = touch.identifier || 0;
            var pos = this.normalizeTouch(touch,stage);
  
            stage.regrid(pos,true);
            var col = stage.collide(pos,touchType), obj;
  
            if(col || stageIdx === touchStage.length - 1) {
              obj = col && col.obj;
              pos.obj = obj;
              this.trigger("touch",pos);
            }
  
            if(obj && !this.touchedObjects[obj]) {
              this.activeTouches[touch.identifier] = {
                x: pos.p.px,
                y: pos.p.py,
                origX: obj.p.x,
                origY: obj.p.y,
                sx: pos.p.ox,
                sy: pos.p.oy,
                identifier: touch.identifier,
                obj: obj,
                stage: stage
              };
              this.touchedObjects[obj.p.id] = true;
              obj.trigger('touch', this.activeTouches[touch.identifier]);
              break;
            }
  
          }
  
        }
        //e.preventDefault();
      },
  
      drag: function(e) {
        var touches = e.changedTouches || [ e ];
  
        for(var i=0;i<touches.length;i++) {
          var touch = touches[i];
          touch.identifier = touch.identifier || 0;
  
          var active = this.activeTouches[touch.identifier],
              stage = active && active.stage;
  
          if(active) {
            var pos = this.normalizeTouch(touch,stage);
            active.x = pos.p.px;
            active.y = pos.p.py;
            active.dx = pos.p.ox - active.sx;
            active.dy = pos.p.oy - active.sy;
  
            active.obj.trigger('drag', active);
          }
        }
        e.preventDefault();
      },
  
      touchEnd: function(e) {
        var touches = e.changedTouches || [ e ];
  
        for(var i=0;i<touches.length;i++) {
          var touch = touches[i];
  
          touch.identifier = touch.identifier || 0;
  
          var active = this.activeTouches[touch.identifier];
  
          if(active) {
            active.obj.trigger('touchEnd', active);
            delete this.touchedObjects[active.obj.p.id];
            this.activeTouches[touch.identifier] = null;
          }
        }
        e.preventDefault();
      }
  
    });
  
    Q.touch = function(type,stage) {
      Q.untouch();
      touchType = type || null;
      touchStage = stage || [0];
      if(!Q._isArray(touchStage)) {
        touchStage = [touchStage];
      }
  
      if(!Q._touch) {
        Q.touchInput = new Q.TouchSystem();
      }
      return Q;
    };
  
    Q.untouch = function() {
      if(Q.touchInput) {
        Q.touchInput.destroy();
        delete Q['touchInput'];
      }
      return Q;
    };
  
  };
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.