Why Won't it work?

CryoEnix

Regular
Joined
Jan 11, 2003
Messages
93
Location
Wrexham, Wales
Hey guys - included here is the source code for a game I'm creating called 'Nukerz', a bomberman clone that I'm sure you're all familiar with.

Anyhoo, the problem is with the timers I use to move the player around - they only seem to last for about a second before cutting out by themselves. Simply run the program and click the 'test' label, and wait a few seconds to initialize it. The controls use WASD.

Please get back to me as to why the movement is staggered - I haven't even implemented collision detection yet, so I'm at a loss.

Oh, the movement code resides in the 'Player' class!

Thanks
 

Attachments

Last edited by a moderator:
Code:
Sub KeyDown
    If key is upArrow Then
        If char.CanMoveUp() Then
            char.Y = char.Y - movementSpeed
        End If
    ElseIf key is downArrow Then
        If char.CanMoveDown() Then
            char.Y = char.Y + movementSpeed
        End If
    ElseIf key is leftArrow Then
        If char.CanMoveLeft() Then
            char.X = char.X - movementSpeed
        End If
    ElseIf key is rightArrow Then
        If char.CanMoveRight() Then
            char.X = char.X + movementSpeed
        End If
    End If
    Paint()
End Sub
Sub Paint
    e.Graphics.DrawImage(char.Image, char.X, char.Y)
End Sub
There is no need for timers or such like becuase the KeyDown event is repeatedly called whilst the key is held down.
 
Interesting - but is the keydown event is triggered at different speed intervals depending on the PC, or is it consistent? I don't want faster computers getting an advantage...
 
To be honest I'm not sure if the repeat speed of keys varies dependent on the PC, but I would suggest it does. Well the best way forward is to have a fixed speed gameloop which checks the state of the key.

It sounds like your building a multiplayer game in which case most of the processing could be done server side. Basically you'd end up with something like the following.

- Clients KeyDown event sends a message to the server telling it that players pressed the button.
- On each game loop the server moves the clients character.
- Server then sends player positions to each client.
- Clients KeyUp event sends a message to the server telling it the player has stoped pressing the button.
- On each game loop the server doesn't move the clients character.

The servers game loop would look something like this.
Code:
while(gameAlive)
{
    // calulates any game logic like moving players, bomb explosions etc.
    UpdateGameStates() 
   
    // sends information back to clients
    UpdateClients()

     // waits for next permited game loop
    while(currentTime <= nextFrameTime)
    {
    }
    nextFrameTime = currentTime + frameLength
}

If I'm honest I'm not entirely sure how all of this would be programmed, but from the articles I've read about game development, this is the approach I would take.
 
For all intents and purposes the events should fire at the same rate. I wouldn't worry about leveling the playing field too much.
 
If you are looking at implementing a fixed rate loop (as Cags suggested) you will probably want to use the GetAsyncKeyState function.
Also DirectInput offers it's own means of getting at this information - however that is overkill for your needs.
 
Good catch. I have a couple of counter points, though.

1. Variable character repeat is intended to aid users with "mobility impairments", not gain an advantage in gaming. The default is the fastest rate. This would imply (at least to me) that the rate is determined by the OS, not the CPU. reference

2. Graphics rendering and network performance will have a greater impact on gameplay than the rate at which key events are fired. These are factors that are very hardware dependent. You should spend more time optimizing these factors than worrying about event fire rates in my opinion.

Another possible solution:
What about catching the key down event, setting a flag, moving while the flag is true, and catching the key up event, unsetting the flag, and stop moving while the flag is false? There's a lot of details to take care of in there, but it might work. With this method the rate of event fire won't matter.

Now, it is possible that I am horribly incorrect since I am making assumptions about the OS having control of the character repeat rate. ;) Maybe we could find a benchmarking program (or someone could quickly right one up) and we can actually put some hard evidence behind this one way or another? This is really just curiousity for me at this point.
 
By the look of it I think the keydown fire event id governed by the BIOS - as setting called 'Typematic somethingorother', If I remember correctly. Holding the direction-key and firing it with keydown will move the sprite a pixel, pause, then move it constantly - not unlike holding down a key in any text editor.

I think the problem with my app is the timers I've been using - being generated instead of being drawn on a form might have missed something in the creation. I'll let you know when I have the results of my newly written timer class.

Also, thanks for the game design tips with the one big loop - It'd probably be the best way to implement the game!
 
The operating system overrides the BIOS's key repeat rate settings, and I, for one, would not depend on the keyboard repeat rate. Yes, most users probably will remain at the default, but that one out of twenty (could be more, could be less, not the point) people who went on an expedition exploring vast depths of the control panel could have altered the repeat rate, and will be very frustrated when the game doesn't work right not matter how he changes the settings. And if you're of the opinion that it serves him right, well, I'm offended because I'm one of the people who likes to explore things like the Control Panel. Also consider, for example, the poor little kid who is playing on Grandma's computer, which has the repeat rate set at something lower than what she considers insane. And the fact that some utility programs might change settings like this without asking the user (it's happened to me).

The biggest problem of all, I would think, is that there is a pause between the initial key press and the automatic repeat.

A very simple solution I have used in the past with programs that run on timers is to simply keep track of which keys are pressed by setting boolean variables in the KeyDown and KeyUp events, for example:
Visual Basic:
Dim UpKey As Boolean
 
Private Sub Form_KeyDown(sender As Object, e As EventArgs) Handles MyBase.KeyDown
    If e.KeyCode = Keys.Up Then UpKey = True
End Sub
 
Private Sub Form_KeyUp(sender As Object, e As EventArgs) Handles MyBase.KeyDown
    If e.KeyCode = Keys.Up Then UpKey = False
End Sub
The only problem with that is that it may be vulnerable to keyboard confusion when the player mashes the keyboard (a keyboard can only transmit three or so keys, depending on which keys, to the PC at a time and things get erratic when lots of keys are pressed). I'm not sure if this is the case, and it could be tested, but I'm lazy.

I'd say that PlausiblyDamp's solution would probably be the best though.
 
Thanks marble_eater, that was quite in-depth. However, I've solved the keydown/keyup problem by using directinput to detect the keys during the game loop. I'd advise anyone else to use this method to avoid the problem that I had.
 
Back
Top