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.
Cool…. 😉
Awesome. What is needed to get this run?
Very, very cool!
(BTW some mouse interaction would be nice as well for a demo:)
Very nice!
Some work needed on the indentation when view source 🙂
@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.
Bravo Eric! Nicely done! 🙂
Really interesting work!. I’m really looking forward to working with it!.
very cool!