|
al_draw_bitmap_region does not return |
sasha199568
Member #16,095
October 2015
|
Simple background scrolling program. It works almost fine on Ubuntu: I am trying to make it work on Windows. 1
2#include <allegro5/allegro.h>
3#include <allegro5/allegro_image.h>
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <time.h>
8
9#define EXITWITHERROR(E, R) { strcpy_s(error_buffer, E); quit(R); }
10
11ALLEGRO_DISPLAY *display = NULL;
12ALLEGRO_KEYBOARD_STATE kstate;
13char error_buffer[128] = { 0 };
14ALLEGRO_BITMAP *background;
15ALLEGRO_DISPLAY_MODE *dm;
16int x = 0, y = 0, bw, bh;
17
18void init();
19void gameLoop();
20void quit(const char *reason);
21
22int main(int argc, char **argv)
23{
24 init();
25 while (true) gameLoop();
26 return 0;
27}
28
29void quit(const char * r)
30{
31 int errnumber = al_get_errno();
32 al_destroy_display(display);
33 al_destroy_bitmap(background);
34 al_uninstall_system();
35 if (!error_buffer[0])
36 strcpy_s(error_buffer, "Everything is fine");
37 fprintf(stderr, "%s\nerror message: %s\nerror number: %i\n",
38 r, error_buffer, errnumber);
39 getchar();
40 exit(errnumber);
41}
42
43void gameLoop()
44{
45 fprintf_s(stdout, "game loop\n");
46 // process game world
47 if (x < 0) x = bw - dm->width;
48 if (x > bw - dm->width) x = 0;
49 if (y < 0) y = bh - dm->height;
50 if (y > bh - dm->height) y = 0;
51
52 // get and process input
53 al_get_keyboard_state(&kstate);
54 if (al_key_down(&kstate, ALLEGRO_KEY_ESCAPE)) {
55 fprintf_s(stdout, "escape pressed\n");
56 quit("Execution finished");
57 }
58 if (al_key_down(&kstate, ALLEGRO_KEY_LEFT)) x -= 10;
59 if (al_key_down(&kstate, ALLEGRO_KEY_UP)) y -= 10;
60 if (al_key_down(&kstate, ALLEGRO_KEY_RIGHT)) x += 10;
61 if (al_key_down(&kstate, ALLEGRO_KEY_DOWN)) y += 10;
62
63 // draw
64 al_draw_bitmap_region(background, x, y, dm->width, dm->height, 0, 0, 0);
65 fprintf_s(stdout, "bitmap drawn\n");
66 al_flip_display();
67}
68
69void init()
70{
71 srand(time(NULL));
72 if (!al_init()) EXITWITHERROR("al_init failed", "Init failed");
73 if (!al_init_image_addon()) EXITWITHERROR("image addon cannot be init", "Init failed");
74 ALLEGRO_DISPLAY_MODE ldm;
75 if (!(dm = al_get_display_mode(al_get_num_display_modes() - 1, &ldm)))
76 EXITWITHERROR("could not get display modes", "init failed");
77 al_set_new_display_flags(ALLEGRO_FULLSCREEN);
78 display = al_create_display(dm->width, dm->height);
79 if (!display) EXITWITHERROR("Could not create Display", "Init failed");
80 if (!al_install_keyboard()) EXITWITHERROR("keyboard cannot be installed", "Init failed");
81 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
82 background = al_load_bitmap("map2.jpg");
83 if (!background) EXITWITHERROR("Could not load map2.jpg", "Init failed");
84 bw = al_get_bitmap_width(background);
85 bh = al_get_bitmap_height(background);
86 fprintf_s(stdout, "init successful\n");
87}
I am using windows binaries from here http://liballeg.org/download.html Also I just noticed. There are many weird things about Visual Studio. And here is one. Usually unless you explicitly state that you are ok with fprintf Visual Studio doesn't allow it. It says use fprintf_s instead. This time I just used fprintf_s everywhere. But in quit(const char *) function I used just fprintf and it said nothing. Before using binaries I compiled from source. Basic programs worked. But when I tried al_load_bitmap Visual Studio showed NULL on top of the call stack. It wasn't that the function returned NULL. The issue was that next function on the stack was NULL. al_load_bitmap called two more functions. As I remember they were find_bitmap_flags and find_handler. While I desperately was trying to please visual studio when it hit me with "access violation ... trying to execute 00000000" I wrote this line if (!(dm = al_get_display_mode(al_get_num_display_modes() - 1, &ldm))) with two variables dm and ldm instead of one. and then I accessed display width like dm->width. But al_get_display_mode does not return valid display mode, therefore dm->width contained rubbish. I changed code to have only global ALLEGRO_DISPLAY_MODE and now I don't assign returned value to it. Also I access width with dot: dm.width ... That's a shame. I made such a mess in a simple program. It's not even a game, just a little test. I still wonder why would compiled from source version of allegro try to execute NULL when calling al_load_bitmap; and why there is this little glitch on Ubuntu. |
Matias Persson
Member #15,093
May 2013
|
Works fine for me.
1al_clear_to_color(al_map_rgb(0,0,0));
2
3// Draw
4al_draw_bitmap_region(background, x, y, dm->width, dm->height, 0, 0, 0);
5fprintf_s(stdout, "bitmap drawn\n");
6
7al_flip_display();
Also here if you want it, it's a base you can use which I think is pretty neat; Main function 1#include <fstream>
2#include <memory>
3#include <allegro5/allegro.h>
4
5int initializeAllegro(ALLEGRO_DISPLAY **display, ALLEGRO_EVENT_QUEUE **event_queue, ALLEGRO_TIMER **timer);
6
7void checkInput(ALLEGRO_EVENT &ev, int &running);
8
9void cleanUp(ALLEGRO_DISPLAY **display, ALLEGRO_EVENT_QUEUE **event_queue, ALLEGRO_TIMER **timer);
10
11int main() {
12 ALLEGRO_DISPLAY *display = NULL;
13 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
14 ALLEGRO_TIMER *timer = NULL;
15 ALLEGRO_EVENT ev;
16
17 bool running = true;
18
19 std::unique_ptr<gameState> currentState = std::make_unique<menuState>();
20
21 initializeAllegro(&display, &event_queue, &timer);
22
23 while (running) {
24 while (!al_is_event_queue_empty(event_queue)) {
25 al_wait_for_event(event_queue, &ev);
26
27 checkInput(ev, running);
28
29 if (ev.type == ALLEGRO_EVENT_TIMER) {
30 // Logics within any timer.
31 doTimedLogic();
32
33 }
34 else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
35 running = false;
36 }
37
38 doUntimedLogic();
39 }
40
41 // Render
42 render();
43
44 // Rest for 0.001 sec
45 al_rest(0.001);
46
47 }
48
49 cleanUp(&display, &event_queue, &timer);
50
51 return 0;
52}
initializeAllegro function 1int initializeAllegro(ALLEGRO_DISPLAY **display, ALLEGRO_EVENT_QUEUE **event_queue, ALLEGRO_TIMER **timer) {
2 std::ofstream file("Log.txt");
3
4 if (!al_init()) {
5 file << "Could not initialize Allegro 5" << std::endl;
6 return -1;
7 }
8
9 *display = al_create_display(640, 480);
10 al_set_window_title(*display, "Game");
11 if (!display) {
12 al_destroy_display(*display);
13 file << "Could not create display" << std::endl;
14 return -1;
15 }
16
17 *event_queue = al_create_event_queue();
18 if (!event_queue) {
19 al_destroy_event_queue(*event_queue);
20 file << "Could not create event queue" << std::endl;
21 return -1;
22 }
23
24 const float FPS = 60.0f;
25 *timer = al_create_timer(1.0 / FPS);
26 if (!timer) {
27 al_destroy_timer(*timer);
28 file << "Could not create game timer" << std::endl;
29 return -1;
30 }
31
32 al_install_keyboard();
33 al_install_mouse();
34
35 al_register_event_source(*event_queue, al_get_display_event_source(*display));
36 al_register_event_source(*event_queue, al_get_timer_event_source(*timer));
37 al_register_event_source(*event_queue, al_get_keyboard_event_source());
38 al_register_event_source(*event_queue, al_get_mouse_event_source());
39
40 al_start_timer(*timer);
41
42 return 0;
43}
checkInput function 1void checkInput(ALLEGRO_EVENT &ev, int &running) {
2 if (ev.type == ALLEGRO_EVENT_KEY_DOWN)
3 {
4 switch (ev.keyboard.keycode)
5 {
6 case ALLEGRO_KEY_ESCAPE:
7 running = false;
8 break;
9 }
10 }
11}
cleanUp function 1void cleanUp(ALLEGRO_DISPLAY **display, ALLEGRO_EVENT_QUEUE **event_queue, ALLEGRO_TIMER **timer) {
2 al_destroy_display(*display);
3 al_destroy_event_queue(*event_queue);
4 al_destroy_timer(*timer);
5}
|
RPG Hacker
Member #12,492
January 2011
|
Matias Persson said: But one thing I can see you're forgetting is al_clear_to_color(al_map_rgb(0,0,0)); Well, when drawing something to full screen size, al_clear_to_color() isn't necessarily needed. Since you're redrawing each pixel every frame, anyways, a clear is optional. In fact, you're saving a small amout of performance by skipping the clear. It's probably a neglectible amount, but I'm just saying.
|
Elias
Member #358
May 2000
|
sasha199568 said: ALLEGRO_DISPLAY_MODE ldm; This is a local variable which gets destroyed when the init function returns. So any behavior after that is undefined, program crashes or other weird things are expected. This is the joy of C++, always be careful about memory allocation and lifetime, for every single variable you use Anyway, it could explain both the Linux and Windows issues. -- |
Matias Persson
Member #15,093
May 2013
|
RPG Hacker said: Well, when drawing something to full screen size, al_clear_to_color() isn't necessarily needed. Since you're redrawing each pixel every frame, anyways, a clear is optional. In fact, you're saving a small amout of performance by skipping the clear. It's probably a neglectible amount, but I'm just saying. Oh, well that is good to know! |
|