Danny Danny - 9 days ago 8
C# Question

How can i check constantly the keyboard state? Instead of using the event handler

i'm creating a Galaga type game and i am focusing on the ship's movement. I have this code: `

public partial class MainWindow : Window
{

public MainWindow()
{
InitializeComponent();


}



private void Window_KeyDown(object sender, KeyEventArgs e)
{


if (e.Key == Key.Left)
{
moveLeft();
}
else if (e.Key == Key.Right)
{
moveRight();
}
else if (e.Key == Key.Space)
{
bullet();

}


}

private async void bullet()
{
Line bullet = new Line();
bullet.X1 = Canvas.GetLeft(testMovement) + (testMovement.Width / 2);
bullet.Y1 = Canvas.GetTop(testMovement);

bullet.X2 = bullet.X1;
bullet.Y2 = bullet.Y1 + 3;

bullet.Stroke = new SolidColorBrush(Color.FromRgb(255,255,255));
bullet.StrokeThickness = 3;


horizontalMove.Children.Add(bullet);



for (int i = 0; i < 50; i++)
{

await Task.Delay(20);
shoot(bullet);
}

horizontalMove.Children.Remove(bullet);
}

private void shoot(Line bullet) {

bullet.Y2 = bullet.Y1;
bullet.Y1 -= 5;

}

int x = 0;
private void moveRight() {
if (x>=0 && x <= 370)
{
if(x == 370)
{
x -= 10;
}
Canvas.SetLeft(testMovement, x += 10);
}
else
{
if (x < 0)
x = 0;
else
x = 370;
}
label.Content = x ;
}

private void moveLeft() {
if (x>=0 && x <= 370)
{
if (x == 0) {
x += 10;
}
Canvas.SetLeft(testMovement, x -= 10);
}
else
{
if (x < 0)
x = 0;
else
x = 370;
}

label.Content = x;

}

private void Window_KeyUp(object sender, KeyEventArgs e)
{

}


}


}`

The problem with this code is that when I change directions, it has a certain delay and the animations is not so smooth. So, how should i proceed if I want to constantly check for the keyboard's state(like if left, right or space is clicked) without using the event handler.

Answer

With your code, you're waiting for a event to come before moving your player. It's a commonly misunderstood aspect of game development. The manual of SDL library has a great explaination:

Keyboard events only take place when a keys state changes from being unpressed to pressed, and vice versa.

int alien_x=0, alien_y=0;

/* Main game loop */

/* Check for events */
while( SDL_PollEvent( &event ) ){
    switch( event.type ){
        /* Look for a keypress */
        case SDL_KEYDOWN:
            /* Check the SDLKey values and move change the coords */
            switch( event.key.keysym.sym ){
                case SDLK_LEFT:
                    alien_x -= 1;
                    break;
                case SDLK_RIGHT:
                    alien_x += 1;
                    break;
                case SDLK_UP:
                    alien_y -= 1;
                    break;
                case SDLK_DOWN:
                    alien_y += 1;
                    break;
                default:
                    break;
            }
        }
    }
}

At first glance you may think this is a perfectly reasonable piece of code for the task, but it isn't. Like I said keyboard events only occur when a key changes state, so the user would have to press and release the left cursor key 100 times to move the alien 100 pixels to the left. To get around this problem we must not use the events to change the position of the alien, we use the events to set flags which are then used in a seperate section of code to move the alien. Something like this:

int alien_x=0, alien_y=0;
int alien_xvel=0, alien_yvel=0;

/* Main game loop */

/* Check for events */
while( SDL_PollEvent( &event ) ){
    switch( event.type ){
        /* Look for a keypress */
        case SDL_KEYDOWN:
            /* Check the SDLKey values and move change the coords */
            switch( event.key.keysym.sym ){
                case SDLK_LEFT:
                    alien_xvel = -1;
                    break;
                case SDLK_RIGHT:
                    alien_xvel =  1;
                    break;
                case SDLK_UP:
                    alien_yvel = -1;
                    break;
                case SDLK_DOWN:
                    alien_yvel =  1;
                    break;
                default:
                    break;
            }
            break;
        /* We must also use the SDL_KEYUP events to zero the x */
        /* and y velocity variables. But we must also be       */
        /* careful not to zero the velocities when we shouldn't*/
        case SDL_KEYUP:
            switch( event.key.keysym.sym ){
                case SDLK_LEFT:
                    /* We check to make sure the alien is moving */
                    /* to the left. If it is then we zero the    */
                    /* velocity. If the alien is moving to the   */
                    /* right then the right key is still press   */
                    /* so we don't tocuh the velocity            */
                    if( alien_xvel < 0 )
                        alien_xvel = 0;
                    break;
                case SDLK_RIGHT:
                    if( alien_xvel > 0 )
                        alien_xvel = 0;
                    break;
                case SDLK_UP:
                    if( alien_yvel < 0 )
                        alien_yvel = 0;
                    break;
                case SDLK_DOWN:
                    if( alien_yvel > 0 )
                        alien_yvel = 0;
                    break;
                default:
                    break;
            }
            break;

        default:
            break;
    }
}
/* Update the alien position */
alien_x += alien_xvel;
alien_y += alien_yvel;
Comments