Taming HTML5 verlets with Object Pascal

Click the image below for a little real-time verlet integration animation.

And the source code for that little bit of HTML5 animation is Object Pascal, Delphi Web Script flavor, and is posted below.

It shows off the inline method implementations (you can use classic implementation style, and if that code were in a unit, you would have to), along with the extended Variant syntax. If you look at the HTML source, it also shows off output from an early version of the obfuscator/minifier.

FireFox6 and IE9 handle it fairly well, but Chrome just laughs at it and taunts you to bring it on. Runs on all major mobile platform too, at a reduced framerate of course, but not in slide-show mode (and on Android, FireFox Mobile is king of the hill).

<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<canvas id="canvas" width="300" height="400"></canvas>
<script>
<%pas2js

type 
   TVerletPoint = class
      private
         FX, FY : Float;
         FOldX, FOldY : Float;

      public
         procedure SetPosition(aX, aY : Float);
         begin
            FX := aX; FOldX := aX;
            FY := aY; FOldY := aY;
         end;

         constructor Create(aX, aY : Float);
         begin
            SetPosition(aX, aY);
         end;

         procedure Update;
         begin
            var dx := FX - FOldX;
            var dy := FY - FOldY;
            FOldX := FX;
            FOldY := FY;
            FX := FX + dx;
            FY := FY + dy;
         end;

         function DistanceTo(p : TVerletPoint) : Float;
         begin
            Result := Sqrt(Sqr(p.FX-FX)+Sqr(p.FY-FY));
         end;

         property X : Float read FX write FX;
         property Y : Float read FY write FY;
   end;

type
    TVerletStick = class
      private
         FDistance : Float;
         FA, FB : TVerletPoint;

      public
         constructor Create(pA, pB : TVerletPoint);
         begin
            FA := pA;
            FB := pB;
            FDistance := pA.DistanceTo(pB);
         end;

         procedure Apply;
         begin
            var dx := FA.X - FB.X;
            var dy := FA.Y - FB.Y;
            var d := Sqrt(dx*dx+dy*dy);
            var f := (d - FDistance) * 0.5 / d;
            FA.X := FA.X - dx * f;
            FB.X := FB.X + dx * f;
            FA.Y := FA.Y - dy * f;
            FB.Y := FB.Y + dy * f;
         end;

         property A : TVerletPoint read FA;
         property B : TVerletPoint read FB;
   end;

const cCOLS = 30;
const cROWS = 25;
const cSPACING = 10;
var points : array of TVerletPoint;
var sticks : array of TVerletStick;

procedure InitGrid;
var
   r, c : Integer;
   point : TVerletPoint;
begin
   for r:=0 to cROWS-1 do begin
      for c:=0 to cCOLS-1 do begin
         point:=new TVerletPoint(c*cSPACING, r*cSPACING);
         points.Add(point);
         if c>0 then
            sticks.Add(new TVerletStick(points[r*cCOLS+c-1], point));
         if r>0 then
            sticks.Add(new TVerletStick(point, points[(r-1)*cCOLS+c]));
      end;
   end;
end;

procedure UpdateGrid(canvas : Variant);
var
   i, j : Integer;
   stick : TVerletStick;
begin
   for i:=0 to points.High do begin
      points[i].Y := points[i].Y + 0.1; // gravity
      points[i].Update;
   end;
   for i:=1 to 3 do begin
      points[0].X := 0;
      points[0].Y := 0;
      points[cCOLS-1].X := (cCOLS-1)*cSPACING;
      points[cCOLS-1].Y := 0;
      for j:=0 to sticks.High do begin
         sticks[j].Apply;
      end;
   end;

   canvas.clearRect(0, 0, 300, 400);
   canvas.beginPath();
   for i:=0 to sticks.High do begin
      stick:=sticks[i];
      canvas.moveTo(stick.A.X, stick.A.Y);
      canvas.lineTo(stick.B.X, stick.B.Y);
   end;
   canvas.stroke();
end;

InitGrid();

procedure Animate(stepFunc : procedure(canvas : Variant)); external;

Animate(UpdateGrid);

%>

var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
canvas.strokeStyle = "black";
canvas.lineWidth = 0.8;

function Animate(f) {
    setInterval(
        function () {
            f(context);
        },
        10);
}

</script>

Source loosely based on Alex Nino’s.

8 thoughts on “Taming HTML5 verlets with Object Pascal

  1. @Heinz Z.
    All you need is DWScript (SVN version, preview zip might do)

    @Ajasja Ljubeti?
    Left as an exercise to the reader 😉

    @JP
    It’s the minifier packing everything tight on purpose, when minification & obfuscation aren’t active, the output is well formatted, readable and uses original Pascal function/class/variable names as much as possible.

Comments are closed.