EpicKip
EpicKip

Reputation: 4043

Character delay c#

I am trying to make a moving picturebox (with an image of my 'player'), this all works fine but I get trouble with the windows character delay.
For you who don't know what this is: if you press and hold a key windows will print it, wait for a second and then spam it.

So what happens is my player moves 10px waits and then moves as it should.

Code for moving:

if (e.KeyCode == Keys.Left)
{
    if (shipBox.Left >= 7)
    {
        shipBox.Left -= 10;
    }
}
if (e.KeyCode == Keys.Right)
{
    if (shipBox.Left <= 375)
    {
        shipBox.Left += 10;
    }
}
if (e.KeyCode == Keys.Up)
{
    if (shipBox.Top >= 120)
    {
        shipBox.Top -= 10;
    }
}
if (e.KeyCode == Keys.Down)
{
    if (shipBox.Top <= 520)
    {
        shipBox.Top += 10;
    }
}

Upvotes: 0

Views: 217

Answers (2)

Carbine
Carbine

Reputation: 7903

There is one workaround

Basically you have a timer which will be moving the picture at a regular interval of your choice

Turn On the timer to move on OnKeyDown and turn it Off on OnKeyUp. Make sure OnKeyDown you give a X/Y coordinate which you can move. and Reset that value on OnKeyUp event.

public class MyForm : Form
{
    private int deltaX;
    private int deltaY;

    private const int movementAmount = 10;

    private Timer movementTimer = new Timer();

    public MyForm()
    {
        movementTimer.Interval = 100; // make this whatever interval you'd like there to be in between movements

        movementTimer.Tick += new EventHandler(movementTimer_Tick);
    }

    void movementTimer_Tick(object sender, EventArgs e)
    {
        myMonster.Location = new Point(myMonster.X + deltaX, myMonster.Y + deltaY);
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);

        switch (e.KeyCode)
        {
            case Keys.Left:
                {
                    deltaX -=movementAmount;
                } break;
            case Keys.Right:
                {
                    deltaX += movementAmount;
                } break;
            case Keys.Up:
                {
                    deltaY -= movementAmount;
                } break;
            case Keys.Down:
                {
                    deltaY += movementAmount;
                } break;
        }

        UpdateTimer();
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        switch (e.KeyCode)
        {
            case Keys.Left:
                {
                    deltaX += movementAmount;
                } break;
            case Keys.Right:
                {
                    deltaX -= movementAmount;
                } break;
            case Keys.Up:
                {
                    deltaY += movementAmount;
                } break;
            case Keys.Down:
                {
                    deltaY -= movementAmount;
                } break;
        }

        UpdateTimer();
    }

    private void UpdateTimer()
    {
        movementTimer.Enabled = deltaX != 0 || deltaY != 0;
    }
}

Note: Try Switch..Case when you have lot of conditions

Upvotes: 1

Leff
Leff

Reputation: 582

I suppose you're trying to create some kind of game. You should not update the position of your player's image, or redraw it's image in keyboard/mouse event handlers if you want it's movements to be smooth. As instead you should implement some kind of main loop (in a separate thread, timer callback function, or maybe in the main window loop) that will update on screen position of your player according to currently pressed keys and the time passed since last update and redraw it.

Upvotes: 0

Related Questions