krikara
krikara

Reputation: 2435

Syncing object passed to thread with timer

I previously made a simple ball and paddle program all running in one form. Now I am trying to have the ball run on a separate thread, but don't quite understand conceptually how to have the ball run a separate thread while keeping the rest of my program the same.

Originally the timer would make the ball move, so I thought I can insert that move line into my ballUpdate class. But now my question is if there is a way to make the thread work my current timer implemented.

This is what my form1 looks like

public partial class Form1 : Form
    {
        Graphics paper;
        Paddle paddle = new Paddle();
        Ball ball = new Ball();
        Thread myThread;
        BallUpdate ballUpdate = new BallUpdate();

        public Form1()
        {
            InitializeComponent();
            myThread = new Thread(() => ballUpdate.ballMotion(ball));
            myThread.Start();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            paper = e.Graphics;
            paddle.drawPaddle(paper);
            ball.drawBall(paper);

        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            //ball.moveBall();
            ball.collide();
            ball.hitPaddle(paddle.PaddleRec);
            this.Invalidate();
        }

I thought this might get something going, but the ball doesn't move at all.

class BallUpdate
{
    public BallUpdate(){}

    public void ballMotion(Ball x)
    {
        while(true)
        {
            x.moveBall();
            Thread.Sleep(30);
        }   
    }
}

Upvotes: 0

Views: 206

Answers (2)

Dustin Kingen
Dustin Kingen

Reputation: 21245

You need to initialize your ballUpdate and start your myThread. Only the ball's logic should be on a separate thread.

public partial class Form1 : Form
    {
        Graphics paper;
        Paddle paddle = new Paddle();
        Ball ball = new Ball();
        Thread myThread;
        BallUpdate ballUpdate = new BallUpdate();

        public Form1()
        {
            InitializeComponent();
            myThread = new Thread(() => ballUpdate.ballMotion(ball));
            myThread.Start();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            paper = e.Graphics;
            paddle.drawPaddle(paper);
            ball.drawBall(paper);

        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            //ball.moveBall();
            ball.collide();
            ball.hitPaddle(paddle.PaddleRec);
            this.Invalidate();
        }

In BallUpdate change if(true) to while(true) to prevent the thread from exiting. Incorporate delay so your ball doesn't go flying.

class BallUpdate
{
    public BallUpdate(){}

    public void ballMotion(Ball x)
    {
        while(true)
        {
            x.moveBall();
            Thread.Sleep(10000);
        }   
    }
}

Upvotes: 1

DasKrümelmonster
DasKrümelmonster

Reputation: 6060

I'd recommend building a thread method that loops over the following:

  1. Calculate the Timespan in milliseconds since the last calculation
  2. Move all the objects accordingly
  3. Collision checking and resolving
  4. Invoke the display method to render the frame
  5. Return to Step 1

Please do not create a new thread in each frame, that will have abysmal performance. Also, do not manipulate graphics objects in a thread.

Upvotes: 0

Related Questions