topical media & game development

talk show tell print

mobile-game-ch21-pong-public-pong.js / js



  $(function() {
  
    var Q = window.Q = Quintus()
                       .include('Input,Sprites,Scenes')
                       .setup('quintus');
    var socket = io.connect();
  
    Q.input.keyboardControls()
    Q.input.touchControls({ 
              controls:  [ ['left','<' ],[],[],[],['right','>' ]]
            });
  
    var gameType = null, delay = 0;
  
    Q.Paddle = Q.Sprite.extend({
      init: function(props) {
        this._super(_(props).defaults({
          w: 60, h: 20,
          speed: 200,
          direction: null
        }));
      },
  
      step: function(dt) {
        dt += this.p.paddleDelay / 1000;
        this.p.paddleDelay = 0;
  
        if(this.p.direction == 'left') {
          this.p.x -= this.p.speed * dt;
        } else if(this.p.direction == 'right') {
          this.p.x += this.p.speed * dt;
        } 
  
        if(this.p.x < 0) { this.p.x = 0; }
        if(this.p.x > Q.width - this.p.w) { this.p.x = Q.width - this.p.w; }
      },
  
      draw: function(ctx) {
        ctx.fillStyle = "black";
        ctx.fillRect(Math.floor(this.p.x),
                     Math.floor(this.p.y),
                     this.p.w,this.p.h);
  
      }
    });
  
    Q.PlayerPaddle = Q.Paddle.extend({
      step: function(dt) {
        var lastDirection = this.p.direction;
  
        this.p.direction = null;
        if(Q.inputs['left']) {
          this.p.direction = 'left';
        } else if(Q.inputs['right']) {
          this.p.direction = 'right';
        }
  
        this._super(dt);
  
        if(lastDirection != this.p.direction) {
          socket.emit("move",[this.p.direction,this.p.x]);
        }
      }
    });
  
    Q.EnemyPaddle = Q.Paddle.extend({ 
      init: function(props) {
        this._super(props);
  
        var self = this, p = this.p;
        socket.on("move",function(data) {
          p.direction = data[0];
          p.x = data[1];
          self.step(delay/1000);
        });
      }
    });
  
    Q.Ball = Q.Sprite.extend({
      init: function(props) {
        this._super(_(props||{}).defaults({
          x: 200, y: 100,
          w: 10,  h: 10,
          dx: -1, dy: -1,
          speed: 100,
          ballRate: 0.5,
          ballSend: 0.5
        }));
  
        var self = this, p = this.p;
        if(gameType == 'slave') {
          socket.on("ball",function(pos) {
            p.x = pos.x;
            p.y = pos.y;
            p.dx = pos.dx;
            p.dy = pos.dy;
            self.step(delay/1000);
          });
        }
  
      },
  
      step: function(dt) {
        var p = this.p;
  
        var hit = Q.stage().collide(this);
        if(hit) {
          p.dy = hit.p.y < 100 ? 1 : -1;
        }
  
        p.x += p.dx * p.speed * dt;
        p.y += p.dy * p.speed * dt;
  
        var maxX = Q.width - p.w;
  
        if(p.x < 0) { p.x = 0; p.dx = 1; } 
        else if(p.x > maxX) { p.dx = -1; p.x = maxX; }
        
        if(p.y < 0 || p.y > Q.height) { 
          p.x = 200; p.y = 100;
          p.dy *= -1;
        } 
  
        if(gameType == 'master') {
          p.ballSend -= dt;
          if(p.ballSend < 0) {
            socket.emit("ball", { x: p.x, y: p.y, dx: p.dx, dy: p.dy });
            p.ballSend += p.ballRate;
          }
        }
      },
  
      draw: function(ctx) {
        ctx.fillStyle = "black";
        ctx.beginPath();
        ctx.arc(this.p.x + this.p.w/2,
                this.p.y + this.p.h/2,
                this.p.w/2,0,Math.PI*2); 
        ctx.fill();
      }
  
    });
  
    Q.scene('game',new Q.Scene(function(stage) {
  
      if(gameType == 'master') {
        stage.insert(new Q.PlayerPaddle({ x:0, y: 40}));
        stage.insert(new Q.EnemyPaddle({ x:0, y: Q.height - 100}));
      } else if(gameType == 'slave') {
        stage.insert(new Q.EnemyPaddle({ x:0, y: 40}));
        stage.insert(new Q.PlayerPaddle({ x:0, y: Q.height - 100}));
      }
      stage.insert(new Q.Ball());
  
    }));
  
    socket.on("master",function() {
      gameType = 'master';
      Q.stageScene("game");
    });
  
    socket.on("slave",function() {
      gameType = 'slave';
      Q.stageScene("game");
    });
  
    socket.on("end",function() {
      Q.clearStage(0);
    });
    
    socket.on('delay',function(data) {
      if(data.steps == 3) {
        // delay 1/2 of the round trip time
        delay = (new Date().getTime() - data.timer)/2;
        if(delay > 50) {
          delay = 50;
        }
      } else {
        data.steps += 1;
        socket.emit('delay',data);
      }
    });
  
    setInterval(function() {
      socket.emit('delay',{ steps: 0, timer: new Date().getTime() });
    },2000);
  
  });
  
  


(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.