setscreen ("offscreenonly, nobuttonbar, graphics:max;max")
Mouse.ButtonChoose ("multibutton")
Music.PlayFileLoop ("Osmos.mp3")
var wells, maxballs, balls, maxwells, backclr, mx, my, b, ballradius : int
var angle, wellmass, grav : real
var click1, click100, spacepress, uppress, downpress, leftpress, rightpress, mid, large, pageuppress, pagedownpress
: boolean := false
var topbound, bottombound, leftbound, rightbound, small : boolean := true
var keys : array char of boolean
maxballs := 200
maxwells := 100
var ballx, bally, ballvx, ballvy : array 1 .. maxballs of real
var ballclr : array 1 .. maxballs of int
var d, wellmassmem : array 1 .. maxballs of real
var click10 : array 1 .. maxwells of boolean
balls := 0
wells := 0
backclr := white
ballradius := 8
grav := 1
/* CONTROLS */
/* LEFT CLICK : spawn a ball at the mouse*/
/* RIGHT CLICK : spawn a gravity well at the mouse*/
/* SCROLL CLICK : change the mass (between positive, zero, and negative) of a gravity well*/
/* red wells : poisitve mass (attract balls)
green wells : zero mass (don't effect balls)
blue wells : negative mass (repel balls)*/
/* SPACE BAR : toggle background colour between white and black*/
/* UP ARROW : toggle top boundary*/
/* DOWN ARROW : toggle bottom boundary*/
/* LEFT ARROW : toggle left boundary*/
/* RIGHT ARROW : toggle right boundary*/
/* CTRL (CONTROL) : change between large, medium and small wells and balls
this will effect only wells and balls drawn after the change is made*/
/* PAGE UP : increase strength of gravity (multiply by 10)*/
/* PAGE DOWN : decrease strength of gravity (divide by 10)*/
type gravwell :
record
x : real
y : real
mass : real
radius : int
clr : int
end record
var well : array 1 .. 100 of gravwell
function getAngle (x, y : real) : real
if x = 0 and y = 0 then
result 0
elsif x = 0 and y > 0 then
result 90
elsif x < 0 and y = 0 then
result 180
elsif x = 0 and y < 0 then
result 270
elsif x > 0 and y > 0 then
result arctand (y / x)
elsif x < 0 and y > 0 then
result 180 + arctand (y / x)
elsif x < 0 and y < 0 then
result 180 + arctand (y / x)
elsif x > 0 and y < 0 then
result 360 + arctand (y / x)
else
result 0
end if
end getAngle
function getDistance (x1, y1, x2, y2 : real) : real
if sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2) = 0 then
result .001
else
result sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2)
end if
end getDistance
proc Boundaries
for count : 1 .. balls
% left bound
if leftbound = true then
if ballx (count) + ballvx (count) - 8 <= 0 then
ballvx (count) *= -.5
end if
if ballx (count) < 0 then
ballx (count) := 1
end if
elsif leftbound = false then
if ballx (count) < 0 then
ballx (count) := maxx
end if
end if
% right bound
if rightbound = true then
if ballx (count) + ballvx (count) + 8 >= maxx then
ballvx (count) *= -.5
end if
if ballx (count) > maxx then
ballx (count) := maxx - 1
end if
elsif rightbound = false then
if ballx (count) > maxx then
ballx (count) := 0
end if
end if
% bottom bound
if bottombound = true then
if bally (count) + ballvy (count) - 8 <= 0 then
ballvy (count) *= -.5
end if
if bally (count) < 0 then
bally (count) := 1
end if
elsif bottombound = false then
if bally (count) < 0 then
bally (count) := maxy
end if
end if
% top bound
if topbound = true then
if bally (count) + ballvy (count) + 8 >= maxy then
ballvy (count) *= -.5
end if
if bally (count) > maxy then
bally (count) := maxy - 1
end if
elsif topbound = false then
if bally (count) > maxy then
bally (count) := 0
end if
end if
end for
end Boundaries
proc Moving
for count : 1 .. balls
for count2 : 1 .. wells
angle := getAngle (well (count2).x - ballx (count), well (count2).y - bally (count))
d (count2) := getDistance (well (count2).x, well (count2).y, ballx (count), bally (count))
ballvx (count) += (cosd (angle) * well (count2).mass) / (d (count2) ** 2) * grav
ballvy (count) += (sind (angle) * well (count2).mass) / (d (count2) ** 2) * grav
end for
ballx (count) += ballvx (count)
bally (count) += ballvy (count)
end for
% spawning balls
if b = 1 and balls < maxballs and mx >= 0 and mx <= maxx and my >= 0 and my <= maxy then
if click1 = false then
balls += 1
ballx (balls) := mx
bally (balls) := my
ballvx (balls) := 0
ballvy (balls) := 0
ballclr (balls) := Rand.Int (0, 255)
end if
click1 := true
else
click1 := false
end if
for count : 1 .. wells
if well (count).clr not= green then
wellmass := well (count).mass
else
wellmass := 0
end if
% changing mass of wells
if b = 10 and (well (count).x - mx) ** 2 + (well (count).y - my) ** 2 < well (count).radius ** 2 then
if click10 (count) = false then
if wellmass > 0 then
wellmassmem (count) := well (count).mass
well (count).mass := 0
well (count).clr := green
elsif wellmass = 0 then
well (count).mass := wellmassmem (count)
well (count).mass *= -1
well (count).clr := blue
elsif wellmass < 0 then
well (count).mass *= -1
well (count).clr := red
end if
end if
click10 (count) := true
else
click10 (count) := false
end if
end for
% spawning wells
if b = 100 and wells < maxwells and mx >= 0 and mx <= maxx and my >= 0 and my <= maxy then
if click100 = false then
wells += 1
well (wells).x := mx
well (wells).y := my
if small then
well (wells).radius := 50
wellmassmem (wells) := 5000
elsif mid then
well (wells).radius := 20
wellmassmem (wells) := 2000
elsif large then
well (wells).radius := 10
wellmassmem (wells) := 1000
end if
well (wells).mass := 0
well (wells).clr := green
end if
click100 := true
else
click100 := false
end if
Input.KeyDown (keys)
if keys (' ') then
if spacepress = false then
if backclr = black then
backclr := white
elsif backclr = white then
backclr := black
end if
end if
spacepress := true
else
spacepress := false
end if
if keys (KEY_UP_ARROW) then
if uppress = false then
if topbound = true then
topbound := false
elsif topbound = false then
topbound := true
end if
end if
uppress := true
else
uppress := false
end if
if keys (KEY_DOWN_ARROW) then
if downpress = false then
if bottombound = true then
bottombound := false
elsif bottombound = false then
bottombound := true
end if
end if
downpress := true
else
downpress := false
end if
if keys (KEY_LEFT_ARROW) then
if leftpress = false then
if leftbound = true then
leftbound := false
elsif leftbound = false then
leftbound := true
end if
end if
leftpress := true
else
leftpress := false
end if
if keys (KEY_RIGHT_ARROW) then
if rightpress = false then
if rightbound = true then
rightbound := false
elsif rightbound = false then
rightbound := true
end if
end if
rightpress := true
else
rightpress := false
end if
if keys ('1') then
small := true
mid := false
large := false
ballradius := 8
for count : 1 .. wells
well (count).radius := 50
if well (count).mass < 0 then
well (count).mass := -5000
elsif well (count).mass = 0 then
wellmassmem (count) := 5000
elsif well (count).mass > 0 then
well (count).mass := 5000
end if
end for
end if
if keys ('2') then
small := false
mid := true
large := false
ballradius := 3
for count : 1 .. wells
well (count).radius := 20
if well (count).mass < 0 then
well (count).mass := -2000
elsif well (count).mass = 0 then
wellmassmem (count) := 2000
elsif well (count).mass > 0 then
well (count).mass := 2000
end if
end for
end if
if keys ('3') then
small := false
mid := false
large := true
ballradius := 1
for count : 1 .. wells
well (count).radius := 10
if well (count).mass < 0 then
well (count).mass := -1000
elsif well (count).mass = 0 then
wellmassmem (count) := 1000
elsif well (count).mass > 0 then
well (count).mass := 1000
end if
end for
end if
if keys ('r') then
small := true
mid := false
large := false
ballradius := 8
balls := 0
wells := 0
grav := 1
cls
end if
if keys (chr (201)) /* PAGE UP */ and grav <= 100 then
if pageuppress = false then
grav *= 10
end if
pageuppress := true
else
pageuppress := false
end if
if keys (chr (209)) /* PAGE DOWN */ and grav >= .001 then
if pagedownpress = false then
grav /= 10
end if
pagedownpress := true
else
pagedownpress := false
end if
end Moving
loop
colourback (backclr)
cls
Mouse.Where (mx, my, b)
Boundaries
Moving
for count : 1 .. wells
drawfilloval (round (well (count).x), round (well (count).y), well (count).radius, well (count).radius, well (count).clr)
end for
for count : 1 .. balls
drawfilloval (round (ballx (count)), round (bally (count)), ballradius, ballradius, ballclr (count))
end for
% border indicators
if topbound then
drawline (0, maxy, maxx, maxy, blue)
elsif not topbound then
drawline (0, maxy, maxx, maxy, red)
end if
if leftbound then
drawline (0, 0, 0, maxy, blue)
elsif not leftbound then
drawline (0, 0, 0, maxy, red)
end if
if bottombound then
drawline (0, 0, maxx, 0, blue)
elsif not bottombound then
drawline (0, 0, maxx, 0, red)
end if
if rightbound then
drawline (maxx, 0, maxx, maxy, blue)
elsif not rightbound then
drawline (maxx, 0, maxx, maxy, red)
end if
Time.DelaySinceLast (30)
View.Update
end loop
|