Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Game Crashing and I'm not sure why?

This thread is locked; no one can reply to it. rss feed Print
Game Crashing and I'm not sure why?
childski
Member #17,771
June 2020

Hi. I am very new to Allegro and trying to make an RPG game.

In game_run(), I intend to show a couple of dialogues before continuing the game in the if(dialogue) bit. Though for some reason after the dialogue ends, the game will crash and the console says:

Process returned -1073741819 (0xC0000005)

I'm not sure what I did wrong, can somebody point out my mistakes?

Please take a look at my really messy code and bear with me:
[EDIT] some clean up, which I'm not even sure will matter :'(

#SelectExpand
1#include <stdio.h> 2#include <allegro5/allegro_native_dialog.h> 3#include <allegro5/allegro.h> 4#include <allegro5/allegro_font.h> 5#include <allegro5/allegro_ttf.h> 6#include <allegro5/allegro_audio.h> 7#include <allegro5/allegro_acodec.h> 8#include <allegro5/allegro_primitives.h> 9#include <allegro5/allegro_image.h> 10#include <string> 11#define GAME_TERMINATE -1 12 13 14ALLEGRO_TIMER* timer = NULL; 15ALLEGRO_TIMER* timer2 = NULL; 16ALLEGRO_DISPLAY* display = NULL; 17ALLEGRO_FONT* font = NULL; 18ALLEGRO_SAMPLE* song = NULL; 19ALLEGRO_BITMAP* player = NULL; 20ALLEGRO_BITMAP* bg = NULL; 21ALLEGRO_BITMAP* title = NULL; 22ALLEGRO_BITMAP* papa = NULL; 23ALLEGRO_BITMAP* shadow = NULL; 24ALLEGRO_BITMAP* titlejohnny = NULL; 25ALLEGRO_BITMAP* textbox = NULL; 26 27//new bitmaps for window 2 here 28ALLEGRO_BITMAP* papa_1 = NULL; 29ALLEGRO_BITMAP* door = NULL; 30ALLEGRO_BITMAP* frame = NULL; 31ALLEGRO_BITMAP* family = NULL; 32 33ALLEGRO_EVENT_QUEUE *event_queue = NULL; 34 35enum KEYS { DOWN, LEFT, RIGHT, UP}; 36enum STATE {IDLE, DIALOGUE, FRAME, DOOR1}; 37 38const char *gametitle = "johnny johnny"; 39const int width = 1280; 40const int height = 720; 41int window = 1; 42int state; 43bool next_window = false; 44bool draw = true; 45bool active = false; 46 47int pos_x = width / 2 - 50; //starting pos_x 48int pos_y = height / 2 + 200; //starting pos_y 49int dir = DOWN, sourcex = 0, sourcey = 0; 50float movespeed = 5; 51 52void show_err_msg(int msg); 53void game_init(); 54void game_begin(); 55void game_destroy(); 56int game_run(); 57int process_event(); 58 59//dialogue stuff 60 61int dialogueindex = 0; 62char* dialogue1[12] = {"papa: johnny, johnny...","johnny: yes papa?","papa: eating sugar?","johnny: no, papa...","papa: telling lies?","johnny: no, papa...","papa: well, then. prove it.","johnny: 'i really did not eat sugar.", "what should i say to convince him?'","johnny: 'oh, i know... i will give","papa's favorite letters.'","hint: find papa's favorite letters."}; 63 64char* door1text= "what's papa's favorite word?"; 65 66typedef struct character 67{ 68 int x = 10; 69 int y = 10; 70 ALLEGRO_BITMAP *image_path; 71 72} Character; 73 74Character character1; 75 76bool Collision(float x, float y, float ex, float ey, int width, int height) 77{ 78 if(x + width < ex || x > ex + width || y + height < ey || y > ey + height) 79 { 80 return false; 81 } 82 return true; 83} 84 85void stopmoving() 86{ 87 if(dir == DOWN) 88 character1.y-= movespeed; 89 if (dir == LEFT) 90 character1.x+=movespeed; 91 if(dir == RIGHT) 92 character1.x-=movespeed; 93 if(dir == UP) 94 character1.y+=movespeed; 95} 96 97 98int main(int argc, char *argv[]) 99{ 100 int msg = 0; 101 102 printf("Loading...\n"); 103 game_init(); 104 game_begin(); 105 106 while (msg != GAME_TERMINATE) 107 { 108 msg = game_run(); 109 if (msg == GAME_TERMINATE) 110 printf("Bye\n"); 111 } 112 game_destroy(); 113 return 0; 114} 115 116 117void show_err_msg(int msg) 118{ 119 fprintf(stderr, "unexpected msg: %d", msg); 120 game_destroy(); 121 exit(9); 122} 123 124void game_init() 125{ 126 if (!al_init()) 127 show_err_msg(-1); 128 129 //Initialize Timer 130 float FPS = 60.0; 131 timer = al_create_timer(1.0/FPS); 132 al_start_timer(timer); 133 134 event_queue = al_create_event_queue(); 135 display = al_create_display(width,height); 136 137 al_set_window_position(display, 0, 0); 138 al_set_window_title(display, gametitle); 139 al_init_font_addon(); 140 al_init_ttf_addon(); 141 al_init_primitives_addon(); 142 al_init_image_addon(); 143 al_init_acodec_addon(); 144 al_install_audio(); 145 al_install_keyboard(); 146 147 al_register_event_source(event_queue,al_get_display_event_source(display)); 148 al_register_event_source(event_queue,al_get_keyboard_event_source()); 149 al_register_event_source(event_queue,al_get_timer_event_source(timer)); 150 151 152} 153 154 155void game_begin() 156{ 157 song = al_load_sample("liar.ogg"); 158 if (!song){ 159 printf( "Audio clip sample not loaded!\n" ); 160 show_err_msg(-6); 161 } 162 // Loop the song until the display closes 163 al_play_sample(song, 1,0,1,ALLEGRO_PLAYMODE_LOOP, NULL); 164 ALLEGRO_COLOR al_map_rgb(unsigned char r, unsigned char g, unsigned char b); 165 font = al_load_ttf_font("Wildy-Sans.ttf", 40, 0); 166 player = al_load_bitmap("spritejohnny.png"); 167 al_draw_bitmap(player,0, 0, 0); //for character 168 bg = al_load_bitmap("title_bg.png"); 169 title = al_load_bitmap("title.png"); 170 shadow = al_load_bitmap("shadow.png"); 171 papa = al_load_bitmap("papa.png"); 172 titlejohnny = al_load_bitmap("title_johnny.png"); 173 174 //for window 2 175 papa_1 = al_load_bitmap("papa_1.png"); 176 textbox = al_load_bitmap("textbox.png"); 177 family = al_load_bitmap("family.png"); 178 frame = al_load_bitmap("frame.png"); 179 door = al_load_bitmap("door.png"); 180 bg = al_load_bitmap("title_bg.png"); 181 182 183 al_draw_bitmap(bg, 0, 0, 0); 184 al_draw_bitmap(shadow, 55, 10, 0); 185 al_draw_bitmap(papa, 150, 0, 0); 186 al_draw_bitmap(title, 500, 250, 0); 187 al_draw_bitmap(titlejohnny, 220, 350, 0); 188 al_draw_text(font,al_map_rgb(255,255,255),800,500,0,"press enter to start"); 189 al_flip_display(); 190 191} 192 193int process_event() 194{ 195 ALLEGRO_EVENT event; 196 ALLEGRO_KEYBOARD_STATE keystate; 197 al_wait_for_event(event_queue, &event); 198 al_get_keyboard_state(&keystate); 199 al_get_keyboard_event_source(); 200 al_get_timer_event_source(timer); 201 202 bool hitframe = false; 203 204 if(al_key_down(&keystate, ALLEGRO_KEY_ENTER)) 205 next_window = true; 206 207 if(al_key_down(&keystate, ALLEGRO_KEY_ESCAPE)) 208 return GAME_TERMINATE; 209 210 active = true; 211 if(al_key_down(&keystate, ALLEGRO_KEY_DOWN)) 212 { 213 character1.y += movespeed; 214 dir = DOWN; 215 } 216 else if(al_key_down(&keystate, ALLEGRO_KEY_UP)) 217 { 218 character1.y -= movespeed; 219 dir = UP; 220 } 221 else if(al_key_down(&keystate, ALLEGRO_KEY_RIGHT)) 222 { 223 character1.x += movespeed; 224 dir = RIGHT; 225 } 226 else if(al_key_down(&keystate, ALLEGRO_KEY_LEFT)) 227 { 228 character1.x -= movespeed; 229 dir = LEFT; 230 } 231 else 232 active = false; 233 234 if(active) 235 sourcex += al_get_bitmap_width(player) / 3; 236 else 237 sourcex = 100; 238 239 if(sourcex >= al_get_bitmap_width(player)) 240 sourcex = 0; 241 sourcey = dir; 242 draw = true; 243 244 if(Collision(character1.x, character1.y,260,160, al_get_bitmap_width(frame)/2+10, al_get_bitmap_height(frame)/2)) 245 { 246 state = FRAME; 247 printf("frame"); 248 stopmoving(); 249 } 250 251 if(Collision(character1.x, character1.y,950,280, al_get_bitmap_width(papa_1)/2+10, al_get_bitmap_height(papa_1)/2)) 252 { 253 printf("dad"); 254 stopmoving(); 255 } 256 257 if(Collision(character1.x, character1.y,585,0, al_get_bitmap_width(door)/2-10, al_get_bitmap_height(door)/2)) 258 { 259 state = DOOR1; 260 printf("door1"); 261 stopmoving(); 262 } 263 264 if(event.type == ALLEGRO_EVENT_KEY_DOWN) 265 { 266 if(event.keyboard.keycode == ALLEGRO_KEY_Z) 267 { 268 switch(state) 269 { 270 case DIALOGUE: 271 dialogueindex++; 272 break; 273 /*case FRAME: 274 al_draw_bitmap(family,300,200,0); 275 break; 276 case DOOR1: 277 al_draw_bitmap(textbox,300,200,0); 278 al_draw_text(font,al_map_rgb(255,255,255),600,250,ALLEGRO_ALIGN_CENTER,door1text); 279 break;*/ 280 } 281 282 } 283 } 284 285 /*if(event.type == ALLEGRO_EVENT_KEY_CHAR && door1) 286 { 287 const int inputChar = event.keyboard.unichar; 288 if 289 ( 290 (inputChar >= 48 && inputChar <= 57) //is a number 291 || ( inputChar >= 65 && inputChar <= 90) //is a capital letter 292 || ( inputChar >= 97 && inputChar <= 122) //is a lower-case letter 293 || ( inputChar == 95) //is an underscore 294 ){ 295 keyboard_string += inputChar; 296 } 297 }*/ 298 299 return 0; 300} 301 302 303int game_run() 304{ 305 int error = 0; 306 al_play_sample(song,5,0,1,ALLEGRO_PLAYMODE_LOOP,0); 307 if(window == 1) 308 { 309 if (!al_is_event_queue_empty(event_queue)) 310 { 311 error = process_event(); 312 if(next_window) 313 { 314 window++; 315 character1.x = pos_x; 316 character1.y = pos_y; 317 character1.image_path = player; 318 //bg = al_load_bitmap("title_bg.png"); --> moved to game-begin 319 } 320 } 321 } 322 // Second window(Main Game) 323 else if(window == 2) 324 { 325 al_draw_bitmap(bg, 0,0,0); 326 al_draw_bitmap(papa_1,950,250,0); 327 al_draw_bitmap(frame,290,220,0); 328 al_draw_bitmap(door,550,0,0); 329 330 // Change Image for animation 331 if(draw) 332 { 333 al_draw_bitmap_region(character1.image_path, sourcex, sourcey * al_get_bitmap_height(character1.image_path) / 4, 100, 100, character1.x, character1.y, 0); 334 } 335 336 state = DIALOGUE; 337 338 switch(state) 339 { 340 case IDLE: 341 al_draw_bitmap(bg, 0,0,0); 342 al_draw_bitmap(papa_1,950,250,0); 343 al_draw_bitmap(frame,290,220,0); 344 al_draw_bitmap(door,550,0,0); 345 break; 346 case DIALOGUE: 347 if(dialogueindex<sizeof(dialogue1)-1) 348 { 349 al_draw_bitmap(textbox,300,200,0); 350 al_draw_text(font,al_map_rgb(255,255,255),600,250,ALLEGRO_ALIGN_CENTER,dialogue1[dialogueindex]); 351 } 352 else state = IDLE; 353 break; 354 case FRAME: 355 al_draw_bitmap(family,300,200,0); 356 break; 357 case DOOR1: 358 al_draw_bitmap(textbox,300,200,0); 359 al_draw_text(font,al_map_rgb(255,255,255),600,250,ALLEGRO_ALIGN_CENTER,door1text); 360 break; 361 default: 362 al_draw_bitmap_region(character1.image_path, sourcex, sourcey * al_get_bitmap_height(character1.image_path) / 4, 100, 100, character1.x, character1.y, 0); 363 } 364 365 al_flip_display(); 366 367 // Listening for new event 368 if (!al_is_event_queue_empty(event_queue)) 369 { 370 error = process_event(); 371 } 372 } 373 return error; 374} 375 376void game_destroy() 377{ 378 al_destroy_display(display); 379 al_destroy_font(font); 380 al_destroy_event_queue(event_queue); 381 al_destroy_timer(timer); 382 al_destroy_timer(timer2); 383 al_destroy_bitmap(player); 384 al_destroy_bitmap(papa); 385 al_destroy_bitmap(title); 386 al_destroy_bitmap(bg); 387 al_destroy_bitmap(titlejohnny); 388 al_destroy_bitmap(papa_1); 389 al_destroy_bitmap(textbox); 390 al_destroy_bitmap(family); 391 al_destroy_bitmap(frame); 392 al_destroy_bitmap(door); 393 al_uninstall_keyboard(); 394 al_destroy_sample(song); 395}

Thank you so much!

pmprog
Member #11,579
January 2010
avatar

Can you not step through it with a debugger and see the stack trace... That would help you loads

MikiZX
Member #17,092
June 2019

I believe you need to move your:

timer  = al_create_timer(1.0/FPS);
al_register_event_source(event_queue, al_get_timer_event_source(timer)) ;
al_start_timer(timer);

outside of the game loop (possibly to your init function) - right now I believe you are creating a new timer each iterration of the loop.

EDIT: Also, your process_event(); function does not contain the part that would be processing the timer events. Have a look at https://github.com/liballeg/allegro5/blob/master/examples/ex_timer.c lines from 141-161 for an example of an event processing loop.
Eventually if you get stuck please let us know and we'll do our best to help you fix this.

childski
Member #17,771
June 2020

Hi, thank you for all the replies.

@pmprog: sorry, what is a stack trace?

@MikiZX: thank you for the reference and suggestions. I've moved the timer to init now. From the sample code that I've seen, they only used the timer to animate some sprites. I'm still confused about the timer concept; is it to make sure that the game runs on a stable FPS?

---

From the source codes that I've seen in Allegro game development, it's either too complicated that I can't understand the structure or too basic.

As my function if(dialogue) causes the game to crash due to infinite loop, I want to ask: is there a way to show a dialogue text box like in most RPG style games?

Again, thanks for the feedback and guidance.

LennyLen
Member #5,313
December 2004
avatar

childski said:

I'm still confused about the timer concept; is it to make sure that the game runs on a stable FPS?

The main purpose of timers is to ensure that your game runs at the same speed on different computers.

pmprog
Member #11,579
January 2010
avatar

@childski, A stack trace is a list of functions that the current execution leading up to your crash.

Personally, i think debugging is just as important as coding, so I'd honestly recommend learning how to use a debugger. Depending on what language/toolchain you're using, they're all a little different, but the concepts are generally consistent

childski
Member #17,771
June 2020

@LennyLen thanks! that cleared me up a bit. I'll just have to somehow implement it...

@pmprog Ok, so I've found that my problem is in the if(dialogue) part, which now I've cleaned up a bit, but still have problems with.

In my game_run() function, I understand that it loops until the game stops. The problem arises when I set dialogue=false (i.e the dialogueindex reaches 12), and then the game crashes. Until today, I'm still not sure why and what could be done to actually fix it :'(

MikiZX
Member #17,092
June 2019

I had a second look at your source and possibly you need to test this line:
case DIALOGUE:
if(dialogueindex<sizeof(dialogue1)-1)

My programming skill is not that good (and I'm too lazy to test) but maybe sizeof(char* x) will not return the number of elements in the array?
Maybe test this part with something like:
case DIALOGUE:
if(dialogueindex<5)

As for displaying the dialogue there is no special way - you choose how to do it (you can just print text to the screen).

Some people here that understand C++ better can also confirm if your code is C or C++ since you are using #include <string> .. I am not sure if this changes anything.

As for timers....

Hm.. I'll try to explain part of the situation.

I have had a look at your game code and your game actually does not have a fixed speed at which it is executed because at the moment you only make things happen when there is some input to your game (like a keypresses for example) - the main loop of your game is executed as fast as your computer/operating system can run it.

Even if this is OK for a game to run only when there is input - this is not what majority of game devs do.
You can make a game without using a timer - they are only there to help with things (like animations and movement being executed at a fixed speed on different computers). In your case you can remove the timer completely and depend on keypresses to advance the dialog.

You can create multiple timers that can run in parallel - one timer to be executed 60 times a second, another that executes only once every 5 minutes, etc... Each time the timer ticks (is executed) there will be a new ALLEGRO_EVENT_TIMER in the event queue and your main loop can be designed to do something when it this event appears.
Timers are there to provide timing facility - a tool for you to use if you see the need.

On the other hand, you will have to add processing for different events in your loop (like window managment for example).
This is needed as things will happen outside the game (at operating system level) but that will cause Allegro5 to add a new event to the event queue. Your game needs to process these events to continue working without hickups (example here is when someone tries to close the game by clicking on the X button (or red circle) in the corner of the window - your game needs to process even this and close itself; another example is when someone resizes the window that your game has opened) - you process these events in your main loop(s) as you see fit - there is no special procedure to follow.

If your game was just running in a loop without a timer (as it is doing so now) then you will need to calculate time elapsed between two frames (two iterrations of the loop) of the game and move and animate the game assets using this delta time in order for the movement and animation to be done at the same speed/rate on different computers. Using a fixed timer simplyfies things in this regard as you can always use the same values to advance animation or change position.
Using a fixed timer that ticks 30 or 60 times a second will not change your game code much (actually very little) but might prove to be easier to manage later when you will want to add ide animation to your main game character or similar.

Do not take all this I have written as 100% true (as I am learning Allegro as well) but it is there to give you some general idea of why timers could be usefull for you (or not needed at all).

Please let me know if there is any particuar reason you wish to create your game without a fixed timer - or if you see no problem to re-arranging your main loop so it fits the 30 or 60 ticks per second type of executing as I can eventually (if you get stuck) change your code so it runs at fixed rate using a timer.

pmprog
Member #11,579
January 2010
avatar

I think i know what your problem is, but seriously, invest some time into a debugger.

Failing that... I used to be taught what was called a dryrun. Where you run line by line through your head, keeping track of the variables on a bit of paper

I really just want to say the problem i see, but part of me hopes you'll try the debugging

Edit: A hint is that you are actually overflowing your dialogue array, which is why it's crashing
Edit 2: Hmmm, maybe that's not even totally correct, but you can never leave the dialogue system

childski
Member #17,771
June 2020

@MikiZX That was very helpful and eye-opening! Thanks a lot for the explanation. And yes, I've now implemented the correct way to calculate the elements of the char* array, now it's fixed! :')

It's not that I do not want to use a timer, it's just that I probably have no idea how to correctly use one. Though I am currently trying to incorporate it into my game loop. I do wish my game can be run consistently on every computer, just... figuring it out.

Again, thanks for the great help :)

---
@pmprog I am running this code in code::blocks using the GDB debugger and there were no errors regarding the array part. Although now I've solved it. The mistake is in calculating the elements of the char* array. I used sizeof(), which does not return the number of elements.

I'm not sure if you're referring to another type of debugger/debugging? I'm confused.
but thanks for the hints and suggestions!

pmprog
Member #11,579
January 2010
avatar

@childski: Then yes, you were overrunning the array. Whilst that in itself doesn't error, it leads you to access incorrect/invalid memory, which is what causes the error.

Also line 336 always sets your state to DIALOGUE, you'll never be able move on from the dialogue section

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Go to: