﻿// Ajax Sprite Toolkit
//      code by Andy Beaulieu
//      http://www.andybeaulieu.com

// portions (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.


Type.registerNamespace('AjaxSprite');

AjaxSprite.SpriteBehavior = function(element) {

    AjaxSprite.SpriteBehavior.initializeBase(this, [element]);

    //=====================
    // Property variables 
    //=====================
    this._GameWindowControlIdValue = null;
    this._ImageUrl = null;
    this._FrameWidth = 0;
    this._FrameHeight = 0;
    this._FrameCount = 1;
    this._FramesPerRow = 1;
    this._FrameSpeed = 1;
    this._FrameSpeedCounter = 0;
    this._CurrentFrame = 0;
    this._IsActive = false;
    this._x = 0;
    this._y = 0;
    this._XSpeed = 0;
    this._YSpeed = 0;
    this._Velocity = 0;
    this._clpLeft = 0;
    this._clpTop = 0;
    this._diminishCollisionRectangle = {left:0, top:0, right:0, bottom:0};
    
    this._firstFrameInRange = 0;
    this._lastFrameInRange = 0;
}

AjaxSprite.SpriteBehavior.prototype = {

    initialize : function() {
        AjaxSprite.SpriteBehavior.callBaseMethod(this, 'initialize');

        //=====================
        // Initialization
        //=====================
        var element = this.get_element();
        if (!element) throw new Error.invalidOperation('AjaxControlToolkit.Animation.AnimationBehavior must have an element');

        // set up the image
        this._element.style.visibility="hidden";
        this._element.src = this._ImageUrl;

        // add the sprite to the GameWindow
        $find(this._GameWindowControlIdValue).addSprite(this._id);
        this._IsActive = true;
        
        this.set_CurrentFrame(0);
        this._lastFrameInRange = this._FrameCount - 1;

        this._element.style.visibility="";
        // we need to clip the source image to the appropriate frame!
        this._element.style.overflow="hidden";
        this._element.style.position="absolute";

    },

    dispose : function() {
        //=====================
        // Cleanup Code
        //=====================
        AjaxSprite.SpriteBehavior.callBaseMethod(this, 'dispose');
    },
    
    // refresh the sprite's current frame and position
    animate : function() {
        
        if (this.get_IsActive() == false) return;

        this._FrameSpeedCounter += 1;
        if (this._FrameSpeedCounter >= this._FrameSpeed)
        {
            this.nextFrame();
            this._FrameSpeedCounter = 0;
        }
        
        // move the sprite
        this.set_x(this._x + this._XSpeed);
        this.set_y(this._y + this._YSpeed);
        
    },
    
    // advance the sprite one frame
    nextFrame : function() {
        var iNewFrame = (this._CurrentFrame + 1);
        if (iNewFrame > this._lastFrameInRange) 
            iNewFrame = this._firstFrameInRange
        
        this.set_CurrentFrame(iNewFrame);
    },

    // back up the current frame
    prevFrame : function() {
        var iNewFrame = (this._CurrentFrame - 1);
        if (iNewFrame < this._firstFrameInRange) 
            iNewFrame = this._lastFrameInRange

        this.set_CurrentFrame(iNewFrame);
    },

    ////////////////////////
    // Property Accessors
    ////////////////////////
    get_GameWindowControlId : function() {
        return this._GameWindowControlIdValue;
    },
    set_GameWindowControlId : function(value) {
        this._GameWindowControlIdValue = value;
    },

    // the sprite's current X position
    get_x : function() {
        return this._x;
    },
    set_x : function(value) {
        this._x = value;
		this._element.style.left= (Math.round(value) - this._clpLeft) + "px";
    },
    
    // the sprite's current Y position
    get_y : function() {
        return this._y;
    },
    set_y : function(value) {
        this._y = value;
		this._element.style.top = (Math.round(value) - this._clpTop) + "px";
    },

    // the URL to the sprite's source image    
    get_ImageUrl : function() {
        return this._ImageUrl;
    },
    set_ImageUrl : function(value) {
        this._ImageUrl = value;
    },
    
    // the number of frames the sprite has
    get_FrameCount : function() {
        return this._FrameCount;
    },
    set_FrameCount : function(value) {
        this._FrameCount = parseInt(value);
    },
    
    // the Width, in pixels of each frame
    get_FrameWidth : function() {
        return this._FrameWidth;
    },
    set_FrameWidth : function(value) {
        this._FrameWidth = parseInt(value);
    },

    // the Height, in pixels of each frame
    get_FrameHeight : function() {
        return this._FrameHeight;
    },
    set_FrameHeight : function(value) {
        this._FrameHeight = parseInt(value);
    },

    // the sprite's currently displayed frame
    get_FramesPerRow : function() {
        return this._FramesPerRow;
    },
    set_FramesPerRow : function(value) {
        if (value > 0)
            this._FramesPerRow = parseInt(value);
    },

    // the sprite's currently displayed frame
    get_FrameSpeed : function() {
        return this._FrameSpeed;
    },
    set_FrameSpeed : function(value) {
        this._FrameSpeed = parseInt(value);
    },
        
    // the sprite's frame range for animation
    get_FrameRange : function() {
        return {start: this._firstFrameInRange, end: this._lastFrameInRange};
    },
    set_FrameRange : function(start, end) {
        this._firstFrameInRange = parseInt(start);
        this._lastFrameInRange = parseInt(end);
        this._CurrentFrame = this._firstFrameInRange;
    },

    
    // the sprite's currently displayed frame
    get_CurrentFrame : function() {
        return this._CurrentFrame;
    },
    set_CurrentFrame : function(value) {
        this._CurrentFrame = parseInt(value);
        var frmColumn = this._CurrentFrame % this._FramesPerRow;
        var frmRow = parseInt(this._CurrentFrame / this._FramesPerRow);

        this._clpLeft = (frmColumn) * this._FrameWidth;
        this._clpTop = frmRow * this._FrameHeight;
        var clpRight = (frmColumn + 1) * this._FrameWidth;
        var clpBottom = (frmRow + 1) * this._FrameHeight;
        
        this._element.style.clip = "rect(" + this._clpTop + "px," + clpRight + "px," + clpBottom + "px," + this._clpLeft + "px)";
    },

    // get an offset position of the sprite based on direction.
    get_OffsetPosition : function(direction) {
        var x1, y1;
        
        switch (direction) {
            case 0:
                x1 = this._x + Math.round(this._FrameWidth);
                y1 = this._y + Math.round(this._FrameHeight/2);
                break;

            case 1:
                x1 = this._x + Math.round(this._FrameWidth);
                y1 = this._y + Math.round(this._FrameHeight);
                break;

            case 2:
                x1 = this._x + Math.round(this._FrameWidth/2);
                y1 = this._y + Math.round(this._FrameHeight);
                break;

            case 3:
                x1 = this._x;
                y1 = this._y + Math.round(this._FrameHeight);
                break;

            case 4:
                x1 = this._x;
                y1 = this._y + Math.round(this._FrameHeight/2);
                break;

            case 5:
                x1 = this._x;
                y1 = this._y;
                break;

            case 6:
                x1 = this._x + Math.round(this._FrameWidth/2);
                y1 = this._y;
                break;

            case 7:
                x1 = this._x + Math.round(this._FrameWidth);
                y1 = this._y;
                break;
        }

        return { x: x1, y: y1};
 
    },

    // whether the sprite is active
    get_IsActive : function() {
        return this._IsActive;
    },
    set_IsActive : function(value) {
        this._IsActive = value;
        if (!value)
        {
            // hide the sprite
            this._element.style.visibility = 'hidden';
        }
        else
        {
            // show the sprite
            this._element.style.visibility = '';
        }
    },
    
    // the direction (angle) the sprite is moving
    get_Direction : function() {
        return this._Direction;
    },
    set_Direction : function(value) {
        this._Direction = value;
        this.calculateMovement();
    },
    
    // the speed of the sprite's movement
    get_Velocity : function() {
        return this._Velocity;
    },
    set_Velocity : function(value) {
        this._Velocity = value;
        this.calculateMovement();
    },
    
    // a sprite can optionally diminish its collision rectangle
    // for more accurate collision detection for the frames.
    get_DiminishCollisionRectangle : function() {
        return this._diminishCollisionRectangle;
    },
    set_DiminishCollisionRectangle : function(newLeft, newTop, newRight, newBottom) {
        this._diminishCollisionRectangle = {left:newLeft, top:newTop, right:newRight, bottom:newBottom};
    },

    
    // the rectangle for determining collisions
    get_CollisionRectangle : function() {

        var left = this._x + this._diminishCollisionRectangle.left;
        var top = this._y + this._diminishCollisionRectangle.top;
        var right = left + this._FrameWidth - this._diminishCollisionRectangle.right;
        var bottom = top + this._FrameHeight - this._diminishCollisionRectangle.bottom;


        return { x1: left, y1: top, x2: right, y2: bottom };
    },
    
    // sprite's center point
    get_CenterPoint : function() {

        var x1 = this._x + Math.round(this._FrameWidth/2);
        var y1 = this._y + Math.round(this._FrameHeight/2);

        return { x: x1, y: y1};
    },
    
    calculateMovement: function() {
        // determine x/y increments based on angle
        var rads = this._Direction * 0.0174532925199433;
        this._XSpeed = this._Velocity * Math.cos(rads);
        this._YSpeed = this._Velocity * Math.sin(rads);
    }

}

AjaxSprite.SpriteBehavior.registerClass('AjaxSprite.SpriteBehavior', AjaxControlToolkit.BehaviorBase);

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();