#include "geometry.h"
#include "mesh.h"
#include "texture.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/sdl.h>
#include <string>
#include <stdarg.h>
#include<time.h>
#undef main
#include<deque>
#include "soundloader.h"
#include "audiomanager.h"
#include "font.h"

#define FACEPLANT 100
#define SPIKES 50
#define SHOOT 300
#define JUGGLE 200

int score = 0;
int score2 = 0;
int maxjuggle = 0;
char* reet = 0;

char* fmt2str( const char* fmt, ... ){
    if( reet != 0 ) free( reet );
    va_list a;
    va_start(a, fmt);
    int l = vsnprintf( 0, 0, fmt, a );
    //va_end( a );
    char* t = (char*) malloc( (l + 1)*sizeof( char ) );
    va_start(a, fmt);
    vsnprintf( t, l+1, fmt, a );
    //va_end( a );
    reet = t;
    return reet;
}

texture t_metal;
texture t_stone;
texture t_fabric;
texture t_pull;
texture t_shotgun;
texture t_crosshair;
texture t_blood;

mesh m_shotgun;

font f_hud;
font f_score;

char* messages[] = {
    "Oh hello there son!",
    "I didn't expect to see you up so early!",
    "I guess I can't hide it any longer...",
    "So I might as well give this to you now!",
    "Do you like it?",
    "It's that shotgun you always wanted!",
    "How about we go test it out downstairs.",
    "I have a fresh shipment of people...",
    "You know, the ones who hate my guts.",
    "Now I want you to show me your skills.",
    "When you're ready, just pull the lever.",
    "The farther you pull it, the further they fly!",
    "Try to be stylish!",
    "Style makes me very happy.",
    "You want a happy papa, don't you?",
    "I'll give you five minutes.",
    "How many can you bring to justice in that time?",
    "Go forth, Horrible Jr.!",
    0, 0, 0
};

void intro(){
    glPushMatrix();

    int msg = 0;
    double ypos = 0;
    double msgpos = 0;
    bool brk = false;
    while( messages[msg] != 0 ){
        SDL_Event event; while(SDL_PollEvent(&event)) {
        switch (event.type){
            case SDL_QUIT: exit(0); break;
            case SDL_KEYDOWN: switch(event.key.keysym.sym) {
                case SDLK_ESCAPE: exit(0); break;
                default: brk = true; break;
            } break;
            case SDL_MOUSEBUTTONDOWN: if( event.button.button == SDL_BUTTON_LEFT ){ msg++; } break;
            default: break;
            }
        }
        if( brk ) break;
        ypos = (msg+1) * 25;
        msgpos += ( ypos - msgpos ) / 8;
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glOrtho( 0, 640, 0, 480, -10, 10 );
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glDisable( GL_LIGHTING);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
        glClearColor( 0,0,0,1 );
        glColor3ub(255,255,255);
        glDisable( GL_TEXTURE_2D );
        glPushMatrix();
            glTranslated( 10, msgpos + 5, 0 );
            glPushMatrix();
                for( int i = 0; messages[i] != 0; ++i ){
                    glTranslated( 0, -25, 0 );
                    glPushMatrix();
                    glScaled( 12, 12, 12 );
                    f_hud.render_string( messages[i] );
                    glPopMatrix();
                }
            glPopMatrix();
        glPopMatrix();
        glColor3ub(255,255,255);
        glPushMatrix();
            glTranslated( 500, 450, 0 );
            glScaled( 20, 20, 20);
            f_hud.render_string( "CLICK" );
        glPopMatrix();
        SDL_GL_SwapBuffers( );
        SDL_Delay(10);
    }
    glPopMatrix();
}


struct msg3d{
    std::string txt;
    double x, y, z;
    double zspeed;
    double dzspeed;
    GLubyte color[4];
    msg3d( double X, double Y, double Z, const char* msg ){
        txt = msg;
        x = X; y = Y; z = Z;
        zspeed = 0;
        dzspeed = .04;
        color[0] = 255; color[1] = 0; color[2] = 0; color[3] = 255;
    }
    void step(){
      z += zspeed;
          zspeed += dzspeed;
        if( color[1] < 255 ) color[1] += 5;
        if( color[1] >= 255 ) color[3] -= 5;
    }
    void draw(){
        glDisable( GL_LIGHTING );
        glDisable( GL_TEXTURE_2D );
        glDisable( GL_DEPTH_TEST );
        glPushMatrix();
        double w = f_score.string_width( txt.c_str() );
        glColor4ubv( color );

        glTranslated(x, y, z );
        glScaled( 5,5,5 );
        glRotated( 90, 0, 1, 0 );
        glRotated( 90, 0, 0, 1 );
        //draw::box(10, 10, 10, 0 );
        glTranslated(0, -w, 0 );

        f_score.render_string( txt.c_str() );
        //printf( "%f \t%f \t%f\t%s\n", w, y, z, txt);
        glPopMatrix();
        glEnable( GL_LIGHTING );
        glEnable( GL_DEPTH_TEST );
    }
};

std::vector<msg3d*> message;

double random( double min, double max ){
    return min + (max - min) * (((double) rand()) / RAND_MAX );
}


double deg2rad(double a){
    return a / 180 * asin(1) * 2;
}

int oofs[5];
int shoots[5];
int hits[4];
int spikes[3];

double waterlevel = -100;

audiomanager* audio;

void play_oof(){
    int id = rand()%5;
    (*audio)[oofs[id]]->getdata()->samps.rewind();
    (*audio)[oofs[id]]->play(true);
}
void play_shoot(){
    int id = rand()%5;
    (*audio)[shoots[id]]->getdata()->samps.rewind();
    (*audio)[shoots[id]]->play(true);
}
void play_hit(){
    int id = rand()%4;
    (*audio)[hits[id]]->getdata()->samps.rewind();
    (*audio)[hits[id]]->play(true);
}
void play_spike(){
    int id = rand()%3;
    (*audio)[spikes[id]]->getdata()->samps.rewind();
    (*audio)[spikes[id]]->play(true);
}



double slx1, slx2, sly1, sly2, slz1, slz2;


double point_angle( double x1, double y1, double x2, double y2 ){
    double dx = x2 - x1;
    double dy = y2 - y1;

    return atan2( dx, dy ) * 180 / (asin(1) * 2);
}
double vgravair = -.31;;
double vgravwater = 2.301;;


struct __verlet_node__{
    double __x, __y, __z, __xp, __yp, __zp, __mass, __damp, __grav;
    double __fx, __fy, __fz;
    int ong;
    bool __fixed;
    __verlet_node__()
    {
        __x = 0; __y = 0; __z = 0; __xp = __x; __yp = __y; __zp = __z;
        __mass = 1; __damp = 1; __grav = -.011;
        __fixed = false;
        ong = false;
    }
    __verlet_node__( double x, double y, double z, double mass = 1, double damp = 1 )
    {
        __x = x; __y = y; __z = z; __xp = __x; __yp = __y; __zp = __z;
        __mass = mass; __damp = damp; __grav = vgravair;
        damp = .94;
        __fixed = false;
        ong = false;
    }
    __verlet_node__( double mass, double damp = 1 )
    {
        __x = 0; __y = 0; __z = 0; __xp = __x; __yp = __y; __zp = __z;
        __mass = mass; __damp = damp; __grav = -.0051;
        __fixed = false;
        ong = false;
    }
    __verlet_node__( __verlet_node__* v )
    {
        __x = v->__x; __y = v->__y; __z = v->__z; __xp = v->__xp; __yp = v->__yp; __zp = v->__zp;
        __mass = v->__mass; __damp = v->__damp; __grav = v->__grav;
        __fixed = v->__fixed;
        ong = v->ong;
    }

    void reset(){
        __xp = __x;
        __yp = __y;
        __zp = __z;
    }
    void move()
    {
        ong-=ong>0;
        double xp2 = __x, yp2 = __y, zp2 = __z;
        __x += ( __x - __xp ) * __damp * (1 - 1 / (__mass+50));
        __y += ( __y - __yp ) * __damp * (1 - 1 / (__mass+50));
        __z += ( __z - __zp ) * __damp * (1 - 1 / (__mass+50)) + __grav;
        __xp = xp2; __yp = yp2; __zp = zp2;
        if( __fixed )
        {
            __x = __fx;
            __y = __fy;
            __z = __fz;

        }

    }
    void moveTo( double x, double y, double z )
    {
        __x = x;
        __y = y;
        __z = z;
    }
    void moveRel( double x, double y, double z )
    {
        __x += x;
        __y += y;
        __z += z;
    }
    void moveDir( double latDir, double vertDir, double distance )
    {
        __x += cos( latDir ) * cos( vertDir );
        __y += sin( latDir ) * cos( vertDir );
        __z += sin( vertDir );
    }
    void fix( double x, double y, double z )
    {
        __fixed = true;
        __fx = x;
        __fy = y;
        __fz = z;
    }
    void fix( )
    {
        __fixed = true;
        __fx = __x;
        __fy = __y;
        __fz = __z;
    }
    void unfix()
    {
        __fixed = false;
    }

};

#define T_X1 -10
#define T_X2 10
#define T_Y1 -10
#define T_Y2 10
#define T_Z1 6
#define T_Z2 70


struct __verlet_constraint__{
    struct __verlet_node__ *n1;
    struct __verlet_node__ *n2;
    double __len;
    bool sat;
    bool side;
    int __ret_time;
    __verlet_constraint__( struct __verlet_node__ *_n1, struct __verlet_node__ *_n2 )
    {
        sat = true;
        n1 = _n1;
        n2 = _n2;
        __ret_time = 1.0;
        double dx = n2->__x - n1->__x;
        double dy = n2->__y - n1->__y;
        double dz = n2->__z - n1->__z;
        __len = sqrt( dx*dx+dy*dy+dz*dz );
        side = false;
    }
    __verlet_constraint__( struct __verlet_node__ *_n1, struct __verlet_node__ *_n2, double len )
    {
        sat = true;
        n1 = _n1;
        n2 = _n2;
        __ret_time = 1;
        __len = len;
        side = false;
    }

    void satisfy()
    {
        if( !sat) return;
        double dx = n2->__x - n1->__x;
        double dy = n2->__y - n1->__y;
        double dz = n2->__z - n1->__z;
        //if( side )
        {
            dx *=.985;
            dy *=.985;
            dz *=.985;

        }
        //else
        {
            //dx /=.9999;
            //dy /=.9999;
            //dz /=.9999;

        }
        side = !side;
        double h = sqrt( dx*dx+dy*dy+dz*dz);
        double scale = (__len - h) / h;
        double massRatio1 = n2->__mass / (n1->__mass+n2->__mass);
        double massRatio2 = n1->__mass / (n1->__mass+n2->__mass);

        n1->moveRel( -( dx * scale ) / __ret_time * massRatio1, -( dy * scale ) / __ret_time * massRatio1, -( dz * scale ) / __ret_time * massRatio1 );
        n2->moveRel(  ( dx * scale ) / __ret_time * massRatio2,  ( dy * scale ) / __ret_time * massRatio2,  ( dz * scale ) / __ret_time * massRatio2 );
    }
};

struct blood{
    __verlet_node__* node;
    int time;
    double size;
    blood( __verlet_node__* velocity ){
        time = 0;
        node = new __verlet_node__( velocity->__x,velocity->__y,velocity->__z, .1, .94 );
        node->__xp = velocity->__xp + random( -1, 1 );
        node->__yp = velocity->__yp + random( -1, 1 );
        node->__zp = velocity->__z + 3 + random( -1, 1 );
        size = random( .1, .5 );
        if( velocity->__fixed ) time = 10000;
    }
    ~blood(  ){
        delete node;
    }
    void step(){
        node->move();
        if( node->__z < 0 ) {node->__z = 0; node->__damp = 0;};
        if( node->__y < -100 ) {node->__y = -97; node->__damp = random(.4, .8);}

    }
    void draw(){
        ++time;
        /*float modelview[16];
        int i,j;

        glPushMatrix();

        glGetFloatv(GL_MODELVIEW_MATRIX , modelview);

        for( i=0; i<3; i++ )
            for( j=0; j<3; j++ ) {
                if ( i==j )
                    modelview[i*4+j] = 1.0;
                else
                    modelview[i*4+j] = 0.0;
            }

        glLoadMatrixf(modelview);*/
        glPushMatrix();

        glTranslated( node->__x, node->__y, node->__z );
        glEnable(GL_TEXTURE_2D);
        glRotated( 90, 0, 1, 0 );
        glColor3ub(255,255,255);
        glScaled( size, size, size );
        t_blood.bind();
        glBegin( GL_QUADS );
        glColor3ub(255,255,255);


            glTexCoord2d(0, 0);
            glVertex2d( -16, -16 );
            glTexCoord2d(1, 0);
            glVertex2d( 16, -16 );
            glTexCoord2d(1, 1);
            glVertex2d( 16, 16 );
            glTexCoord2d(0, 1);
            glVertex2d( -16, 16 );
        glEnd();
        glPopMatrix();
    }
};

std::vector<blood*> BLOOD;

struct person{
    std::vector<__verlet_node__*> nodes;
    std::vector<__verlet_constraint__*> cons;
    bool simulate;
    GLubyte shirt[3], pants[3], skin[3];
    double gx, gy, gz;
    double gstep;
    bool moving;
    bool oofed;
    bool rem;
    int jugtime;
    int juggle;
    bool dead;
    person(){
        dead = false;
        jugtime = -1;
        rem = false;
        oofed = false;
        simulate = false;
        moving = false;
        shirt[0] = rand()%255;
        shirt[1] = rand()%255;
        shirt[2] = rand()%255;
        pants[0] = rand()%255;
        pants[1] = rand()%255;
        pants[2] = rand()%255;
        skin[0] = 0xff;
        skin[1] = 0xd0;
        skin[2] = 0xbd;
        //head top
        nodes.push_back( new __verlet_node__(0*2, 0*2, 1*2) );
        //1
        nodes.push_back( new __verlet_node__(0*2, 0*2, -1*2) );
        //2
        nodes.push_back( new __verlet_node__(0*2, 0*2, -4*2) );
        //3
        nodes.push_back( new __verlet_node__(2*2, 0*2, -7*2) );
        //4
        nodes.push_back( new __verlet_node__(3*2, 0*2, -10*2) );
        //5
        nodes.push_back( new __verlet_node__(-2*2, 0*2, -7*2) );
        //6
        nodes.push_back( new __verlet_node__(-3*2, 0*2, -10*2) );
        //7
        nodes.push_back( new __verlet_node__(-3*2, 0*2, -2*2) );
        //8
        nodes.push_back( new __verlet_node__(-5*2, 0*2, -3*2) );
        //9
        nodes.push_back( new __verlet_node__(3*2, 0*2, -2*2) );
        //10
        nodes.push_back( new __verlet_node__(5*2, 0*2, -3*2) );

        cons.push_back( new __verlet_constraint__(nodes[0], nodes[1]) );
        cons.push_back( new __verlet_constraint__(nodes[1],nodes[2]) );
        cons.push_back( new __verlet_constraint__(nodes[2],nodes[3]) );
        cons.push_back( new __verlet_constraint__(nodes[3],nodes[4]) );
        cons.push_back( new __verlet_constraint__(nodes[2],nodes[5]) );
        cons.push_back( new __verlet_constraint__(nodes[5],nodes[6]) );
        cons.push_back( new __verlet_constraint__(nodes[1],nodes[7]) );
        cons.push_back( new __verlet_constraint__(nodes[7],nodes[8]) );
        cons.push_back( new __verlet_constraint__(nodes[1],nodes[9]) );
        cons.push_back( new __verlet_constraint__(nodes[9],nodes[10]) );


    }
    ~person(){
    for( int i = 0; i < cons.size();++i){
        delete cons[i];
    }
    for( int i = 0; i < nodes.size();++i){
        delete nodes[i];
    }

    }
    void translate( double x, double y, double z, bool OT = false, double s = 0 ){
        if( !OT ){
            double dx, dy, dz;
            dx = x - nodes[0]->__x;
            dy = y - nodes[0]->__y;
            dz = z - nodes[0]->__z;

            for( int i = 0; i < nodes.size(); ++i ){
                nodes[i]->moveRel( dx, dy, dz );
                nodes[i]->reset();
            }
        }
        else{
            moving = true;
            gx = x; gy = y; gz = z;
            gstep = s;
        }
    }
    void sever( int n ){
        for( int i = 0; i < cons.size(); ++i ){
            if( cons[i]->n2 == nodes[n] ){
                __verlet_node__* a = new __verlet_node__( nodes[n] );
                nodes.push_back( a );
                cons[i]->n2 = a;
            }
        }
    }
    void step(){
        if( jugtime > 0 ) jugtime --;
        if( simulate ){
            bool rm = true;
            for( int i = 0; i < nodes.size(); ++i){
                if( nodes[i]->__x < 20){ rm = false; break; }
            }
            rem = rm;
            double X = slx1;
            double Y = sly1;
            double Z = slz1;
            double DX = slx2 - slx1;
            double DY = sly2 - sly1;
            double DZ = slz2 - slz1;
            double sldist = sqrt( DX*DX+DY*DY+DZ*DZ );


            for( double j = 0; j < sldist; j += sldist / 25 ){
                for( int i = 0; i < nodes.size(); ++i ){
                    double dx = X - nodes[i]->__x;
                    double dy = Y - nodes[i]->__y;
                    double dz = Z - nodes[i]->__z;

                    if( dx*dx+dy*dy+dz*dz < 30 ){
                        play_hit();
                        if( !oofed ){
                        play_oof();
                        oofed = true;
                        juggle = 1;
                        jugtime = 10;
                        message.push_back( new msg3d( nodes[i]->__x - 29, nodes[i]->__y, nodes[i]->__z, fmt2str( "BLOWN AWAY +%i", SHOOT ) ));
                        score += SHOOT;
                        }
                        int num = rand() %2 + 1;
                        for( int k = 0; k < num; ++k ){
                            BLOOD.push_back( new blood( nodes[i] ) );

                            //printf("ow");
                        }
                        if( oofed && dead == false && nodes[i]->__z > 13 ){
                                if( jugtime == 0 ){
                                    juggle ++;
                                    jugtime = 10;
                                    message.push_back( new msg3d( nodes[i]->__x - 29, nodes[i]->__y, nodes[i]->__z, fmt2str( "JUGGLE X%i +%i", juggle, juggle * JUGGLE ) ));
                                    score += JUGGLE * juggle;
                                    if( juggle > maxjuggle ) maxjuggle = juggle;
                                }
                        }
                        if( nodes[i]->__fixed == false ){
                            nodes[i]->moveRel( -.5, 0, 2 );
                            sever( i );}
                    }
                }
                X += DX / 25;
                Y += DY / 25;
                Z += DZ / 25;
            }
            dead = true;
            for( int i = 0; i < nodes.size(); ++i ){
                if( nodes[i]->__z > 13 ) dead = false;
                nodes[i]->move();
                if( nodes[i]->__z < 0 )nodes[i]->__z = 0;
                if( nodes[i]->__x < -100 )nodes[i]->__x = -100;

                if( nodes[i]->__y < -100 ){nodes[i]->__y = -97;
                    if( abs(nodes[i]->__y-nodes[i]->__yp) > 0 ){
                        nodes[i]->reset();
                        int num =  abs(nodes[i]->__y-nodes[i]->__yp) / 5 + 1;
                        if( !oofed ){
                        play_oof();
                        play_hit();
                        oofed = true;
                        message.push_back( new msg3d( nodes[i]->__x - 29, nodes[i]->__y, nodes[i]->__z, fmt2str( "FACEPLANT +%i", FACEPLANT ) ));
                        score += FACEPLANT;
                        jugtime = 10;
                        juggle = 0;
                        }
                        for( int k = 0; k < num; ++k ){
                            BLOOD.push_back( new blood( nodes[i] ) );

                            //printf("ow");
                        }
if( !(nodes[i]->__fixed) ){
                        nodes[i]->moveRel( 0, 4, 1 );
                        sever( i );}
                    }
                }
                if( nodes[i]->__y > 100 && nodes[i]->__z < 40 ) nodes[i]->__z = 40;

            }
            for( int i = 0; i < cons.size(); ++i ){
                cons[i]->satisfy();
            }
        }
        if( moving ){
            double dx, dy, dz;
            dx = gx - nodes[0]->__x;
            dy = gy - nodes[0]->__y;
            dz = gz - nodes[0]->__z;
            for( int i = 0; i < nodes.size(); ++i ){
                nodes[i]->moveRel( dx/gstep, dy/gstep, dz/gstep );
                nodes[i]->reset();
            }
            if( abs(nodes[0]->__x - gx) <= 3 && abs(nodes[0]->__y - gy) <= 3 && abs(nodes[0]->__z - gz) <= 3 )
                moving = false;
        }

    }

    void draw_box_pt( double w, double d, double x1, double y1, double z1, double x2, double y2, double z2 ){
        double vx = x2-x1;
        double vy = y2-y1;
        double vz = z2-z1;
        if(vz == 0)
        vz = .0001;

        double v = sqrt( vx*vx + vy*vy + vz*vz );
        double ax = 57.2957795*acos( vz/v );
        if ( vz < 0.0 )
        ax = -ax;
        double rx = -vy*vz;
        double ry = vx*vz;
        glPushMatrix();
        glTranslatef( x1,y1,z1 );
        glRotatef(ax, rx, ry, 0.0);
        glTranslated( 0, 0, v/2 );
        draw::box( w, d, v, 0);
        glPopMatrix();
    }
    void draw(){
        glColor3ubv( skin );
        /*glBegin( GL_LINES );
        for( int i = 0; i < cons.size(); ++i){
                //printf( "%f\t%f\t%f\n", cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z );
            glVertex3d( cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z );
            glVertex3d( cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        }
        glEnd();*/
        //double s = cons[i]->__len;
        int i = 0;
        glDisable( GL_TEXTURE_2D );
        draw_box_pt( 3, 3, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        glColor3ubv( shirt );
        glEnable( GL_TEXTURE_2D );
        t_fabric.bind();
        i = 1; draw_box_pt( 3, 3, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 6; draw_box_pt( 2, 2, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 7; draw_box_pt( 2, 1, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 8; draw_box_pt( 2, 2, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 9; draw_box_pt( 2, 1, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        glColor3ubv( pants );
        i = 2; draw_box_pt( 2, 3, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 3; draw_box_pt( 2, 2, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 4; draw_box_pt( 2, 3, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );
        i = 5; draw_box_pt( 2, 2, cons[i]->n1->__x, cons[i]->n1->__y, cons[i]->n1->__z, cons[i]->n2->__x, cons[i]->n2->__y, cons[i]->n2->__z );


    }

};





void glPerspective( GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar )
{
    const GLdouble pi = 3.1415926535897932384626433832795;
    GLdouble fW, fH;
    fH = tan( fovY / 360 * pi ) * zNear;
    fW = fH * aspect;
    glFrustum( -fW, fW, -fH, fH, zNear, zFar );
}

void set_camera( double x, double y, double z, double roll, double pitch, double yaw ){
    //roll /= 2 * M_PI;
    //roll = 2 * M_PI * ( roll - floor(roll) );
    //if( roll == M_PI )
      //  roll += .0000000001;
      int t = (int)(( roll + M_PI / 2 ) / M_PI) % 2 == 0 ? 1: -1;
      int b = (int)(( pitch + M_PI / 2 ) /(M_PI)) % 2 == 0 ? 1: -1;

    gluLookAt( x, y, z, x + cos( yaw ) * cos( pitch ), y + sin( yaw ) * cos( pitch ), z + sin( pitch ), 0, t * tan(roll), t*b );
}


struct dungeon{
    std::vector<double> bloody;
    double get( int x, int y){
        if( x + y * 200 < 0 || x + y * 200 >= bloody.size() ) return 0;
        return bloody[x + y * 200];
    }
    double set( int x, int y, double v){
        if( x + y * 200 < 0 || x + y * 200 >= bloody.size() ) return 0;
        return bloody[x + y * 200] = v;
    }
    double inc( int x, int y, double v){
        return set(x,y,get(x,y) + v);
    }

    void putblood( int x, int y, int r, double a ){
        for( int i = -r; i < r; ++i){
            for( int j = -r; j < r; ++j ){
                if( (i * i + j * j) < r * r ){
                    inc( x + i, y + j, a );
                }
            }
        }
    }
    std::deque<person*> people;
    std::deque<person*> people2;

    void reload( bool pop = true ){
        double yy = 90;
        if( pop )
            people.pop_front();//
        people.front()->translate( -70, 110, 63, true, 10 );
        for( int i = 1; i < people.size(); ++i ){
            people[i]->translate( -115, yy, 63, true, 10 );
            yy -= 10;
        }
        person* a = new person();
        a->translate( -115, yy, 63 );
        yy -= 10;
        people.push_back( a );
        people2.push_back( a );
        //people.pop_front();
    }
    dungeon(){
        double yy = 90;
        for( int i = 0; i < 20; ++i){
            person* a = new person();
            a->translate( -115, yy, 63 );
            yy -= 10;
            people.push_back( a );
            people2.push_back( a );

        }
        bloody.resize( 200*200, 0 );
        //putblood( 40, 100, 20, .5 );
        //putblood( 40, 100, 20, .5 );
        reload(false);
        ttr = -1;

    }

    int ttr;
    void draw(){

        glEnable( GL_TEXTURE_2D );
        t_stone.bind();
        glColor3ub(255,255,255);
        glBegin( GL_QUADS );
        //spike floor
        glNormal3d( 0, 0, 1 );
        glTexCoord2d( 0, 0 );
        glVertex3d( -100, -100, 0 );
        glTexCoord2d( 4, 0 );
        glVertex3d( 100, -100, 0 );
        glTexCoord2d( 4,4 );
        glVertex3d( 100, 100, 0 );
        glTexCoord2d( 0, 4 );
        glVertex3d( -100, 100, 0 );


        //jail face bot
        glNormal3d( 1, 0, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-100, -100, 0 );
        glTexCoord2d( 0, 2 );
        glVertex3d(-100, -100, 50 );
        glTexCoord2d( 4, 2 );
        glVertex3d(-100, 100, 50 );
        glTexCoord2d( 4, 0 );
        glVertex3d( -100, 100, 0 );
        //jail face top
        glNormal3d( 1, 0, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-100, -100, 70 );
        glTexCoord2d( 0, 2 );
        glVertex3d(-100, -100, 70+50 );
        glTexCoord2d( 4, 2 );
        glVertex3d(-100, 150, 70+50 );
        glTexCoord2d( 4, 0 );
        glVertex3d( -100, 150, 70 );

        //jail face bg
        glColor3ub(111,111,111);
        glNormal3d( 1, 0, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-130, -300, 0 );
        glTexCoord2d( 0, 4 );
        glVertex3d(-130, -300, 100 );
        glTexCoord2d( 4*3, 4 );
        glVertex3d(-130, 300, 100 );
        glTexCoord2d( 4*3, 0 );
        glVertex3d( -130, 300, 0 );

        //jail floor

        glNormal3d( 0, 0, 1 );
        glTexCoord2d( 0, 0 );
        glVertex3d( -101, -100, 40 );
        glTexCoord2d( 4, 0 );
        glVertex3d( -140, -100, 40 );
        glTexCoord2d( 4,4 );
        glVertex3d( -140, 100, 40 );
        glTexCoord2d( 0, 4 );
        glVertex3d( -101, 100, 40 );


        glColor3ub(255,255,255);


        //left side
        glNormal3d( 0, 1, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-110, -100, 0 );
        glTexCoord2d( 0, 4 );
        glVertex3d(-110, -100, 100 );
        glTexCoord2d( 4 + 10./25., 4 );
        glVertex3d(100, -100, 100 );
        glTexCoord2d( 4 + 10./25., 0 );
        glVertex3d( 100, -100, 0 );



        //jail ledge
        glNormal3d(0, 0, 1);
        glTexCoord2d( 0, 0 );
        glVertex3d(-100, -100, 50 );
        glTexCoord2d( 10./25, 0 );
        glVertex3d(-110, -100, 50 );
        glTexCoord2d( 10./25, 4 );
        glVertex3d(-110, 100, 50 );
        glTexCoord2d( 0, 4 );
        glVertex3d(-100, 100, 50 );

        //right side A
        glNormal3d( 0, -1, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-110, 100, 0 );
        glTexCoord2d( 0, 40./25. );
        glVertex3d(-110, 100, 40 );
        glTexCoord2d( 4 + 10./25., 40./25. );
        glVertex3d(100, 100, 40 );
        glTexCoord2d( 4 + 10./25., 0 );
        glVertex3d( 100, 100, 0 );

        //right side B
        glColor3ub(111,111,111);
        glNormal3d( 0, -1, 0 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-140, 130, 40 );
        glTexCoord2d( 0, 60./25. );
        glVertex3d(-140, 130, 100 );
        glTexCoord2d( 4 + 10./25., 60./25. );
        glVertex3d(100, 130, 100 );
        glTexCoord2d( 4 + 10./25., 0 );
        glVertex3d( 100, 130, 40 );

        glColor3ub(255,255,255);

        //right side floor
        glNormal3d( 0, 0, 1 );
        glTexCoord2d( 0, 30./25. );
        glVertex3d(-140, 130, 40 );
        glTexCoord2d( 0, 0 );
        glVertex3d(-140, 100, 40 );
        glTexCoord2d( 240./25., 0 );
        glVertex3d(100, 100, 40 );
        glTexCoord2d( 240./25., 30./25. );
        glVertex3d( 100, 130, 40 );

        glColor3ub(255,255,255);


        //t_metal.bind();
        //bars
        for( int i = 0; i < 10; ++i ){
            glNormal3d( 1, 0, 0 );
            double xx = -100 + i * (200 / 10 ) + 10;
            glTexCoord2d( 0, 0 );
            glVertex3d( -104, xx - 1, 50 );
            glTexCoord2d( 0, 1 );
            glVertex3d( -104, xx - 1, 70 );
            glTexCoord2d( .2, .4 );
            glVertex3d( -104, xx + 1, 70 );
            glTexCoord2d( .2, 0 );
            glVertex3d( -104, xx + 1, 50 );

        }

        glEnd();
        int rr = rand();
        srand( 10 );
        glDisable( GL_TEXTURE_2D );
        for( int i = -100 + rand() % 5 ; i < 100; i += rand() % 7 + 2){
            for( int j = -100 + rand() % 5 ; j < 100; j += rand() % 6 + 2){
                glPushMatrix();


                glTranslated( i + random(-2,2), j + random(-2,2), 4 + random(-2,2) );
                glRotated( random( 0, 360 ), 0, 0, 1);
                glRotated( random( -20, 10 ), 1, 0, 0 );
                glRotated( random( -10, 20 ), 0, 1, 0 );
                double h = random( 5,20 );
                glTranslated(0, 0, h/2);
                if( waterlevel > 0 )
                    glTranslated( 0, 0, - h / (10/waterlevel) );
                double P = get(i+100,j+100);
                if( P > 1 ) P = 1;
                double PP = get(i+100,j+100);
                if( PP < 1 ) PP = 0;
                if( PP >= 1 ) PP -= 1;
                if( PP >= 1 ) PP = 1;

                draw::pyramid( random( 2,4 ), random( 3,5 ), h, 0, 150+(255-150)*P, 152+(0-152)*P,150+(0-150)*P, 150+(255-150)*PP, 152+(0-152)*PP,150+(0-150)*PP );
                if( waterlevel > 10 && get(i+100,j+100) > 0 ) inc( i+100, j+100, -.01 );

                glPopMatrix();
            }

        }
        srand( rr );
        for( int i = 0; i < people2.size(); ++i){
            if( people2[i]->rem ){
                delete people2[i];
                people2.erase( people2.begin() + i );
                --i;
                continue;
            }
            glColor3ub(252,255,255);
            people2[i]->draw();
            //people[i]->simulate = true;;

            people2[i]->step();
            for( int k = 0; k < people2[i]->nodes.size(); ++k){
                if(people2[i]->nodes[k]->__z < waterlevel ){
                    people2[i]->nodes[k]->unfix();
                    people2[i]->nodes[k]->moveRel(.01, 0, .32);

                    //people2[i]->nodes[k]->__grav = vgravwater;

                }
                else{
                if( people2[i]->nodes[k]->__z < 10 && people2[i]->nodes[k]->__zp >= 10 ){
                    putblood( people2[i]->nodes[k]->__x + 100, people2[i]->nodes[k]->__y + 100, 10, .1 );
                    people2[i]->nodes[k]->fix();

                    BLOOD.push_back( new blood(people2[i]->nodes[k] ));
                    BLOOD.push_back( new blood(people2[i]->nodes[k] ));
                    BLOOD.push_back( new blood(people2[i]->nodes[k] ));

                    if( people2[i]->oofed == false ){
                         play_oof();
                         message.push_back( new msg3d( people2[i]->nodes[k]->__x - 29, people2[i]->nodes[k]->__y, people2[i]->nodes[k]->__z, fmt2str( "IMPALED +%i", SPIKES ) ));
                         score += SPIKES;

                    }
                    play_spike();
                    people2[i]->oofed = true; }
            }
            //people2[i]->nodes[k]->__grav = vgravair;

            }
        }
        if( ttr == 0 ) reload();
        ttr -= ttr > -1;
        for( int i = 0; i < BLOOD.size(); ++i){
            BLOOD[i]->step();
            BLOOD[i]->draw();
            if( BLOOD[i]->node->__z < 10 && BLOOD[i]->node->__zp > 10 ) putblood( BLOOD[i]->node->__x + 100, BLOOD[i]->node->__y + 100, 3, .2  );
            if( BLOOD[i]->time > 100 ){
                delete BLOOD[i];
                BLOOD.erase( BLOOD.begin() + i );
                --i;
            }

        }
        for( int i = 0; i < message.size(); ++i ){
            message[i]->step();
            message[i]->draw();
            if( message[i]->color[3] < 10 ){
                delete message[i];
                message.erase(message.begin() + i);
                --i;
                continue;
            }
        }

    }
    void fling( double magnitude){
        if( people.front()->moving ) return;
        for( int i = 0; i < 11; ++i )
        //people.front()->nodes[i ]->moveRel( 1, -i, 1 );
        people.front()->nodes[i ]->moveRel( random( 1, 9 ) - 4., -magnitude * random( 0, 2) / 4 -.3, random( 3, 7 ) );

        people.front()->simulate = true;

        ttr = 5;
    }
};

void setcam( double x, double y, double z, double wid, double hig, double roll, double pitch, double yaw, double znear, double zfar ){
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 80, wid/hig, znear, zfar );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    set_camera( x, y, z + 5, roll, pitch, yaw );
}

int main(){

    SDL_Init( SDL_INIT_EVERYTHING );
    const SDL_VideoInfo* info = 0;
    if( !(info = SDL_GetVideoInfo( ))) return 2;
    IMG_Init(IMG_INIT_PNG);
    int bpp = info->vfmt->BitsPerPixel;

    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
    SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );


    SDL_Surface* screen = SDL_SetVideoMode( 640, 480, bpp, SDL_OPENGL );
    if( screen <= 0 ){
        SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 );
        SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 0 );
        screen = SDL_SetVideoMode( 640, 480, bpp, SDL_OPENGL );
        if( screen <= 0 ) return 0;
    }
    //SDL_ShowCursor( 0 );
    glPixelStorei(GL_UNPACK_ALIGNMENT,4);

    glTexEnvf( GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE );

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    //glEnable( GL_TEXTURE_2D );


    glEnable( GL_DEPTH_TEST );
    glEnable( GL_LIGHTING );
    glEnable( GL_COLOR_MATERIAL );
    glEnable( GL_LIGHT0 );
    GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
    GLfloat diffuseLight[] = { 0.5f, 0.5f, 0.5, 0.3f };
    GLfloat specularLight[] = { 0.2f, 0.2f, 0.2f, .5f };
    GLfloat position[] = { -8.0f, 1.0f, 6.0f, .2f };
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
    glLightfv(GL_LIGHT0, GL_POSITION, position);

    audio = new audiomanager();
    t_stone.load( "textures/stone.png" );
    t_pull.load( "textures/pull.png" );
    t_fabric.load( "textures/fabric.png" );
    t_shotgun.load( "textures/shotgun.png" );
    t_crosshair.load( "textures/crosshair.png" );
    t_blood.load( "textures/blood.png" );


    oofs[0] = audio->load( "sounds/oof1.wav" );
    oofs[1] = audio->load( "sounds/oof2.wav" );
    oofs[2] = audio->load( "sounds/oof3.wav" );
    oofs[3] = audio->load( "sounds/oof4.wav" );
    oofs[4] = audio->load( "sounds/oof5.wav" );
    shoots[0] = audio->load( "sounds/shoot1.wav" );
    shoots[1] = audio->load( "sounds/shoot2.wav" );
    shoots[2] = audio->load( "sounds/shoot3.wav" );
    shoots[3] = audio->load( "sounds/shoot4.wav" );
    shoots[4] = audio->load( "sounds/shoot5.wav" );
    hits[0] = audio->load( "sounds/hit1.wav" );
    hits[1] = audio->load( "sounds/hit2.wav" );
    hits[2] = audio->load( "sounds/hit3.wav" );
    hits[3] = audio->load( "sounds/hit4.wav" );
    spikes[0] = audio->load( "sounds/spike1.wav" );
    spikes[1] = audio->load( "sounds/spike2.wav" );
    spikes[2] = audio->load( "sounds/spike3.wav" );
    int music = audio->load( "sounds/music.mp3" );


    m_shotgun.load_from_bzw( "models/shotgun.bzw" );
    init();
    f_hud.load("fonts/Skir.ttf");
    f_score.load("fonts/Skir.ttf");




    (*audio)[music]->play( true );
    (*audio)[music]->loop( true );



    srand(time(0));

    dungeon d;
    double a = 0;
    double mouse_x, mouse_y;
    mouse_x = mouse_y = 0;
    bool mbl = false;
    glEnable( GL_BLEND );
    double sliderx = 0;
    bool sliding = false;
    bool flung = false;
    double crossrot = 0;
    int shots = 0;
    bool spaced = false;
    double waterdelta = 0;

    intro();
    int seconds = 5 * 60;
    time_t tim = time(0);

    while( true ){
        if( time(0) != tim ){
            seconds-=1;
            tim = time(0);
            if( seconds < 0 )
                seconds = 0;
        }
             glEnable( GL_LIGHTING );
        bool mblp = mbl;
        bool canshoot = 1;
        //waterlevel -= .5;
        waterdelta -= .005;
        //if( waterdelta < -4 )
        if( spaced ) {
            waterdelta += .007;
            if( waterdelta > 2 ) waterdelta = 2;
            if( waterlevel < 0 ){
                waterlevel = 0;
                waterdelta = 0;
            }

        }
        else{

        }
        //if( waterlevel < 30 )
        waterlevel += waterdelta;
        if( waterlevel > 30 ) {waterlevel = 30; waterdelta = 0;}


        SDL_Event event; while(SDL_PollEvent(&event)) {
        switch (event.type){
            case SDL_QUIT: exit(0); break;
            case SDL_KEYDOWN: switch(event.key.keysym.sym) {
                case SDLK_ESCAPE: exit(0); break;
                case SDLK_SPACE: spaced = true; break;
                //case SDLK_UP: case SDLK_w: e.type = world::player::KEY_U; e.value = 1; break;
                //case SDLK_DOWN: case SDLK_s: e.type = world::player::KEY_D; e.value = 1; break;
                //case SDLK_LEFT: case SDLK_a: e.type = world::player::KEY_L; e.value = 1; break;
                //case SDLK_RIGHT: case SDLK_d: e.type = world::player::KEY_R; e.value = 1; break;
                default: break;
            } break;
            case SDL_KEYUP: switch(event.key.keysym.sym) {
                case SDLK_SPACE: spaced = false;  break;
                //case SDLK_UP: case SDLK_w: e.type = world::player::KEY_U; e.value = 0; break;
                //case SDLK_DOWN: case SDLK_s: e.type = world::player::KEY_D; e.value = 0; break;
                //case SDLK_LEFT: case SDLK_a: e.type = world::player::KEY_L; e.value = 0; break;
                //case SDLK_RIGHT: case SDLK_d: e.type = world::player::KEY_R; e.value = 0; break;
                default: break;
            } break;

            case SDL_MOUSEMOTION: mouse_x = event.motion.x; mouse_y = event.motion.y; break;
            case SDL_MOUSEBUTTONDOWN: if( event.button.button == SDL_BUTTON_LEFT ){ mbl = 1;} break;
            case SDL_MOUSEBUTTONUP: if( event.button.button == SDL_BUTTON_LEFT ){ mbl = 0; } break;
            default: break;
            }

        }
        if( seconds <= 0 ) spaced = true;
        if( seconds > 0 ){
        if( mbl && mouse_x > sliderx + 20 && mouse_x < sliderx + 20 + 64 && mouse_y > 480 - 100 && mouse_y < 480 - 100 + 40 ){
            sliding = true;
            canshoot = false;
        }
        if( sliding ){
            sliderx = mouse_x - 20 - 32;
            if( sliderx < 0 ) sliderx = 0;
            if( sliderx > 640 - 40 ) sliderx = 600;
            flung = true;
        }
        if( !mbl && flung ) {
                flung = false;
                sliding = false;
                d.fling( sliderx / 10 );
                sliderx = 0;

        }
        }
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
        glClearColor( 0,0,0,1 );
        setcam( 30, 0, 100, 640, 480, 0, -.7 , asin(1)*2, 1, 100000);

        double zrot, yrot;

        glPushMatrix();
            glColor3ub(255,255,255);
            glTranslated( 30, 0, 95);
            glScaled( 7,7,7 );
            zrot = -(mouse_x - 640 / 2) / 6 + 180;
            yrot = -(mouse_y - 480 / 2) / 5 - 40;
            glRotated( yrot, 0, 1, 0 );
            glRotated( zrot, 0, 0, 1 );

            //glRotated( 180, 0, 0, 1 );
            glRotated( 90, 1, 0, 0 );
            glEnable( GL_TEXTURE_2D );
            t_shotgun.bind();
            m_shotgun.render();
            glDisable( GL_TEXTURE_2D );
            //glBegin( GL_LINES );
            //glVertex3d( 0, 0, 0 );
            //glVertex3d( 1000, 0, 0 );
            //glEnd();


        glPopMatrix();
        slx1 = slx2 = sly1 = sly2 = slz1 = slz2 = 0;
        if( seconds > 0)
            if( mbl && !mblp && canshoot ){
                shots = 6;
                play_shoot();
            }
        if( shots > 0 ){ shots --;

            slx1 = 30;
            sly1 = 0;
            slz1 = 95;
            zrot += +random(-6,6);
            yrot += +random(-6,6);

            slx2 = slx1 + 200 * cos( deg2rad(zrot) ) * cos( deg2rad( yrot ) );
            sly2 = sly1 + 200 * sin( deg2rad(zrot) );
            slz2 = slz1 + 200 * sin( deg2rad( yrot ) );

        }
        glColor3ub(255,255,0);
            //glBegin( GL_LINES );
            //glVertex3d( slx1, sly1, slz1 );
            //glVertex3d( slx2, sly2, slz2 );
            //glEnd();
        //gluLookAt( 300, 0, 50, 10, 0, 5, 0, 0, 1 );
        d.draw();
        glColor4ub(10, 20, 200, 170 );
        glDisable( GL_TEXTURE_2D );
        glBegin(GL_QUADS);
        glNormal3d( 0, 0, 1 );
        glVertex3d(-100, -100, waterlevel);
        glVertex3d(-100, 100, waterlevel);
        glVertex3d(100, 100, waterlevel);
        glVertex3d(100, -100, waterlevel);
        glEnd();
                glFlush();
            glDisable( GL_LIGHTING );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glOrtho( 0, 640, 480, 0, -10, 10 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        if( seconds > 0 ){
            glColor3ub( 255, 255, 255 );
            glEnable( GL_TEXTURE_2D);
            t_pull.bind();
            glBegin( GL_QUADS );
            glTexCoord2d( 0, 0 );
            glVertex2d( sliderx + 20, 480 - 100 );
            glTexCoord2d( 1, 0 );
            glVertex2d( sliderx + 20 + 64, 480 - 100 );
            glTexCoord2d( 1, 1 );
            glVertex2d( sliderx + 20 + 64, 480 - 100 + 64 );
            glTexCoord2d( 0, 1 );
            glVertex2d( sliderx + 20, 480 - 100 + 64 );
            glEnd();
            glDisable(GL_TEXTURE_2D);
            glColor3ub( 155,155,155 );
            glLineWidth( 3 );
            glTranslated( 0, 0, -1 );
            glBegin( GL_LINES );
            glVertex2d( 25, 480 - 100 + 20 );
            glVertex2d( 640 - 25, 480 - 100 + 20 );
            glEnd();
            glPushMatrix();
            glTranslated( mouse_x, mouse_y, 0 );
            crossrot += 3.6;
            glRotated( crossrot, 0, 0, 1 );
            glTranslated( 0, 0, -2 );
            t_crosshair.bind();
            glBegin( GL_QUADS );
            glColor3ub(255,255,255);
                glEnable(GL_TEXTURE_2D);

                glTexCoord2d(0, 0);
                glVertex2d( -16, -16 );
                glTexCoord2d(1, 0);
                glVertex2d( 16, -16 );
                glTexCoord2d(1, 1);
                glVertex2d( 16, 16 );
                glTexCoord2d(0, 1);
                glVertex2d( -16, 16 );
            glEnd();
            glPopMatrix();
            glDisable(GL_TEXTURE_2D);
            //glTranslated( 100, 100, 0 );
            glPushMatrix();
            glTranslated( 640/2, 50, 0 );
            glLineWidth( 1 );
            glColor3ub(255,255,255);
            glScaled( 20, -20, 20 );
            score2 += 25 * (score2 < score);
            if( score2 > score ) score2 = score;
            const char* tstr = fmt2str( "%i", (int)score2);
            double tlen = f_hud.string_width( tstr );
            glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();

            glPushMatrix();
            glTranslated( 20, 50, 0 );
            glLineWidth( 1 );
            //if( seconds > 0 )
                glColor3ub(255, 0, 0);
            if( seconds > 10 )
                glColor3ub(255, 255 ,0);

            if( seconds > 60 )
                glColor3ub(255, 255 ,255);

            glScaled( 20, -20, 20 );
            tstr = fmt2str( "%01i:%02i", seconds / 60, seconds % 60);
            tlen = f_hud.string_width( tstr );
            //glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();
        }
        else{
            glPushMatrix();
            glTranslated( 640/2, 50, 0 );
            glLineWidth( 1 );
            glColor3ub(255,255,255);
            glScaled( 20, -20, 20 );

            const char* tstr = "Great work, son!";
            double tlen = f_hud.string_width( tstr );
            glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();

            glPushMatrix();
            glTranslated( 640/2, 200, 0 );
            glLineWidth( 1 );
            glColor3ub(255,255,255);
            glScaled( 20, -20, 20 );

            tstr = fmt2str( "SCORE: %i", score);
            tlen = f_hud.string_width( tstr );
            glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();

            glPushMatrix();
            glTranslated( 640/2, 280, 0 );
            glLineWidth( 1 );
            glColor3ub(255,255,255);
            glScaled( 20, -20, 20 );
            tstr = fmt2str( "MAX JUGGLE: %i", maxjuggle);
            tlen = f_hud.string_width( tstr );
            glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();

            glPushMatrix();
            glTranslated( 640/2, 370, 0 );
            glLineWidth( 1 );
            glColor3ub(255,255,255);
            glScaled( 10, -10, 10 );
            tstr = "Looks like someone needs a Promotion";
            tlen = f_hud.string_width( tstr );
            glTranslated( -tlen/2, 0, 0);
            f_hud.render_string( tstr );
            glPopMatrix();


        }




        SDL_GL_SwapBuffers( );
        SDL_Delay(10);
        //printf( "%f\n", point_angle( 640/2, 480/2, mouse_x, mouse_y ) );
    }

}
