snake²

by hemingway
as an obsessive fan of tower defense games, I will write my own with inclusions of ideas which I believe is missing from generic tower defense solutions.

aiming for balance, fun-threshold, and addictiveness
♥0 | Line 305 | Modified 2012-12-11 05:16:38 | MIT License
play

ActionScript3 source code

/**
 * Copyright hemingway ( http://wonderfl.net/user/hemingway )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5ExH
 */

package
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*;
    
    [SWF(frameRate = 60, width = 1024, height = 768)]
    public class SnakeSquared extends Sprite
    {
        public const gridHeight :Number = (768 / 16);
        public const gridWidth  :Number = (1024 / 16);   
        
        internal var gridArray  :Array = [];
        internal var frameCount :Number = 0;

        public function SnakeSquared()
        {    
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            if (stage) {_init()}
            else       {stage.addEventListener(Event.ADDED_TO_STAGE, addedToStage)}
        }
        
        public function _init() :void
        {
            for (var $x:Number = 0; $x < gridWidth; $x ++)
            {
                if (gridArray[$x+1] == undefined) gridArray[$x+1] = [];
                
                for (var $y:Number = 0; $y < gridHeight; $y ++)
                {
                    gridArray[$x+1][$y+1] = new GridNode(($x+1), ($y+1));
                    addChild(gridArray[$x+1][$y+1]);
                }
            }
            
            for (var i:Number = 1; i < (48 + 1); i++)
                {gridArray[1][i].color = 0x0000FF
                 gridArray[64][i].color = 0x0000FF}
             
            for (var j:Number = 1; j < (64 + 1); j++)
                {gridArray[j][1].color = 0x0000FF
                 gridArray[j][48].color = 0x0000FF}

            graphics.clear     ();
            graphics.lineStyle (1, 0, 0.25);
            graphics.drawRect  (0, 0, 1024, 768);
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        public function addedToStage($e:Event) :void
        {
            _init();
        }
        
        public function removeAllChildren() :void
        {}
        
        public function onEnterFrame($e:Event) :void
        {
           ++frameCount;
           
           if (frameCount == 30)
           {
               frameCount = 0;
               snake(new Point(20, 20), new Point(29, 46), 5);
           }
        }
        
        internal var count :Number;
        internal var _strt :Point = new Point();
        internal var _temp :Point = new Point();
        
        public function snake($start:Point, $end:Point, $offset:Number) :void
        {
            /*
             *  Works better than last block of code,
             *  using color tests to determine if corners and start grid have been written to before moving onto next axis
             */

             if (_temp.x == 0) { _temp.x = _strt.x = $start.x }
             if (_temp.y == 0) { _temp.y = _strt.y = $start.y }
            
             if (gridArray[_temp.x][_temp.y].color == 0xFF0000)
                {_temp.x -= sign(_temp.x - $end.x);
                if (gridArray[$end.x][_temp.y].color == 0xFF0000)
                   {_temp.y -= sign(_temp.y - $end.y);}}

             gridArray[_temp.x][_temp.y].color = 0xFF0000;
             
             count++;
             
             if (count > 5) {gridArray[_strt.x][_strt.y].color = 0x000000}
             
        }
        
        public function sign($value:Number) :Number
        {return ($value > 0) ? 1 : (($value < 0) ? -1 : 0)}
    }
}

import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;

class GridNode extends Sprite
{
    internal var towerMenu :TowerMenu = new TowerMenu(400, 300);
    
    private var T_EMPTY :Number = 0x000000;
    private var T_SNAKE :Number = 0xFF0000;
    private var T_DART  :Number = 0x00FF00;
    private var T_ICE   :Number = 0x0000FF;
    
    protected var _x :Number;
    protected var _y :Number;
    protected var _a :Number;
    protected var _c :Number;
    protected var _t :Number;
    
    internal var mouseObj :Object;
    
    public function GridNode($x:Number = 0, $y:Number = 0, $a:Number = 0.25, $c:Number = 0)
    {
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);

        addChild(towerMenu);
        
        _x = $x-1;
        _y = $y-1;
        _a = $a;
        _c = _t = $c;
    }
    
    public function _init() :void
    {
        graphics.clear     ();
        graphics.beginFill (_c, _a);
        graphics.drawRect  (1 + (_x * 16), 1 + (_y * 16), 15, 15);
        graphics.endFill   (); 
        
        switch (type)
        {
            case (0x000000): //empty
            break;
            
            case (0xFF0000): //snake
            break;
            
            case (0x00FF00): //dart
            break;
            
            case (0x0000FF): //ice
            break;
        }
    }
    
    public function addedToStage($e:Event) :void
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
        addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
        addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        
        _init();
    }
    
    public function onMouseOver($e:MouseEvent) :void
    {
        addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
        
        alpha = 0.15625;
    }
    
    public function onMouseOut($e:MouseEvent) :void
    {
        removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
        
        alpha = 0.25;
    }
    
    public function onMouseDown($e:MouseEvent) :void
    {     
        mouseObj = ($e.target == this.getChildAt(0)) ? this : this;
        mouseObj.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    }
    
    public function onMouseUp($e:MouseEvent) :void
    {    
        mouseObj.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        
        if (!Resource.menuState) {if (type != T_SNAKE) {towerMenu.menuBehavior(Number(!towerMenu.state), mouseObj)}}
    }
    
    public function get type() :Number
    { return _t }
    public function get color() :Number
    { return _c }
    public override function get alpha() :Number
    { return _a }
    public override function get x() :Number
    { return (_x * 16) }
    public override function get y() :Number
    { return (_y * 16) }
    public function set type($value:Number) :void
    { _t = $value; _init(); }
    public function set color($value:Number) :void
    { _c = type = $value; _init(); }
    public override function set alpha($value:Number) :void
    { _a = $value; _init(); }
}

class TowerMenu extends Sprite
{
    protected var _x:Number;
    protected var _y:Number;
    protected var _w:Number;
    protected var _h:Number;
    protected var _a:Number;
    protected var _c:Number;  
      
    protected var _state :Boolean = false;

    internal var expansionValue :Point = new Point;
    
    internal var mouseObj :Object;
    
    public function TowerMenu($x:Number, $y:Number, $w:Number = 0, $h:Number = 0, $a:Number = 0.5, $c:Number = 0)
    {
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
        
        _x = $x;
        _y = $y;
        _w = $w;
        _h = $h;
        _a = $a;
        _c = $c;
    }

    public function _init() :void
    {
        graphics.clear         ();
        graphics.lineStyle     (2, _c, _a + 0.125);
        graphics.beginFill     (_c, _a);
        graphics.drawRoundRect (_x, _y, _w, _h, 6, 6);
        graphics.endFill       ();
    }
    
    public function addedToStage($e:Event) :void
    {
        removeEventListener(Event.ADDED_TO_STAGE, addedToStage);

        _init();
        
        stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
    }
    
    public function onMouseDown($e:MouseEvent) :void
    {
        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        
        if (state) {if (!(($e.stageX > x) && ($e.stageY > y) && ($e.stageX < (x + width)) && ($e.stageY < (y + height)))) 
        { addEventListener(Event.ENTER_FRAME, contract); }}
    }
    
    public function onMouseUp($e:MouseEvent) :void
    {
        stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    }
    
    public function menuBehavior($anim:Number, $target:Object) :void
    {
        mouseObj = $target;     
        
        switch ($anim)
        {
            case 0: //false
                addEventListener(Event.ENTER_FRAME, contract);
            break;
            
            case 1: //true
                
                if (!Resource.menuState)
                {
                    x = (mouseObj.x + 8);
                    y = (mouseObj.y - 17);
            
                    addEventListener(Event.ENTER_FRAME, expand);
                }

            break;
        }
    }
    
    public function expand($e:Event) :void
    {
        mouseObj.color = 0x0000FF; 
        
        expansionValue.x += 1.50;
        expansionValue.y += 1.20;
        
        if ((width < 120) && (height < 90))
        {
            x      -= expansionValue.x / 2;
            width  += expansionValue.x;
            
            if ((y - height) < -64)
            {
                y      += expansionValue.y / 2;
                height += expansionValue.y;
            }else{    
                y      -= expansionValue.y;
                height += expansionValue.y;
            }
        }else{
            expansionValue.x = 0;
            expansionValue.y = 0;
                         
            Resource.menuState = _state = true;

            removeEventListener(Event.ENTER_FRAME, expand);
        }
    }
    
    public function contract($e:Event) :void
    {
        expansionValue.x += 1.50;
        expansionValue.y += 1.20;
        
        if ((width > 4) && (height > 4))
        {
            x      += expansionValue.x / 2;
            width  -= expansionValue.x;
            y      += expansionValue.y;
            height -= expansionValue.y;
        }else{
            width     = 0;
            height    = 0;
            
            expansionValue.x = 0;
            expansionValue.y = 0;
            
            mouseObj.color = mouseObj.type;
            Resource.menuState = _state = false;
            
            removeEventListener(Event.ENTER_FRAME, contract);
        }
    }
    
    public override function get x() :Number
    { return _x }
    public override function get y() :Number
    { return _y } 
    public override function get width() :Number
    { return _w } 
    public override function get height() :Number
    { return _h }
    public override function get alpha() :Number
    { return _a }
    public function get color() :Number
    { return _c }
    public function get state() :Boolean
    { return _state }
    public override function set x($value:Number) :void
    { _x = $value; _init(); }
    public override function set y($value:Number) :void
    { _y = $value; _init(); }
    public override function set width($value:Number) :void
    { _w = $value; _init(); }
    public override function set height($value:Number) :void
    { _h = $value; _init(); }
    public override function set alpha($value:Number) :void
    { _a = $value; _init(); }
    public function set color($value:Number) :void
    { _c = $value; _init(); }
}

class Resource
{
    public static var _menuState :Boolean = false;
    
    public static function get menuState() :Boolean
    { return _menuState }
    
    public static function set menuState($value:Boolean) :void
    { _menuState = $value }
}