PixelSort

by James Hall: L6 Age ~16

Introduction

James has produced a spectacular motion graphics application in only about a hundred lines of code. You can now try a web version. Click the left mouse button to create randomly coloured lines emanating from the cursor. Drag the mouse with the left button down to create effects similar to the example shown below. The path of each line depends upon the red, green and blue components of its colour.

Sample output

Output

In order to run program PixelSort, you will need to have downloaded Stefan Berinde`s wingraph.zip file as described in our Graphics tutorial. You should copy the unzipped wincrt.pas, wingraph.pas and winmouse.pas (from the src folder) into your program folder. (The compiled units are included in the zip file but you might as well have the source code available for reference). You should find these three files useful for your own motion graphics programs.

The Program

program PixelSort;
{
    Copyright (c) 2011 James Hall
    
    Licensed under the Apache License, Version 2.0 (the "License"); you may not 
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
uses
  SysUtils, wingraph, wincrt, winmouse, math;
type
  Tpeeps = record
   x, y : array[1..200] of integer;
   colr, colg, colb : integer;
   realx, realy, targx, targy, speed, angle : real;
  end;
var
  gd, gm : smallint;
  mousex, mousey, numpeeps, i, j, len : integer;
  screen : array[1..700,1..700] of integer;
  tehpeeps : array[1..10000] of Tpeeps;
  tri : array[1..3,1..3] of real;
begin
  len := 2;
  numpeeps := 0;
  randomize;
  gd := 9;
  gm := 13;
  setwindowsize(700,700);
  initgraph(gd,gm,'PixelSort');
  updategraph(updateoff);
  tri[1,1] := 0;
  tri[2,1] := 2*pi/3;
  tri[3,1] := 4*pi/3;
  repeat
    mousex := getmousex;
    mousey := getmousey;
    case getmousebuttons of
      MouseLeftButton : begin
                          if numpeeps < 5000 then
                            begin
                              inc(numpeeps);
                              with tehpeeps[numpeeps] do
                                begin
                                  for i := 1 to len do
                                    begin
                                      x[i] := mousex;
                                      y[i] := mousey;
                                    end;
                                  realx := mousex;
                                  realy := mousey;
                                  colr := random(256);
                                  colg := random(256);
                                  colb := random(256);
                                  speed := 7;
                                  angle := 0;
                                end;
                            end;
                        end;
    end; //case
    for i := 1 to 3 do
      begin
        tri[i,1] := tri[i,1] + pi/180;
        if tri[i,1] > 2*pi then
          tri[i,1] := tri[i,1] - 2 * pi;
        if tri[i,1] < 0 then
          tri[i,1] := tri[i,1] + 2 * pi;
        tri[i,2] := 350 + round(sin(tri[i,1])*200);
        tri[i,3] := 350 + round(cos(tri[i,1])*200);
      end;
    if numpeeps > 0 then for i := 1 to numpeeps do
      begin
        with tehpeeps[i] do
          begin
            angle := angle + pi/360;
            if colr+colb+colg <> 0 then
              begin
                targx := (colr*tri[1,2] + colg*tri[2,2] + colb * tri[3,2])/(colr+colb+colg);
                targy := (colr*tri[1,3] + colg*tri[2,3] + colb * tri[3,3])/(colr+colb+colg);
              end;
            if (targy-realy) < 0 then
              angle := arctan((targx-realx)/(targy-realy)) + pi;
            if (targy-realy) > 0 then
              angle := arctan((targx-realx)/(targy-realy));
            if ((targy-realy) = 0) then
              if (targx-realx) > 0 then
                angle := pi/2
              else
                angle := 3*pi/2;
            if angle > 2*pi then
              angle := angle - 2*pi;
            if angle < 0 then
              angle := angle + 2*pi;
            realx := realx + sin(angle)*speed;
            realy := realy + cos(angle)*speed;
            for j := 1 to len-1 do
              begin
                x[len+1-j] := x[len-j];
                y[len+1-j] := y[len-j];
              end;
            x[1] := round(realx);
            y[1] := round(realy);
            for j := 1 to len-1 do
              begin
                setcolor(colr+256*colg+65536*colb);
                line(x[j],y[j],x[j+1], y[j+1]);
              end;
            end;
      end;
    updategraph(updatenow);
  until closegraphrequest;
end.

We intend to replace this code with a commented version using meaningful variable names.

Remarks

Can you think of a program like this that you could write?

Programming - a skill for life!

Seven programs including GameOfLife, PixelSort and SuperHappyFunLand by James Hall