Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Allegro Wait for Event(Pretty slow)

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Allegro Wait for Event(Pretty slow)
Thomas Fjellstrom
Member #476
June 2000
avatar

Events are only slow if you don't make sure to drain/use-up all the events before drawing the next frame. They back up, and will start slowing all input and rendering down.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Lísias de Castro
Member #14,882
January 2013
avatar

If this way I am using is wrong, why it does work when I catch by the state's function?!
The al_wait_for_event behavior is not the same as al_get_keyboard_state and al_get_mouse_state. It is working normally with the last 2, even with a lot of objects on the screen. Behind them there are great deal of memory to handle, and even so it works well with those damned functions ??? ...
I will wait for thoru's answer in order to see if he could figure the bug out.

Thomas Fjellstrom
Member #476
June 2000
avatar

State doesn't get backed up if you don't check it often enough. Events do.

Try this.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Lísias de Castro
Member #14,882
January 2013
avatar

Hey Thomas. I have tried exactly the way you show me right now.
But it kept in the same way as before. The only choice I am seeing
now is continue to use the al_state functions. When I try to use
the function camera_mouse_move which catches the axis from the mouse,
it only updates when I move the axes. This way I am not able to do a
function like "mouse_over". Because I have to move the mouse to prove
it is in somewhere. Otherwise, with al_get_mouse_state, I don't need to
move the mouse to verify that it is in somewhere in on the screen.
I think the problem here is the way the function al_wait_for_event was
designed to. I think it has been designed not to get a lot of memory from
the program, but it coast some important factors. :(
About the keyboard.keycode, it is not very good either, because I am only
able to get one key at time. While with al_get_keyboard_state I am able to
use multiple keys, just like on the example I posted in here. It's a shame
that the events catched by al_wait_for_event does not work like that... I
guess it could be using less memory in the whole system. :'(

Thomas Fjellstrom
Member #476
June 2000
avatar

That same code and code like it works great for many people. It is extremely likely you are doing something wrong.

I don't need to
move the mouse to verify that it is in somewhere in on the screen.

You can just store the last position of the mouse somewhere and use that :P

Quote:

it coast some important factors.

It really doesn't.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Lísias de Castro
Member #14,882
January 2013
avatar

By creating two more variables I am getting more memory from the system in anyway.
It could be really wise doing this? ???

Thomas Fjellstrom
Member #476
June 2000
avatar

Two integers isn't going to make a lick of difference. The state functions create a much larger struct to store its data.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Lísias de Castro
Member #14,882
January 2013
avatar

But this suggestion could only solve my mouse problem. What about the keyboard, there is a way to get multiple keys through events too? ???
And thinking about structures, If I don't register the mouse and keyboard events inside the event_row it won't get my memory I think. Can you tell me if those registers that I did not do could be worth the variables state. Instead of load the mouse and keyboard register I load the keyboard and mouse states.

Thomas Fjellstrom
Member #476
June 2000
avatar

But this suggestion could only solve my mouse problem. What about the keyboard, there is a way to get multiple keys through events too?

Each key press comes with one or more (usually more) events. A KEY_DOWN, a KEY_UP and sometimes a KEY_CHAR (sometimes many if key repeat is on).

When you get an event, you store it in your game some place where you can check to see what keys are pressed. With events you can even avoid losing key presses. With the keyboard state struct, you always store all key state. if you stored it yourself, you'd only have to store what keys you need.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

torhu
Member #2,727
September 2002
avatar

I don't think I have anything to add, I agree with Thomas ;)

Lísias de Castro
Member #14,882
January 2013
avatar

All right. So I have to figure out how to do it myself.
Anyway thank you all.

Neil Roy
Member #2,229
April 2002
avatar

You seem to me to be worried about all the wrong things. Function calls slowing things down by an amount that nobody can notice and 8 bytes of memory taken up by using two variables to store values, when you're program is slowing down.

I have variables I store the values into, if someone cannot afford 8bytes of memory these days, it's time to take up a new hobby, knitting maybe. ;)

I use all of the suggestions that Thomas and torhu suggest and my games run smoothly. Actually, I can think of a few improvements after reading this (I probably don't use enough functions either). About functions, your compiler can do some things which make these just as fast, inline functions etc... for example, so I wouldn't worry about those. The benefits you gain from organizing your code far outweighs any speed or memory losses you will get! When you have repeating code, you have an increased chance of getting a bug that will be more difficult to track down. Also, you can update a function and you're done, no need to search through your code and update who knows how many lines of code (and if you forget to do one, as I have, you are really screwed because they can be a bitch to track down!).

Another thing is that the event queue can be cleared if you think it is getting bogged down, although I prefer to deal with what is in there, that could be a solution depending on your situation.

Personally, I have a key array where I store the state of each keypress as it comes in (thereby emptying the queue) then dealing with them later on and resetting the key state in that array. This becomes very important if someone is holding down a key and the queue is getting filled up with that keypress, you want to clear it out of there. Same for the mouse.

I would also check your timers, make sure they're set properly. Try profiling your code to see where it is being slowed down etc. But the problem is not with Allegro.

In my own Deluxe Pacman 2 game, my main game loop is something like this (I can't post the actual code, it is too lengthy)

(coded in C 2011, so some may need to be altered for VC)

#SelectExpand
1while(!done && !pacman.dead) { 2 al_wait_for_event(event_queue, &event); 3 4 switch(event.type) { 5 case ALLEGRO_EVENT_DISPLAY_CLOSE: 6 // do stuff here 7 break; 8 case ALLEGRO_EVENT_KEY_DOWN: { 9 int k = event.keyboard.keycode; 10 switch(k) { // deal with some keypresses here 11 case ALLEGRO_KEY_ESCAPE: 12 // do stuff here 13 break; 14 case ALLEGRO_KEY_UP: 15 // do stuff here 16 break; 17 } 18 // store all keypresses here 19 pressed_key[k] = true; 20 break; 21 } 22 case ALLEGRO_EVENT_KEY_UP: { 23 int k = event.keyboard.keycode; 24 switch(k) { // deal with some key up events immediately 25 case ALLEGRO_KEY_LCTRL: 26 case ALLEGRO_KEY_RCTRL: 27 // do stuff here 28 break; 29 } 30 // reset key array member to indicate it is no longer pressed 31 pressed_key[k] = false; 32 break; 33 } 34 case ALLEGRO_EVENT_TIMER: 35 // update player and enemy movement here 36 } 37 38 if(redraw) { // set true usually when there is movement or timer etc 39 // update display 40 } 41}

Note, I don't have mouse code in here, but I would deal with it by adding in a new CASE to do with it as I do keyboard if needed and setting variables to store the mouse values. Variables only take up 4 bytes of memory (8 bytes for 64bit) so when modern computers measure RAM in the gigabytes, I wouldn't worry about a few extra variables. ;)

---
“I love you too.” - last words of Wanda Roy

Thomas Fjellstrom
Member #476
June 2000
avatar

Neil, that loop doesn't seem to be draining the event queue every frame ;) Maybe you trimmed a little too much out when posting?

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Neil Roy
Member #2,229
April 2002
avatar

Neil, that loop doesn't seem to be draining the event queue every frame ;) Maybe you trimmed a little too much out when posting?

Hmmm... you seem to be right about that. I may need to insert a while loop in there to drain it. Never noticed that before, but then it never slows down or causes me problems. I may have to do that. :)

Edit 2: OH, I see what you are talking about, yeah... I did leave some out! I probably shouldn't have as it is the point of it all... but my display update part ACTUALLY looks like this! ;)

if((redraw == true) && (al_is_event_queue_empty(event_queue) == true)) {
   redraw = false;

   if(!update_screen(cplayer)) {
      shut_down();
      exit(1);
   }

   al_flip_display();

   frames++;
   fps = (double)frames / (al_get_time() - start_time);
}

I guess I did trim that down a tad too much. :P (not sure why I put `== true` in there)

Anyhow, that will not redraw t he screen while the queue is not empty, so it just runs in that loop handling all the events before it updates the display and continues.

---
“I love you too.” - last words of Wanda Roy

Bruce Pascoe
Member #15,931
April 2015
avatar

@Thomas:
So draining the event queue (as via while loop) is encouraged then? I remember reading in another thread here that the common wisdom is not to do that, but rather to only pump through one event at a time. I don't remember what the thread was now...

Thomas Fjellstrom
Member #476
June 2000
avatar

@Thomas:
So draining the event queue (as via while loop) is encouraged then? I remember reading in another thread here that the common wisdom is not to do that, but rather to only pump through one event at a time. I don't remember what the thread was now...

The only argument I know about is really just a stylistic choice.

while(!done)
{
  wait_for_event(&evt);
  if(evt.type == TIMER)
  { 
    draw == true;
  }

  if(draw == true && queue_empty(queue)) 
  {
    drawStuff(); 
  } 
}

Vs.

#SelectExpand
1while(!done) 2{ 3 while(!queue_empty(queue)) 4 { 5 if(!get_next_event(&evt)) 6 break; 7 8 if(evt.type == TIMER) 9 { 10 draw = true; 11 } 12 } 13 14 if(draw) 15 { 16 drawStuff(); 17 } 18}

I happen to prefer the former, with the single loop. But they are functionally equivalent.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Neil Roy
Member #2,229
April 2002
avatar

I happen to prefer the former, with the single loop. But they are functionally equivalent.

Agreed. I may change my code to look more like the second example you posted though. The extra loop makes it more readily apparent as to what it is doing, which to me is more important.

I am wondering though if this setup could possibly lead to some "hiccups" in the game? That is to say, you're playing it and the characters seem to jump perhaps or possible delays due to an event queue being too full? On faster systems this would probably not be an issue, but on slower systems I am wondering if it would be? Maybe extra code in there that sets a limit on how long the game stays in that loop emptying the queue before perhaps it is forced to redraw.

---
“I love you too.” - last words of Wanda Roy

Thomas Fjellstrom
Member #476
June 2000
avatar

If you have too many events to handle in a given frame, the drawing of that frame may be skipped. Basically what the loops do (when they check for the queue being empty) is give you "frame dropping" in case your loop takes too long to execute in the time you asked for given the logic timer. You can get two or more timer events in the queue, but not actually act until the queue empties.

If things are SUPER slow, you're just never going to render. At that point you want to force a minimum draw interval. that slow's the actual logic, but it may be better than never rendering anything ;) In the end, dropping too many frames or slowing logic is usually bad and you need to be able to reduce the complexity of your scene and/or logic to get back to a decent frame and logic rate.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Lísias de Castro
Member #14,882
January 2013
avatar

Well. I have looked in many sites and could not discover out a single way to deal multiple keys with keyboard.keycode. This code that Ney have posted can't show either.
So I decided to knit. I've heard the allegro community was the best helping people... :'(

Thomas Fjellstrom
Member #476
June 2000
avatar

This code that Ney have posted can't show either.

A single event carries one key. But you can store key state in your code, so you can then check to see if more than one of the keys you care about are currently pressed, and for how long as the event carries the time the key was first pressed.

You don't have to process your movement logic when a key is pressed, rather you handle it when you do you get your logic timer event.

Quote:

I've heard the allegro community was the best helping people... :'(

We're not bad. But it seems to some of us that you've been ignoring helpful advice and just want us to give you code.

What I (and others) suggest is in the key down event, you store the key state in an array like Neil suggested, in the key up event you clear that state, and in your timer event, you process your logic, like movement, and actions based on the current state stored in your array. That way, you can tell that multiple keys are pressed, and logic happens at even intervals, instead of whenever you get input events.

I'm basically trying to get you to understand what you need to do so you can do it yourself, rather than giving you the solution as code. Give a man a fish, etc.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Neil Roy
Member #2,229
April 2002
avatar

I've heard the allegro community was the best helping people.

This community is helpful, but if you're looking for someone to write code for you, you might want to hire someone. I doubt you will get much better anywhere else.

I just posted my own code (or a skeleton of it) that works for me.

Quote:

Well. I have looked in many sites and could not discover out a single way to deal multiple keys with keyboard.keycode.

If you need more than one key to be pressed at the same time, than you need to avoid things like:

if(ALLEGRO_KEY_A) {
  // do stuff if 'A' is pressed
}
else if(ALLEGRO_KEY_B) {
  // do stuff if 'B' is pressed
}
else if(ALLEGRO_KEY_C) {
  // do stuff if 'B' is pressed
}

The above code will only respond to one keypress at a time.

if(ALLEGRO_KEY_A) {
  // do stuff if 'A' is pressed
}
if(ALLEGRO_KEY_B) {
  // do stuff if 'B' is pressed
}
if(ALLEGRO_KEY_C) {
  // do stuff if 'B' is pressed
}

...the above code will respond to every keypress, like when more than one are pressed.

You might want to create a key array like key_pressed[] and set the keys that are pressed, then you can deal with them later in your code with...

k = event.keyboard.keycode;
if(key_pressed[ALLEGRO_KEY_A] && key_pressed[ALLEGRO_KEY_B]) {
  // do stuff if both keys are pressed at once
}

If you look in the code I posted earlier you will see I do precisely that. I deal with certain keys that need to be dealt with immediately, and the rest are stored in the array to be dealt with as needed. In my game I detect two keys at once for example if the player presses CTRL+ARROW, the game knows to speed up in the direction pressed.

It's really straight forward coding. If you don't know how, you will need to experiment and think it through like everyone else. It's why you don't see everyone programming. :)

---
“I love you too.” - last words of Wanda Roy

torhu
Member #2,727
September 2002
avatar

If he's going to store the keyboard and mouse state anyway, he might just as well use Allegro's state functions :P

Another way to do it when using events is to do the relevant movement logic as each event is received. That way nothing gets missed, and the order of keypresses is not partially lost.

Thomas Fjellstrom
Member #476
June 2000
avatar

I don't think you actually want to do the logic as soon as the events come in in all cases. It really depends on what you want to do. Maybe tell the "thing" that some event came in, and then it handles that in its logic update. In the end it just moves the state around.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

 1   2 


Go to: