
#include "template.h"

using namespace AGK;

// *************************************************
//        User's GLOBAL ENUM blocks
// *************************************************

// *************************************************
//            System Defined Constants
// *************************************************


#define cSizeOfDefaultString 2048

// *************************************************
//            User Defined Constants
// *************************************************

// *************************************************
//          User Defined Types, Unions and Classes
// *************************************************


// *************************************************
//            User Global Variables
// *************************************************

app     App;
int     input_method;
int     screen_left;
int     screen_right;
int     screen_top;
float   max_speed = 5.0f;
float   acceleration = 0.005f;
float   turn_speed = 4.0f;
int     game_state = 0;
float   speed = 0.0f;
int     score = 0;
int     high_score = 0;


// *************************************************
//               User Prototypes
// *************************************************

void    _screen_setup (void);
void    _set_input_method (void);
void    _load_media (void);
void    _initiate (void);
void    _start (void);
void    _play_game (void);
void    _game_over (void);

// *************************************************
//            User Global Initialized Arrays
// *************************************************



// *************************************************
//                 Runtime Functions
// *************************************************


// *************************************************
//       User Subs, Functions and Class Methods
// *************************************************

void app::Begin ()
{
    agk::SetFolder("/media");
    _screen_setup();
    _set_input_method();
    _load_media();
    game_state = 0;
}


int app::Loop ()
{
    if (agk::GetRawKeyPressed(27))
    {
        fflush(stdout);
        exit(0 );
    }
    if (game_state == 0 )
    {
        _initiate();
        goto L1000;
    }
    if (game_state == 1 )
    {
        _start();
        goto L1000;
    }
    if (game_state == 2 )
    {
        _play_game();
        goto L1000;
    }
    if (game_state == 3 )
    {
        _game_over();
    }
L1000:
    ;
    agk::Sync();
    return 0;
}


void app::End ()
{
}


void _screen_setup ()
{
    agk::SetWindowTitle("Tunnel Rush");
    agk::SetWindowSize(1280, 720, 0);
    agk::SetVirtualResolution(1280, 720);
    agk::SetOrientationAllowed(0, 0, 1, 0);
    agk::SetSyncRate(30, 0);
    agk::SetScissor(0, 0, 0, 0);
    screen_left = agk::GetScreenBoundsLeft();
    screen_right = agk::GetScreenBoundsRight();
    screen_top = agk::GetScreenBoundsTop();
    agk::SetClearColor(255, 255, 0);
}


void _set_input_method ()
{
    agk::CompleteRawJoystickDetection();
    if (agk::GetJoystickExists() == 1 )
    {
        input_method = 3;
    }
    else
    {
        if (agk::GetKeyboardExists() == 1 )
        {
            input_method = 1;
        }
        else
        {
            if (agk::GetMultiTouchExists() == 1 )
            {
                input_method = 2;
            }
        }
    }
}


void _load_media ()
{
    agk::LoadImage(1, "tunnel_1.png");
    agk::LoadImage(2, "block_1.png");
    {
        int i;
        for (i = 1; i <= 5; i += 1)
        {
            agk::LoadObject(i, "tunnel_1.obj");
            agk::SetObjectImage(i, 1, 0);
            agk::SetObjectFogMode(i, 1);
            agk::CreateObjectBox(i + 10, 20, 20, 1);
            agk::SetObjectImage(i + 10, 2, 0);
            agk::SetObjectFogMode(i + 10, 1);
            agk::SetObjectCollisionMode(i + 10, 1);
        }
    }

    agk::SetFogMode(1);
    agk::SetFogColor(255, 255, 0);
    agk::SetFogRange(250, 400);
    agk::SetSunActive(1);
    agk::SetAmbientColor(150, 150, 150);
    agk::SetTextDefaultFontImage(agk::LoadImage("font_002.png"));
    {
        int i;
        for (i = 1; i <= 4; i += 1)
        {
            agk::CreateText(i, "");
            agk::SetTextSize(i, 50);
            agk::SetTextColor(i, 0, 0, 0, 255);
        }
    }

    agk::SetTextPosition(1, 640, 300);
    agk::SetTextAlignment(1, 1);
    agk::SetTextPosition(2, 640, 380);
    agk::SetTextAlignment(2, 1);
    agk::SetTextPosition(3, screen_left + 5, screen_top + 5);
    agk::SetTextString(3, agk::Str(score));
    agk::SetTextPosition(4, screen_right - 5, screen_top + 5);
    agk::SetTextAlignment(4, 2);
    agk::SetTextString(4, agk::Str(high_score));
    agk::LoadMusicOGG(1, "music.ogg");
    agk::PlayMusicOGG(1, 1);
}


void _initiate ()
{
    {
        int i;
        for (i = 1; i <= 5; i += 1)
        {
            agk::SetObjectPosition(i, 0, 0, (i - 1) * 100);
            agk::SetObjectRotation(i, 0, 0, 0);
            agk::SetObjectPosition(i + 10, 0, 0, agk::GetObjectZ(i));
            agk::SetObjectRotation(i + 10, 0, 0, agk::GetObjectAngleZ(i));
            agk::RotateObjectLocalZ(i + 10, agk::Random(0, 7) * 45);
            agk::MoveObjectLocalY(i + 10, 10);
        }
    }

    agk::SetCameraPosition(1, 0, -8, 0);
    agk::SetCameraRotation(1, 0, 0, 0);
    game_state = 1;
}


void _start ()
{
    if (input_method == 1 )
    {
        agk::SetTextString(1, "left and right key to move");
        agk::SetTextString(2, "press left or right key to start");
        if (agk::GetRawKeyState(37) == 1 || agk::GetRawKeyState(39) == 1 )
        {
            agk::PlayMusicOGG(1, 1);
            game_state = 2;
        }
        goto L1004;
    }
    if (input_method == 2 )
    {
        agk::SetTextString(1, "touch left or right of screen to move");
        agk::SetTextString(2, "touch left or right of screen to start");
        int     touch = 0;
        touch = agk::GetRawFirstTouchEvent( 1);
        int     touch_x = agk::GetRawTouchCurrentX(touch);
        if (touch > 0 )
        {
            if (touch_x < screen_left + 300 || touch_x > screen_right - 300 )
            {
                game_state = 2;
            }
        }
        goto L1004;
    }
    if (input_method == 3 )
    {
        agk::SetTextString(1, "left joystick to move");
        agk::SetTextString(2, "move left joystick to start");
        if (fabs(agk::GetRawJoystickX(1)) > 0.1 )
        {
            game_state = 2;
        }
    }
L1004:
    ;
    if (game_state == 2 )
    {
        agk::SetTextVisible(1, 0);
        agk::SetTextVisible(2, 0);
        score = 0;
        speed = 0.1;
    }
}


void _play_game ()
{
    score += (10);
    float   rotate;
    if (input_method == 1 )
    {
        rotate = ( agk::GetRawKeyState( 37) - agk::GetRawKeyState( 39)) * turn_speed;
        goto L1005;
    }
    if (input_method == 2 )
    {
        rotate = 0.0;
        int     touch = 0;
        touch = agk::GetRawFirstTouchEvent( 1);
        int     touch_x = agk::GetRawTouchCurrentX(touch);
        if (touch > 0 )
        {
            if (touch_x < screen_left + 300 )
            {
                rotate = turn_speed;
            }
            if (touch_x > screen_right - 300 )
            {
                rotate = - 1 * turn_speed;
            }
        }
        goto L1005;
    }
    if (input_method == 3 )
    {
        rotate = - 1 * agk::GetRawJoystickX( 1) * turn_speed;
    }
L1005:
    ;
    speed +=   acceleration;
    if (speed > max_speed )
    {
        speed = max_speed;
    }
    {
        int i;
        for (i = 1; i <= 5; i += 1)
        {
            agk::MoveObjectLocalZ(i, -speed);
            agk::RotateObjectLocalZ(i, rotate);
            float   z_pos = agk::GetObjectZ(i);
            agk::SetObjectPosition(i + 10, 0, 0, z_pos);
            agk::RotateObjectLocalZ(i + 10, rotate);
            agk::MoveObjectLocalY(i + 10, 10.0);
            if (z_pos < -100.0 )
            {
                agk::SetObjectPosition(i, 0, 0, z_pos + 500);
                agk::SetObjectPosition(i + 10, 0, 0, z_pos + 500);
                agk::RotateObjectLocalZ(i + 10, agk::Random(0, 7) * 45);
                agk::MoveObjectLocalY(i + 10, 10.0);
            }
        }
    }

    agk::SetTextString(3, agk::Str(score));
    if (agk::ObjectSphereCast(0, 0, -8, 0, 0, -8, max_speed, 0.25) > 0 )
    {
        game_state = 3;
        if (score > high_score )
        {
            high_score = score;
            agk::SetTextString(1, "!! new high score !!");
            agk::SetTextString(4, agk::Str(high_score));
        }
        else
        {
            agk::SetTextString(1, "! crashed !");
        }
    }
}


void _game_over ()
{
    agk::SetTextVisible(1, 1);
    agk::SetTextVisible(2, 1);
    if (input_method == 1 )
    {
        agk::SetTextString(2, "press space to replay");
        if (agk::GetRawKeyPressed(32) == 1 )
        {
            game_state = 0;
        }
        goto L1007;
    }
    if (input_method == 2 )
    {
        agk::SetTextString(2, "touch centre of screen to replay");
        int     touch = 0;
        touch = agk::GetRawFirstTouchEvent( 1);
        int     touch_x = agk::GetRawTouchCurrentX(touch);
        if (touch > 0 )
        {
            if (touch_x > screen_left + 400 && touch_x < screen_right - 400 )
            {
                game_state = 0;
            }
        }
        goto L1007;
    }
    if (input_method == 3 )
    {
        agk::SetTextString(2, "press start to replay");
        if (agk::GetRawJoystickButtonPressed(1, 8) == 1 )
        {
            game_state = 0;
        }
    }
L1007:
    ;
    {
        int i;
        for (i = 1; i <= 5; i += 1)
        {
            agk::MoveObjectLocalZ(i, 0.5);
            agk::RotateObjectLocalZ(i, 1.0);
            float   z_pos = agk::GetObjectZ(i);
            agk::SetObjectPosition(i + 10, 0, 0, z_pos);
            agk::RotateObjectLocalZ(i + 10, 1.0);
            agk::MoveObjectLocalY(i + 10, 10.0);
            if (z_pos > 400.0 )
            {
                agk::SetObjectPosition(i, 0, 0, z_pos - 500);
                agk::SetObjectPosition(i + 10, 0, 0, z_pos - 500);
                agk::MoveObjectLocalY(i + 10, 10.0);
            }
        }
    }

}



