function AnimLotus(canvas)
{
    // offsets
    var height_sky = 12;
    var floor_height = SCREEN_HEIGHT - height_sky;
    
    // constructor
    var NUM_COLORS = 18;
    var m_colTable= new cColorTable();
    m_colTable.Init(NUM_COLORS);
    m_colTable.AddColor(0,   122,    0);    // FLOOR   
    m_colTable.AddColor(31,  153,    31);   // FLOOR2   
    m_colTable.AddColor(160,   200,    160);    // Street1   
    m_colTable.AddColor(100,   160,    100);    // Street1   
    m_colTable.AddColor(80,   160,    80);    // Street3   
    m_colTable.AddColor(65,   155,    34);    // Street4   
        

        
    var g = canvas;
    
    // states
    var STATE_NONE = -1;
    var STATE_TITLE = 0;
    var STATE_INGAME = 1;

    var NUMBER_OF_STATES = 2;    
    var m_stateDuration = new Array(NUMBER_OF_STATES);
    var states = new Array(NUMBER_OF_STATES);
    var m_nextState = new Array(NUMBER_OF_STATES);
    
    // state defs 
    m_stateDuration[STATE_TITLE] = 35/SPEEDER_LOTUS;       m_nextState[STATE_TITLE] = STATE_INGAME;
    m_stateDuration[STATE_INGAME] = 786/SPEEDER_LOTUS;    m_nextState[STATE_INGAME] = STATE_NONE;        
    var currentState = STATE_TITLE;  
    
    var DURATION = 0;
    for (var i = 0; i < m_stateDuration.length; i++)
    {
        DURATION+=m_stateDuration[i];
    }
    var m_duration = DURATION;       
    var m_timeLastChange = m_duration;
    
    //////////////////////////////////////////////////////
    this.Reset = function()
    {
        m_duration = DURATION;  
        m_timeLastChange = m_duration;
        currentState = STATE_TITLE;  
    }
    
    //////////////////////////////////////////////////////
    this.Update = function()
    {
        switch (currentState)
        {
            case STATE_TITLE:
            {
                g.ClearScreen("#000000");
                DrawTitle();
            }
            break;
            case STATE_INGAME:
            {
                DrawSky();
                DrawFloor();            
            }
            break;
        }
        
        // automatic state change
        if ((m_timeLastChange - m_stateDuration[currentState]) >= m_duration)
        {
            currentState = m_nextState[currentState];
            m_timeLastChange = m_duration;
        }
        // timer
        m_duration--;
        if (m_duration <= 0)
        {
            return false;
        }
        return true; 
    }
    
    ///////////////////////////////////////////////
    var title_change = 4;
    var title_alternatecounter = title_change;
    var title_image = 0;
    
    function DrawTitle()
    {
        if (title_alternatecounter == 0)
        {
            title_alternatecounter = title_change;
            title_image++;
        }
        title_alternatecounter--;
        if (title_image>1)
            title_image = 0;
            
        switch (title_image)
        {
            case 0: g.DrawSprite(SpriteLotustitle, 0, 2); break;
            case 1: g.DrawSprite(SpriteLotustitle, 0, 2); g.DrawSprite(SpriteLotustitle2, 0, 2); break;
        }
    }

    ////////////////////////////////////////////////
    var floorColors = new Array(2);
    floorColors[0] = m_colTable[0];
    floorColors[1] = m_colTable[1];
    
    var startColor = 0;
    
    var sinCounter = 0;
    var sinInfluence = 0;
    var sinInfluenceStep;
    
    var MODE_STRAIGHT = 0;
    var MODE_LEFT_CURVE = 1;
    var MODE_RIGHT_CURVE = 2;
    var NUMBER_OF_MODES = 3;
    var mode = MODE_LEFT_CURVE;
    
    var maxSteering = 7;
    var cCarX = 0;
    
    var nextModeChange = 30;
    
    var sinY = 0;
    
    function DrawFloor()
    {
        var alternateAfter = 3;
        var nextChange = alternateAfter;
        var currentColor = startColor;
        
        var skyStart = height_sky - 1;
        var streetPerpective = -15;
        
        sinInfluenceStep = 1 / (SCREEN_HEIGHT-skyStart+10);
        sinInfluence = 0;
        
        nextModeChange--;
        if (nextModeChange < 0)
        {
            nextModeChange = 8 + Math.round(Math.random()*8);
            mode = Math.round(Math.random()*(NUMBER_OF_MODES-1));
            if (mode>3)
                mode = 0;
            var debug = document.getElementById("debug");
            if (debug)
                debug.innerHTML = "mode " + mode + "/" + nextModeChange;
        }
        
        for (var y = SCREEN_HEIGHT-1; y>=skyStart; y--)
        {
            nextChange--;
            if (nextChange < 0)
            {
                alternateAfter--;
                nextChange = alternateAfter;
                currentColor++;
                if (currentColor>=2)
                    currentColor = 0;
            }

            var streetStartX = streetPerpective;
            var streetEndX = SCREEN_WIDTH - streetPerpective;
            
        
            
            var sinVal = Math.round((17*Math.sin(sinCounter + ((y-skyStart)/4))) * sinInfluence);     
            sinInfluence+=sinInfluenceStep;
            
            switch (mode)
            {
                 case MODE_STRAIGHT:
                    if (cCarX>0)
                        cCarX--;
                    else if (cCarX<0)
                        cCarX++;   
                     if (sinCounter>0)
                        sinCounter-=0.01;
                     else if (sinCounter<0)
                        sinCounter+=0.01;                     
                     break;
                case MODE_LEFT_CURVE:
                    sinCounter+=0.01;
                    if (sinCounter>1.5)
                        sinCounter = 1.5;
                                       
                    cCarX--;
                    if (cCarX < (-16*maxSteering))                  
                        cCarX = -16*maxSteering;
                    
                    break;
                case MODE_RIGHT_CURVE:
                    sinCounter-=0.01;
                    if (sinCounter<-1.5)
                        sinCounter = -1.5;
                      
                    cCarX++;
                    if (cCarX > (16*maxSteering))                  
                        cCarX = 16*maxSteering;
                    
                     break;
            }
            if(sinInfluence>1)
                sinInfluence = 1;                        
            
            
            if (sinVal<0)
            {
                streetStartX+=sinVal;
                streetEndX+=sinVal/2;
            }
            else if (sinVal > 0)
            {
                streetStartX+=sinVal/2;
                streetEndX+=sinVal;            
            }

            streetEndX = Math.round(streetEndX);
            streetStartX = Math.round(streetStartX);
            
            for (var x = SCREEN_WIDTH-1; x >= 0; x--)
            {
                
                var locColor = currentColor;
                if (x>streetStartX && x < streetEndX)
                    locColor+=2; // add street
                if (x==streetStartX || x==streetEndX)
                    locColor+=4; // add side
    
                g.PutPixel(x,y,m_colTable.GetColor(locColor));
            }         
            streetPerpective+=2.25;     
        }
        
        // car
        sinY+=0.1;
        var carY = Math.round(Math.sin(sinY));
        
        g.DrawSprite(SpriteLotuscar, 10 + Math.round(cCarX/16), 13 + carY);
        
        startColor++;
        if (startColor>=2)
            startColor = 0;
    }
    
    
    ///////////////////////////////////////////////
    var skyX = 0;
    function DrawSky()
    {
        var sinVal = Math.round((SCREEN_WIDTH*Math.sin(sinCounter)));     
        g.DrawSpriteMode(SpriteLotusmtn, skyX + sinVal, 0, g.MODE_WRAP_X);
    }
        
}

