Problem! WM_KEYDOWN messages are interfering with WM_TIMER messages!

Started by
5 comments, last by Anachronism 21 years, 3 months ago
Hello, My problem isn''t related to games so this post DOES belong in this category. OK... I''m making a tetris clone. For the most part I''m done. The only element of gameplay left is tweaking the controls just right. There are 4 events a user can cause that will affect the falling game peice. Left Arrow and Right arrow move it left and right. Up arrow rotates the object. Down Arrow moves the object down a unit. There is 1 event caused by a timer. When a timer message is received the gamepeice falls down a unit. The problem is this... when hitting a directional key, the block moves SUPER fast. It registers as many keystrokes unless you can hit the very fast. To get around this I did the following: 1) I created a variable: static bool keyDownOnce; 2) When a keydown event is registered, if keyDownOnce is true, then the game peice will either move left, right, or down depending on the keydown event. 3) keyDownOnce is set to false. 4) When a keyup event is registered, it sets keyDownOnce to true. This way a key has to come up and go back down again before it will register as multiple keypresses. This works good. On to my problem..... Another event can make the game peice fall down besides the down arrow. The timer event. Here is the code for when the timer event registers:
  
        case WM_TIMER:

            switch(wParam) {

                case DROP_TIMER:

                   keyDownOnce = true;
                   PostMessage(hwnd, WM_KEYDOWN, VK_DOWN, NULL);

                break;

            }

            break;
  
By itself, this works beautifully as well. The problem is combining the user controls with the timer event. If you press an arrow key, in the middle of the timer event executing keyDownOnce is in the middle of being processed and the arrow key wont register. I tried created another variable like this just for the timer so each event could run on its own path... But I still get problems... Any ideas or help is greatly appreciated. I don''t want to sleep until I get this done Thanks -Dennis
Advertisement
I think you should not post a KEYDOWN/VK_DOWN message when you process your DROP message. Both message KEYDOWN/VK_DOWN and DROP should call the same function controlling the piece fall.


  /* used to hold for each direction wether the key was used once or more /**//* this is usefull if you press together down and left: the piece will fall diagonally to the left/**/char KeyDown[4];...*** In the message pump ***...case WM_TIMER:   switch(wParam) {      case DROP_TIMER:         Make_Piece_Fall();         break;         }   break;...case WM_KEYDOWN:   switch(wParam) {      case VK_DOWN:         ++KeyDown[0];         if (KeyDown[0] == 1)            Make_Piece_Fall();         break;   }   break;...case WM_KEYUP:   switch(wParam) {      case VK_DOWN:         KeyDown[0] = 0;         break;   }   break;  

Hope that helps.
Ghostly yours,
Red.

PS: I used that icon because it is the closest to a christmas tree under the snow. Merry XMas. Red.
Ghostly yours,Red.
You can test bit 30 of the lParam for WM_KEYDOWN messages to see if the key was down before the message was sent (i.e. if its been held down)

Member of the Unban Mindwipe Society (UMWS)
not sure if this is smart, but since ur lparam is unused, y not use it as a means of testing for the timer-triggered movement...

- To learn, we share... Give some to take some -
Red Ghost,

I originally tried doing what you recommended with both events calling the same function, and I have been trying again since you posted.

That will just not work right. I''m not sure why.

But when I take the same code under the VK_DOWN event, and paste the code right under the WM_TIMER event, the blocks fall down very fast, almost instantly.

The only explanation I have for why it would be doing this, is if every time a timer event registers it posts it many many times.

I don''t know why it would do that...

Evil Bill,

Thanks for the suggestion, but I don''t think that helps my problem.

crazee,
Thanks, that sounds like kind of a last resort thing... And I''m almost there

Any suggestions from anyone are still greatly appreciated.

Thanks...

-Dennis
Hey,

I followed a very similar path a few years ago when I made my Tetris clone. While I got the rest of the game up and running, I used the windows message system for input, eventually replacing it with DirectInput. My advice is to switch to DirectInput. I found that the latency in the windows message system made the game almost unplayable.

Also, don’t use the WM_TIMER message for timing (basically, avoid using the message system for anything you expect real time performance from). They, like the WM_PAINT message, have a lower priory than other messages, so their processing can be delayed. And yes, if they are delayed long enough they will queue up. Once the other messages have been processed any WM_TIMER messages will run through one after the other.

I don't think the issues I just spoke of are affecting your game, but I'd hate to see you spend time fixing your current implementation only to find that it simply doesn't perform.


[edited by - Solo on December 24, 2002 1:02:46 PM]
// Ryan
You really need to separate the input and timer events from the actual action of making the block drop. Red Ghost had the right idea. Faking events so that you only do something in one place is going to make your code confusing and difficult to maintain. You didn''t really say why it didn''t work, but I do believe that you should try again as that is the ''best'' way of doing it.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

This topic is closed to new replies.

Advertisement