The Plasma Effect

Overview

This is an basic effect that is easy to program, but can look quite good. Its a bit out of date now, but it's a good introduction to more complicated effects.

How to code it

I'm assuming you know basic Mode 13h graphics techniques. If not, have a look at the tutorial I wrote.

The first thing to do after changing to Mode 13h is to set up the palette. You should know how to change the palette from my VGA programming page, mentioned above. Set the colours to go from black to blue to red to green to black, which will give a nice picture. Here's some sample code to do that:

for (int i=0; i<64; i++)
{
  outp(0x3c8, b);
  outp(0x3c9, 0);
  outp(0x3c9, 0);
  outp(0x3c9, b);

  outp(0x3c8, b+64);
  outp(0x3c9, b);
  outp(0x3c9, 0);
  outp(0x3c9, 63-b);

  outp(0x3c8, b+128);
  outp(0x3c9, 63-b);
  outp(0x3c9, b);
  outp(0x3c9, 0);

  outp(0x3c8, b+128+64);
  outp(0x3c9, 0);
  outp(0x3c9, 63-b);
  outp(0x3c9, 0);
}

Next we have to set up a table based on the cosine function. Our table will have 256 entries, and in this case will go from 32 to 64 to 32 to 0 to 32. You should notice that this is just the function (32 cos x)+32, where x goes from 0 to 2*PI. Here's the code to set it up.
unsigned char table[256];

for (int i=0; i<256; i++)
  table[i] = (cos((double)a*360.0/255.0*M_PI/180.0)*32)+32;
The M_PI/180.0 part is to convert from degrees to radians. This table is cyclical, which is important. Now we come to actually drawing the plasma. The screen is drawn left to right, and then top to down. The method is easier to show than to describe, so I'll show the code first.
char doublebuffer[64000];

//ptr stores the original pointers at the start of each frame
unsigned char ptr[4];
for (int i=0; i<4; i++)
  ptr[i] = 0;
unsigned char hptr1,hptr2,vptr1,vptr2;
do
{
  //screenpos is the current pixel number we are drawing
  int screenpos = 0;
  //now we will restore the vertical pointers
  vptr1 = ptr[2];
  vptr2 = ptr[3];
  int y=0;
  do
  {
    //increment the vertical pointers
    vptr1++;
    vptr2 += 2;
    //and restore the horizontal pointers
    hptr1 = ptr[0];
    hptr2 = ptr[1];
    int x=0;
    do
    {
      //increment horizontal pointers
      hptr += 2;
      hptr += 3;
      //now we plot the pixel. It's value is the sum of 4 values, as follows.
      doublebuffer[screenpos] = table[hptr1] + table[hptr2]
                                + table[vptr1] + table[vptr2];
    } while (++x < 320);
  } while (++y < 200);
  //increment the original pointers, to make the plasma move.
  ptr[0] -= 3;
  ptr[1] += 2;
  ptr[2] -= 3;
  ptr[3] += 1;

  //now copy the doublebuffer to the screen
  // for efficiency this should really copy 32 bits at a time. Use one of
  //  the block copy functions to do this...
  for (int i=0; i<64000; i++)
  {
    _farpokeb(_dos_ds, 0xA0000+i, doublebuffer[i]);
  }  
} while (!kbhit());
We have 4 index variables, two horizontal indexes and two vertical indexes. As we move from left to right, the horizontal pointers are incremented. When we start a new line, we reset the horizontal pointers to their original values. When we finish a line, the vertical pointers are incremented. This will generate the plasma pattern on the screen. To make the plasma move, just change the original pointers at the end of each frame. And that's all there is to it!

Other things to change, would be different palettes, adding different amounts to the pointers, and changing the starting position by using a cosine and sine function to move it in a circle. You could also try adding values less than 1 to your pointers, to make the plasma bigger, as well.

Back to the index.