setscreen ("graphics:max;max,offscreenonly")
type Node :
record
x, y, vx, vy : real
end record
const g := -0.1
const wind := -0.0
const N := 9
const d := 100
const k := 0.08
const decay := 0.98
const radius := 8
var nodes : array 1 .. N of Node
for i : 1 .. N
if i = 1 then
nodes (i).x := maxx / 2
nodes (i).y := maxy / 2
else
nodes (i).x := maxx / 2 + cosd (360 / N * i) * d
nodes (i).y := maxy / 2 + sind (360 / N * i) * d
end if
nodes (i).vx := 0
nodes (i).vy := 0
end for
var F : real
var mx, my, md, mxl, myl : int
var holding : int := -1
var connected : array 1 .. N, 1 .. N of boolean
for i : 1 .. N
for j : 1 .. N
%connected (i, j) := i ~= j & (i = 1| j = 1| abs (i - j) = 1| abs (j - i) = 1| (i = 2 & j = N)| (i = N & j = 2)) %connected in a loop and to a center node
connected (i, j) := i ~= j %everyone connected to each other
end for
end for
function whatAngle (dx, dy : real) : real
var ratio, angle : real
if abs (dx) > 0.0000001 then
ratio := dy / dx
else
ratio := dy / 0.000001
end if
angle := arctand (abs (ratio))
if dx < 0 then
angle := 180 - angle
end if
if dy < 0 then
angle := 360 - angle
end if
result angle
end whatAngle
loop
mousewhere (mx, my, md)
for i : 1 .. N
nodes (i).vx := nodes (i).vx * decay + wind
nodes (i).vy := nodes (i).vy * decay + g
for j : 1 .. N
if connected (i, j) then
F := -k * (Math.Distance (nodes (j).x, nodes (j).y, nodes (i).x, nodes (i).y) - d)
nodes (i).vx += cosd (whatAngle (nodes (i).x - nodes (j).x, nodes (i).y - nodes (j).y)) * F
nodes (i).vy += sind (whatAngle (nodes (i).x - nodes (j).x, nodes (i).y - nodes (j).y)) * F
end if
end for
end for
for i : 1 .. N
for j : 1 .. N
if connected (i, j) then
drawline (nodes (i).x div 1, nodes (i).y div 1, nodes (j).x div 1, nodes (j).y div 1, grey)
end if
end for
end for
for i : 1 .. N
if i ~= holding then
nodes (i).x += nodes (i).vx
nodes (i).y += nodes (i).vy
if (nodes (i).x < radius| nodes (i).x > maxx - radius) then
nodes (i).vx *= -1
end if
if (nodes (i).y < radius| nodes (i).y > maxy - radius) then
nodes (i).vy *= -1
end if
nodes (i).x := min (max (radius, nodes (i).x), maxx - radius)
nodes (i).y := min (max (radius, nodes (i).y), maxy - radius)
if Math.Distance (mx, my, nodes (i).x, nodes (i).y) <= radius then
drawfilloval (nodes (i).x div 1, nodes (i).y div 1, radius, radius, grey)
else
drawfilloval (nodes (i).x div 1, nodes (i).y div 1, radius, radius, white)
end if
else
drawfilloval (nodes (i).x div 1, nodes (i).y div 1, radius, radius, yellow)
end if
drawoval (nodes (i).x div 1, nodes (i).y div 1, radius, radius, black)
end for
if md > 0 then
if holding = -1 then
for i : 1 .. N
if Math.Distance (mx, my, nodes (i).x, nodes (i).y) <= radius then
holding := i
exit
end if
end for
end if
else
if holding ~= -1 then
nodes (holding).vx := mx - mxl
nodes (holding).vy := my - myl
end if
holding := -1
end if
if holding ~= -1 then
nodes (holding).x := mx
nodes (holding).y := my
end if
mxl := mx
myl := my
Time.DelaySinceLast (10)
View.Update
cls
end loop |