CanJS - Model Queue

canjs

Model Queue:

<strong>Move around with the arrow keys, and click replay after you're done.</strong>
<div class="rpg"></div>

<script type="text/mustache" id="avatar">
  <div class="map">
      <div class="character {{#isMoving}}moving{{/isMoving}} {{ player.position.direction }}" 
    style="left: {{ player.position.left }}px; top: {{ player.position.top}}px"></div>
    <div class="fire-pit"></div> 
  </div>
  <button class="replay" {{#player.hasQueuedRequests}}disabled="disabled"{{/player.hasQueuedRequests}}>Replay!</button>
  <span>{{#player.hasQueuedRequests}}Saving!{{/player.hasQueuedRequests}}</span>
</script>

// JavaScript:
$(document).ready(function(){

/* SERVER EMULATION */

    var getRandomInt = function(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    var positions = [];

    can.fixture('POST /players', function(req){
        var attrs = req.data || {};
        positions.push(attrs.position); // Save current position
        attrs.id  = 1;
        return attrs;
    })

    can.fixture('PUT /players/{id}', function(req, respondWith){
        var attrs    = req.data || {},
                position = attrs.position;

        if(position.top > 80 && position.top < 100 
            && position.left > 60 
            && position.left < 100) { // you stepped on the fire, you die
            respondWith(406);
        } else {
                positions.push(attrs.position);  // save current position
                setTimeout(function(){
                    respondWith(attrs);
                }, getRandomInt(10, 50)) // change delay to simulate slow and spotty connection
        }
    })

    can.fixture('GET /game', function(req){
        return positions;
    })

    var directions = {
        37 : 'LEFT',
        38 : 'UP',
        39 : 'RIGHT',
        40 : 'DOWN'
    },
    max = function(val, max){
        return val > max ? max : val;
    },
    min = function(val, min){
        return val < min ? min : val;
    };

    var Player = can.Model({
        create : "POST /players",
        update : "PUT /players/{id}"
    }, {});

    var Replay = can.Model({
        findAll : "GET /game"
    }, {})

    var RPG = can.Control({
        init : function(){
            this.player = new Player({
                position: {
                    top  : 0,
                    left : 0,
                    direction: "down"
                }
            });
            this.isMoving = can.compute(false); 
            this.element.html(can.view('avatar', {
                    player : this.player,
                    isMoving : this.isMoving
            }));

            // save starting position
            this.savePosition();
        },
        move : function(direction){
            var position, direction;
            if(direction){
                this.isMoving(true);
                this.player.attr('position.direction', direction.toLowerCase());
                // move the avatar in the right direction
                if(direction === 'UP'){
                    this.player.attr('position.top', min(this.player.attr('position.top') - 5, 0));
                } else if(direction === 'DOWN'){
                    this.player.attr('position.top', max(this.player.attr('position.top') + 5, 300 - 32));
                } else if(direction === 'RIGHT'){
                    this.player.attr('position.left', max(this.player.attr('position.left') + 5, 300 - 24));
                } else if(direction === 'LEFT'){
                    this.player.attr('position.left', min(this.player.attr('position.left') - 5, 0));
                }
                // after we move the avatar save the position again
                this.savePosition();
            }
        },
        ".replay click" : function(){
            Replay.findAll({}, $.proxy(this.replay, this));
        },
        replay : function(positions){
            var currentPosition = positions.shift(),
                self            = this;
            if(currentPosition){
                this.isMoving(true);
                this.player.attr('position').attr(currentPosition.attr());
                setTimeout(function(){
                    self.replay(positions);
                }, 50)
            } else {
                this.isMoving(false);
            }
        },
        // On each keydown event move the avatar
        "{document} keydown" : function(el, ev){
            this.move(directions[ev.which]);
            ev.preventDefault();
        },
        // When user stops pressing arrow keys remove moving class
        "{document} keyup" : function(el, ev){
            this.isMoving(false);
        },
        savePosition : function(){
            // save position to the server
            // we don't need a success callback since live binding takes care of it
            this.player.save(undefined, $.proxy(this.loadBackup, this));
        },
        loadBackup : function(){
            alert('You walked in to the fire. Resurrecting you to the last good position')
            this.player.restore(true);
            this.isMoving(false);
        }
    })
    new RPG('.rpg');
})
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License