Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Is there a reason why this code will not display the bitmaps correctly?

Credits go to Jonny Cook and ReyBrujo for helping out!
This thread is locked; no one can reply to it. rss feed Print
Is there a reason why this code will not display the bitmaps correctly?
Matt Kindy
Member #7,331
June 2006
avatar

I typed up this code and changed some stuff, but now the animation isn't showing. In this, I have a 1280 * 1024 bitmap that I basically use as the buffer(white_screen), and a bunch of animation code. For some reason, instead of the animation showing up after the whole screen turns white, I get a small white square in the upper right corner(about 100 * 100 large). Can anybody help me with this? Thanks!

1void bar_attack(int buffer_x, int buffer_y){
2 //bar bitmap array
3 char bar_bmp_name[10];
4 //fal bitmap array
5 char fal_bmp_name[10];
6 //load a white square(size 1280 * 1024)
7 white_screen = load_bitmap("whitescreen.bmp", NULL);
8 int i,j;
9 //load all of the bmps(16)
10 for(i=0; i < 16; i++){
11 sprintf(bar_bmp_name,"bar20%d.bmp", i);
12 bar<i> = load_bitmap(bar_bmp_name, NULL);
13 }
14 for(j=0; j<21; j++){
15 sprintf(fal_bmp_name,"f%d.bmp",j);
16 fal[j] = load_bitmap(fal_bmp_name, NULL);
17 }
18 //clear the key buffer so it doesn't exit 1st time
19 clear_keybuf();
20 //set coordinates
21 buffer_x = 500;
22 buffer_y = 450;
23 //as long as a key is not pressed(unless the key pressed is not ESC), go
24 while(!keypressed() || ((buffer_x != 0 || buffer_y != 0)&&(!key[KEY_ESC]))){
25 //animation
26 clear_keybuf();
27
28 for(i=0; i < 7; i++){
29 clear_bitmap(screen);
30 //make 'buffer' white and clear it
31 clear_to_color(white_screen, makecol(255,255,255));
32 //draw the bar animation, and only draw the first fal frame
33 draw_sprite(white_screen, bar<i>, buffer_x, buffer_y);
34 draw_sprite(white_screen, fal[0], buffer_x-20, buffer_y+100);
35 //provide instructions
36 textout_ex(white_screen, font, "Press Enter to Re-Center Animation," "Arrow Keys to Move Animation,"
37 " Hold Escape to quit",300,1000, makecol(0,0,0), -1);
38 put buffer on screen
39 blit(white_screen, screen, 0,0,0,0,1280,1024);
40 //only let it move if it isn't outside screen limits
41 if((buffer_x < 1271) && (buffer_y < 1015) && (buffer_x > -16) && (buffer_y > -1 )){
42 if(key[KEY_RIGHT]) // right
43 {
44 buffer_x +=10; // Moving right so up the X coordinate by 1
45 }
46 if(key[KEY_LEFT]) // left
47 {
48 buffer_x -=10; // Moving left, so lower the X coordinate by 1
49 }
50 if(key[KEY_UP]) // up
51 {
52 buffer_y -=10; // Moving up, so lower the Y coordinate by 1
53 }
54 if(key[KEY_DOWN]) // down
55 {
56 buffer_y +=10; // moving down, so up the Y coordinate by 1
57 }
58 }
59 else{//if it is at limits, inform user
60 textout_ex(white_screen, font, "Cannot go further!", 500,600, makecol(0,0,0), -1);
61 blit(white_screen, screen, 0,0,0,0,1280,1024);
62
63 } //re-center picture at (500,450)
64 if(key[KEY_ENTER] || key[KEY_ENTER_PAD]){
65 buffer_x = 500;
66 buffer_y = 450;
67 }//stop for 70ms between frames
68 rest(70);
69 if(i==4){
70 //if fal is about to get hit, play death animation function
71 fal_death(buffer_x, buffer_y, fal);
72 //clear 'buffer' for next animation
73 clear_to_color(white_screen, makecol(255,255,255));
74 }
75 }
76 }
77 rest(1500);
78 clear_bitmap(screen);
79 clear_bitmap(white_screen);
80}//end of bar_attack()
81 
82void fal_death(int buffer_x, int buffer_y, BITMAP *fal[]){
83 
84 int f;
85
86 for(f=0; f < 20; f++){
87 //only draw bar animation while to first 6 frames of death are going
88 if(f<6){
89
90 draw_sprite(white_screen, bar[f+8], buffer_x, buffer_y);
91 }else{
92 //after first 6 frames, keep drawing this one frame
93 draw_sprite(white_screen, bar[15], buffer_x, buffer_y);
94 }//draw fal anim
95 draw_sprite(white_screen, fal[f], buffer_x-15, buffer_y+95);
96
97 //same as bar anim func
98 textout_ex(white_screen, font, "Press Enter to Re-Center Animation, Arrow Keys to Move Animation,"
99 " Hold Escape to Quit",300,1000, makecol(0,0,0), -1);
100 blit(white_screen, screen, 0,0,0,0,1280,1024);
101 clear_to_color(white_screen, makecol(255,255,255));
102 if((buffer_x < 1271) && (buffer_y < 1015) && (buffer_x > -16) && (buffer_y > -1 )){
103 if(key[KEY_RIGHT]) // right
104 {
105 buffer_x +=10;// Moving right so up the X coordinate by 10
106
107 }
108 if(key[KEY_LEFT]) // left
109 {
110 buffer_x -=10; // Moving left, so lower the X coordinate by 10
111
112 }
113 if(key[KEY_UP]) // up
114 {
115 buffer_y -=10; // Moving up, so lower the Y coordinate by 10
116
117 }
118 if(key[KEY_DOWN]) // down
119 {
120 buffer_y +=10; // moving down, so up the Y coordinate by 10
121
122 }
123 }
124 else{
125 textout_ex(white_screen, font, "Cannot go further!", 500,600, makecol(0,0,0), -1);
126 blit(white_screen, screen, 0,0,0,0,1280,1024);
127
128 }
129
130 if(key[KEY_ENTER] || key[KEY_ENTER_PAD]){
131 buffer_x = 500;
132 buffer_y = 450;
133 } //rest for 80 ms between frames
134 rest(80);
135 }
136
137 rest(1500);
138 clear_to_color(white_screen, makecol(255,255,255));
139}//end of fal_death()

Jonny Cook
Member #4,055
November 2003

Yes, there most certainly is a reason. And it's probably because you're doing it all wrong! You shouldn't mix your drawing code with your logic code like that. Very slow. I don't think I can tell you how to fix your code, because I honestly don't understand what it's suppose to accomplish. However, I can show you what your should look like.
Split it up like this.

1 
2int main() {
3 Init(); // All your initialization code goes here (allegro_init(), install_keyboard(), set_gfx_mode(), etc.)
4 BITMAP *buffer = create_bitmap(SCREEN_W, SCREEN_H); // This could also go in your init function, I'm just putting it here to show you that I'm doing it.
5 // Draw everything to your buffer, then at the end blit the whole thing to the
6 // screen. Drawing to the screen is slow, so it's best to do it all at once.
7 int x = 0;
8 int y = 0;
9 bool done = false;
10 while (!done) {
11 // This is where your logic should be. Absolutely no drawing! That comes after
12 // You should implement some timer to make sure your logic doesn't go to fast.
13 // Do NOT use rest for this! It might seem like a good quick solution, but in
14 // the end it just complicates things. Update everthing here (animations,
15 // ai, physics). Store all positions in variables so they can later be
16 // drawn to the screen.
17 if (key[KEY_ESC]) {
18 done = true;
19 }
20 ++ x;
21 ++ y;
22 if (x >= SCREEN_W) {
23 x = 0;
24 }
25 if (y >= SCREEN_H) {
26 y = 0;
27 }
28 
29 
30 // Here comes your drawing code.
31 // First, make sure the buffer is clean
32 clear_to_color(buffer, makecol(255, 255, 255));
33 // Draw a rectangle at our coordinates
34 rect(buffer, x, y, x + 100, y + 100, makecol(255, 150, 150));
35 // ... draw whatever else you want to. Here you should draw the map, your
36 // sprites, the GUI. Everything.
37 // Now blit it to the screen
38 blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
39 }
40 // Clean up your mess. I noticed in your code you forgot to destroy your
41 // bitmaps. This is not good. It will fill up your memory with junk that will
42 // stay untill you restart your computer. Whevenver you dynamically allocate
43 // memory, it is up to you to also destroy it. If you do not know this, put
44 // games on hold and read a tutorial on C.
45 destroy_bitmap(buffer);
46 return 0;
47} END_OF_MAIN()

That's basically what you game should consist of. By no means does it have to look exactly like that (I'm sure if you are using threads it will be significantly different), but that should give you a general idea of what is right. Once you structure your code better, finding bugs will be a lot easier. Then, when you come here asking for help, people might actually be able to help you.

I also suggest you read the Allegro manual. It might help you understand timing and drawing a little better. Reading the source to a simple game might also help. Check out the open source games in the Depot.

The face of a child can say it all, especially the mouth part of the face.

Matt Kindy
Member #7,331
June 2006
avatar

Jonny Cook said:

...I honestly don't understand what it's suppose to accomplish

How can you not?? It's only simple C with some allegro drawing elements! It was working fine but then I changed some stuff and now it's not. First I load the bmps. Then I draw them to the buffer, blitting the buffer to the screen each time I do that, and clearing the buffer in between(achieving the 'motion'!). Then, once the Fallen monster gets 'hit' (frame 6), the Fallen starts to die. If you press the arrow keys, the animation moves up, down, left, or right. When you press enter, it re-centers. If you hold ESC, it quits. Any other questions?

Jonny Cook
Member #4,055
November 2003

Well, I'm sorry if I missed all the signs. To me, it looks like a big mess of rest, blits, clears, and perhaps a few comments that only point out the obvious. It's not well formed code. Yes, I admit that I didn't spend a considerable amount of time decrypting it, but to me it's quite obvious why it won't run properly. And thank you for ignoring the big block of text which points out some of the major flaws of your code.

The face of a child can say it all, especially the mouth part of the face.

Matt Kindy
Member #7,331
June 2006
avatar

I admit that I forgot the destroy_bitmaps()... I should've caught that., but there's no reason to pick apart my code when you imply that you don't even know what it means. I just want someone to analyze this code for me to see if they maybe notice something wrong that I missed. In your case, you did spot the destroy_bitmaps, so I thank you. I will improve my code, but I've been doing so much trying to get this done for one of my classes, that I haven't been able to refine it. I understand why not to use rest. It is a quick solution, albeit not a good one. I just do not have the time right now to learn timers.

EDIT: I did have a bunch of destroy_bitmap()s in my 'destroybitmap()' function. So I had destroyed almost everything... but not the fal sprite array.

1void destroybitmap(void){
2 int x;
3
4 destroy_bitmap(white_screen);
5 for(x=0; x < 9; x++){
6 destroy_bitmap(bar[x]);
7 }
8 for(x=0;x < 16; x++){
9 destroy_bitmap(fal[x])
10 }
11 destroy_bitmap(buffer);
12 destroy_bitmap(diablosprite);
13 destroy_bitmap(titlesprite);
14 destroy_bitmap(title2);
15 destroy_bitmap(menu);
16 destroy_bitmap(heading);
17 destroy_bitmap(buffer);
18 destroy_bitmap(menu2);
19 
20 
21 
22}//end of destroybitmap()

ReyBrujo
Moderator
January 2001
avatar

One quick note:

    char fal_bmp_name[10];
    /*  ...  */
    for(i=0; i < 16; i++){
        sprintf(bar_bmp_name,"bar20%d.bmp", i);

"bar2011.bmp" has 11 characters (plus '\0'), so your arrays should be 12 at least, not 10.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

Matt Kindy
Member #7,331
June 2006
avatar

Oh, thanks Rey! That was one of the things I changed... I only had 9 frames at first, so it was alright.Then I changed it to 16 so i would've needed 11

EDIT: Could be not loading because the images are set to 16 million. Hold on , let me check...

EDIT[2]: Yes! The bar images were set to 16 million color mode. But, sadly: NO! It still doesn't work... and I changed: white_screen = create_bitmap(1280,1024);
but that didn't help either...

Jonny Cook
Member #4,055
November 2003

I was not aware that you are on a time schedule, but nonetheless. What I was getting at in my earlier posts is that it would take less time to do it right, even if initially there is a little bit of extra learning to do. Setting up a timer takes about 8 lines of code and it can be summed up in 30 seconds. Based on what information you gave us about your problem, it's hard to tell what's wrong. The quality of your code makes it even harder.

One of the many reason people separate their logic code from their drawing code is it makes it easier to debug. Such a simple program, if coded correctly, would take very little time to both create and debug.

Also, checking the return values from the create and load bitmaps functions is always a good idea.

And perhaps you could tell us the last major change you made to your code before it stopped working.

1volatile int logic_counter = 0;
2void inc_logic_counter() {
3 ++ logic_counter;
4} END_OF_FUNCTION(inc_logic_counter)
5 
6int main() {
7 // Normal setup functions
8 LOCK_VARIABLE(logic_counter);
9 LOCK_FUNCTION(inc_logic_counter);
10 install_timer();
11 install_int_ex(inc_logic_counter, BPS_TO_TIMER(60));
12 
13 bool done = false;
14 while (!done) {
15 while (logic_counter > 0) {
16 if (key[KEY_ESC]) {
17 done = true;
18 }
19 // ... Do logic
20 -- logic_counter;
21 }
22 // Drawing
23 }
24 // Cleanup
25 return 0;
26} END_OF_MAIN()

That's the standard Allegro timer implementation.

The face of a child can say it all, especially the mouth part of the face.

Matt Kindy
Member #7,331
June 2006
avatar

Quote:

while (logic_counter > 0) {
            if (key[KEY_ESC]) {
                done = true;
            }
            // ... Do logic
            -- logic_counter;
        }

I don't understand this here... so, you're in a loop.if user presses escape, it will exit after ALL the logic is done(when logic_counter <= 0). What purpose does the logic_counter serve, outside of that? You have the variable also continually going up( at least, that's what I assume)... so the only thing I can make out would be that.. it would be going up at a constant rate and once enough things were finished in the loop, the --logic_counter would overcome(loop finishing cycles more quickly) the ++ and you would quit the logic loop, possibly even before you were intending. Are my conclusions correct(most likely not)? Could you explain why they are false? and what your code really means.

ReyBrujo
Moderator
January 2001
avatar

Remember that your timer is executed every 1/60 seconds (in example). So, the logic_counter variable will be incremented around 60 times per second. Your logic can be extremely fast (say, it can be executed in 1/100 seconds), but since the counter increases only 1/60, your logic will be executed 60 times per second (and thus, you will draw on the screen only 60 times per second).

If your logic is too heavy (say, it executes in 1/30 seconds), your timer variable will begin increasing. If this happens, you can stop the execution of the program.

My implementation is a bit different:

while (! quit) {
    while (logic_counter < timer_counter) {
        do_logic();
        logic_counter++;
    }

    do_input();
    do_output();
}

where timer_counter is the variable that is being incremented by the timer, and do_input is the function that sets the quit flag if necessary.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

Jonny Cook
Member #4,055
November 2003

The code sets a function (inc_logic_counter) to be called 60 times a second (BPS_TO_TIMER(60)). Each time the function is called, a counter gets incremented. The counter gets incremented 60 times a second. The logic only runs if the counter is greater than 0 (if (logic_counter > 0) {). Since the counter only gets incremented every 60th of a second, the logic will run no more than 60 times a second. Using this method, on slower computers the graphics might get a little laggy, but you will never miss a logic frame, and it will never go too fast.

The face of a child can say it all, especially the mouth part of the face.

Matt Kindy
Member #7,331
June 2006
avatar

GODDAMN!!!! I found it!!!... it was, of course, not in the code I gave you. I didn't change my array to size 16 from 9.. so ya... now it works. thanks. keep explaining timers please!

EDIT: BTW I am also very inexperienced in Allegro.:-[

ReyBrujo
Moderator
January 2001
avatar

We all have been/still are, don't worry :)

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

Matt Kindy
Member #7,331
June 2006
avatar

Could you also explain how to create basically a map that you can scroll through?
I don't know whether you would make sections and display them at certain times, or hide parts of it and just move the bitmap over or what, and I can't find a good tutorial to explain it. )I like the 2nd option :))

EDIT: BUT TIMERS ARE MORE IMPORTANT!!!

EDIT: I'm gonna make a new thread called 'I don't get timers...!' post there, ok?.
I won't be on until tomorrow. see ya.

Go to: