View.Set ("offscreenonly,graphics:600;600,nobuttonbar")
type Point :
record
x, y : real
end record
fcn closestPoint (p1, p2, p3 : Point) : Point
var ret : Point
var u : real := ((p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y)) / Math.Distance (p1.x, p1.y, p2.x, p2.y) ** 2
ret.x := p1.x + u * (p2.x - p1.x)
ret.y := p1.y + u * (p2.y - p1.y)
if ret.x < min (p1.x, p2.x) then
if p1.x < p2.x then
ret := p1
else
ret := p2
end if
elsif ret.x > max (p1.x, p2.x) then
if p1.x > p2.x then
ret := p1
else
ret := p2
end if
end if
result ret
end closestPoint
fcn dist (p1, p2 : Point) : real
result Math.Distance (p1.x, p1.y, p2.x, p2.y)
end dist
fcn whatAngle (x1, y1, x2, y2 : real) : real
var dx, dy, ratio, angle : real
dx := x2 - x1
dy := y2 - y1
if dx not= 0 then
ratio := dy / dx
else
ratio := dy / 0.00001
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 round (angle)
end whatAngle
proc drawLine (p1, p2 : Point)
Draw.Line (round (p1.x), round (p1.y), round (p2.x), round (p2.y), black)
Draw.FillOval (round (p1.x), round (p1.y), 3, 3, white)
Draw.Oval (round (p1.x), round (p1.y), 3, 3, black)
Draw.FillOval (round (p2.x), round (p2.y), 3, 3, white)
Draw.Oval (round (p2.x), round (p2.y), 3, 3, black)
end drawLine
const POINTS := 8
const RADIUS := 20
const GRAVITY := 0.001
var points : array 1 .. POINTS of Point
for i : 1 .. POINTS
%points (i).y := Rand.Int (maxy div 2 - 10, maxy div 2 + 10) - 100
%points (i).x := (maxx / (POINTS - 1)) * (i - 1)
points (i).x := cosd ((-i + 1) * (180 / (POINTS - 1))) * (maxx div 2) + maxx div 2
points (i).y := sind ((-i + 1) * (180 / (POINTS - 1))) * (maxx div 2) + maxy div 2
end for
var p, d, V, P, Z : Point
var vx, vy, angle, mag, s : real := 0
p.x := maxx
p.y := maxy div 2 + 50
Z.x := 0
Z.y := 0
vx := -0.3
loop
for i : 1 .. POINTS - 1
drawLine (points (i), points (i + 1))
Draw.Oval (round (p.x), round (p.y), RADIUS, RADIUS, black)
d := closestPoint (points (i), points (i + 1), p)
if dist (p, d) <= RADIUS then
s := Math.Distance (0, 0, vx, vy)
angle := whatAngle (0, 0, -vx, -vy) - (whatAngle (points (i + 1).x, points (i + 1).y, points (i).x, points (i).y) + 90)
angle := (whatAngle (points (i + 1).x, points (i + 1).y, points (i).x, points (i).y) + 90) - angle
vx := cosd (angle) * s
vy := sind (angle) * s
end if
%drawLine (p, closestPoint (points (i), points (i + 1), p))
end for
if p.x <= RADIUS| p.x >= maxx - RADIUS then
p.x := max (RADIUS, min (maxx - RADIUS, p.x))
vx *= -1
elsif p.y >= maxy - RADIUS then
p.x := maxy - RADIUS
vy *= -1
end if
p.x += vx
p.y += vy
vy -= GRAVITY
locate (1, 1)
put "X: ", p.x, " Y: ", p.y
put "VX: ", vx, " VY: ", vy
put angle
View.Update
cls
end loop |