• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

Any OOP Gurus?

Peter Trend

Senior member
Hi,

I'm struggling with my programming assignment. We have to use animation and graphics in C# to demonstrate a scientific principle. I was hoping to do either conservation of momentum or Brownian motion, and either would need 2d "balls" moving, bouncing off the "walls" and colliding with each other...so similar code.

I decided to create a Particle class, and use a for loop to instantiate an array of n Particles, each with random x and y starting values.

This part seems to have worked. At least it compiles.
However, I'm not able to access parameters of my Particles array in the way in which I thought I would be able to:

e.g.
Code:
//particlesArray is 8 by 1000 array of doubles
//numParticles is previously declined public int and equals 100;

int i;
int xValue;
int yValue;
xValue=Convert.ToInt32(particlesArray[i].x); //this part doesn't work
yValue=Convert.ToInt32(particlesArray[i].y); //this part doesn't work either
// I get the error "The name particlesArray does not exist in the current context."
🙁
Could anybody help me please?

See full code below:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ParticleBox
{
    public partial class ParticleBoxForm : Form
    {

        public ParticleBoxForm()
        {
            InitializeComponent();
        }

        int numParticles = 100;
        private Thread trd;
        Graphics g = null;
        Brush myBlackBrush = new SolidBrush(Color.Black);
        int count;


        public void initializeParticlesArray()
        {
            int i;
            Random xRandom = new Random();
            Random yRandom = new Random();
            Random dXRandom = new Random();
            Random dYRandom = new Random();
            int G; // used for testing only, see below.
            Particle[] particlesArray = new Particle[numParticles];
            for (i = 0; i < numParticles; i++)
            {
                particlesArray[i] = new Particle(1.0, 1.0, xRandom.Next(0, particlePictureBox.Width), yRandom.Next(0, particlePictureBox.Height), dXRandom.Next(-1, 1), dYRandom.Next(-1, 1), 0.0, 0.0);
                G = Convert.ToInt32(particlesArray[0].x); // this is here as a test only. It appears to work (no error or red underlines etc.) 
            }
        }



        private void ThreadTask()
        {
            int i;
            initializeParticlesArray();

            while (true)
            {
                g = particlePictureBox.CreateGraphics();
                g.Clear(Color.White);
                for (i = 0; i < numParticles; i++)
                {

                    DrawCircle(Convert.ToInt32(particlesArray[i].X), Convert.ToInt32(particlesArray[i].Y), Convert.ToInt32(particlesArray[i].size));
                    ///////////////////////////////////////////
                    //Why can't my array be seen by DrawCircle?


                    Thread.Sleep(10);
                }

            }
        }

        public void DrawCircle(int x, int y, int size)
        {
            Rectangle myRectangle = new Rectangle(x, y, size, size);
            g.FillPie(myBlackBrush, myRectangle, 0, 360);
        }

        private void startButton1_Click(object sender, EventArgs e)
        {
            startButton1.Text = "Start";
            trd = new Thread(new ThreadStart(this.ThreadTask));
            trd.IsBackground = true;
            trd.Start();
        }

        private void particlePictureBox_Paint(object sender, PaintEventArgs e)
        {

        }

        private void stopButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Abort();
            }
            else
                return;
        }

        private void pauseButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Suspend();
                startButton1.Text = "Resume";
            }
            else
                return;
        }

        private void numParticlesComboBox1_TextUpdate(object sender, EventArgs e)
        {
            numParticles = Convert.ToInt32(numParticlesComboBox1.Text);
        }

        public class Particle
        {
            public double size = 1.0, mass = 1.0, x = 0.0, y = 0.0, dX = 1.0, dY = 0.0, dPrevX = 0.0, dPrevY = 0.0;
            Random myRandom = new Random();
            bool moving = true;
            private Random xRandom;
            private Random yRandom;
            //bool collide = false; //use for colision handling
            public Particle(double pSize, double pMass, double pX, double pY, double dPX, double dPY, double dPrevPX, double dPrevPY)
            {
                mass = pMass;
                size = pSize;
                x = pX;
                y = pY;
                dX = dPX;
                dY = dPY;
                dPrevX = dPrevPX;
                dPrevY = dPrevPY;
            }
        }
        /*public double xMove()
        {
            if (moving == true)
            {
                x += dX;
                if (x < 0 || x > 600)
                {
                    x *= -1;
                }
                return x;
            }
            else
                return x;
        }

        public double yMove()
        {
            if (moving == true)
            {
                y += dY;
                if (y < 0 || y > 270)
                {
                    y *= -1;
                }
                return y;
            }
            else
                return y;
        }
         */

    }
}

Thanks in advance,

Pete
 
Last edited:
You have declared
Code:
Particle[] particlesArray = new Particle[numParticles];
inside function
Code:
initializeParticlesArray()
thus, only that function has access to it.

Instead, you need to declare them as member variable of class such as:

Code:
public ParticleBoxForm()
        {
            InitializeComponent();
            particlesArray = new Particle[numParticles];
        }

        Particle[] particlesArray;
        int numParticles = 100;
        private Thread trd;
        Graphics g = null;
        Brush myBlackBrush = new SolidBrush(Color.Black);
        int count;
...
 
Thanks, this has helped a lot!

I'm now able to compile but I'm struggling to set parameters in particlesArray.
I'll need to do this for all parameters initially, set x and y every frame, and (eventually) change dX and dY every time there is a collision.

The way I'm trying to set my parameters inside a function (that I'm passing particlesArray to) is not working - I get a NullReferenceException when I start my thread.

Code:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ParticleBox
{
    public partial class ParticleBoxForm : Form
    {

        public ParticleBoxForm()
        {
            InitializeComponent();
            Particle[] particlesArray = new Particle[numParticles];
        }

        Particle[] particlesArray;
        int numParticles = 100;
        private Thread trd;
        Graphics g = null;
        Brush myBlackBrush = new SolidBrush(Color.Black);
        Random xRandom = new Random();
        Random yRandom = new Random();
        Random dXRandom = new Random();
        Random dYRandom = new Random();

        public void initializeParticlesArray(ref Particle[] particlesArray) //this is supposed to be making changes to the object "particlesArray" itself
        {
            int i;
            //define all eight parameters of each object
            for (i = 0; i < numParticles; i++)
            {
                particlesArray[i].mass = 1.0; //this line generates a NullException when initializeParticlesArray(ref particlesArray) is called
                particlesArray[i].size = 10.0;
                particlesArray[i].x = xRandom.Next(0, particlePictureBox.Width);
                particlesArray[i].y = xRandom.Next(0, particlePictureBox.Height);
                particlesArray[i].dX = dXRandom.Next(-1, 1);
                particlesArray[i].dY = dYRandom.Next(-1, 1);
                particlesArray[i].prevDX = 0.0;
                particlesArray[i].prevDX = 0.0;
            }
            return;
        }

        private void ThreadTask()
        {

            initializeParticlesArray(ref particlesArray); // is this correct usage?
            /* //I commented this section out until I fix initialization problems
            while (true)
            {
                g = particlePictureBox.CreateGraphics();
                g.Clear(Color.White);
                for (i = 0; i < numParticles; i++)
                {
                    DrawCircle(Convert.ToInt32(particlesArray[i].x), Convert.ToInt32(particlesArray[i].y), Convert.ToInt32(particlesArray[i].size));
                    Thread.Sleep(10);
                }
            }
             */
        }

        public void DrawCircle(int x, int y, int size)
        {
            Rectangle myRectangle = new Rectangle(x, y, size, size);
            g.FillPie(myBlackBrush, myRectangle, 0, 360);
        }

        private void startButton1_Click(object sender, EventArgs e)
        {
            startButton1.Text = "Start";
            trd = new Thread(new ThreadStart(this.ThreadTask));
            trd.IsBackground = true;
            trd.Start();
        }

        private void particlePictureBox_Paint(object sender, PaintEventArgs e)
        {

        }

        private void stopButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Abort();
            }
            else
                return;
        }

        private void pauseButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Suspend();
                startButton1.Text = "Resume";
            }
            else
                return;
        }

        private void numParticlesComboBox1_TextUpdate(object sender, EventArgs e)
        {
            numParticles = Convert.ToInt32(numParticlesComboBox1.Text);
        }

        public class Particle
        {
            public double size = 1.0, mass = 1.0, x = 0.0, y = 0.0, dX = 1.0, dY = 0.0, prevDX = 0.0, prevDY = 0.0;
            Random myRandom = new Random();
            //bool moving = true;
            //bool collide = false; //use for colision handling
            public Particle(double pSize, double pMass, double pX, double pY, double dPX, double dPY, double prevDPX, double prevDPY)
            {
                mass = pMass;
                size = pSize;
                x = pX;
                y = pY;
                dX = dPX;
                dY = dPY;
                prevDX = prevDPX;
                prevDY = prevDPY;
            }
        }

        private void applyButton1_Click(object sender, EventArgs e)
        {

        }
    }
}
 
remove argument
ref Particle[] particlesArray
it is not needed. any function that is part of your class will have access to every member variable.
 
OK, have done that. Also had to delete it from
Code:
initializeParticlesArray(ref particlesArray);
As "No overload for method 'initialiseParticlesArray' takes 1 arguments"
So this now reads:
Code:
initializeParticlesArray();
I'm still getting the same NullReferenceException on the same line :| and I also now get a warning:

"Field 'ParticleBox.ParticleBoxForm.particlesArray' is never assigned to, and will always have its default value null"

Edit: was told "an issue with scope: the particleArray that you are initializing in the constructor is scoped local to the constructor. To initialize the class level array to the proper size, do not include a declaration in the constructor:
Code:
public partial class ParticleBoxForm : Form
{
        Particle[] particlesArray;
        int numParticles = 100;

        public ParticleBoxForm()
        {
            InitializeComponent();
            particlesArray = new Particle[numParticles];
        }
...
"

Have tried this and it got rid of my warning but not the NullReferenceException not handled error!

Updated code below:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ParticleBox
{
    public partial class ParticleBoxForm : Form
    {
        Particle[] particlesArray;
        int numParticles = 100;

        public ParticleBoxForm()
        {
            InitializeComponent();
            particlesArray = new Particle[numParticles];
        }
        
        private Thread trd;
        Graphics g = null;
        Brush myBlackBrush = new SolidBrush(Color.Black);
        Random xRandom = new Random();
        Random yRandom = new Random();
        Random dXRandom = new Random();
        Random dYRandom = new Random();

        public void initializeParticlesArray() //this is supposed to be making changes to the object "particlesArray" itself
        {
            int i;
            //define all eight parameters of each object
            for (i = 0; i < numParticles; i++)
            {
                particlesArray[i].mass = 1.0; //this line generates a NullException when initializeParticlesArray(ref particlesArray) is called
                particlesArray[i].size = 10.0;
                particlesArray[i].x = xRandom.Next(0, particlePictureBox.Width);
                particlesArray[i].y = xRandom.Next(0, particlePictureBox.Height);
                particlesArray[i].dX = dXRandom.Next(-1, 1);
                particlesArray[i].dY = dYRandom.Next(-1, 1);
                particlesArray[i].prevDX = 0.0;
                particlesArray[i].prevDX = 0.0;
            }
            return;
        }

        private void ThreadTask()
        {

            initializeParticlesArray(); // is this correct usage?
            /* //I commented this section out until I fix initialization problems
            while (true)
            {
                g = particlePictureBox.CreateGraphics();
                g.Clear(Color.White);
                for (i = 0; i < numParticles; i++)
                {
                    DrawCircle(Convert.ToInt32(particlesArray[i].x), Convert.ToInt32(particlesArray[i].y), Convert.ToInt32(particlesArray[i].size));
                    Thread.Sleep(10);
                }
            }
             */
        }

        public void DrawCircle(int x, int y, int size)
        {
            Rectangle myRectangle = new Rectangle(x, y, size, size);
            g.FillPie(myBlackBrush, myRectangle, 0, 360);
        }

        private void startButton1_Click(object sender, EventArgs e)
        {
            startButton1.Text = "Start";
            trd = new Thread(new ThreadStart(this.ThreadTask));
            trd.IsBackground = true;
            trd.Start();
        }

        private void particlePictureBox_Paint(object sender, PaintEventArgs e)
        {

        }

        private void stopButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Abort();
            }
            else
                return;
        }

        private void pauseButton1_Click(object sender, EventArgs e)
        {
            if (trd.IsAlive)
            {
                trd.Suspend();
                startButton1.Text = "Resume";
            }
            else
                return;
        }

        private void numParticlesComboBox1_TextUpdate(object sender, EventArgs e)
        {
            numParticles = Convert.ToInt32(numParticlesComboBox1.Text);
        }

        public class Particle
        {
            public double size = 1.0, mass = 1.0, x = 0.0, y = 0.0, dX = 1.0, dY = 0.0, prevDX = 0.0, prevDY = 0.0;
            Random myRandom = new Random();
            //bool moving = true;
            //bool collide = false; //use for colision handling
            public Particle(double pSize, double pMass, double pX, double pY, double dPX, double dPY, double prevDPX, double prevDPY)
            {
                mass = pMass;
                size = pSize;
                x = pX;
                y = pY;
                dX = dPX;
                dY = dPY;
                prevDX = prevDPX;
                prevDY = prevDPY;
            }
        }

        private void applyButton1_Click(object sender, EventArgs e)
        {

        }
    }
}
 
Last edited:
see my first answer, that is how I have told you; you didn't copy it right. anyway, I think that you need to get some book on oo basics.
 
Yes, quite. Sadly I have to make this work and present it on Wednesday!
Will get a coffee and re-read this thread and my code. Sorry for being fairly clueless, I do appreciate your time 🙂

Edit: I have read through this thread and I think I have it copied right now. I'm still hitting the same brick wall with this Null Exception.

Code:
{
    public partial class ParticleBoxForm : Form
    {
        public ParticleBoxForm()
        {
            InitializeComponent();
            particlesArray = new Particle[numParticles];
        }

        Particle[] particlesArray;
        int numParticles = 100;
        private Thread trd;
        Graphics g = null;
        Brush myBlackBrush = new SolidBrush(Color.Black);
        int count;
        Random xRandom = new Random();
        Random yRandom = new Random();
        Random dXRandom = new Random();
        Random dYRandom = new Random();

        public void initializeParticlesArray() //this is supposed to be making changes to the object "particlesArray" itself
        {
            //define all eight parameters of each object
            int i;
            for (i = 0; i < numParticles; i++)
            {
                particlesArray[i].mass = 1.0; //this line generates a NullException when initializeParticlesArray(ref particlesArray) is called
                particlesArray[i].size = 10.0;
                particlesArray[i].x = xRandom.Next(0, particlePictureBox.Width);
                particlesArray[i].y = xRandom.Next(0, particlePictureBox.Height);
                particlesArray[i].dX = dXRandom.Next(-1, 1);
                particlesArray[i].dY = dYRandom.Next(-1, 1);
                particlesArray[i].prevDX = 0.0;
                particlesArray[i].prevDX = 0.0;
            }
            return;
        }

        private void ThreadTask()
        {

            initializeParticlesArray(); 
         }
...
 
Last edited:
If you're still hitting the NullReferenceException:
When you declare an array of objects (rather than primitives like int), you still need to create the object for each individual element too. So:
Code:
particlesArray = new Particle[numParticles];
for (int i=0; i<numParticles; i++)
{
  particlesArray[i] = new Particle(...);
}
// use particlesArray
 
If you're still hitting the NullReferenceException:
When you declare an array of objects (rather than primitives like int), you still need to create the object for each individual element too. So:
Code:
particlesArray = new Particle[numParticles];
for (int i=0; i<numParticles; i++)
{
  particlesArray[i] = new Particle(...);
}
// use particlesArray

It's working thanks to this! Thank you so much! I now have an app which draws n circles at random x and y coordinates. Working on getting them moving. Collision handling will be interesting. It's the handshake problem - each particle needs to check each other particle to see if it has similar coordinates...

Edit: Corrected typos.
Edit: I have animation and all particles bounce off the walls! Just need to suss out how to get them to bounce off each other, as I was saying above. 🙂
 
Last edited:
Back
Top