View.Set ("graphics:max,max") % Constants, Fonts & Pictures const newtonGravConst := 6.6723e-11 % The Newtonian Gravitational Constant const shipWeight := 3 const maxSpeed := 15 var planetSizes : array 1 .. 4 of int := init (10, 20, 40, 55) var planetWeights : array 1 .. 4 of real := init (3.3e23, 4.87e24, 5.97e24, 5.68e26) var planetCols : array 1 .. 4 of int := init (red, blue, green, 42) var mx, my, mb : int := 13 var gameOver : boolean := false % The Planet Class :) class planet import newtonGravConst, shipWeight export initialize, describe, drawPlanet, calcAttraction, hitTest % Export functions for use in the game % Declare the planet variables var x, y, size, col : int var weight : real proc initialize (planX, planY, planSize, planCol : int, planWeight : real) x := planX y := planY size := planSize col := planCol weight := planWeight end initialize proc drawPlanet drawfilloval (x, y, size, size, col) end drawPlanet proc calcAttraction (shipX, shipY : int, var xForce, yForce : int) var angle : int var mag, distance : real distance := sqrt ((shipX - x) ** 2 + (shipY - y) ** 2) mag := newtonGravConst * weight * shipWeight / (distance * 1000) ** 2 locate (1, 1) put mag if shipX not= x then angle := round (arctand (abs (shipY - y) / abs (shipX - x))) xForce := round (cosd (angle) * mag) yForce := round (cosd (angle) * mag) if shipX > x then xForce *= -1 end if if shipY > y then yForce *= -1 end if end if end calcAttraction proc describe % Temporary function, delete this later :) put "X: ", x put "Y: ", y put "Size: ", size put "Colour: ", col end describe function hitTest (shipX, shipY : int) : boolean var halfPlanetSize := size div 2 if (shipX - 5 > x - halfPlanetSize and shipX + 5 < x + halfPlanetSize and shipY - 5 > y - halfPlanetSize and shipY + 5 < y + halfPlanetSize) then put "Hit" result true end if result false end hitTest end planet var planets : flexible array 0 .. 0 of pointer to planet % Set up pointers to the Planet Class proc initializePlanets (numPlanets : int) var planetNum : int for i : 1 .. numPlanets new planets, i new planet, planets (i) planetNum := Rand.Int (1, 4) planets (i) -> initialize (Rand.Int (100, maxx - 100), Rand.Int (100, maxy - 100), planetSizes (planetNum), planetCols (planetNum), planetWeights (planetNum)) planets (i) -> drawPlanet end for end initializePlanets proc redrawPlanets (num : int) for i : 1 .. num planets (i) -> drawPlanet end for end redrawPlanets proc launchSS (var x, y, xSpeed, ySpeed : int, numPlanets : int) var startAngle, startMagnitude : int % Let the player move the spaceship to desired location loop mousewhere (mx, my, mb) drawfilloval (mx, my, 10, 10, grey) View.Update delay (15) redrawPlanets (numPlanets) exit when mb = 1 drawfilloval (mx, my, 10, 10, black) end loop x := mx y := my delay (150) % Let the player determine the power loop mousewhere (mx, my, mb) drawfilloval (x, y, 10, 10, grey) drawline (x, y, mx, my, grey) redrawPlanets (numPlanets) delay (15) View.Update drawline (x, y, mx, my, black) exit when mb = 1 end loop startMagnitude := round (sqrt (abs (mx - x) ** 2 + abs (my - y) ** 2)) startAngle := round (arctand (abs (my - y) / abs (mx - x))) % Break it up into its component vectors if (mx < x) and (my > y) then xSpeed := round (cosd (startAngle) * startMagnitude) div 10 ySpeed := round (sind (startAngle) * startMagnitude) div 10 * -1 elsif (mx < x) and (my < y) then xSpeed := round (cosd (startAngle) * startMagnitude) div 10 ySpeed := round (sind (startAngle) * startMagnitude) div 10 elsif (mx > x) and (my < y) then xSpeed := round (cosd (startAngle) * startMagnitude) div 10 * -1 ySpeed := round (sind (startAngle) * startMagnitude) div 10 else xSpeed := round (cosd (startAngle) * startMagnitude) div 10 * -1 ySpeed := round (sind (startAngle) * startMagnitude) div 10 * -1 end if end launchSS proc moveSS (xSpeed, ySpeed : int, var x, y : int) drawfilloval (x, y, 10, 10, black) x += xSpeed y += ySpeed drawfilloval (x, y, 10, 10, grey) View.Update delay (15) end moveSS proc calcAllForces (x, y, numPlanets : int, var xSpeed, ySpeed : int) for i : 1 .. numPlanets var totalXForce, totalYForce, tempX, tempY : int := 0 planets (i) -> calcAttraction (x, y, tempX, tempY) totalXForce += tempX totalYForce += tempY locate (1, 1) xSpeed += totalXForce div (10000 * shipWeight) ySpeed += totalYForce div (10000 * shipWeight) %put totalXForce if xSpeed > maxSpeed then xSpeed := maxSpeed elsif ySpeed > maxSpeed then ySpeed := maxSpeed end if end for end calcAllForces % The main program! :) var numPlanets : int := 1 var ssXSpeed, ssYSpeed, ssX, ssY : int drawfillbox (-20, -20, maxx + 20, maxy + 20, black) initializePlanets (numPlanets) launchSS (ssX, ssY, ssXSpeed, ssYSpeed, numPlanets) loop if gameOver = false then calcAllForces (ssX, ssY, numPlanets, ssXSpeed, ssYSpeed) moveSS (ssXSpeed, ssYSpeed, ssX, ssY) if ssX <= 10 or ssX >= maxx - 10 then ssXSpeed *= -1 elsif ssY <= 10 or ssY >= maxy - 10 then ssYSpeed *= -1 end if for i : 1 .. numPlanets exit when planets (i) -> hitTest (ssX, ssY) = true end for end if exit when gameOver = true end loop