Any OOP Gurus?

Peter Trend

Senior member
Jan 8, 2009
405
1
0
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:

postmortemIA

Diamond Member
Jul 11, 2006
7,721
40
91
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;
...
 

Peter Trend

Senior member
Jan 8, 2009
405
1
0
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)
        {

        }
    }
}
 

postmortemIA

Diamond Member
Jul 11, 2006
7,721
40
91
remove argument
ref Particle[] particlesArray
it is not needed. any function that is part of your class will have access to every member variable.
 

Peter Trend

Senior member
Jan 8, 2009
405
1
0
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:

postmortemIA

Diamond Member
Jul 11, 2006
7,721
40
91
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.
 

Peter Trend

Senior member
Jan 8, 2009
405
1
0
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:

MSCoder610

Senior member
Aug 17, 2004
831
0
71
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
 

Peter Trend

Senior member
Jan 8, 2009
405
1
0
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: