HOME - - - - - Lazarus Tutorials TOC - - - - - - Other material for programmers
Delicious.Com Bookmark this on Delicious     StumbleUpon.Com Recommend to StumbleUpon

Arrays and plotting pixels in Lazarus or Delphi

Starting point for many simulations
(e.g. a swarm of bees)

Another atypical tutorial for this site. (Is any of them "typical"??)

This gives you the sourcecode for something "simple"... but complex! But doesn't do a lot of explaining. The sourcecode, though I say it myself, is elegant and "powerful". Also flexible.

Furthermore, while what it gives you is "pretty", it isn't particularly useful, as it stands. It is more of a starting point.

With it, you could create a simulation of bees swarming, ships moving in the English Channel, etc, etc. (I wrote it as a starting point for re-creating a program I wrote for the Acorn Archimedes in the 1980s. That program simulated a population of mobile protists, each with a simple genetic character, and they evolved as the simulation ran.)

Or just have fun with pretty animations. Or expand the ability of your brain to work with arrays in your programming.

The following static image, enhanced with Serif's PhotoPlus, really doesn't do the program justice. What you can't see here is that the "amoebas" are, in a somewhat un-lifelike symmetry, streaming across the page on parallel paths.

ldn199 screenshot- amoebas

I've posted the .exe on its own for you to download so that you can see the animation in action. Download LTN199.exe, Streaming Amoebas

And, as promised, you can also download the Lazarus sourcecode.

Notes on the programming

At the heart of this is what happens when its timer times out... which in "Prestissimo" mode it nominally does once a millisecond. (I'm not sure how the system copes with the fact that the timer times out more quickly than the OnTimer event handler executes... maybe the timer is disabled while the code is executing? I haven't done any of that explicitly, however, and the code runs for hours without crashing. Pretty cool endorsement of the way Lazarus is put together, don't you think?)

Anyway... When the timer times out, "all" that happens is...

  ShowAmoebas;
  MoveAmoebas;

  inc(wCycles);
  if wCycles>60000 then wCycles:=0;//Could add "cycles of cycles" counter, to
    //track overflows.... but want to keep this fast!
  laCycles.caption:=inttostr(wCycles);

... of which only the first two lines are at all "clever".

(Digression... I think it was working with arrays of smart LEDs (WS2812s) driven by an Arduino recently that "inspired" me to take this elegant approach.)

Everything in the program revolves around a few arrays.

MoveAmoebas makes changes to the contents of the arrays... and does a few other things. (More on this in a moment.)

ShowAmoebas simply reads what is in the arrays (and a crucial pointer), and from that paints pixels on the screen.

Let's look "behind the scenes" a little; let's look into the mechanism behind the illusion of the "movement" of the amoebas. (Or birds or ships or whatever you want to simulate!) The following shows one amoeba, first as it was at a moment in time, and then as it was in the next moment....

-

"The amoeba" is the one dark blue cell. It is "moving" to the right. "Behind it" (to its left), there is a "fading trail" showing where it has been. Depending on your monitor, you will see a pale blue pixel just to the left of the amoeba, and a paler blue pixel to the left of that. The pixel above the "Note A" pointer is drawn in white. (More on that anon!)

(In the .exe supplied with this tutorial, the "trails" are longer. You can change the length of the trail by changing the value in kMaxPixelsIndex.)

That amoeba is represented inside the program by one row of four elements in the array WhereX plus one row of four elements in the array WhereY.

To keep things simple, we'll talk only of the values in, and manipulation of WhereX. Of course, similar things are happening to and with WhereY, although as long as all the amoebas stream across the page horizontally, the code for the values in WhereY doesn't have to be as complex as that for WhereX... although the relevant code for ShowAmoebas was fully developed as fast as the code for WhereX. In MoveAmoebas, full development was restricted to changing what was in WhereX, and the code for WhereY, while inserted alongside, and parallel to the WhereX code, is not as fully developed.

A slightly clever bit

Obviously, during ShowAmoebas, a lot of pixels are plotted on the screen. And, at first, you might thing you need some sort of "erase" stage, to get rid of the old "ink".

Well... yes and no. Look at the example of one amoeba just above: If, in "time=x+1", you draw the three "new" blue squares, you will have overwritten two of the old squares. They don't need to be erased. The only old blue square that needs erasing is the old "end of trail" (the one with x coordinate=12).

While it may seem that we've drawn just three pixels, in fact we draw four... three in different shades of blue, and one in the background color. That "oldest bit of trail" is drawn in the background color not because you are going to "see" it, but to blot out oldest pixel of the old trail.

The very clever bit

You could of course say that you'd hold the position of the amoeba in element 0 of the array, the most recent trail pixel's coordinate in element 1, and so on.

And if you did, drawing the new screen with ShowAmoebas would be really simple.

But you'd pay a time penalty. All of the coordinates of all of the pixels would have to be moved "across" the WhereX and WhereY arrays between each generation!

Instead, the arrays are used like this...

Initially (If we have a trail as long as the one in the illustration), we start with the following in the row for this amoeba...

11  12  13  14

However, for the next generation (time=x+1), only the value in the first element of the row was changed. The whole row became....

15  12  13  14

The secret to this is the variable "bColPointerHead". Initially, it held 3, then it was changed to 0. The "3" said that "at the moment, the amoeba's X (and Y) coordinate(s) is stored in column "3" of the array." And, in the next generation, the amoeba's X coordinate could be found in column "0" of the array. (The first column being "named" "the zeroth", as is usual inside code.)

It works! It takes some clever code to make it work.. but that's what's going on, inside the program.

In a related vein: There is a table of what color to use for the amoeba, for the freshest pixel of the trail, the next freshest, etc.

Again: The values in the array are not moved around as the program runs. The software knows how to pick the right one.

A little note on ShowAmoebas

The ShowAmoebas routine works as follows. When I speak of "an element" of an amoeba, I mean....

(pseudo-code)
For each element of each amoeba... do..
   For each amoeba... do...
      Plot a pixel, in the relevant color
   (End "do each amoeba")
(End "do each element)

So what?

"Yeah, yeah... big deal", I hear you saying. Fine! Go out write an equivalent program! You'll find it a bit more fraught than you thought it might be!

Or, to see just what is going on in the program you've been given, try any of the following. (If anyone is teaching Lazarus to a class, they are welcome to "set" these challenges to students. I'd be interested to hear about the results...

More colors

It would be a simple matter of extending some of the arrays to an additional dimension to provide for different sorts of amoebas... some red ones, some blue ones, etc.

The obvious and easy...

The obvious (and easy) challenge is to extend the program so that the amoebas move in the Y dimension too.

Not so obvious...

Can you make different amoebas move at different speeds? Move in straight lines which are not parallel to the edges of the image, or at 45 degrees to an edge?

Strength

Give each amoeba a "strength" property. Phase 1: The strength values are fixed, a variety being assigned when the world is created. Extend that to something under which strengths wax and wane. Maybe coming near the upper edge makes an amoeba stronger, coming near the bottom edge makes it weaker>

And have the strength of an amoeba somehow displayed in what it looks like on the screen. Oh, and a graph at the side of the screen showing the current distribution of strengths across the population?

Natural Selection

Got all that done? Now give all the amoebas (and other organisms... you do have more than just amoebas present by now, don't you?) genes. And have the simulation demonstrate evolution by natural selection. You'll probably have to add feeding, and a mechanism to "rain" "food" from the sky...

That's not too much to attempt. I had most of it running in a program for an Archimedes in about 1988. The idea wasn't mine, but all of the code was.

I hope you've had fun? Or at least learned something? Maybe both??





Search across all my sites with the Google search...

Custom Search
            powered by FreeFind
  Site search Web search
Site Map    What's New    Search This search merely looks for the words you enter. It won't answer "Where can I download InpOut32?"
Ad from page's editor: Yes.. I do enjoy compiling these things for you. I hope they are helpful. However... this doesn't pay my bills!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

Link to Lazarus Tutorials main page
How to contact the editor of this page, Tom Boyd


Please consider contributing to the author of this site... and if you don't want to do that, at least check out his introduction to the new micro-donations system Flattr.htm....



Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes. There were two "unknown attributes" in Google+ button code. Sigh.


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....