Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [a5] Problem with upgrade of images/text and loop

This thread is locked; no one can reply to it. rss feed Print
[a5] Problem with upgrade of images/text and loop
Jefferson Almeida
Member #12,659
March 2011

I tried to use "map_edit();" after of state2 == QUESTMODE; but did not work, appears only if I'm holding the ENTER and when I try add a new "if" or "switch", my screen stayed flashing between images and the text of map_edit().

void map_edit()
{
    bool passa = false;

    al_clear_to_color(al_map_rgb(0, 0, 0));

    font2 = al_load_ttf_font("DejaVuSans.ttf", 15, 0);
    al_draw_text(font2, al_map_rgb(255, 255, 255), 300, 300, 0, "Editor de Mapa Isometrico");
    al_draw_text(font2, al_map_rgb(255,255,255),300, 320, 0," Selecione o que deseja fazer");
    al_flip_display();
};

#SelectExpand
1bool redraw = true; 2while (!doexit) { 3 if (redraw) { 4 al_clear_to_color(al_map_rgb(0,0,0)); 5 al_draw_bitmap(remakelogo, 150, 150, 0); 6 al_draw_bitmap(credits, 120, 451, 0); 7 switch (state) { 8 case PRESSKEY : 9 myflasher.Draw(); 10 break; 11 case SHOWSTART : 12 al_clear_to_color(al_map_rgb(0,0,0)); 13 al_draw_bitmap(remakelogo, 150, 150, 0); 14 al_draw_bitmap(credits, 120, 451, 0); 15 16 al_draw_bitmap(newgame, 250, 280, 0); 17 al_draw_bitmap(continuar, 250, 296, 0); 18 al_draw_bitmap(questmode, 250, 312, 0); 19 al_draw_bitmap(quit, 250, 328, 0); 20 21 al_draw_bitmap(seta, 280, 395 + 16*menu_choice, 0 ); 22 break; 23 } 24 al_flip_display(); 25 redraw = false; 26 } 27 while (1) { 28 ALLEGRO_EVENT ev; 29 al_wait_for_event(event_queue , &ev); 30 switch (state) { 31 case PRESSKEY : 32 if (ev.type == ALLEGRO_EVENT_TIMER) { 33 myflasher.Update(1.0/FPS); 34 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 35 if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 36 state = SHOWSTART; 37 } 38 } 39 break; 40 case SHOWSTART : 41 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 42 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 43 doexit = true; 44 } 45 else if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 46 if (menu_choice > 0) { 47 menu_choice--; 48 } 49 } 50 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 51 if (menu_choice < NUM_MENU_ITEMS-1) { 52 menu_choice++; 53 } 54 } 55 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 56 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 57 } 58 else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 59 } 60 else if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 61 switch (menu_choice) { 62 case 0 : 63 state2 = STARTNEWGAME; 64 case 1 : 65 state2 = LOADGAME; 66 break; 67 case 2 : 68 state2 = QUESTMODE; 69// map_edit(); 70 break; 71 case 3 : 72 doexit = true; 73 break; 74 } 75 } 76 } 77 } 78 } 79 if (ev.type == ALLEGRO_EVENT_TIMER) { 80 redraw = true; 81 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 82 doexit = true; 83 break; 84 } 85 if (al_is_event_queue_empty(event_queue)) {break;} 86 } 87} 88 return 0; 89} 90 91 92 93//END_OF_MAIN()

Edgar Reynaldo
Member #8,592
May 2007
avatar

I tried to use "map_edit();" after of state2 == QUESTMODE; but did not work, appears only if I'm holding the ENTER and when I try add a new "if" or "switch", my screen stayed flashing between images and the text of map_edit().

Use a single state variable. In your if (redraw) {/*...*/}, check for the state there, and then call map_edit (which would be more appropriately named draw_map_editor_intro).

Use uma única variável de estado. Em sua if (redraw) {/*...*/}, para verificar o estado lá, e depois chamar map_edit (o que seria mais apropriadamente chamado draw_map_editor_intro).

Jefferson Almeida
Member #12,659
March 2011

I try something like:

if (redraw) {
   if (state2 == QUESTMODE){
   draw_map_editor_intro();
   }
...

but, did not work!

Edgar Reynaldo
Member #8,592
May 2007
avatar

Edgar said:

Use a single state variable.

Use uma única variável de estado.

enum ProgramState {
   PRESSKEY,
   SHOWSTART,
   QUESTMODE,
   LOADGAME
};

ProgramState state = PRESSKEY;

Jefferson Almeida
Member #12,659
March 2011

Hi! I put everything into a single state but when they get to the part of the "menu_choice" I think happens any conflict.

enum GameState {
   PRESSKEY,
   SHOWSTART,
   STARTNEWGAME,
   LOADGAME,
   QUESTMODE
};

GameState state = PRESSKEY;

const int NUM_MENU_ITEMS = 4;
int menu_choice = 0;

I have to change the order of "case numbers" to work... but still gets all messy.
example, case 1: case: 2... etc

menu_choice code:

switch (menu_choice) {
                       case 0 :
                          state = STARTNEWGAME;
                          printf("teste...");
                       case 1 :
                          state = LOADGAME;
                       break;
                       case 2 :
                           state = QUESTMODE;
                       break;
                       case 3 :
                         doexit = true;
                       break;

ALL code!

#SelectExpand
1bool redraw = true; 2while (!doexit) { 3 if (redraw) { 4 al_clear_to_color(al_map_rgb(0,0,0)); 5 al_draw_bitmap(remakelogo, 150, 150, 0); 6 al_draw_bitmap(credits, 120, 451, 0); 7 switch (state) { 8 case PRESSKEY : 9 myflasher.Draw(); 10 break; 11 case SHOWSTART : 12 al_clear_to_color(al_map_rgb(0,0,0)); 13 al_draw_bitmap(remakelogo, 150, 150, 0); 14 al_draw_bitmap(credits, 120, 451, 0); 15 16 al_draw_bitmap(newgame, 250, 280, 0); 17 al_draw_bitmap(continuar, 250, 296, 0); 18 al_draw_bitmap(questmode, 250, 312, 0); 19 al_draw_bitmap(quit, 250, 328, 0); 20 21 al_draw_bitmap(seta, 280, 395 + 16*menu_choice, 0 ); 22 break; 23 } 24 al_flip_display(); 25 redraw = false; 26 } 27 while (1) { 28 ALLEGRO_EVENT ev; 29 al_wait_for_event(event_queue , &ev); 30 switch (state) { 31 case PRESSKEY : 32 if (ev.type == ALLEGRO_EVENT_TIMER) { 33 myflasher.Update(1.0/FPS); 34 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 35 if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 36 state = SHOWSTART; 37 } 38 } 39 break; 40 case SHOWSTART : 41 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 42 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 43 doexit = true; 44 } 45 else if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 46 if (menu_choice > 0) { 47 menu_choice--; 48 } 49 } 50 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 51 if (menu_choice < NUM_MENU_ITEMS-1) { 52 menu_choice++; 53 } 54 } 55 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 56 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 57 } 58 else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 59 } 60 else if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 61 switch (menu_choice) { 62 case 0 : 63 state = STARTNEWGAME; 64 printf("teste..."); 65 case 1 : 66 state = LOADGAME; 67 break; 68 case 2 : 69 state = QUESTMODE; 70 break; 71 case 3 : 72 doexit = true; 73 break; 74 } 75 } 76 } 77 } 78 } 79 if (ev.type == ALLEGRO_EVENT_TIMER) { 80 redraw = true; 81 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 82 doexit = true; 83 break; 84 } 85 if (al_is_event_queue_empty(event_queue)) {break;} 86 } 87} 88 return 0; 89}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Please start using consistent indentation in your code. It is really hard to read without it.

Por favor, começar a usar o recuo consistente em seu código. É realmente difícil de ler sem ele.

Don't check for the event type inside a block that has already checked the event type. You did this in your code, and the second if will never be executed :

Não verificar o tipo de evento dentro de um bloco que já verifiquei o tipo de evento. Você fez isso no seu código, eo segundo, se nunca vai ser executado:

if (ev.type == ALLEGRO_EVENT_KEY_CHAR) {
if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
} }

You're missing a break statement in case 0 of your switch (state) code :

Você está perdendo uma instrução break no caso de 0 a chave do código (estado):

                       case 0 :
                          state = STARTNEWGAME;
                          printf("teste...");
                          /// MISSING BREAK STATEMENT HERE!

I reformatted and fixed your code. I took out the bad if statements, added break statements where needed, and fixed all the indentation problems. If I have to reformat your code again, I will no longer help you. So, here it is :

Eu reformatado e fixa seu código. Tirei o ruim se as declarações, acrescentou quebrar declarações, quando necessário, e corrigiu todos os problemas de recuo. Se eu tiver que formatar o seu código novamente, eu não vou mais te ajudar. Então, aqui está :

#SelectExpand
1 2 3int main(int argc , char** argv) { 4 5///.................... 6 7 bool redraw = true; 8 while (!doexit) { 9 if (redraw) { 10 al_clear_to_color(al_map_rgb(0,0,0)); 11 al_draw_bitmap(remakelogo, 150, 150, 0); 12 al_draw_bitmap(credits, 120, 451, 0); 13 switch (state) { 14 case PRESSKEY : 15 myflasher.Draw(); 16 break; 17 case SHOWSTART : 18 al_clear_to_color(al_map_rgb(0,0,0)); 19 al_draw_bitmap(remakelogo, 150, 150, 0); 20 al_draw_bitmap(credits, 120, 451, 0); 21 22 al_draw_bitmap(newgame, 250, 280, 0); 23 al_draw_bitmap(continuar, 250, 296, 0); 24 al_draw_bitmap(questmode, 250, 312, 0); 25 al_draw_bitmap(quit, 250, 328, 0); 26 27 al_draw_bitmap(seta, 280, 395 + 16*menu_choice, 0 ); 28 break; 29 } 30 al_flip_display(); 31 redraw = false; 32 } 33 while (1) { 34 ALLEGRO_EVENT ev; 35 al_wait_for_event(event_queue , &ev); 36 switch (state) { 37 case PRESSKEY : 38 if (ev.type == ALLEGRO_EVENT_TIMER) { 39 myflasher.Update(1.0/FPS); 40 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 41 if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 42 state = SHOWSTART; 43 } 44 } 45 break; 46 case SHOWSTART : 47 if (ev.type == ALLEGRO_EVENT_KEY_CHAR) { 48 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 49 doexit = true; 50 } 51 else if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 52 if (menu_choice > 0) { 53 menu_choice--; 54 } 55 } 56 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 57 if (menu_choice < NUM_MENU_ITEMS-1) { 58 menu_choice++; 59 } 60 } 61 else if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER) { 62 switch (menu_choice) { 63 case 0 : 64 state = STARTNEWGAME; 65 printf("teste..."); 66 break; 67 case 1 : 68 state = LOADGAME; 69 break; 70 case 2 : 71 state = QUESTMODE; 72 break; 73 case 3 : 74 doexit = true; 75 break; 76 } 77 } 78 } 79 break; 80 } 81 if (ev.type == ALLEGRO_EVENT_TIMER) { 82 redraw = true; 83 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 84 doexit = true; 85 } 86 if (al_is_event_queue_empty(event_queue)) {break;} 87 if (doexit) {break;} 88 } 89 } 90 return 0; 91}

Your code is getting really complex because of all the states it has to handle. I would suggest moving your code into a class. It will allow you to separate handling of different states in your code very easily :

Seu código está ficando muito complexo, porque de todos os estados tem que segurar. Eu sugiro mover o seu código em uma classe. Ele permitirá que você separe tratamento de estados diferentes no seu código muito facilmente:

#SelectExpand
1 2enum GameState { 3 PRESSKEY, 4 SHOWSTART, 5 STARTNEWGAME, 6 LOADGAME, 7 QUESTMODE 8}; 9 10class Game { 11private : 12 GameState state; 13 14 // Drawing for each state 15 void DrawPressKey(); 16 void DrawShowStart(); 17 void DrawStartNewGame(); 18 void DrawLoadGame(); 19 void DrawQuestMode(); 20 21 // input for each state 22 void CheckPressKeyInput(ALLEGRO_EVENT& ev); 23 void CheckShowStartInput(ALLEGRO_EVENT& ev); 24 void CheckStartNewGameInput(ALLEGRO_EVENT& ev); 25 void CheckLoadGameInput(ALLEGRO_EVENT& ev); 26 void CheckQuestModeInput(ALLEGRO_EVENT& ev); 27 28public : 29 bool quit; 30 bool redraw; 31 32 33 Game() : state(PRESSKEY) , quit(false) {} 34 35 void Draw() { 36 switch (state) { 37 case PRESSKEY : 38 DrawPressKey(); 39 break; 40 case SHOWSTART : 41 DrawShowStart(); 42 break; 43 case STARTNEWGAME : 44 DrawStartNewGame(); 45 break; 46 case LOADGAME : 47 DrawLoadGame(); 48 break; 49 case QUESTMODE : 50 DrawQuestMode(); 51 break; 52 } 53 } 54 55 void CheckInput(ALLEGRO_EVENT& ev) { 56 switch (state) { 57 case PRESSKEY : 58 CheckPressKeyInput(ev); 59 break; 60 case SHOWSTART : 61 CheckShowStartInput(ev); 62 break; 63 case STARTNEWGAME : 64 CheckStartNewGameInput(ev); 65 break; 66 case LOADGAME : 67 CheckLoadGameInput(ev); 68 break; 69 case QUESTMODE : 70 CheckQuestModeInput(ev); 71 break; 72 } 73 if ev.type == ALLEGRO_EVENT_TIMER) { 74 redraw = true; 75 } 76 else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 77 if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 78 quit = true; 79 } 80 } 81 else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 82 quit = true; 83 } 84 } 85}; 86 87int main() { 88 89 Game game; 90 91 while (!game.quit) { 92 if (game.redraw) { 93 game.Draw(); 94 } 95 while (!game.quit) { 96 ALLEGRO_EVENT ev; 97 al_wait_for_event(event_queue , &ev); 98 game.CheckInput(ev); 99 if (al_is_event_queue_empty(event_queue)) {break;} 100 } 101 } 102 103 return 0; 104}

See how much cleaner that is?

Veja como muito mais limpo que é isso?

Jefferson Almeida
Member #12,659
March 2011

Hi, thanks! sorry for not using consistent indentation... I did not know!

Really with class the code stayed much cleaner :)
I'm reading about class... My doubt is like I'll to use the DrawPressKey()...
I tryed but..

undefined reference to `Game::DrawPressKey()'|

Edgar Reynaldo
Member #8,592
May 2007
avatar

You have to define the functions declared in the class, or you will get undefined references during linking.

Você tem que definir as funções declaradas na classe, ou você vai ter referências indefinidas durante a ligação.

Jefferson Almeida
Member #12,659
March 2011

Can you give me an example with one of the functions for I based me to do the rest?

Edgar Reynaldo
Member #8,592
May 2007
avatar

As an example :

void DrawPressKey() {
   al_clear_to_color(al_map_rgb(0,0,0));
   al_draw_bitmap(remakelogo, 150, 150, 0);
   al_draw_bitmap(credits, 120, 451, 0);
   myflasher.Draw();
   al_flip_display();
}

So now you will need to add your ALLEGRO_BITMAP*'s to your class, as well as your Flasher. That means you will need to load and free the ALLEGRO_BITMAP*'s in your class as well. You might want to load / free the ALLEGRO_BITMAP*'s based on your GameState too.

Então, agora você terá que adicionar o teu * ALLEGRO_BITMAP "para sua classe, bem como o seu pisca-pisca. Isso significa que você vai precisar carregar e livre é a * ALLEGRO_BITMAP "em sua classe também. Você pode querer carregar / grátis * ALLEGRO_BITMAP é baseado em seu estado de jogo também.

Jefferson Almeida
Member #12,659
March 2011

Thankful..., I get it to work, I just do not get the flasher, I have to put everything on class: "game" and remove the class Flasher?

Edgar Reynaldo
Member #8,592
May 2007
avatar

No, just add a Flasher object to your Game class.

Não, basta adicionar um objeto de pisca-pisca para a classe Game.

Jefferson Almeida
Member #12,659
March 2011

My "myflasher.Update(1.0/FPS);" work, but my "myflasher.Draw();" makes the program crash :|

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Yeah friend! If I put the myflasher.Draw() inside of the "void DrawPressKey() {" the program crash... if I put out of the void... do not work the flasher!

Edgar Reynaldo
Member #8,592
May 2007
avatar

The only reason al_draw_bitmap would fail is if you passed it NULL, or if you passed it an ALLEGRO_BITMAP* that was destroyed with al_destroy_bitmap.

Let's see (all) your code again.

O al_draw_bitmap única razão pela qual não é se você passou NULL, ou se você passou um * ALLEGRO_BITMAP que foi destruído com al_destroy_bitmap.

Vamos ver (tudo) o código novamente.

Jefferson Almeida
Member #12,659
March 2011

I had forgotten that detail, thanks! :)

Edgar Reynaldo
Member #8,592
May 2007
avatar

The problem is that you define your Flasher myflasher before you load your ALLEGRO_BITMAP* that you pass to it. So you are passing an uninitialized ALLEGRO_BITMAP* to the Flasher constructor.

Solution 1 :
Don't create your myflasher object until after you initialize Allegro and load your ALLEGRO_BITMAP*. Then you would have to pass a reference to your myflasher object to your game object, and so you would have to add a Flasher* to your Game class.

Solution 2 :
Add a Flasher object to your Game class and initialize it in the Game class constructor initialization list (Don't create your game object until after Allegro is initialized and the flasher's ALLEGRO_BITMAP* is loaded).

Solution 3 :
Add a Flasher* to your Game class. Create your Flasher myflasher object after initializing Allegro and loading the necessary ALLEGRO_BITMAP. Set the Game::Flasher* to the address of your myflasher object.

O problema é que você define o seu myflasher Flasher antes de carregar o * ALLEGRO_BITMAP que você passar para ele. Então você está passando uma * ALLEGRO_BITMAP inicializada para o construtor Flasher.

Solução 1:
Não crie o seu objeto myflasher até depois de inicializar Allegro e carregar seu ALLEGRO_BITMAP *. Então você teria que passar uma referência ao seu objeto myflasher para o objeto do jogo, e assim você teria que adicionar um * pisca-pisca para a classe Game.

Solução 2:
Adicione um objeto Flasher para sua classe Game e inicializá-lo na lista de inicialização do construtor da classe Game (Não crie o seu objeto de jogo até depois Allegro é inicializado e * o pisca-pisca da ALLEGRO_BITMAP é carregado).

Solução 3:
Adicionar Flasher * a sua classe Game. Crie seu objeto myflasher Flasher Allegro após inicializar e carregar o ALLEGRO_BITMAP necessário. Defina o jogo:: Flasher * para o endereço do seu objeto myflasher.

Jefferson Almeida
Member #12,659
March 2011

I tryed the option 3 but do not work! I'll have coffee and then review the code! Thanks a lot!

Edgar Reynaldo
Member #8,592
May 2007
avatar

An example of option 3 :

class Game {
private :
   Flasher* flasher;
   GameState state;
   bool redraw;
   bool quit;

public :
   Game() : flasher(0) , state(PRESSKEY) , redraw(true) , quit(false) {}

   void SetFlasher(Flasher* f) {flasher = f;}

///..... Same as before
};

And to use it :

// in main

// initialize allegro, load bitmaps

Flasher myflasher(bmp , 200 , 200 , 0.5);
Game game;
game.SetFlasher(&myflasher);

///..... Same as before

Jefferson Almeida
Member #12,659
March 2011

My code until was similar to yours, only a few details and the names
It is showing up: \ main.cpp | 98 | error: 'myflasher' was not declared in this scope |

#SelectExpand
1class Game { 2private : 3 Flasher* flasher; 4 GameState state; 5 6public : 7 bool quit; 8 bool redraw; 9 Game() : flasher(0) , state(PRESSKEY) , redraw(true) , quit(false) {} 10 11 void SetFlasher(Flasher* f) {flasher = f;} 12 13// as before 14}; 15 16// int main 17 18// allegro, load bitmaps... 19 20Flasher myflasher(bmp, 250, 320, 0.5); 21Game game; 22game.SetFlasher(&myflasher); 23 24// as before

Edgar Reynaldo
Member #8,592
May 2007
avatar

It is showing up: \ main.cpp | 98 | error: 'myflasher' was not declared in this scope |

Huh? That's odd. Show all of your code again.

Actually, I bet the problem is inside the definition of your Game class methods. You need to refer to it as 'flasher' now, not 'myflasher', because the member is named 'flasher' :

   void CheckPressKeyInput(ALLEGRO_EVENT &ev) {
      if (ev.type == ALLEGRO_EVENT_TIMER) {
flasher->Update(1.0/FPS);
} else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { if (ev.keyboard.keycode == ALLEGRO_KEY_ENTER); state = SHOWSTART; } }

   void DrawPressKey() {
      al_clear_to_color(al_map_rgb(0,0,0));
      al_draw_bitmap(remakelogo, 150, 150, 0);
      al_draw_bitmap(credits, 120, 451, 0);
flasher->Draw();
al_flip_display(); }

Jefferson Almeida
Member #12,659
March 2011

oh... I changed and it worked, thanks

Edgar Reynaldo
Member #8,592
May 2007
avatar

Yeah, that was the problem - you're referring to it as 'myflasher.' instead of 'flasher->'. See my edit in the last post.

Jefferson Almeida
Member #12,659
March 2011

I had forgotten that detail, thanks! :)

Go to: