如何不断检查键盘状态?而不是使用事件处理程序

时间:2016-11-26 17:29:41

标签: c# wpf loops

我创造了一个Galaga型游戏,我专注于船舶运动。我有这段代码:

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) {}

}

这段代码的问题在于,当我改变方向时,它有一定的延迟并且动画不是那么顺利。

那么,如果我想在不使用事件处理程序的情况下不断检查键盘的状态(例如,是否单击左,右或空格),我应该如何继续?

1 个答案:

答案 0 :(得分:2)

使用您的代码,您可以在移动播放器之前等待活动。这是游戏开发中常被误解的方面。 SDL库手册有a great explaination

  

键盘事件仅在键状态发生变化时发生   按下按下,反之亦然。

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;
            }
        }
    }
}
     乍一看,你可能认为这是一个非常合理的部分   任务的代码,但它不是。就像我说的键盘事件一样   当键改变状态时发生,因此用户必须按和   释放左光标键100次以将外星人100像素移动到   左边。要解决这个问题,我们不能使用这些事件   改变外星人的位置,我们用事件来设置旗帜   然后用于单独的代码部分来移动外星人。   像这样:

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;