Source: Snake.js

/*jslint plusplus: true, white: true, indent: 2, maxlen: 90 */
/*global $wk$, $app$*/
/**
 *  @author    Wolfgang Kowarschick
 *  @copyright 2013, Wolfgang Kowarschick
 *  <br/>
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted under the terms of the 
 *  Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported    
 *  (CC BY-NC-SA 3.0: http://creativecommons.org/licenses/by-nc-sa/3.0/). 
 */

$wk$(
function()
{ "use strict";
////////////////////////////////////////////////////////////////////////////////
// Class "Snake"
////////////////////////////////////////////////////////////////////////////////

//import
var Body = $app$.game.snake.Body,
    Food = $app$.game.snake.Food,
    
    Snake;

/** 
 *  @class
 *  @name $app$.game.snake.Snake
 *  
 *  @param {Object} p_init
 *         Should contain three initialization objects to initialize the snake:
 *         <code>p_init.tail</code>,
 *         <code>p_init.length</code>, and
 *         <code>p_init.direction</code>.
 *  @param {$app$.game.snake.Plane} p_plane 
 *         The plane where the snake is to be placed. 
 */
Snake = $wk$.WKcClass(
{ name: "$app$.game.snake.Snake",
  
  staticMethods:
  { /** @constant {Object} $app$.game.snake.Snake.NORTH */
    NORTH: { name: "north", x:  0, y: -1 },
    
    /** @constant {Object} $app$.game.snake.Snake.EAST  */
    EAST:  { name: "east",  x: +1, y:  0 },
    
    /** @constant {Object} $app$.game.snake.Snake.SOUTH */
    SOUTH: { name: "south", x:  0, y: +1 },
    
    /** @constant {Object} $app$.game.snake.Snake.WEST  */
    WEST:  { name: "west",  x: -1, y:  0 },

    /** @constant {String} $app$.game.snake.Snake.LEFT  */
    LEFT:  "left",
    
    /** @constant {String} $app$.game.snake.Snake.RIGHT */
    RIGHT: "right" ,
    
    init:
    function()
    { this.NORTH.left  = this.WEST;
      this.NORTH.right = this.EAST;
      this.EAST.left   = this.NORTH;
      this.EAST.right  = this.SOUTH;
      this.SOUTH.left  = this.EAST;
      this.SOUTH.right = this.WEST;
      this.WEST.left   = this.SOUTH;
      this.WEST.right  = this.NORTH;

      this.v_direction =  // this == Snake!!
      { north: this.NORTH, east: this.EAST, 
        south: this.SOUTH, west: this.WEST
      }; 
      this.v_ignore = 
      { north: this.SOUTH, east: this.WEST, 
        south: this.NORTH, west: this.EAST
      }; 
    }
  },
  
  methods:
  { init:
    function (p_init, p_plane)
    { this.v_plane                    = p_plane;
      this.v_init_tail                = p_init.tail;
      this.v_init_direction           = Snake.v_direction[p_init.direction];
      this.v_init_length              = p_init.length;
      this.v_ignore_oposite_direction = p_init.ignoreOppositeDirection;
    },

  /** 
   *  The current length of the snake.
   *  @var {int} $app$.game.snake.Snake#length  
   */
    
  /**
   *  Resets the snake. 
   *  
   *  @method
   *  @name $app$.game.snake.Snake#reset
   */
  reset:
    function()
    { var i, n,
          l_tail = this.v_init_tail;

      // Cleanup the plane
      this.v_plane.reset();
 
      // Place the initial snake on the plane.
      this.v_head      = 
      this.v_tail      = new Body(l_tail.x, l_tail.y);
      this.v_direction = this.v_init_direction;
      this.v_plane.addItem(this.v_head);
      for (i = 1, n = this.v_init_length; i < n; i++)
      { this.v_growing = true;
        this.move();
      }
      this.length = n;
    },
    
  /**
   *  Moves the snake one field further. If it hits a food item, it grows.
   *  If it hits a wall or body item, it dies.
   *  
   *  @method
   *  @name $app$.game.snake.Snake#move
   *  
   *  @returns {Boolean} 
   *           <code>true</code>, if and only if the snake is dead.
   */
  move:
    function()
    { var l_plane     = this.v_plane,
          l_head      = this.v_head,
          l_head_new,
          l_tail      = this.v_tail,
          l_direction = this.v_direction,
          l_x         = l_head.x + l_direction.x,
          l_y         = l_head.y + l_direction.y,
          l_item      = l_plane.getItem(l_x, l_y);
    
      if (!l_item || l_item instanceof Food)
      { l_head_new  = new Body(l_x, l_y);
        l_head.pred = l_head_new;
        this.v_head = l_head_new;
        l_plane.addItem(l_head_new);
        // If food has been eaten, the snake is growing.
        if (l_item)
        { this.v_growing = true;
          this.length++;
          l_plane.foodNr--;
        }
      }
      else
      { return true; }
    
      // If the snake is not growing, the current tail is removed.
      if (!this.v_growing)
      { this.v_tail = l_tail.pred;
        l_plane.removeItem(l_tail);
      }
      
      this.v_growing = false;
      
      return false;
    },
     
  /**
   *  Turns the snake 90° to the left or to the right. 
   *  
   *  @method
   *  @name $app$.game.snake.Snake#turnLeft
   *  
   *  @param {String} p_direction
   *                  Either <code>Snake.LEFT</code> or <code>Snake.RIGHT</code>.
   */
  turn:
    function(p_direction) 
    { if (p_direction === Snake.LEFT || p_direction === Snake.RIGHT)
      { this.v_direction = this.v_direction[p_direction]; }
      else
      { if (   !this.v_ignore_oposite_direction
            ||     Snake.v_direction[p_direction] 
               !== Snake.v_ignore[this.v_direction.name]
           )
        { this.v_direction = Snake.v_direction[p_direction]; }
      }
    }
      
  }
});

////////////////////////////////////////////////////////////////////////////////
// End of Class "Snake"
////////////////////////////////////////////////////////////////////////////////
});
W. Kowarschick © 2013 (CC BY-NC-SA 3.0: http://creativecommons.org/licenses/by-nc-sa/3.0/)
Documentation generated by JSDoc 3.3.0-dev on Sun Dec 15 2013 11:46:54 GMT+0100 (MEZ) using the DocStrap template.