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!
| 1 | void 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 | |
| 82 | void 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() |
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 | |
| 2 | int 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.
...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?
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.
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.
| 1 | void 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() |
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.
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...
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.
| 1 | volatile int logic_counter = 0; |
| 2 | void inc_logic_counter() { |
| 3 | ++ logic_counter; |
| 4 | } END_OF_FUNCTION(inc_logic_counter) |
| 5 | |
| 6 | int 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.
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.
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.
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.
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.:-[
We all have been/still are, don't worry
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.