- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# main.c

Go to the documentation of this file.

    00001
    00005 //    /**
    00006 //      *@defgroup main main.c
    00007 //      *The entry point of the program and contains the main_loop function
    00008 //      *@{
    00009 //      */
    00010
    00011 /*----------------------------------------------------------------------------------------------------------*/
    00012
    00013 // Headers
    00014 #ifndef _ALLEGRO5_
    00015 #define _ALLEGRO5_
    00016 #include <allegro5/allegro5.h>
    00017 #endif // _ALLEGRO5_
    00018
    00019 #ifndef _ALLEGRO5FONT_
    00020 #define _ALLEGRO5FONT_
    00021 #include <allegro5/allegro_font.h>
    00022 #endif // _ALLEGRO5FONT_
    00023
    00024 #ifndef _ALLEGRO5TTF_
    00025 #define _ALLEGRO5TTF_
    00026 #include <allegro5/allegro_ttf.h>
    00027 #endif // _ALLEGRO5TTF_
    00028
    00029 #ifndef _ALLEGRO5IMAGE_
    00030 #define _ALLEGRO5IMAGE_
    00031 #include <allegro5/allegro_image.h>
    00032 #endif // _ALLEGRO5IMAGE_
    00033
    00034 #ifndef _ALLEGRO5PRIMITIVES_
    00035 #define _ALLEGRO5PRIMITIVES_
    00036 #include <allegro5/allegro_primitives.h>
    00037 #endif // _ALLEGRO5PRIMITIVES_
    00038
    00039 #ifndef _ALLEGRO5NATIVEDIALOG_
    00040 #define _ALLEGRO5NATIVEDIALOG_
    00041 #include <allegro5/allegro_native_dialog.h>
    00042 #endif // _ALLEGRO5NATIVEDIALOG_
    00043
    00044 #ifndef _ALLEGROOPENGL_
    00045 #define _ALLEGROOPENGL_
    00046 #include <allegro5/allegro_opengl.h>
    00047 #endif // _ALLEGROOPENGL_
    00048
    00049 #ifndef _ALLEGROPHYSFS_
    00050 #define _ALLEGROPHYSFS_
    00051 #include <allegro5/allegro_physfs.h>
    00052 #endif // _ALLEGROPHYSFS_
    00053
    00054 #ifndef _PHYSFS_
    00055 #define _PHYSFS
    00056 #include <physfs.h>
    00057 #endif // _PHYSFS_
    00058
    00059 #ifndef _CHIPMUNK_
    00060 #define _CHIPMUNK_
    00061 #include "chipmunk.h"
    00062 #endif // _CHIPMUNK_
    00063
    00064 #ifndef _STDIO_
    00065 #define _STDIO_
    00066 #include <stdio.h>
    00067 #endif // _STDIO_
    00068
    00069 #ifndef _COMMONS_
    00070 #define _COMMONS_
    00071 #include "../include/commons.h"
    00072 #endif // _COMMONS_
    00073
    00074 #ifndef _IMAGESCALE_
    00075 #define _IMAGESCALE_
    00076 #include "../include/imagescale.h"
    00077 #endif // _IMAGESCALE_
    00078
    00079 #ifndef _PROGRESSBAR_
    00080 #define _PROGRESSBAR_
    00081 #include "../include/progressbar.h"
    00082 #endif // _PROGRESSBAR_
    00083
    00084 #ifndef _INITS_
    00085 #define _INITS_
    00086 #include "../include/inits.h"
    00087 #endif // _INITS_
    00088
    00089 #ifndef _KEYBOARD_
    00090 #define _KEYBOARD_
    00091 #include "../include/keyboard.h"
    00092 #endif // _KEYBOARD_
    00093
    00094 #ifndef _MOUSE_
    00095 #define _MOUSE_
    00096 #include "../include/mouse.h"
    00097 #endif // _MOUSE_
    00098
    00099 #ifndef _BUTTONS_
    00100 #define _BUTTONS_
    00101 #include "../include/buttons.h"
    00102 #endif // _BUTTONS_
    00103
    00104 #ifndef _EVENTHANDLER_
    00105 #define _EVENTHANDLER_
    00106 #include "../include/eventhandler.h"
    00107 #endif // _EVENTHANDLER_
    00108
    00109 #ifndef _SPRITES_
    00110 #define _SPRITES_
    00111 #include "../include/sprites.h"
    00112 #endif // _SPRITES_
    00113
    00114 #ifndef _MAINGAME_
    00115 #define _MAINGAME_
    00116 #include "../include/maingame.h"
    00117 #endif // _MAINGAME_
    00118
    00119 #ifndef _RENDER_
    00120 #define _RENDER_
    00121 #include "../include/render.h"
    00122 #endif // _RENDER_
    00123
    00124 #ifndef _PHYSCOL_
    00125 #define _PHYSCOL_
    00126 #include "../include/physcol.h"
    00127 #endif // _PHYSCOL_
    00128
    00129 #ifndef _OPTIONS_
    00130 #define _OPTIONS_
    00131 #include "../include/options.h"
    00132 #endif // _OPTIONS_
    00133
    00134 #ifndef _MAIN_
    00135 #define _MAIN_
    00136 #include "../include/main.h"
    00137 #endif // _MAIN_
    00138
    00139 /*----------------------------------------------------------------------------------------------------------*/
    00140
    00141 static GDATAPTR data;
    00142
    00143 /*----------------------------------------------------------------------------------------------------------*/
    00144
    00145 // TODO: remove init_core_sprites, put instead ini_base_images.
    00146 // Game entry point, calls all initialization functions before calling main_loop
    00147 int main(int argc, char** argv)
    00148 {
    00149     // Declare main struct containing the important data
    00150     data = (GDATAPTR)malloc(sizeof(GDATA));
    00151
    00152     // Initialize Allegro 5 and addon routines
    00153     al_init();
    00154     al_init_image_addon();
    00155     al_init_font_addon();
    00156     al_init_ttf_addon();
    00157     cpInitChipmunk();
    00158     PHYSFS_init(argv[0]);
    00159
    00160     // Initialize the core game data structure
    00161     if(!data_init()) exit(EXIT_FAILURE);
    00162
    00163     // Creates a player sprite
    00164     if(!init_core_sprites()) exit(EXIT_FAILURE);
    00165
    00166     // Initializes the buttons
    00167     if(!init_buttons()) exit(EXIT_FAILURE);
    00168
    00169     // Initializes the physics and collision detection
    00170     if(!init_chipmunk()) exit(EXIT_FAILURE);
    00171
    00172     // Create the progress bar
    00173     loader();
    00174
    00175     // Enters the main loop, where everything happens
    00176     main_loop();
    00177
    00178     // Cleanup before exit
    00179     cleanup(data);
    00180
    00181     // Return 0 before exit
    00182     return 0;
    00183 }
    00184
    00185 /*----------------------------------------------------------------------------------------------------------*/
    00186
    00187 // Initializes the the GDATA struct
    00188 _Bool data_init(void)
    00189 {
    00190     // Create a window to display things on: 800x600 pixels
    00191     al_set_new_display_flags(ALLEGRO_RESIZABLE | ALLEGRO_OPENGL);
    00192     al_set_new_display_refresh_rate(60);
    00193     data->display = al_create_display(res_width, res_height);
    00194     if(data->display == NULL)
    00195     {
    00196         al_show_native_message_box("Error!", "Display Error:", "Failed to create window!", NULL,
    00197                                    ALLEGRO_MESSAGEBOX_ERROR);
    00198         return false;
    00199     }
    00200
    00201     // Sets the physfs file interface to be used for loading files
    00202     al_set_physfs_file_interface();
    00203     PHYSFS_addToSearchPath("images", 1);
    00204     PHYSFS_addToSearchPath("fonts", 1);
    00205     PHYSFS_addToSearchPath("buttons", 1);
    00206
    00207     // Well, looks like we're gonna have to draw our own mouse *SIGH*
    00208     al_hide_mouse_cursor();
    00209     data->cursor = al_load_png("cursor_darkgrey.png");
    00210     if(data->cursor == NULL)
    00211     {
    00212         al_show_native_message_box("Error!", "Cursor Error:", "Failed to locate cursor!", NULL,
    00213                                    ALLEGRO_MESSAGEBOX_ERROR);
    00214         return false;
    00215     }
    00216
    00217     // Set the title of the window
    00218     al_set_window_title("SpeedRun!");
    00219
    00220     // Sets the window's icon
    00221     data->icon = al_load_png("speedrundisplayicon.png");
    00222     if(data->icon == NULL)
    00223     {
    00224         al_show_native_message_box("Error!", "Icon Error:", "Failed to locate icon!", NULL,
    00225                                    ALLEGRO_MESSAGEBOX_ERROR);
    00226         return false;
    00227     }
    00228     al_set_display_icon(data->icon);
    00229
    00230     // Load a font
    00231     data->font = al_load_ttf_font("times.ttf", 25, 0);
    00232     data->b_font = al_load_ttf_font("impact.ttf", 25, 0);
    00233     if(data->font == NULL || data->b_font == NULL)
    00234     {
    00235         al_show_native_message_box("Error!", "Font Error:", "Failed to load font!", NULL,
    00236                                    ALLEGRO_MESSAGEBOX_ERROR);
    00237         return false;
    00238     }
    00239
    00240     // Make and set a color to draw with
    00241     data->text_color = al_map_rgba(80, 112, 255, 255);
    00242
    00243     // Set background color
    00244     data->background_color = al_map_rgba(0, 0, 0, 0);
    00245
    00246     // Install the keyboard handler
    00247     if(!al_install_keyboard())
    00248     {
    00249         al_show_native_message_box("Error!", "Keyboard Error:", "Failed to install keyboard handler!", NULL,
    00250                                    ALLEGRO_MESSAGEBOX_ERROR);
    00251         return false;
    00252     }
    00253
    00254     // Install the mouse handler
    00255     if(!al_install_mouse())
    00256     {
    00257         al_show_native_message_box("Error!", "Mouse Error:", "Failed to install mouse handler!", NULL,
    00258                                    ALLEGRO_MESSAGEBOX_ERROR);
    00259         return false;
    00260     }
    00261
    00262     // Detect and set refresh rate
    00263     int refresh_rate = al_get_display_refresh_rate();
    00264     if(refresh_rate == 0)
    00265     {
    00266         refresh_rate = 60;
    00267     }
    00268
    00269     // Install timer with refresh rate
    00270     data->timer = al_install_timer(1.0/refresh_rate);
    00271     if(data->timer == NULL)
    00272     {
    00273         al_show_native_message_box("Error!", "Timer Error:", "Failed to initialize timer!", NULL,
    00274                                    ALLEGRO_MESSAGEBOX_ERROR);
    00275         return 1;
    00276     }
    00277     al_start_timer(data->timer);
    00278
    00279
    00280     // Start the event queues to handle keyboard input, mouse input, display input and timer input
    00281     data->queue = al_create_event_queue();
    00282     al_register_event_source(data->queue, (ALLEGRO_EVENT_SOURCE*)data->timer);
    00283     data->queue2 = al_create_event_queue();
    00284     al_register_event_source(data->queue2, al_get_keyboard_event_source());
    00285     al_register_event_source(data->queue2, (ALLEGRO_EVENT_SOURCE*)data->display);
    00286     al_register_event_source(data->queue2, al_get_mouse_event_source());
    00287
    00288     // Set the quit and gamestarted flags to false initially
    00289     data->exit = false;
    00290     data->gamestarted = false;
    00291     data->options = false;
    00292     data->highscores = false;
    00293     data->howtoplay = false;
    00294
    00295
    00296     return true;
    00297 }
    00298
    00299 /*----------------------------------------------------------------------------------------------------------*/
    00300
    00301 // The main Allegro loop, all input handling, animation and drawing is done here
    00302 _Bool main_loop(void)
    00303 {
    00304     // Flag for drawing
    00305     _Bool needredraw = true;
    00306     // Declare primitive data types
    00307     float old_time = 0.0, current_time = 0, dt = 0;
    00308
    00309     while(!data->exit)
    00310     {
    00311         if(needredraw && al_event_queue_is_empty(data->queue) && al_event_queue_is_empty(data->queue2))
    00312         {
    00313             // Clear, draw, flip
    00314             al_clear_to_color(data->background_color);
    00315             render();
    00316             if(get_fps_status())
    00317                 al_draw_textf(data->font, 0, res_height-30, 0, "fps: %.2f", 1/dt);
    00318             al_flip_display();
    00319             needredraw = false;
    00320         }
    00321
    00322         // Block until an event enters the queue
    00323         al_wait_for_event(data->queue, &(data->event));
    00324
    00325         while(!al_event_queue_is_empty(data->queue2))
    00326         {
    00327             al_get_next_event(data->queue2, &(data->event2));
    00328             switch(data->event2.type)
    00329             {
    00330                 case ALLEGRO_EVENT_DISPLAY_CLOSE:
    00331                 {
    00332                     // If x button is pressed on window
    00333                     data->exit = true;
    00334                     data->gamestarted = false;
    00335                 }
    00336                 break;
    00337                 case ALLEGRO_EVENT_DISPLAY_RESIZE:
    00338                 {
    00339                     al_acknowledge_resize(data->event2.display.source);
    00340                     scale(res_width, res_height);
    00341                 }
    00342                 break;
    00343                 case ALLEGRO_EVENT_MOUSE_AXES:
    00344                 {
    00345                     // Stores the mouse's new position and change in position
    00346                     mouseaxes(&(data->event2.mouse));
    00347                 }
    00348                 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
    00349                 {
    00350                     // Stores the mouse button pressed
    00351                     mousedown(&(data->event2.mouse));
    00352                 }
    00353                 break;
    00354                 case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
    00355                 {
    00356                     // Stores the mouse button released
    00357                     mouseup(&(data->event2.mouse));
    00358                 }
    00359                 break;
    00360                 case ALLEGRO_EVENT_KEY_DOWN:
    00361                 {
    00362                     // Stores keydown keycode into keycode array for processing
    00363                     keydown(&(data->event2.keyboard));
    00364                 }
    00365                 break;
    00366                 case ALLEGRO_EVENT_KEY_UP:
    00367                 {
    00368                     // Stores keycode into keycode array for processing
    00369                     keyup(&(data->event2.keyboard));
    00370                 }
    00371                 break;
    00372                 case ALLEGRO_EVENT_KEY_REPEAT:
    00373                 {
    00374                     // Notifies keyboardhandler of repeated events of either keyup or keydown
    00375                     keyrepeat(&(data->event2.keyboard));
    00376                 }
    00377                 break;
    00378                 default:
    00379                 break;
    00380             }
    00381         }
    00382
    00383         switch (data->event.type)
    00384         {
    00385             case ALLEGRO_EVENT_TIMER:
    00386             {
    00387                 // Determine the change in time between frames, in seconds
    00388                                 current_time = al_current_time();
    00389                                 dt = current_time-old_time;
    00390
    00391                                 // If the computer lags for some reason, don't penalize the player
    00392                                 // Cap dt at 0.5 seconds
    00393                                 if(dt > 0.25)
    00394                                 {
    00395                     dt = 0.25;
    00396                                 }
    00397
    00398                                 // Handle Mouse and Keyboard events and Button Events
    00399                                 buttoncheck(&buttonhandler, data);
    00400                                 keycheck(&keyhandler, data);
    00401                                 mousecheck(&mousehandler, data);
    00402                                 keyupdate();
    00403                 mouseupdate();
    00404
    00405                 // Check if data->quit has been set before updating and drawing
    00406                 if(data->exit) break;
    00407
    00408                 // Update the game, always
    00409                 update();
    00410
    00411                 // Skip drawing frames if computer lags
    00412                 if(current_time - data->event.timer.timestamp <= 1.0/al_get_display_refresh_rate())
    00413                 {
    00414                     needredraw = true;
    00415                 }
    00416
    00417                                 // Make the time at this frame the old time, for the next frame
    00418                                 old_time = current_time;
    00419             }
    00420             break;
    00421             default:
    00422             break;
    00423         }
    00424     }
    00425     return true;
    00426 }
    00427
    00428 /*----------------------------------------------------------------------------------------------------------*/
    00429
    00430 // Returns a pointer to the main game struct, GDATA *data
    00431 GDATAPTR get_game_data(void)
    00432 {
    00433     return data;
    00434 }
    00435
    00436 /*----------------------------------------------------------------------------------------------------------*/
    00437
    00438 void loader(void)
    00439 {
    00440     ALLEGRO_BITMAP *bg = al_load_png("background_day.png");
    00441     PROGRESSBARPTR pb1 = create_new_progress_bar("pb1", 243, 275, 300, 50, 10, 10, al_map_rgba(0, 0, 0, 127),
    00442                                                  al_map_rgba(0, 0, 255, 127), 5, true);
    00443     while(pb1->bar_width < pb1->width)
    00444     {
    00445         pb1->counter++;
    00446         al_acknowledge_resize(get_game_data()->display);
    00447         scale(res_width, res_height);
    00448         al_clear_to_color(data->background_color);
    00449         al_draw_bitmap(bg, 0, 0, 0);
    00450         render_progress_bars();
    00451         al_flip_display();
    00452         if(pb1->counter == 3)
    00453         {
    00454             pb1->bar_width += pb1->increment;
    00455             pb1->counter = 0;
    00456         }
    00457     }
    00458     al_destroy_bitmap(bg);
    00459     remove_element_from_progress_bar_list("pb1");
    00460 }
    00461
    00462 /*----------------------------------------------------------------------------------------------------------*/
    00463
    00464 void cleanup(GDATAPTR game)
    00465 {
    00466     empty_render_queue(get_first_element_from_render_queue());
    00467     empty_sprite_list(get_first_element_from_sprite_list());
    00468     empty_base_image_list(get_first_element_from_base_image_list());
    00469     empty_button_list(get_first_element_from_button_list());
    00470     empty_button_image_list(get_first_element_from_button_image_list());
    00471     empty_progress_bar_list(get_first_element_from_progress_bar_list());
    00472     al_destroy_event_queue(game->queue);
    00473     al_uninstall_timer(game->timer);
    00474     al_destroy_font(game->font);
    00475     al_destroy_font(game->b_font);
    00476     al_destroy_bitmap(game->icon);
    00477     al_destroy_bitmap(game->cursor);
    00478     PHYSFS_deinit();
    00479 }
    00480
    00481 /*----------------------------------------------------------------------------------------------------------*/
    00482
    00483 //    /**
    00484 //      *@}
    00485 //      */