Swarm Screen Saver
There are chasing bees and one bee trying to escape from the average location of the chasing bees. All the bees own a property mass and a property friction. The friction is a force which is linearly proportional to the speed and directed into the opposite directon than the speed vector. As you know, a mass is a resistance against a change of speed (F = m*a, a = dv/dt, F: Force, m: Mass, a: acceleration, v: speed, t: time) and a friction is a resistance against a speed (F = k*v, F: Force, k: friction per speed, v: speed). Thus the friction value together with the accelerating force determines the maximal speed a bee can achieve (Vmax = F/k). The mass determines, how fast this speed can be achieved. One pixel on the screen matches 1m. The force accelerating the chasers is always directed to the location of the escaping bee and has always the value 1N. The force which is accelerating the escaping bee is directed so, to get away from the average location of the chasing bees. The value of this force does change between min-force and max-force. Min-force is used as long as the distance between the location of the escaping bee and the average location of the chasing bees is larger than low-radius. In case of this distance becomes smaller than low-radius, max-force will be used until the distance is larger than high-radius. The escaping bee is not able to leave the screen. The value of Border-Repulsion determines the repulsion of the escaping bee from the limits of the screen. In case of Border-Repulsion is 1.0, the bee will be reflected with the same speed. In case of this value is zero, the matching component of the speed vector of the escaping bee will be zero after having touched the screen border. The value of timer determines the intervall between two screen updates in ms. Before an update Number-Of-Steps steps will be calculated, each step with a time intervall of timer divided by Number-Of-Steps.
This version of the screen saver contains the following changes compared to the previous version:
1. I´ve used my German-English dictionary but again no spell checker.
2. For storage of initialization data the registry is used instead of an .ini file.
Thus, every user will have his own initialization data, which cannot be messed up by another user.
3. In case of color-palette animation is available, it will be used. The last version was published without color-palette animation. The result were step-wise color-changes (on 256 and 16 Color resolutions) only using the colors available instead of floating color-changes.
4. A better mathematical method is used resulting in higher accuracy.
The mathematical model used is a System of nonlinear differential equations:
m*a + k*v = F
a + k/m*v = F/m
v = dx/dt
a = dv/dt
There are two differential equations for every bee -- one for every dimension -- the bees live in a two dimensional space (x, y). The system is nonlinear, since the accelerating force for e.g. the chasing bees is calculated like that:
Fx = (Xescape - Xchase)/sqrt(sqr(Xescape - Xchase) + sqr(Yescape - Ychase))
Fy = (Yescape - Ychase)/sqrt(sqr(Xescape - Xchase) + sqr(Yescape - Ychase))
For the escaping bee the force is calculated like that:
Fx = (Xescape - Xchase)/sqrt(sqr(Xescape - Xchase) + sqr(Yescape - Ychase))*F
Fy = (Yescape - Ychase)/sqrt(sqr(Xescape - Xchase) + sqr(Yescape - Ychase))*F
with F equal min. Force or equal max. Force (see rule described above).
This system may be simplified, by asuming stepwise constant values for F. This simplification results in a set of independend linear differential equations.
The last version was using the Trapez-Rule to integrate the step-wise linear differential equation.
I remembered that there is no need to solve a linear differential equation by using a numerical integration method like the trapez rule, but that there is a analytical solution:
x(t) = C1*exp(-k/m*t) + F/k*t + C2
x(t = 0) = C1 + C2
v(t = 0) = dx/dt(0) = -k/m*C1 + F/k
Since time is relative (grin) there is no need to use an absolute time in this system, but it is possible to reset the time before every timestep to zero and to determine C1 and C2 by using the current x and v. Thus there is no need to calculate exp(...) at every timestep, since the argument in the exp() function will always be equal to -k/m*h with h equal the step-lenght.
This approach does not require more operations for one step than the trapez rule. The advantage is, that a system with a very small mass (the bees may accelerate very fast) will be solved accurate. Using the trapez rule (and even worse using forward euler rule, which I've used in the very first non-published version) the speed calculated may be higher than the maximum speed possible, determined by the friction and force.
But there is still a need to use a step-lenght which is as small as possible (Number Of Steps as high as possible) to make the force to be updated as often as possible.
I've used C++ with exception handling. You may easily check this by removing the write permissions of the matching registry entry (\HKEY_CURRENT_USER\Software\Peter_Foelsche\swarm\1.1) and trying to use the OK button in the setup-dialog-box.
There are no global variables, despite there is no need to not use global variables, which would even make the code faster.
Storing into registry is done using my persistent object technology. This technology is heavily using C++-Exception-Handling. This technology may be used to write/read to/from somewhere, including common files, named pipes, TCP/IP sockets, .ini files, registry. Thus it may also be used to do IPC.
This is realized by using -- to use a catch word -- plug&play, a programmer would say: interface definition using abstract base classes.
Only one method must be written to make objects of a class persistent. This method is a constructor and this constructor is used for writing and reading. Thus there is no need to use a void constructor and to initialize the object later in a method (which is kind of C-Programming). There is also no problem in case of storing or restoring of an object fails.
Storing/Restoring may be done via defineable serialization methods for simple types (integers, char, double, ...). This serialization methods realize machine-independency or translation from/into human readable strings e.g. for storage into .ini files. A persistent class may than be used without any need for changes with any storage object to store binary or human reable into files or registry or for IPC.
My coding style has heavily changed since I started using C++-Exception-Handling, 2 or 3 years ago using Borland C++ v1.5 for OS/2 2.0. Usually the exception classes provided in the standard C++ library do not fullfill my requirements. This additional requirements are: An exception object must be able to contain a pointer to another exception object. An exception object must be able to create a copy of itself on the freestore. Thus an exception object may in fact be the head of a chain of exception objects. This is what I understand is hierarchicle exception handling. There should not just an object be thrown, telling the caller of the code that the write() system call has failed because of BADF, but the user should see some more explanation made by catching an exception object and rethrowing a new one which contains a pointer to a copy of the catched one to explain the context of the catched exception object. This may also be realized in base-class/member-class relations -- obviously not by catching/rethrowing, since you cannot put a call to a base-class/member-class constructor into a try-catch-block.