简体   繁体   中英

How to keep timer(winforms timer) in a continuos loop

Ok, so my problem is as follows, I have a timer that draws a frame every 2 seconds (testing purposes) when I press D (by press I mean the D key is continuously held down), anyways when I first press D, the form will wait 2 seconds then draws the images as it should, but the problem is it does this only once. Hence after the 2 seconds,the remanding frames will be drawn at the fastest speed in which the form can draw it at. So, how do I make sure the frame will be drawn only every 2 seconds continuously, while keeping the interval of 2 seconds no matter how long I press the D key... here is my code

public partial class Form1 : Form 
{
    Keys moveRight;
    Keys moveLeft;

    public static bool isMovingR = false;
    public static bool isMovingL = false;
    public static bool canMoveR = false;

    Bitmap stnd = new Bitmap(Properties.Resources.Standing);
    static Bitmap wlk_1_RL = new Bitmap(Properties.Resources.Walk_1_RL);
    static Bitmap wlk_3_RL = new Bitmap(Properties.Resources.Walk_3_RL);
    static Bitmap wlk_4_LL = new Bitmap(Properties.Resources.Walk_4_LL);
    static Bitmap wlk_6_LL = new Bitmap(Properties.Resources.Walk_6_LL);

    Animation animate = new Animation(new Bitmap[] { wlk_1_RL, wlk_3_RL,
        wlk_4_LL, wlk_6_LL });


    Timer timer = new Timer();

    int imageX = 5;
    int imageY = 234;

    public Form1()
    {
        InitializeComponent();
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        if (isMovingR == false)
        {
            e.Graphics.DrawImage(stnd, imageX, imageY);
            //Refresh();
        }
        if (canMoveR == true)
        {
            e.Graphics.DrawImage(animate.Frame2Draw(), imageX, imageY);
            timer.Stop();// this simply stops the animation from continuing once I have stopped press D
        }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        moveRight = Keys.D;
        moveLeft = Keys.A;

        if (e.KeyCode == moveRight)
        {
            isMovingR = true;
            timer.Enabled = true;
            timer.Interval = 2000;                
            timer.Tick += Timer1_Tick;
            //imageX += 5;
            Refresh();
        } else if (e.KeyCode == moveLeft)
        {
            isMovingL = true;
            imageX -= 5;
            Refresh();
        } 

    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.D)
        {
            isMovingR = false;
            canMoveR = false;
            Animation.slctdImg = 0;
            this.Refresh();
        }
    }

    private void Timer1_Tick(object sender, EventArgs e)
    {
        canMoveR = true;
        this.Invalidate(); // calls the OnPaint event
        timer.Stop(); // testing purposes and also to let you know timer.stop() doesn't really fix my problem in this case
    }
} 

}

UPDATED CODE, based on Kirak solution

public Form1()
    {
        InitializeComponent();
        timer.Enabled = true;
        timer.Interval = 1000;
        timer.Tick += Timer1_Tick;
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        if (canMoveR == true)
        {
            e.Graphics.DrawImage(animate.Frame2Draw(), imageX, imageY);
            timer.Stop();
        }


    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        moveRight = Keys.D;
        moveLeft = Keys.A;

        if (e.KeyCode == moveRight)
        {
            isMovingR = true;
            //imageX += 5;
            Refresh();
        } else if (e.KeyCode == moveLeft)
        {
            isMovingL = true;
            imageX -= 5;
            Refresh();
        } 

    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.D)
        {
            isMovingR = false;
            canMoveR = false;
            Animation.slctdImg = 0;
            this.Refresh();
        }
    }

    private void Timer1_Tick(object sender, EventArgs e)
    {
        if (isMovingR == true)
        {
            canMoveR = true;
            this.Invalidate(); // calls the OnPaint event, hence all things that the OnPaint 
//event draws, will be redrawn, you make ask your self why i would need 
//the canMoveR to be set to true then, this is because i plan on adding more things
// so for future purpose, all things to be drawn in the game will
// will only be drawn when i want them to be drawn or under specific circumstances
        }
    }
} 

}

Don't set the timer on button press - have a timer ticking every 2 seconds that checks if the button is pressed and takes action if it is. eg (pseudocode):

public Form1()
{
    timer.Enabled = true;
    timer.Interval = 2000;
}

KeyCode keyPressed;

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    keyPressed = e.KeyCode;
}

private void Timer1_Tick(object sender, EventArgs e)
{
    if (keyPressed == Keys.D)
    {
        // do something
    }
}

Update to address new code: If you want to unset the "canMoveR" you may want to set a timeout variable - something like this:

int timeout = 0;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    keyPressed = e.KeyCode;
    timeout = 2; // 2 seconds assuming your timer ticks every 1000ms
}

then on timer tick:

private void Timer1_Tick(object sender, EventArgs e)
{
    --timeout; //will go down to 1 the first tick, then down to 0 on the second
    if (timeout == 0)
    {
        canMoveR = false;
    }
}

Every time press D, the event Timer1_Tick is added, so, on second time press D, the event run 2 times. Set event on constructor.

public Form1()
    {
        InitializeComponent();
            timer.Enabled = false;
            timer.Interval = 2000;                
            timer.Tick += Timer1_Tick;

    }


    protected override void OnPaint(PaintEventArgs e)
    {
        if (isMovingR == false)
        {
            e.Graphics.DrawImage(stnd, imageX, imageY);
            //Refresh();
        }
        if (canMoveR == true)
        {
            e.Graphics.DrawImage(animate.Frame2Draw(), imageX, imageY);
            timer.Stop();// this simply stops the animation from continuing once I have stopped press D
        }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        moveRight = Keys.D;
        moveLeft = Keys.A;

        if (e.KeyCode == moveRight)
        {
            isMovingR = true;
            //imageX += 5;
   timer.Enabled = true;
            Refresh();
        } else if (e.KeyCode == moveLeft)
        {
            isMovingL = true;
            imageX -= 5;
            Refresh();
        } 

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM