This control simulates a particle swarm dynamic system. Each particle has different weight and electronic charge. So they implement different attract and dispel forces on each other as they move around with changing velocity and acceleration. The system also simulates dump forces and other attenuation characteristics, so that they can finally get into a stable status after a while.
The particles in this system also have attributes such as background and front color, picture, font, text, shape etc.. The control detects mouse events and changes the color of the corresponding particle. When a user clicks on one of the particles, the control can trigger several events. In fact, I make it a very useful button control like what you might see in Britica 2000, which serves as an excellent navigating tool with keyword buttons jumping out one by one like bubbles blown out of a pipe.
Double buffering and other techniques to accelerate the animation are also demonstrated in this control. System timers are used as the engine of this simulation instead of the idle thread.
Besides the programming stuff, some problem concerned with the discreet time sampling in computer simulation are also addressed and solved in this control. You might get a discussion with me if you'd ever made high calculus points :-).
Get a quick look at how to use the control
Let's demonstrate the usage in VB first for the simplicity (thanks to Microsoft). Create a new project and import the component
SmartGravityBubbleCtrl. Then drag it onto your form and place it anywhere you like. Now, in the object browser, you'll see two classes
CSmartBubble. The first one is our dynamic system container, i.e., the playground of our particles, and the latter is our player - the particle itself. When you drag the control onto your form, you've already setup a playground for our players. What you have to do next is to create
CSmartBubble objects (the players) and add them to the playground. The source code looks like this:
Dim b As CSmartBubble
Set b = New CSmartBubble
b.Shape = RoundedRect
b.id = 1
Really easy, right? The electronic and gravity parameters are tuned thoroughly that you don't have to specify values other than the default one. But if you want something special, just go ahead and specify your own parameters. You can add as many particles as you like, and watch them moving and jumping until they all get tired and move into a beautiful and regular pattern. But one thing you shall be careful: in this edition, every
CSmartBubble object added into the container shall have distinct ID values. This might be a stupid idea because when I wrote the control, I decided that every bubble shall be identified by their ID, so I can trigger an event when the user clicks on one of them and tell the client which one is clicked with this ID. You may get rid of the guard code in the source.
What else you've got?
The control is not just a toy of codes. It is full fledged with many properties and events. The extensive description and reference has been packed into the source packet.
Besides that, there are two demos, demo1 and xmlDemo, all written in VB6. Demo1 handles the
LeftButtonDown event of the control and adds a particle where the user clicks, the code in the handler is below:
Private Sub Bubble1_OnLeftButtonDown(ByVal X As Long, ByVal Y As Long)
Dim b As CSmartBubble
Set b = New CSmartBubble
b.xPos = X b.yPos = Y
b.Width = 50 b.Height = 20
b.Text = "Green" b.ElectronicCharge = 1
b.Shape = RoundedRect
b.id = id + 1
b.Weight = 2
b.TextHighlightColor = RGB(255, 255, 255)
id = id + 1 Bubble1.AddBubble b
xmlDemo is much more complicated and I built it to mimic Britica 2000 knowledge navigator. It is used for navigating a tree structure such as disk directories, and creates fascinating effects. I wrote a tree structure in XML and parsed it with Microsoft XML 4.0. The content of this tree structure is mainly a self introduction of myself.
At initialization, the program creates a particle with text and style specified in the root node of this XML file, and this root particle is fixed in the center of the control. Then its children were popped out from it one after another with 500 ms delay time triggered by a timer. So the whole process looks like blowing out bubbles with a pipe. When user clicks one of them, and this particle is also a parent node, then it is fixed to the center and all other bubbles are eliminated while its children are pumping out continuously. To compile and run this demo, you have to install MS XML 4.0.
Particle swarm explained
The basic idea of this dynamic system comes from the Kulun's law and Newton's gravity law. We give each particle positive electronic charge and weight, so they expel each other by their electronic charge while attract each other by their gravity. These forces make the system dynamic. According to Kulun's law, the electronic force between two particles p1 and p2 is:
The formula is in vector form, and I omitted the Kulun parameter. Q1 and Q2 are their electronic charge and P1 and P2 are their pos vector. The gravity between the particles is originally in the same form, but this won't make the system stable because expel force will always be greater than the gravity, so particles will run further and further, the system goes stable, but that's not what I want. So, I use the gravity in the form:
W1 and W2 are the weights of the two particles.
Obviously, the expel forces go smaller when the distance between particles increases while gravity forces become greater. So if the distance between particles are too small, the expel forces push them apart while the distance exceeds a value, the gravity forces dominates and bound them closer.
The relationship between the two kinds of forces can be demonstrated as below:
Clearly, they got joint points, that's where the particles should stop. Well, one may simply think that as we implement these forces and calculate the acceleration and speed at every sample time, the system would go fine and go stable as we wish. However, this is wrong, because the forces we discussed do not even confirm to the energy law, i.e., the energy of the system goes bigger and bigger with time, the particles pump like mad with acceleration greater and greater until they finally jump out of our sight.
The system we simulate never exists in the real world. We shall give it attenuation characteristics to cut down its energy slowly and make it stable. Dump forces is the first thing I chose. As an object moving in the air, its dump force can be expressed as:
S is the speed vector of this object and k is a constant. The negative sign before it means the dump force has opposite direction with speed.
Simulation of the dump force makes the whole process more realistic. But it still cannot stabilize the system. So we use another method which attenuates the gravity and expel forces by a function of simulation time. As the time passes by, the gravity and expel forces are attenuated with a speed linear to the square root of the simulation time. When a particle is added into the container, the simulation time will be reset to zero and the system restarts simulation.
Much has been said about the theory stuff. Let's take a look at the source now. I enjoy developing ActiveX controls in Visual Studio .Net with ATL7, because everything becomes simple and neat, especially the support for COM events. I need to just type in a few attributes before the COM class and say: "be there!". Then everything is done like magic. The source is too much to be explained in detail here. I just give some points and leave it to you to check it out: The whole design used a simple container pattern because I can't find a suitable container for my particles in STL.
Double buffering is used in this control for better performance. A complex number template class in STL is used for vector calculation. A helper class from one of The Code Project contributors is used and extended for the implementation of font and picture property of the control. You can find it in the VCUE namespace. All the background pictures in the control are implemented as
IPicture interfaces for easy usage and supporting transparent pictures like GIF. The simulation is driven by a timer, not an idle thread. You may correct this with ease.
We may all know that speed is the integration of acceleration and distance is the integration of speed. In our simulation, the integration is in fact a summation of discrete samples. As we have to do the integration twice, and the acceleration of particles can be very huge if they are close, the bias between the summation and integration can be extraordinarily large that the system looks flakey. So you may see much "round off" and "cut off" in my program. These codes are hard to understand, you can just forget about them.