SHARE
TWEET

Untitled

a guest Dec 14th, 2019 123 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // [main.c]
  2. // this template is provided for the 2D shooter game.
  3.  
  4. #define _CRT_SECURE_NO_DEPRECATE
  5. #include <stdio.h>
  6. #include <allegro5/allegro.h>
  7. #include <allegro5/allegro_primitives.h>
  8. #include <allegro5/allegro_image.h>
  9. #include <allegro5/allegro_font.h>
  10. #include <allegro5/allegro_ttf.h>
  11. #include <allegro5/allegro_audio.h>
  12. #include <allegro5/allegro_acodec.h>
  13. #include <math.h>
  14.  
  15. // If defined, logs will be shown on console and written to file.
  16. // If commented out, logs will not be shown nor be saved.
  17. #define LOG_ENABLED
  18.  
  19. /* Constants. */
  20.  
  21. // Frame rate (frame per second)
  22. const int FPS = 60;
  23. // Display (screen) width.
  24. const int SCREEN_W = 800;
  25. // Display (screen) height.
  26. const int SCREEN_H = 600;
  27. // At most 4 audios can be played at a time.
  28. const int RESERVE_SAMPLES = 4;
  29. // Same as:
  30. // const int SCENE_MENU = 1;
  31. // const int SCENE_START = 2;
  32. enum {
  33.     SCENE_MENU = 1,
  34.     SCENE_START = 2,
  35.     SCENE_SETTING = 3
  36.     // [HACKATHON 3-7]
  37.     // TODO: Declare a new scene id.
  38.     // , SCENE_SETTINGS = 3
  39. };
  40.  
  41. /* Input states */
  42.  
  43. // The active scene id.
  44. int active_scene;
  45. // Keyboard state, whether the key is down or not.
  46. bool key_state[ALLEGRO_KEY_MAX];
  47. // Mouse state, whether the key is down or not.
  48. // 1 is for left, 2 is for right, 3 is for middle.
  49. bool *mouse_state;
  50. // Mouse position.
  51. int mouse_x, mouse_y;
  52. // TODO: More variables to store input states such as joysticks, ...
  53.  
  54. /* Variables for allegro basic routines. */
  55.  
  56. ALLEGRO_DISPLAY* game_display;
  57. ALLEGRO_EVENT_QUEUE* game_event_queue;
  58. ALLEGRO_TIMER* game_update_timer;
  59.  
  60. /* Shared resources*/
  61.  
  62. ALLEGRO_FONT* font_pirulen_32;
  63. ALLEGRO_FONT* font_pirulen_24;
  64. // TODO: More shared resources or data that needed to be accessed
  65. // across different scenes.
  66.  
  67. /* Menu Scene resources*/
  68. ALLEGRO_BITMAP* main_img_background;
  69. ALLEGRO_BITMAP* setting_img;
  70. ALLEGRO_BITMAP* setting_img2;
  71. // [HACKATHON 3-1]
  72. // TODO: Declare 2 variables for storing settings images.
  73. // Uncomment and fill in the code below.
  74. //??? img_settings;
  75. //??? img_settings2;
  76. ALLEGRO_SAMPLE* main_bgm;
  77. ALLEGRO_SAMPLE_ID main_bgm_id;
  78.  
  79. /* Start Scene resources*/
  80. ALLEGRO_BITMAP* start_img_background;
  81. ALLEGRO_BITMAP* start_img_plane;
  82. ALLEGRO_BITMAP* start_img_enemy;
  83. ALLEGRO_BITMAP* img_bullet;
  84. ALLEGRO_SAMPLE* start_bgm;
  85. ALLEGRO_SAMPLE_ID start_bgm_id;
  86. // [HACKATHON 2-1]
  87. // TODO: Declare a variable to store your bullet's image.
  88. // Uncomment and fill in the code below.
  89. //??? img_bullet;
  90.  
  91. typedef struct {
  92.     // The center coordinate of the image.
  93.     float x, y;
  94.     // The width and height of the object.
  95.     float w, h;
  96.     // The velocity in x, y axes.
  97.     float vx, vy;
  98.     // Should we draw this object on the screen.
  99.     bool hidden;
  100.     // The pointer to the object¡¦s image.
  101.     ALLEGRO_BITMAP* img;
  102. } MovableObject;
  103. void draw_movable_object(MovableObject obj);
  104. #define MAX_ENEMY 3
  105. // [HACKATHON 2-2]
  106. // TODO: Declare the max bullet count that will show on screen.
  107. // You can try max 4 bullets here and see if you needed more.
  108. // Uncomment and fill in the code below.
  109. #define MAX_BULLET 5
  110. MovableObject plane;
  111. MovableObject enemies[MAX_ENEMY];
  112. MovableObject bullets[MAX_BULLET];
  113. // [HACKATHON 2-3]
  114. // TODO: Declare an array to store bullets with size of max bullet count.
  115. // Uncomment and fill in the code below.
  116. //??? bullets[???];
  117. // [HACKATHON 2-4]
  118. // TODO: Set up bullet shooting cool-down variables.
  119. // 1) Declare your shooting cool-down time as constant. (0.2f will be nice)
  120. // 2) Declare your last shoot timestamp.
  121. // Uncomment and fill in the code below.
  122. const float MAX_COOLDOWN = 0.2f;
  123. double last_shoot_timestamp;
  124.  
  125. /* Declare function prototypes. */
  126.  
  127. // Initialize allegro5 library
  128. void allegro5_init(void);
  129. // Initialize variables and resources.
  130. // Allows the game to perform any initialization it needs before
  131. // starting to run.
  132. void game_init(void);
  133. // Process events inside the event queue using an infinity loop.
  134. void game_start_event_loop(void);
  135. // Run game logic such as updating the world, checking for collision,
  136. // switching scenes and so on.
  137. // This is called when the game should update its logic.
  138. void game_update(void);
  139. // Draw to display.
  140. // This is called when the game should draw itself.
  141. void game_draw(void);
  142. // Release resources.
  143. // Free the pointers we allocated.
  144. void game_destroy(void);
  145. // Function to change from one scene to another.
  146. void game_change_scene(int next_scene);
  147. // Load resized bitmap and check if failed.
  148. ALLEGRO_BITMAP *load_bitmap_resized(const char *filename, int w, int h);
  149. // [HACKATHON 3-2]
  150. // TODO: Declare a function.
  151. // Determines whether the point (px, py) is in rect (x, y, w, h).
  152. // Uncomment the code below.
  153. bool pnt_in_rect(int px, int py, int x, int y, int w, int h);
  154.  
  155. /* Event callbacks. */
  156. void on_key_down(int keycode);
  157. void on_mouse_down(int btn, int x, int y);
  158.  
  159. /* Declare function prototypes for debugging. */
  160.  
  161. // Display error message and exit the program, used like 'printf'.
  162. // Write formatted output to stdout and file from the format string.
  163. // If the program crashes unexpectedly, you can inspect "log.txt" for
  164. // further information.
  165. void game_abort(const char* format, ...);
  166. // Log events for later debugging, used like 'printf'.
  167. // Write formatted output to stdout and file from the format string.
  168. // You can inspect "log.txt" for logs in the last run.
  169. void game_log(const char* format, ...);
  170. // Log using va_list.
  171. void game_vlog(const char* format, va_list arg);
  172.  
  173. int main(int argc, char** argv) {
  174.     // Set random seed for better random outcome.
  175.     srand(time(NULL));
  176.     allegro5_init();
  177.     game_log("Allegro5 initialized");
  178.     game_log("Game begin");
  179.     // Initialize game variables.
  180.     game_init();
  181.     game_log("Game initialized");
  182.     // Draw the first frame.
  183.     game_draw();
  184.     game_log("Game start event loop");
  185.     // This call blocks until the game is finished.
  186.     game_start_event_loop();
  187.     game_log("Game end");
  188.     game_destroy();
  189.     return 0;
  190. }
  191.  
  192. void allegro5_init(void) {
  193.     if (!al_init())
  194.         game_abort("failed to initialize allegro");
  195.  
  196.     // Initialize add-ons.
  197.     if (!al_init_primitives_addon())
  198.         game_abort("failed to initialize primitives add-on");
  199.     if (!al_init_font_addon())
  200.         game_abort("failed to initialize font add-on");
  201.     if (!al_init_ttf_addon())
  202.         game_abort("failed to initialize ttf add-on");
  203.     if (!al_init_image_addon())
  204.         game_abort("failed to initialize image add-on");
  205.     if (!al_install_audio())
  206.         game_abort("failed to initialize audio add-on");
  207.     if (!al_init_acodec_addon())
  208.         game_abort("failed to initialize audio codec add-on");
  209.     if (!al_reserve_samples(RESERVE_SAMPLES))
  210.         game_abort("failed to reserve samples");
  211.     if (!al_install_keyboard())
  212.         game_abort("failed to install keyboard");
  213.     if (!al_install_mouse())
  214.         game_abort("failed to install mouse");
  215.     // TODO: Initialize other addons such as video, ...
  216.  
  217.     // Setup game display.
  218.     game_display = al_create_display(SCREEN_W, SCREEN_H);
  219.     if (!game_display)
  220.         game_abort("failed to create display");
  221.     al_set_window_title(game_display, "I2P(I)_2019 Final Project <student_id>");
  222.  
  223.     // Setup update timer.
  224.     game_update_timer = al_create_timer(1.0f / FPS);
  225.     if (!game_update_timer)
  226.         game_abort("failed to create timer");
  227.  
  228.     // Setup event queue.
  229.     game_event_queue = al_create_event_queue();
  230.     if (!game_event_queue)
  231.         game_abort("failed to create event queue");
  232.  
  233.     // Malloc mouse buttons state according to button counts.
  234.     const unsigned m_buttons = al_get_mouse_num_buttons();
  235.     game_log("There are total %u supported mouse buttons", m_buttons);
  236.     // mouse_state[0] will not be used.
  237.     mouse_state = malloc((m_buttons + 1) * sizeof(bool));
  238.     memset(mouse_state, false, (m_buttons + 1) * sizeof(bool));
  239.  
  240.     // Register display, timer, keyboard, mouse events to the event queue.
  241.     al_register_event_source(game_event_queue, al_get_display_event_source(game_display));
  242.     al_register_event_source(game_event_queue, al_get_timer_event_source(game_update_timer));
  243.     al_register_event_source(game_event_queue, al_get_keyboard_event_source());
  244.     al_register_event_source(game_event_queue, al_get_mouse_event_source());
  245.     // TODO: Register other event sources such as timer, video, ...
  246.  
  247.     // Start the timer to update and draw the game.
  248.     al_start_timer(game_update_timer);
  249. }
  250.  
  251. void game_init(void) {
  252.     /* Shared resources*/
  253.     font_pirulen_32 = al_load_font("pirulen.ttf", 32, 0);
  254.     if (!font_pirulen_32)
  255.         game_abort("failed to load font: pirulen.ttf with size 32");
  256.  
  257.     font_pirulen_24 = al_load_font("pirulen.ttf", 24, 0);
  258.     if (!font_pirulen_24)
  259.         game_abort("failed to load font: pirulen.ttf with size 24");
  260.  
  261.     /* Menu Scene resources*/
  262.     main_img_background = load_bitmap_resized("main-bg.jpg", SCREEN_W, SCREEN_H);
  263.  
  264.     main_bgm = al_load_sample("S31-Night Prowler.ogg");
  265.     if (!main_bgm)
  266.         game_abort("failed to load audio: S31-Night Prowler.ogg");
  267.     setting_img = al_load_bitmap("settings.png");
  268.     if(!setting_img)
  269.         game_abort("failed to load setting img");
  270.     setting_img2 = al_load_bitmap("settings2.png");
  271.     if(!setting_img)
  272.         game_abort("failed to load setting img2");
  273.     // [HACKATHON 3-4]
  274.     // TODO: Load settings images.
  275.     // Don't forget to check their return values.
  276.     // Uncomment and fill in the code below.
  277.     //img_settings = ???("settings.png");
  278.     //if (!???)
  279.     //  game_abort("failed to load image: settings.png");
  280.     //img_settings2 = ???("settings2.png");
  281.     //if (!???)
  282.     //  game_abort("failed to load image: settings2.png");
  283.  
  284.     /* Start Scene resources*/
  285.     start_img_background = load_bitmap_resized("start-bg.jpg", SCREEN_W, SCREEN_H);
  286.  
  287.     start_img_plane = al_load_bitmap("plane.png");
  288.     if (!start_img_plane)
  289.         game_abort("failed to load image: plane.png");
  290.  
  291.     start_img_enemy = al_load_bitmap("smallfighter0006.png");
  292.     if (!start_img_enemy)
  293.         game_abort("failed to load image: smallfighter0006.png");
  294.  
  295.     start_bgm = al_load_sample("mythica.ogg");
  296.     if (!start_bgm)
  297.         game_abort("failed to load audio: mythica.ogg");
  298.     img_bullet = al_load_bitmap("image12.png");
  299.     if (!img_bullet)
  300.         game_abort("failed to load bullet img");
  301.  
  302.     // [HACKATHON 2-5]
  303.     // TODO: Initialize bullets.
  304.     // 1) Search for a bullet image online and put it in your project.
  305.     //    You can use the image we provided.
  306.     // 2) Load it in by 'al_load_bitmap' or 'load_bitmap_resized'.
  307.     // 3) If you use 'al_load_bitmap', don't forget to check its return value.
  308.     // Uncomment and fill in the code below.
  309.     //img_bullet = ???("image12.png");
  310.     //if (!img_bullet)
  311.     //  game_abort("failed to load image: image12.png");
  312.  
  313.     // Change to first scene.
  314.     game_change_scene(SCENE_MENU);
  315. }
  316.  
  317. void game_start_event_loop(void) {
  318.     bool done = false;
  319.     ALLEGRO_EVENT event;
  320.     int redraws = 0;
  321.     while (!done) {
  322.         al_wait_for_event(game_event_queue, &event);
  323.         if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
  324.             // Event for clicking the window close button.
  325.             game_log("Window close button clicked");
  326.             done = true;
  327.         } else if (event.type == ALLEGRO_EVENT_TIMER) {
  328.             // Event for redrawing the display.
  329.             if (event.timer.source == game_update_timer)
  330.                 // The redraw timer has ticked.
  331.                 redraws++;
  332.         } else if (event.type == ALLEGRO_EVENT_KEY_DOWN) {
  333.             // Event for keyboard key down.
  334.             game_log("Key with keycode %d down", event.keyboard.keycode);
  335.             key_state[event.keyboard.keycode] = true;
  336.             on_key_down(event.keyboard.keycode);
  337.         } else if (event.type == ALLEGRO_EVENT_KEY_UP) {
  338.             // Event for keyboard key up.
  339.             game_log("Key with keycode %d up", event.keyboard.keycode);
  340.             key_state[event.keyboard.keycode] = false;
  341.         } else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
  342.             // Event for mouse key down.
  343.             game_log("Mouse button %d down at (%d, %d)", event.mouse.button, event.mouse.x, event.mouse.y);
  344.             mouse_state[event.mouse.button] = true;
  345.             on_mouse_down(event.mouse.button, event.mouse.x, event.mouse.y);
  346.         } else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
  347.             // Event for mouse key up.
  348.             game_log("Mouse button %d up at (%d, %d)", event.mouse.button, event.mouse.x, event.mouse.y);
  349.             mouse_state[event.mouse.button] = false;
  350.         } else if (event.type == ALLEGRO_EVENT_MOUSE_AXES) {
  351.             if (event.mouse.dx != 0 || event.mouse.dy != 0) {
  352.                 // Event for mouse move.
  353.                 game_log("Mouse move to (%d, %d)", event.mouse.x, event.mouse.y);
  354.                 mouse_x = event.mouse.x;
  355.                 mouse_y = event.mouse.y;
  356.             } else if (event.mouse.dz != 0) {
  357.                 // Event for mouse scroll.
  358.                 game_log("Mouse scroll at (%d, %d) with delta %d", event.mouse.x, event.mouse.y, event.mouse.dz);
  359.             }
  360.         }
  361.         // TODO: Process more events and call callbacks by adding more
  362.         // entries inside Scene.
  363.  
  364.         // Redraw
  365.         if (redraws > 0 && al_is_event_queue_empty(game_event_queue)) {
  366.             // if (redraws > 1)
  367.             //  game_log("%d frame(s) dropped", redraws - 1);
  368.             // Update and draw the next frame.
  369.             game_update();
  370.             game_draw();
  371.             redraws = 0;
  372.         }
  373.     }
  374. }
  375.  
  376. void game_update(void) {
  377.     if (active_scene == SCENE_START) {
  378.         plane.vx = plane.vy = 0;
  379.         if (key_state[ALLEGRO_KEY_UP] || key_state[ALLEGRO_KEY_W])
  380.             plane.vy -= 1;
  381.         if (key_state[ALLEGRO_KEY_DOWN] || key_state[ALLEGRO_KEY_S])
  382.             plane.vy += 1;
  383.         if (key_state[ALLEGRO_KEY_LEFT] || key_state[ALLEGRO_KEY_A])
  384.             plane.vx -= 1;
  385.         if (key_state[ALLEGRO_KEY_RIGHT] || key_state[ALLEGRO_KEY_D])
  386.             plane.vx += 1;
  387.         // 0.71 is (1/sqrt(2)).
  388.         plane.y += plane.vy * 4 * (plane.vx ? 0.71f : 1);
  389.         plane.x += plane.vx * 4 * (plane.vy ? 0.71f : 1);
  390.         // [HACKATHON 1-1]
  391.         // TODO: Limit the plane's collision box inside the frame.
  392.         //       (x, y axes can be separated.)
  393.         // Uncomment and fill in the code below.
  394.         if (plane.x < 20)
  395.             plane.x = 20;
  396.         else if (plane.x > SCREEN_W-20)
  397.             plane.x = SCREEN_W-20;
  398.         if (plane.y < 20)
  399.             plane.y = 20;
  400.         else if (plane.y > SCREEN_H-20)
  401.             plane.y = SCREEN_H-20;
  402.  
  403.         // [HACKATHON 2-7]
  404.         // TODO: Update bullet coordinates.
  405.         // 1) For each bullets, if it's not hidden, update x, y
  406.         // according to vx, vy.
  407.         // 2) If the bullet is out of the screen, hide it.
  408.         // Uncomment and fill in the code below.
  409.         int i;
  410.         for (i=0;i<MAX_BULLET;i++) {
  411.             if (bullets[i].hidden = false)
  412.                 continue;
  413.             bullets[i].x += bullets[i].vx;
  414.             bullets[i].y += bullets[i].vy;
  415.             if (bullets[i].y < 0)
  416.                 bullets[i].hidden = true;
  417.         }
  418.  
  419.         // [HACKATHON 2-8]
  420.         // TODO: Shoot if key is down and cool-down is over.
  421.         // 1) Get the time now using 'al_get_time'.
  422.         // 2) If Space key is down in 'key_state' and the time
  423.         //    between now and last shoot is not less that cool
  424.         //    down time.
  425.         // 3) Loop through the bullet array and find one that is hidden.
  426.         //    (This part can be optimized.)
  427.         // 4) The bullet will be found if your array is large enough.
  428.         // 5) Set the last shoot time to now.
  429.         // 6) Set hidden to false (recycle the bullet) and set its x, y to the
  430.         //    front part of your plane.
  431.         // Uncomment and fill in the code below.
  432.         double now = al_get_time();
  433.         if (key_state[ALLEGRO_KEY_SPACE] && now - last_shoot_timestamp >= MAX_COOLDOWN) {
  434.             for (i = 0; i<MAX_BULLET;i++) {
  435.                 if (bullets[i].hidden == true)
  436.                     break;
  437.             }
  438.             if (i < MAX_BULLET) {
  439.                 last_shoot_timestamp = now;
  440.                 bullets[i].hidden = false;
  441.                 bullets[i].x = plane.x;
  442.                 bullets[i].y = plane.y -20;
  443.             }
  444.         }
  445.     }
  446. }
  447.  
  448. void game_draw(void) {
  449.     if (active_scene == SCENE_MENU) {
  450.         al_draw_bitmap(main_img_background, 0, 0, 0);
  451.         al_draw_text(font_pirulen_32, al_map_rgb(255, 255, 255), SCREEN_W / 2, 30, ALLEGRO_ALIGN_CENTER, "Space Shooter");
  452.         al_draw_text(font_pirulen_24, al_map_rgb(255, 255, 255), 20, SCREEN_H - 50, 0, "Press enter key to start");
  453.         al_draw_bitmap(setting_img,10,10,0);
  454.         // [HACKATHON 3-5]
  455.         // TODO: Draw settings images.
  456.         // The settings icon should be located at (x, y, w, h) =
  457.         // (SCREEN_W - 48, 10, 38, 38).
  458.         // Change its image according to your mouse position.
  459.         // Uncomment and fill in the code below.
  460.         //if (pnt_in_rect(mouse_x, mouse_y, ???, ???, ???, ???))
  461.         //  ???(img_settings2, ???, ???, 0);
  462.         //else
  463.         //  ???(img_settings, ???, ???, 0);
  464.     } else if (active_scene == SCENE_START) {
  465.         int i;
  466.         al_draw_bitmap(start_img_background, 0, 0, 0);
  467.         al_draw_bitmap(setting_img,10,10,0);
  468.         // [HACKATHON 2-9]
  469.         // TODO: Draw all bullets in your bullet array.
  470.         // Uncomment and fill in the code below.
  471.         for (i=0;i<MAX_BULLET;i++)
  472.             draw_movable_object(bullets[i]);
  473.         draw_movable_object(plane);
  474.         for (i = 0; i < MAX_ENEMY; i++)
  475.             draw_movable_object(enemies[i]);
  476.     }
  477.     // [HACKATHON 3-9]
  478.     // TODO: If active_scene is SCENE_SETTINGS.
  479.     // Draw anything you want, or simply clear the display.
  480.     else if (active_scene == SCENE_SETTING) {
  481.         al_clear_to_color(al_map_rgb(0, 0, 0));
  482.         al_draw_bitmap(setting_img,10,10,0);
  483.     }
  484.     al_flip_display();
  485. }
  486.  
  487. void game_destroy(void) {
  488.     // Destroy everything you have created.
  489.     // Free the memories allocated by malloc or allegro functions.
  490.     // Destroy shared resources.
  491.     al_destroy_font(font_pirulen_32);
  492.     al_destroy_font(font_pirulen_24);
  493.  
  494.     /* Menu Scene resources*/
  495.     al_destroy_bitmap(main_img_background);
  496.     al_destroy_sample(main_bgm);
  497.     // [HACKATHON 3-6]
  498.     // TODO: Destroy the 2 settings images.
  499.     // Uncomment and fill in the code below.
  500.     //???(img_settings);
  501.     //???(img_settings2);
  502.  
  503.     /* Start Scene resources*/
  504.     al_destroy_bitmap(start_img_background);
  505.     al_destroy_bitmap(start_img_plane);
  506.     al_destroy_bitmap(start_img_enemy);
  507.     al_destroy_sample(start_bgm);
  508.     al_destroy_sample(img_bullet);
  509.     // [HACKATHON 2-10]
  510.     // TODO: Destroy your bullet image.
  511.     // Uncomment and fill in the code below.
  512.     //???(img_bullet);
  513.  
  514.     al_destroy_timer(game_update_timer);
  515.     al_destroy_event_queue(game_event_queue);
  516.     al_destroy_display(game_display);
  517.     free(mouse_state);
  518. }
  519.  
  520. void game_change_scene(int next_scene) {
  521.     game_log("Change scene from %d to %d", active_scene, next_scene);
  522.     // TODO: Destroy resources initialized when creating scene.
  523.     if (active_scene == SCENE_MENU) {
  524.         al_stop_sample(&main_bgm_id);
  525.         game_log("stop audio (bgm)");
  526.     } else if (active_scene == SCENE_START) {
  527.         al_stop_sample(&start_bgm_id);
  528.         game_log("stop audio (bgm)");
  529.     }
  530.     active_scene = next_scene;
  531.     // TODO: Allocate resources before entering scene.
  532.     if (active_scene == SCENE_MENU) {
  533.         if (!al_play_sample(main_bgm, 1, 0.0, 1.0, ALLEGRO_PLAYMODE_LOOP, &main_bgm_id))
  534.             game_abort("failed to play audio (bgm)");
  535.     } else if (active_scene == SCENE_START) {
  536.         int i;
  537.         plane.img = start_img_plane;
  538.         plane.x = 400;
  539.         plane.y = 500;
  540.         plane.w = al_get_bitmap_width(plane.img);
  541.         plane.h = al_get_bitmap_height(plane.img);
  542.         for (i = 0; i < MAX_ENEMY; i++) {
  543.             enemies[i].img = start_img_enemy;
  544.             enemies[i].w = al_get_bitmap_width(start_img_enemy);
  545.             enemies[i].h = al_get_bitmap_height(start_img_enemy);
  546.             enemies[i].x = enemies[i].w / 2 + (float)rand() / RAND_MAX * (SCREEN_W - enemies[i].w);
  547.             enemies[i].y = 80;
  548.         }
  549.         // [HACKATHON 2-6]
  550.         // TODO: Initialize bullets.
  551.         // For each bullets in array, set their w and h to the size of
  552.         // the image, and set their img to bullet image, hidden to true,
  553.         // (vx, vy) to (0, -3).
  554.         // Uncomment and fill in the code below.
  555.         for (i=0;i<MAX_BULLET;i++) {
  556.             bullets[i].w = al_get_bitmap_width(img_bullet);
  557.             bullets[i].h = al_get_bitmap_height(img_bullet);
  558.             bullets[i].img = img_bullet;
  559.             bullets[i].vx = 0;
  560.             bullets[i].vy = -3;
  561.             bullets[i].hidden = true;
  562.         }
  563.         if (!al_play_sample(start_bgm, 1, 0.0, 1.0, ALLEGRO_PLAYMODE_LOOP, &start_bgm_id))
  564.             game_abort("failed to play audio (bgm)");
  565.     }
  566. }
  567.  
  568. void on_key_down(int keycode) {
  569.     if (active_scene == SCENE_MENU) {
  570.         if (keycode == ALLEGRO_KEY_ENTER)
  571.             game_change_scene(SCENE_START);
  572.     }
  573. }
  574.  
  575. void on_mouse_down(int btn, int x, int y) {
  576.     // [HACKATHON 3-8]
  577.     // TODO: When settings clicked, switch to settings scene.
  578.     // Uncomment and fill in the code below.
  579.     if (active_scene == SCENE_START||active_scene == SCENE_MENU) {
  580.         if (btn == 1) {
  581.             if (pnt_in_rect(x,y, 11, 11, 37, 37))
  582.                 game_change_scene(SCENE_SETTING);
  583.         }
  584.     }
  585.     else if(active_scene == SCENE_SETTING){
  586.         if (btn == 1) {
  587.             if (pnt_in_rect(x,y, 11, 11, 37, 37))
  588.                 game_change_scene(SCENE_MENU);
  589.         }
  590.     }
  591. }
  592.  
  593. void draw_movable_object(MovableObject obj) {
  594.     if (obj.hidden)
  595.         return;
  596.     al_draw_bitmap(obj.img, round(obj.x - obj.w / 2), round(obj.y - obj.h / 2), 0);
  597. }
  598.  
  599. ALLEGRO_BITMAP *load_bitmap_resized(const char *filename, int w, int h) {
  600.     ALLEGRO_BITMAP* loaded_bmp = al_load_bitmap(filename);
  601.     if (!loaded_bmp)
  602.         game_abort("failed to load image: %s", filename);
  603.     ALLEGRO_BITMAP *resized_bmp = al_create_bitmap(w, h);
  604.     ALLEGRO_BITMAP *prev_target = al_get_target_bitmap();
  605.  
  606.     if (!resized_bmp)
  607.         game_abort("failed to create bitmap when creating resized image: %s", filename);
  608.     al_set_target_bitmap(resized_bmp);
  609.     al_draw_scaled_bitmap(loaded_bmp, 0, 0,
  610.         al_get_bitmap_width(loaded_bmp),
  611.         al_get_bitmap_height(loaded_bmp),
  612.         0, 0, w, h, 0);
  613.     al_set_target_bitmap(prev_target);
  614.     al_destroy_bitmap(loaded_bmp);
  615.  
  616.     game_log("resized image: %s", filename);
  617.  
  618.     return resized_bmp;
  619. }
  620.  
  621. // [HACKATHON 3-3]
  622. // TODO: Define bool pnt_in_rect(int px, int py, int x, int y, int w, int h)
  623. // Uncomment and fill in the code below.
  624. bool pnt_in_rect(int px, int py, int x, int y, int w, int h) {
  625.     if((x<px)&&(px<x+w)&&(py>y)&&(py<y+h)) return true;
  626.     return false;
  627. }
  628.  
  629.  
  630. // +=================================================================+
  631. // | Code below is for debugging purpose, it's fine to remove it.    |
  632. // | Deleting the code below and removing all calls to the functions |
  633. // | doesn't affect the game.                                        |
  634. // +=================================================================+
  635.  
  636. void game_abort(const char* format, ...) {
  637.     va_list arg;
  638.     va_start(arg, format);
  639.     game_vlog(format, arg);
  640.     va_end(arg);
  641.     fprintf(stderr, "error occured, exiting after 2 secs");
  642.     // Wait 2 secs before exiting.
  643.     al_rest(2);
  644.     // Force exit program.
  645.     exit(1);
  646. }
  647.  
  648. void game_log(const char* format, ...) {
  649. #ifdef LOG_ENABLED
  650.     va_list arg;
  651.     va_start(arg, format);
  652.     game_vlog(format, arg);
  653.     va_end(arg);
  654. #endif
  655. }
  656.  
  657. void game_vlog(const char* format, va_list arg) {
  658. #ifdef LOG_ENABLED
  659.     static bool clear_file = true;
  660.     vprintf(format, arg);
  661.     printf("\n");
  662.     // Write log to file for later debugging.
  663.     FILE* pFile = fopen("log.txt", clear_file ? "w" : "a");
  664.     if (pFile) {
  665.         vfprintf(pFile, format, arg);
  666.         fprintf(pFile, "\n");
  667.         fclose(pFile);
  668.     }
  669.     clear_file = false;
  670. #endif
  671. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top