Hi, I can add the commands to move the image in my current "main_loop ();" or I'll have to modify it?
EDIT 1: In the Code::Blocks the indentation was perfect, here messed up a little and I do not know the reason :X
1) Use integers local to main_loop and pass them to draw_character :
void draw_character(int x , int y) { al_draw_bitmap(char , x , y , 0); } void main_loop() { int cx = 10; int cy = 10; while (1) { /// blah draw_character(cx,cy); } }
2) Use global integers
In your code, in your function , draw_character(), you lod the bitmap every time.
This isn't wise and will populate your game with memory leaks.
Its just some tips, of couse you would llike to load all characters sprites in the load function, and destroy all in the destroy function.
"I'm trying to figure out why it happens
http://i52.tinypic.com/dcwm7o.jpg"
EDIT 1: The first question I fix with "al_clear_to_color...." Thanks!
If I want to put three sprites to change as the character moves, I can create a simple animation of the three images and put to animate if the condition is = move? or has an easier way?
To animate, you will have to load all the char sprites, and you can put themm all in a vector, and access them by the index of the frame you want to show.
for example:
Thats the basic i think.
PS: std::vector is a c++ class, and you have to include: #include<vector>
I'm trying this way:
When I get back I'll see if I can fix it!
EDIT 1: I managed to animate, now I'm trying to change of
picture the every move!
You have to erase what you've drawn previously (by drawing the scene or just clearing to black for testing) then draw everything again.
... std::vector<ALLEGRO_BITMAP*> sprites; sprites.push_back(al_load_bitmap("Sprites/FFT1/21.bmp")); sprites.push_back(al_load_bitmap("Sprites/FFT1/22.bmp")); sprites.push_back(al_load_bitmap("Sprites/FFT1/23.bmp")); ...
I was trying to use the code that load the images off the "void" to separate the parts that loads the images for not have to load always, but after of the third move with the character... my program give error when I do that!
Do you have new code? I can't see how that's happening with your last paste.
My code...
and I tried to do:
*The indentation is correct?
The first code you posted is not good code. You load three images every time you draw your character.
Only use al_convert_mask_to_alpha once for each sprite that needs it, not every time you draw it.
The indentation is still not totally right :
ALLEGRO_EVENT ev; sprites.push_back(al_load_bitmap("Sprites/FFT1/21.bmp"));
Both lines should be at the same indentation level :
ALLEGRO_EVENT ev; sprites.push_back(al_load_bitmap("Sprites/FFT1/21.bmp"));
Hi... when I separate the images that I have to load of the my "void draw_character..." the my program hangs in the third movement!
**The indentation is correct in my code: blocks, but when I post here some parts stay crooked and i dont know why.**
*The indentation is correct in my code: blocks, but when I post here some parts stay crooked and i dont know why.*
Are you mixing tabs with spaces? Use one or the other, but never both.
Você está misturando as guias com os espaços? Use um ou outro, mas nunca ambos.
void update(void) {ALLEGRO_KEYBOARD_STATE state;int lastFrame = sprites.size();frame+= 0.0;if((int)frame >= lastFrame) frame = 0; } }
Don't mix ALLEGRO_EVENT_KEY_DOWN with ALLEGRO_KEYBOARD_STATE - use one or the other. In your case, I would just use the ALLEGRO_KEYBOARD_STATE, and check that during the timer event :
Não misture com ALLEGRO_EVENT_KEY_DOWN ALLEGRO_KEYBOARD_STATE - use um ou outro. No seu caso, gostaria apenas de usar o ALLEGRO_KEYBOARD_STATE, e verificar que, durante o evento timer :
if (ev.type == ALLEGRO_EVENT_TIMER) { ALLEGRO_KEYBOARD_STATE state; al_get_keyboard_state(&state); if (al_key_down(&state , ALLEGRO_KEY_DOWN)) { ++frame; if ((size_t)frame >= sprites.size()) { frame -= (float)(sprites.size() - 1); } } else if (al_key_down(&state , ALLEGRO_KEY_UP)) { /// } else if (...) {} }
The reason your code is failing now is because you only correct an out of bounds 'frame' variable when the timer ticks. You could have an ALLEGRO_EVENT_KEY_DOWN event just after a timer tick incrementing frames to 3.0 and then access (int)3.0 in your sprites array, which is out of bounds.
O motivo é o seu código não é agora, porque você só corrigir uma variável fora do 'frame' limites quando o cronômetro carrapatos. Você poderia ter um evento ALLEGRO_EVENT_KEY_DOWN logo após um timer tick quadros incremento de 3,0 e, em seguida, (int) Access 3.0 em sua matriz sprites, que está fora dos limites.
Hi... Firstly, thank you! I fix the "update" as you show me , I'm thinking in a solution for animation now, when I'm moving my character... still give error in the third movement, I'm to look for what you said about "frame".
EDIT1: When this party is separated of the function that draw give the error, but a time loaded the images should be stored without the need to reload... I think!
... sprites.push_back(al_load_bitmap("Sprites/FFT1/21.bmp")); sprites.push_back(al_load_bitmap("Sprites/FFT1/22.bmp")); sprites.push_back(al_load_bitmap("Sprites/FFT1/23.bmp")); ...
EDIT 2: I think this is wrong, but it's the only way I could make it work.
Don't load during update. Only load your images once.
++frame; if ((size_t)frame >= sprites.size()) { frame -= (float)(sprites.size() - 1); }
Let me make a correction - I gave you the wrong code earlier - it should be :
frame += inc;// inc must be in the range [0.0 , sprites.size() ) if (frame >= (float)sprites.size()) { frame -= (float)sprites.size(); }
The 'inc' variable is a floating point increment to let you change the frame by less than one. Set it to whatever works for you.
Hi, I updated the code how you said, but still give the same error.
I can't keep guessing what is wrong. Either post your latest full code, or learn how to use a debugger.
You're probably accessing an element outside the boundaries of the vector again. Check for that first.
My last code:
/* Test */ int cx = 10; int cy = 10; int inc = 0.0; float frame = 0; std::vector<ALLEGRO_BITMAP*> sprites;
Draw Character:
void draw_character() { al_convert_mask_to_alpha(sprites[(int)frame], (al_map_rgb(255, 0, 255))); al_draw_bitmap(sprites[(int)frame], cx, cy, 0); }
Update:
Main loop:
Main:
Main loop :
case ALLEGRO_EVENT_KEY_DOWN: if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { cx -= 5; cy -= 5;frame++;break; }
You're still mixing ALLEGRO_EVENT_KEY_DOWN with al_key_down, and you're not checking the bounds of your sprites vector when you modify 'frame'.
Also, you're still converting your bitmap every time you draw it - only convert it once when you load it.
Você ainda está com a mistura ALLEGRO_EVENT_KEY_DOWN al_key_down, e você não está verificando os limites do seu vetor sprites quando você modifica 'frame'.
Além disso, você ainda converter o bitmap de cada vez que desenhá-la - só convertê-lo uma vez quando você carregá-lo.
It might help simplify things if you tried out my basic animation class :
animation class
Then your setup code would look like this :
And you would use it like this :
if (ev.type == ALLEGRO_EVENT_TIMER) { anime.AdvanceFrameTime(1.0/FPS); redraw = true; } // ...... if (redraw) { clear_to_color(al_map_rgb(0,0,0)); anime.Draw(character_x , character_y); al_flip_display(); redraw = false; }
Well... I'm trying to use the animation class but I no have slightest idea where will every thing.
The setup code will inside of main?
Yes, the setup code would go in main, after you initialize allegro and the image addon and create a display.
Hi, again
http://www.allegro.cc/forums/thread/607529/920236#target
... try { frames = new ALLEGRO_BITMAP*[framecount]; } catch { frames = 0; return false; } num_frames = framecount; } ...
That would be "catch(Animation) {..." ?
No, it should have been :
try { frames = new ALLEGRO_BITMAP*[framecount]; }catch (...) {frames = 0; return false; } num_frames = framecount;
Theoretically it would be something more or less so?
Not quite - redraw goes outside of the event loop, and you shouldn't draw during your logic (you do it in the ALLEGRO_EVENT_KEY_CHAR check). Always separate logic from drawing.
Não é bem assim - redesenhar vai para fora do ciclo de eventos, e você não deve chamar durante a sua lógica (que fazê-lo na seleção ALLEGRO_EVENT_KEY_CHAR). Sempre lógica separada do desenho.
Now is almost 04:00 in Brazil and I'm totally lost, sleep will not let me think straight, I go to bed and when I wake up I try to solve it, thanks a lot!
Let me know how it goes.
Here, my last code:
while (!quit) { if(redraw) { al_clear_to_color(al_map_rgb(0,0,0)); anime.Draw(cx , cy);break;} al_flip_display(); redraw = false; }
Without that break statement, you will be stuck in that loop forever, because quit is always false. With the break statement, you only clear the screen and draw the animation, but don't flip the display.
Your drawing code goes inside your game loop.
@@"
edit1: So I do not need to do a "if(redraw).." ?
You don't have to use a redraw flag, but it makes it clearer. Also, it probably looks better if you only redraw when the timer goes off.
The part of animation is correct?
Edit 1: I can to put the "event timer" and then redraw or is better I to put the timer in a "case" in the end?
Game loop :
Look:
It looks fine to me.
So does it work or what?
Just to know if it was right =D
The animation I have to add anything ?
class of the another topic
code that I put in the main!
It still looks fine - does it work or not?
Hi, sorry for delay... I was trying to discover before to ask help!
yeah, My animation no work!
Edit1: Oddly enough... rs... I think this time the indentation are totally right. o_O"
Main:
Sorry, there was a bug in the frame setting code in SetFrameTime. This version should work properly. Just replace the old class with this one.
The bug was in SetFrameTime here :
void SetFrameTime(double frame_time) { // simple forward repeating animation time_passed = frame_time; while (time_passed >= duration) {time_passed -= duration;} while (time_passed < 0.0) {time_passed += duration;}frame_number = (int)((float)num_frames*(time_passed / duration));// shouldn't be necessary, but just in case if (frame_number < 0) {frame_number = 0;} if (frame_number >= num_frames) {frame_number = num_frames - 1;} }
All your code seems (e.g. the 'sprite' vector, the load function, etc) to be set on having just one sprite. What about other sprites in the game or different animations for the same sprite (e.g. moving left, right, jumping, etc).
What you should do is as well as having an animation class, have an animation manager class to store all your animations (I used a config file that stored each animation in a stl map so you could retrieve by namem this also means you don't hard code bitmap names into the executable).
Regarding the Animation class, in my animation I added a set of actions (e.g. pause, manual increment, frame based increment), a sprite step mode (i.e. what happens when you move from one frame to the next and/or get to the start/end) for example FORWARDONLY (first to last then stay at last from), BACKWARDONLY, FLIPFLOP (repeat forwards, backwards), REPEATFORWARD (at end go back to start) and a basic event (i.e. function pointer) to trigger when animation ends (handy for setting an action, like a dying animation then informing the system that the death throws are finished).
Hi... no problem Edgar... Thanks a lot!
Hi Neil, thanks for tips, maybe I use: http://oi54.tinypic.com/2qjvxig.jpg and al_create_sub_bitmap
Edit 1: I saw in the another topic an cool example, I made ​​a small correction!
I realize that this makes the image to animate in all positions, if I want my image to animate for each moviment, RIGHT, LEFT, UP, DOWN I had to do something similar and split into frames?
It would be an animation for each move?
I realize that this makes the image to animate in all positions, if I want my image to animate for each moviment, RIGHT, LEFT, UP, DOWN I had to do something similar and split into frames?
It would be an animation for each move?
Yes, there would be a separate animation for each.
ALLEGRO_BITMAP* bmp_array[40]; for(int x = 0; x < 8; x++) { for(int y = 0; y < 5; y++) { bmp_array[x][y] = al_create_sub_bitmap(bmp, 32*x, 32*y, 32, 32); anime.SetBitmap(bmp_array[x][y] , i); ++i; } }
That is not good coding. You've declared a shadowed variable named bmp_array, and you are assigning the bitmaps to the local bmp_array, not the bmp_array you declared on the first line. That means every sub bitmap created there will be leaked, because the Animation class does not destroy the ALLEGRO_BITMAP*'s that it holds. If you're using MinGW as your compiler, then you should add the compiler flag -Wshadow to your compilation command. It will tell you when you are shadowing (creating more than one variable with the same name) variables.
Isso não é bom de codificação. Você declarou uma variável chamada bmp_array sombra, e você atribuir o bitmaps para o bmp_array local, não a bmp_array você declarou na primeira linha. Isso significa que cada sub bitmap criado haverá vazamento, porque a classe Animação não é destruir o * ALLEGRO_BITMAP 'que detém. Se você estiver usando MinGW como seu compilador, então você deve adicionar o compilador bandeira Wshadow para o comando de compilação. Ele lhe dirá quando você está sombreamento (criando mais de uma variável com o mesmo nome) variáveis.
I saw this code this topic: http://www.allegro.cc/forums/thread/607037/913972#target
I stayed curious to see but do not compiled... so I put this way with the leaked just to see.
I'm trying to do of way that I can to have the animations for all movements for when a key is pressed.
I do not know if is better to have all movements in just one image or have all images apart.
If you're going to use my Animation class, you need to have a separate Animation for each movement of the character - one for left, right, up, down. The Animation class is currently not copy-able, so you can't store it directly in a map, but you could use a map of pointers :
This is just an example, but it should show you how to switch between animations, and only update the animation when you are moving.
Hello, to use "SetBitmap" he needs a member, which I use, already there is:
Anime animation [4];
Anime [0]. reallocate (3, 3.0);
Animation anime[4]; anime[0].Reallocate(3 , 3.0); ALLEGRO_BITMAP* bmp1 = al_load_bitmap("FFT_21.bmp"); anime[0].SetBitmap(0 , bmp1); // repeat for bitmaps 0-2 // repeat for anime[0] thru anime[3]
This way?
Do I have to redraw?
Something like "anime[0].Draw(cx, cy);" ?
or the fact to be a "current frame" him redraw automatically!
Hi... I put this way and work! "Since last post I just change "anime.Draw(cx,cy)" for "current->Draw(cx, cy);"
I just could not update the sprite at every turn, it updates after a long time the button pressed.
Your 'if (redraw)' block should not be inside your 'while (1)' loop.
You also need to break out of the 'while (1)' loop when there are no more events, so you can redraw.
Edit
Actually, never mind what I just said. Your code looks like it should do what you want it to. It waits for an event, then processes it appropriately. One thing though - you never set redraw to false, so it redraws every time there is an event. Not really a problem though.
You can try shortening the duration of the animation :
anime[0].Reallocate(3 , 1.0);
Hi, I changed for "anime[0].Reallocate(4 , 0.1);" and stayed a little better... Thanks a lot!
Now I'm beginning to do a isometric map with some tiles that I have!
Edit1: I can add my "map_draw();" in the "if(redraw){" or I have to create a class for him and to do it work with the "current->" ?
Edit2: Hi... I removed the "if(redraw) {" and add the "if (al_event_queue_is_empty(event_queue)) {" in your place for put the "map_draw();" , but I think this did not the right way!
... while (!quit) { while (1) { ALLEGRO_EVENT ev; if (al_event_queue_is_empty(event_queue)) { current->Draw(cx, cy); al_flip_display(); al_clear_to_color(al_map_rgb(0,0,0)); map_draw(); } al_wait_for_event(event_queue , &ev); if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { ...
Edit1: I can add my "map_draw();" in the "if(redraw){" or I have to create a class for him and to do it work with the "current->" ?
Yes, just add map_draw() to the 'if (redraw)' block.
I removed the "if(redraw) {" and add the "if (al_event_queue_is_empty(event_queue)) {" in your place for put the "map_draw();" , but I think this did not the right way!
Think about it - do you want to redraw when the timer goes off, or do you want to redraw when the event queue has been fully processed?
When I used the "if(redraw) {" and add "map_draw();" the movement of the character stayed with a imense lag.
map_draw(): http://oi51.tinypic.com/1zdywyo.jpg
I think with the time will to give bug!
If the character movement is lagging behind, you are either not altering it's position often enough, or you are not redrawing enough.
I think with the time will to give bug!
What?
Hi, I thought in to create an animation for the character when I press the key F1, but I remember what has many positions: RIGHT, LEFT, UP... has some event that check the last key press for I can to make the animation from him when not in motion.