Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running Methods Simultaneously

I have a Dog class with a method Run which is supposed to move pictures across the screen:

public bool Run()
{
    Point p = PictureBoxDog.Location;

    while(p.X < 530)
    {
        int movement = Randomizer.Next(0, 3);
        p.X += movement;
        PictureBoxDog.Location = p;
    }

    if (Location == 4) //Incomplete section.
        return true;
    else
        return false;
}

This method is called from a button click event in which 4 dog objects are created and the each object calls the Run method:

private void button1_Click(object sender, EventArgs e)
{
    Dog dog1 = new Dog(pictureDog1);
    Dog dog2 = new Dog(pictureDog2);
    Dog dog3 = new Dog(pictureDog3);
    Dog dog4 = new Dog(pictureDog4);

    dog1.Run();
    dog2.Run();
    dog3.Run();
    dog4.Run();
}

The problem is that each method executes one by one, not simultaneously. I want each method to run at the same time. If I remove the while statement, then all methods execute at the same time, but with the while loop, they execute one after another. Any suggestions on how to fix this problem are greatly appreciated. Run method without the while loop:

public bool Run() //Dog1.Run()
{
    Point p = PictureBoxDog.Location;

    int movement = Randomizer.Next(0, 30);
    //Location += movement;

    p.X += movement;
    PictureBoxDog.Location = p;

    if (Location == 4) //Incomplete code.
    return true;
    else
    return false;
}
like image 452
grammer Avatar asked Oct 07 '15 04:10

grammer


1 Answers

Animation and WinForms is generally not straightforward. What programmers usually do is set up a game loop. A game loop does three things - fetch user input, update new position of sprites, and then draw the sprites on screen.

using System.Threading;

public partial class Form1
{ 
   private Timer _timer;
   private Dog _dog1, _dog2, _dog3, _dog4;

   public void InitializeComponent()
   {
      SetupDogs();

      // Every quarter of a second, run the function GameLoop
      _timer = new Timer(GameLoop, null, 
        TimeSpan.FromSeconds(0.25),
        TimeSpan.FromSeconds(0.25));
   }

   private void SetupDogs()
   {
      _dog1 = new Dog(PictureBoxDog1);
      _dog2 = new Dog(PictureBoxDog2);
      _dog3 = new Dog(PictureBoxDog3);
      _dog4 = new Dog(PictureBoxDog4);

   }

   public void GameLoop(object state)
   {
       GetUserInput();
       Update();
       Draw();
   }

   public void GetUserInput()
   {
     // You don't need this now. But if you need to
     // process user input later, you can do it here.
     //
     // e.g. if Last key 
     //   pressed  was arrow-left or 
     //   arrow-right etc.
   }

   public void Update()
   {
     _dog1.Update();
     _dog2.Update();
     _dog3.Update();
     _dog4.Update();
   }

   public void Draw()
   {
      // Draw on the main UI thread
      Dispatcher.BeginInvoke(() => 
      {
         _dog1.Draw();
         _dog2.Draw();
         _dog3.Draw();
         _dog4.Draw();
      });
   }

}

Then your Dog class looks like this. It needs to Update its location everytime the timer ticks, and then draw its position:

public class Dog
{

  bool _isRunning = true;

  Point Location { get; set; }

  Point NextLocation { get; set; }

  PictureBox PictureBoxDog { get; set; }

  public Dog(PictureBox pictureBox) 
  {
     PictureBoxDog = pictureBox;

     Location = GetRandomLocation();

     NextLocation = GetRandomLocation();
  }

  private Point GetRandomLocation()
  {
     var random = new Random();
     return new Point(random.Next(800), random.Next(800));
  }

  public void Update()
  {
    // Calculates the new coordinates for a dog

    // The dog starts from a random position, and is 
    // given a new random position to run towards.

    // If the dog has arrived at the new random position, then
    // give the dog a new random position to run to again
    if (NextLocation.X == Location.X && NextLocation.Y == Location.Y)
    {
      NextLocation = GetRandomLocation();
    }

    if (_isRunning)
    {
       // Move the dog closer to its destination
       // dx and dy can be -1, 0, or 1
       var dx = Math.Sign(NextLocation.X - Location.X);
       var dy = Math.Sign(NextLocation.Y - Location.Y);

       Location = new Point(Location.X + dx, Location.Y + dy);
    }
  }

  public void Draw()
  {
     PictureBoxDog.Location = Location;
  }
}
like image 111
Chui Tey Avatar answered Oct 20 '22 00:10

Chui Tey