KrystianB
KrystianB

Reputation: 502

C# WPF keyboard movement for game

I'm trying to make a small game in c# using wpf. I have my rectangle moving around, the problem I am trying to fix is if you press another key well holding the original key, then release one of them it will go in the direction being held. The code I have works but if ran once a key is released there is a delay then the rectangle will continue moving.

    enum Direction { left, right, up, down, none};
    Direction _direction = Direction.none;
    bool _directionIsPressed = false;
    bool _directionIsReleased = false;
    double x = 0;
    double y = 0;

    public MainWindow()
    {
        InitializeComponent();



        DispatcherTimer timer = new DispatcherTimer();
        timer.Tick += new EventHandler(MovePlayer);
        timer.Start();

        this.KeyDown += new KeyEventHandler(OnButtonKeyDown);
        this.KeyUp += new KeyEventHandler(OnButtonKeyRelease);

    }

    private void MovePlayer(object sender, EventArgs e)
    {
        switch (_direction)
        {
            case Direction.down:
                y += .05;
                Canvas.SetTop(Player, y);
                break;
            case Direction.up:
                y -= .05;
                Canvas.SetTop(Player, y);
                break;
            case Direction.left:
                x -= .05;
                Canvas.SetLeft(Player, x);
                break;
            case Direction.right:
                x += .05;
                Canvas.SetLeft(Player, x);
                break;
        }
    }

    private void OnButtonKeyDown(object sender, KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Down:
                _direction = Direction.down;
                _directionIsPressed = true;
                break;
            case Key.Up:
                _direction = Direction.up;
                _directionIsPressed = true;
                break;
            case Key.Left:
                _direction = Direction.left;
                _directionIsPressed = true;
                break;
            case Key.Right:
                _direction = Direction.right;
                _directionIsPressed = true;
                break;
            default:
                _direction = Direction.none;
                break;
        }
    }

    //When a key is released it will set the direction to none then 
    //reset the direction but there is about a half second delay in 
    //setting the direction again
    private void OnButtonKeyRelease(Object sender, KeyEventArgs e) 
    {
        _direction = Direction.none;
        this.KeyDown += new KeyEventHandler(OnButtonKeyDown);
    }

Edit: If anyone wants smooth keyboard movement in C# using wpf here is how I fixed it. Thank you Stefan for the help.

        public MainWindow()
    {
        InitializeComponent();
        DispatcherTimer timer = new DispatcherTimer();
        timer.Tick += new EventHandler(MovePlayer);
        timer.Start();
    }

    private void MovePlayer(object sender, EventArgs e)
    {
        if(Keyboard.IsKeyDown(Key.Left))
        {
            x -= .05;
            Canvas.SetLeft(Player, x);
        }
        if(Keyboard.IsKeyDown(Key.Up))
        {
            y -= .05;
            Canvas.SetTop(Player, y);
        }
        if(Keyboard.IsKeyDown(Key.Down))
        {
            y += .05;
            Canvas.SetTop(Player, y);
        }
        if(Keyboard.IsKeyDown(Key.Right))
        {
            x += .05;
            Canvas.SetLeft(Player, x);
        }
    }

Upvotes: 2

Views: 3400

Answers (2)

Stefan W.
Stefan W.

Reputation: 352

if you would like to allow to combine movement, for example up + left together then i you can do it only with the timer and Keyboard.IsKeyDown(key) verification

private void MovePlayer(object sender, EventArgs e)
{
    if (Keyboard.IsKeyDown(Key.Down))
    {
        y += .05;
        Canvas.SetTop(Player, y);
    }
    if(Keyboard.IsKeyDown(Key.Up))
    {
        y -= .05;
        Canvas.SetTop(Player, y);
    }
    if (Keyboard.IsKeyDown(Key.Left))
    {
        x -= .05;
        Canvas.SetLeft(Player, x);
    }
    if (Keyboard.IsKeyDown(Key.Right))
    {
        x += .05;
        Canvas.SetLeft(Player, x);
    }
}

other case, if the movement can be done only in one simple direction at the time, you can check the statements in your KeyReleased routine.

private void OnButtonKeyRelease(Object sender, KeyEventArgs e) 
{
    if (Keyboard.IsKeyDown(Key.Down))
        _direction = Direction.down;
    else if(Keyboard.IsKeyDown(Key.Up))
        _direction = Direction.up;
    else if (Keyboard.IsKeyDown(Key.Left))
        _direction = Direction.left;
    else if (Keyboard.IsKeyDown(Key.Right))
        _direction = Direction.right;
    else
        _direction = Direction.none;
}

But if you want to press over 2 movement buttons at the same time you need to save it in some array and check witch was pressed later, and set movement depended from this button.

Upvotes: 2

Raj Kumar Mishra
Raj Kumar Mishra

Reputation: 514

instead of using two switch statements in different functions, try merging them into one. The reason for delay could be the overhead required to jump from one function to another.

Instead of call MovePlayer() separately, you can try to move the player when the key is pressed.

private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    switch (e.Key)
    {
        case Key.Down:
            y += .05;
            Canvas.SetTop(Player, y);
            break;
        case Key.Up:
            y -= .05;
            Canvas.SetTop(Player, y);
            break;
        case Key.Left:
            x -= .05;
            Canvas.SetLeft(Player, x);
            break;
        case Key.Right:
            x += .05;
            Canvas.SetLeft(Player, x);
            break;
        default:
            _direction = Direction.none;
            break;
    }
}

Upvotes: 1

Related Questions