Code: Select all
#Include "fbgfx.bi"
Type int2d
As Integer x, y
Declare Constructor
Declare Constructor(x As Integer, y As Integer)
Declare Operator Cast () As String
End Type
Constructor int2d
End Constructor
Constructor int2d(x As Integer, y As Integer)
This.x = x : This.y = y
End Constructor
Operator = (a As int2d, b As int2d) As boolean
If a.x <> b.x Then Return false
If a.y <> b.y Then Return false
Return true
End Operator
Operator <> (a As int2d, b As int2d) As boolean
If a.x = b.x And a.y = b.y Then Return false
Return true
End Operator
' "x, y"
Operator int2d.cast () As String
Return Str(x) & "," & Str(y)
End Operator
' a + b
Operator + (a As int2d, b As int2d) As int2d
Return Type(a.x + b.x, a.y + b.y)
End Operator
' a - b
Operator - (a As int2d, b As int2d) As int2d
Return Type(a.x - b.x, a.y - b.y)
End Operator
' -a
Operator - (a As int2d) As int2d
Return Type(-a.x, -a.y)
End Operator
' a * b
Operator * (a As int2d, b As int2d) As int2d
Return Type(a.x * b.x, a.y * b.y)
End Operator
' a * mul
Operator * (a As int2d, mul As Integer) As int2d
Return Type(a.x * mul, a.y * mul)
End Operator
' a \ b
Operator \ (a As int2d, b As int2d) As int2d
Return Type(a.x \ b.x, a.y \ b.y)
End Operator
' a \ div
Operator \ (a As int2d, div As Integer) As int2d
Return Type(a.x \ div, a.y \ div)
End Operator
'===============================================================================
Type sgl2d
As Single x, y
Declare Constructor
Declare Constructor(x As Single, y As Single)
Declare Operator Cast () As String
End Type
Constructor sgl2d
End Constructor
Constructor sgl2d(x As Single, y As Single)
This.x = x : This.y = y
End Constructor
' "x, y"
Operator sgl2d.cast () As String
Return Str(x) & "," & Str(y)
End Operator
'---- operators ---
' distance / lenth
Operator Len (a As sgl2d) As Single
Return Sqr(a.x * a.x + a.y * a.y)
End Operator
' a = b ?
Operator = (a As sgl2d, b As sgl2d) As boolean
If a.x <> b.x Then Return false
If a.y <> b.y Then Return false
Return true
End Operator
' a != b ?
Operator <> (a As sgl2d, b As sgl2d) As boolean
If a.x = b.x And a.y = b.y Then Return false
Return true
End Operator
' a + b
Operator + (a As sgl2d, b As sgl2d) As sgl2d
Return Type(a.x + b.x, a.y + b.y)
End Operator
' a - b
Operator - (a As sgl2d, b As sgl2d) As sgl2d
Return Type(a.x - b.x, a.y - b.y)
End Operator
' -a
Operator - (a As sgl2d) As sgl2d
Return Type(-a.x, -a.y)
End Operator
' a * b
Operator * (a As sgl2d, b As sgl2d) As sgl2d
Return Type(a.x * b.x, a.y * b.y)
End Operator
' a * mul
Operator * (a As sgl2d, mul As Single) As sgl2d
Return Type(a.x * mul, a.y * mul)
End Operator
' a / div
Operator / (a As sgl2d, div As Single) As sgl2d
Return Type(a.x / div, a.y / div)
End Operator
'---- extra functions ---
Function cross(a As sgl2d, b As sgl2d) As Single
Return a.x * b.y - a.y * b.x
End Function
Function lengthSqrd(a As sgl2d) As Single
Return (a.x * a.x) + (a.y * a.y)
End Function
Function dist(a As sgl2d, b As sgl2d) As Single
Dim As Single dx = a.x - b.x
Dim As Single dy = a.y - b.y
Return Sqr((dx * dx) + (dy * dy))
End Function
Function distSqrd(a As sgl2d, b As sgl2d) As Single
Dim As Single dx = a.x - b.x
Dim As Single dy = a.y - b.y
Return (dx * dx) + (dy * dy)
End Function
Function normalise(a As sgl2d) As sgl2d
Dim As sgl2d temp
Dim As Single length = Len(a)
Return sgl2d(a.x / length, a.y / length)
End Function
'===============================================================================
'Note: y+ = up, x+ = right, (0,0) = center
Type scaled_graphics_type
Dim As Single scale = 1 ' = 1 / pixel_size 'pixels / meter
'dim as int2d offset' = (scrn_w \ 2, h \ 2) 'offset in pixels
Dim As sgl2d offset
Dim As Integer w = -1, h = -1
Dim As Integer wc = -1, hc = -1 'center x,y
Declare Sub setScreen(w As Integer, h As Integer)
Declare Sub setScaling(scale As Single, offset As sgl2d)
Declare Sub clearScreen(c As ULong)
Declare Function pos2screen(p As sgl2d) As int2d
Declare Sub drawPixel(p As sgl2d, c As ULong)
Declare Sub drawCircle(p As sgl2d, r As Single, c As ULong)
Declare Sub drawCircleFilled(p As sgl2d, r As Single, c As ULong, cFill As ULong)
Declare Sub drawElipse(p As sgl2d, r As Single, aspect As Single, c As ULong)
Declare Sub drawLine(p1 As sgl2d, p2 As sgl2d, c As ULong)
End Type
Sub scaled_graphics_type.setScreen(w As Integer, h As Integer)
This.w = w 'width
This.h = h 'height
wc = w \ 2
hc = h \ 2
ScreenRes w, h, 32
Width w \ 8, h \ 16 'bigger font
End Sub
Sub scaled_graphics_type.setScaling(scale As Single, offset As sgl2d)
This.scale = scale
This.offset = offset
End Sub
Sub scaled_graphics_type.clearScreen(c As ULong)
Line(0, 0)-(w - 1, h - 1), c, bf
End Sub
Function scaled_graphics_type.pos2screen(p As sgl2d) As int2d
Return int2d(Int(wc + (p.x - offset.x) * scale), h - Int(hc + (p.y - offset.y) * scale))
End Function
Sub scaled_graphics_type.drawPixel(p As sgl2d, c As ULong)
Dim As int2d posScrn = pos2screen(p)
PSet(posScrn.x, posScrn.y), c
End Sub
Sub scaled_graphics_type.drawCircle(p As sgl2d, r As Single, c As ULong)
Dim As int2d posScrn = pos2screen(p)
Circle(posScrn.x, posScrn.y), r * scale, c
End Sub
Sub scaled_graphics_type.drawCircleFilled(p As sgl2d, r As Single, c As ULong, cFill As ULong)
Dim As int2d posScrn = pos2screen(p)
Circle(posScrn.x, posScrn.y), r * scale, 0,,,,f
Circle(posScrn.x, posScrn.y), r * scale, c
End Sub
Sub scaled_graphics_type.drawElipse(p As sgl2d, r As Single, aspect As Single, c As ULong)
Dim As int2d posScrn = pos2screen(p)
Circle(posScrn.x, posScrn.y), r * scale, c, , , aspect
End Sub
Sub scaled_graphics_type.drawLine(p1 As sgl2d, p2 As sgl2d, c As ULong)
Dim As int2d posScrn1 = pos2screen(p1)
Dim As int2d posScrn2 = pos2screen(p2)
Line(posScrn1.x, posScrn1.y)-(posScrn2.x, posScrn2.y), c
End Sub
'===============================================================================
Const As Single PI = 4 * Atn(1)
Const As Single RAD_PER_DEG = (PI / 180)
Const As Single DEG_PER_RAD = 180 / PI
Const As Single sinA = Sin((10 / 180) * PI)
Const As Single cosA = Cos((10 / 180) * PI)
Const As Single sinB = Sin((20 / 180) * PI)
Const As Single cosB = Cos((20 / 180) * PI)
Const K_ENTER = Chr(13)
Const K_ESC = Chr(27)
Const K_MIN = Chr(45)
Const K_UND = Chr(95)
Const K_PLU = Chr(61)
Const K_EQU = Chr(43)
Const SCRN_W = 800, SCRN_H = 600
Dim Shared As scaled_graphics_type sg
sg.setScaling(2.0, sgl2d(0, 0))
sg.setScreen(SCRN_W, SCRN_H)
'-------------------------------------------------------------------------------
Sub waitForKey(key As String)
While InKey <> key
Sleep 1
Wend
End Sub
Function limit(value As Single, min As Single, max As Single) As Single
If value < min Then Return min
If value > max Then Return max
Return value
End Function
Type polar
Dim As Single angle
Dim As Single magnitude
End Type
Function polarToCartesian(angle As Single, radius As Single) As sgl2d
Return sgl2d(Cos(angle) * radius, Sin(angle) * radius)
End Function
Function rotatedVector(v As sgl2d, rotAngle As Single) As sgl2d
Dim As sgl2d tmp
tmp.x = Cos(rotAngle) * v.x - Sin(rotAngle) * v.y
tmp.y = Sin(rotAngle) * v.x + Cos(rotAngle) * v.y
Return tmp
End Function
'-------------------------------------------------------------------------------
Sub drawArrow(p1 As sgl2d, p2 As sgl2d, c As ULong)
sg.drawLine(p1, p2, c)
Dim As sgl2d dp = (p2 - p1) * 0.30 'reduce length
sg.drawLine(p2, p2 - sgl2d(cosB * dp.x - sinB * dp.y, sinB * dp.x + cosB * dp.y), c)
sg.drawLine(p2, p2 - sgl2d(cosB * dp.x + sinB * dp.y, cosB * dp.y - sinB * dp.x), c)
End Sub
Sub drawThruster(p1 As sgl2d, p2 As sgl2d, c As ULong)
sg.drawLine(p1, p2, c)
Dim As sgl2d dp = (p2 - p1) * 0.95 'reduce length
sg.drawLine(p1, p1 + sgl2d(cosA * dp.x - sinA * dp.y, sinA * dp.x + cosA * dp.y), c)
sg.drawLine(p1, p1 + sgl2d(cosA * dp.x + sinA * dp.y, cosA * dp.y - sinA * dp.x), c)
End Sub
Sub drawHelium3(p As sgl2d, r As Single, rot As Single, c As ULong)
For i As Integer = 0 To 2
sg.drawCircle(p + polarToCartesian((i / 3) * 2 * PI + rot, 0.15 * r), 0.15 * r, c)
Next
sg.drawElipse(p, r, 2.0, c)
sg.drawElipse(p, r, 0.5, c)
End Sub
Sub drawStar(p As sgl2d, size As Single, c As ULong)
sg.drawLine(p - sgl2d(size / 2, 0) , p + sgl2d(size / 2, 0), c)
sg.drawLine(p - sgl2d(0, size / 2) , p + sgl2d(0, size / 2), c)
End Sub
'-------------------------------------------------------------------------------
Type disc_object
Dim As Single radius '[m]
Dim As Single height '[m]
Dim As Single density '[kg/m^3]
Dim As ULong colour '[m]
'linear motion properties
Dim As sgl2d position 'position [m]
Dim As Single lin_m 'mass [kg]
Dim As sgl2d lin_F 'force [N] [kg*m/s^2]
Dim As sgl2d lin_a 'acceleration [m/s^2]
Dim As sgl2d lin_v 'velocity [m/s]
'dim as sgl2d lin_p 'momentum [kg*m/s]
'dim as single lin_E 'Kinetic energy [J] [kg*m^2/s^2]
'Rotational motion properties
Dim As Single angle 'angular position (theta) [rad]
Dim As Single ang_m 'angular mass, moment of inertia (I) [kg*m^2]
Dim As Single ang_F 'torque (tau) [N*m] [kg*m^2/s^2]
Dim As Single ang_a 'angular velocity (alpha) [rad/s^2]
Dim As Single ang_v 'angular velocity (omega) [rad/s]
'dim as single ang_p 'angular momentum (L) [kg*m^2/s]
'dim as single ang_E 'Kinetic energy [J] [kg*m^2/s^2]
Declare Sub init(r As Single, h As Single, d As Single, p As sgl2d, c As ULong)
Declare Sub update(dt As Double)
Declare Function getKineticEnergy() As Single
End Type
'Set radius, height, density, position
'Calculate mass and rotational inertia
Sub disc_object.init(r As Single, h As Single, d As Single, p As sgl2d, c As ULong)
radius = r
height = h
density = d
position = p
colour = c
lin_m = PI * r ^ 2 * d
ang_m = 0.5 * lin_m * r ^ 2
End Sub
'update position and angle
Sub disc_object.update(dt As Double)
lin_a = lin_F / lin_m
lin_v += lin_a * dt
position += lin_v * dt
ang_a = ang_F / ang_m
ang_v += ang_a * dt
angle += ang_v * dt
End Sub
Function disc_object.getKineticEnergy() As Single
Dim As Single lin_E = 0.5 * lin_m * lengthSqrd(lin_v)
Dim As Single ang_E = 0.5 * ang_m * ang_v * ang_v
Return lin_E + ang_E
End Function
Sub drawShip(ship As disc_object)
'calculate ships tail pointer / triangle
Dim As sgl2d forwardPos = polarToCartesian(ship.angle - 90 * RAD_PER_DEG, ship.radius * 2.2)
Dim As sgl2d leftBackPos = polarToCartesian(ship.angle - 135 * RAD_PER_DEG, ship.radius * 1.0) '(90 + 45)
Dim As sgl2d rightBackPos = polarToCartesian(ship.angle - 45 * RAD_PER_DEG, ship.radius * 1.0) '(90 - 45)
sg.drawCircle(ship.position, ship.radius, ship.colour) 'flying saucer
sg.drawLine(ship.position + forwardPos, ship.position + leftBackPos, ship.colour)
sg.drawLine(ship.position + forwardPos, ship.position + rightBackPos, ship.colour)
End Sub
'-------------------------------------------------------------------------------
Type thruster_type
'''init paramaters
Dim As polar polarForce '(rad, N)
Dim As polar polarPos '(rad, m)
'''variable paramaters
Dim As sgl2d forceVector '(N, N)
Dim As sgl2d relPos, absPos '(m, m)
Dim As Integer active
Declare Sub init(forceMagnitude As Single, forceDirection As Single, posAngle As Single, posRadius As Single)
Declare Sub updatePosition(bodyPos As sgl2d, bodyAngle As Single)
End Type
Sub thruster_type.init(forceDirection As Single, forceMagnitude As Single, posAngle As Single, posRadius As Single)
polarForce = Type(forceDirection, forceMagnitude) 'thruster action
polarPos = Type(posAngle, posRadius) 'position of thruster on ship
End Sub
Sub thruster_type.updatePosition(bodyPos As sgl2d, bodyAngle As Single)
relPos = polarToCartesian(bodyAngle + polarPos.angle, polarPos.magnitude)
absPos = bodyPos + relPos
End Sub
'-------------------------------------------------------------------------------
Const As Single GRAV_CONST = 6.67e-11 '[m3/(kg*s^2)
Type astro_body
Dim As Single radius '[m]
Dim As Single density '[kg/m^3]
Dim As ULong colour '[m]
Dim As sgl2d position 'position [m]
Dim As Single mass '[kg]
Dim As Single rotation '[rad]
Declare Sub init(r As Single, d As Single, p As sgl2d, c As ULong)
End Type
'Set radius, density, position
'Calculate mass and rotational inertia
Sub astro_body.init(r As Single, d As Single, p As sgl2d, c As ULong)
radius = r
density = d
position = p
colour = c
mass = PI * r ^ 2 * d
End Sub
Function gravForce(m1 As Single, m2 As Single, r As Single) As Single
Return GRAV_CONST * (m1 * m2) / (r * r)
End Function
Function gravForceVector(m1 As Single, Pos1 As sgl2d, m2 As Single, pos2 As sgl2d) As sgl2d
Dim As Single distSquared = distSqrd(pos2, Pos1)
Dim As sgl2d unitVector12 = (Pos1 - pos2) / Sqr(distSquared)
Return unitVector12 * (-GRAV_CONST * (m1 * m2) / distSquared)
End Function
Function findNearestBody(refPos As sgl2d, body() As astro_body) As Integer
Dim As Integer nearestBodyId = 0
Dim As Single nearestBodyDistSqrd = distSqrd(refPos, body(0).position)
Dim As Single currentBodyDistSqrd
For i As Integer = 1 To UBound(body)
currentBodyDistSqrd = distSqrd(refPos, body(i).position)
If currentBodyDistSqrd < nearestBodyDistSqrd Then
nearestBodyDistSqrd = currentBodyDistSqrd
nearestBodyId = i
End If
Next
Return nearestBodyId
End Function
Type star_type
Dim As sgl2d position '[m]
Dim As Single size
Dim As ULong colour
Declare Sub init(p As sgl2d, s As Single, c As ULong)
End Type
Sub star_type.init(p As sgl2d, s As Single, c As ULong)
position = p
size = s
colour = c
End Sub
Type bullet_type
Dim As sgl2d position
Dim As sgl2d velocity
Dim As Single radius = 3.0
Dim As Integer active
Dim As Double endTime
Dim As ULong colour
Declare Sub init(p As sgl2d, v As sgl2d, lifeTime As Double, c As ULong)
End Type
Sub bullet_type.init(p As sgl2d, v As sgl2d, lifeTime As Double, c As ULong)
position = p
velocity = v
endTime = Timer + lifeTime
active = 1
colour = c
End Sub
'-------------------------------------------------------------------------------
Const As Single MOON_RADIUS = 1737e+6 '[m]
Const As Single MOON_DENSITY = 3344 '[kg/m^3]
Const NUM_THRUSTERS = 6
Const L_FW_THR = 0 'left forward thruster
Const R_FW_THR = 1 'right forward thruster
Const L_LO_THR = 2
Const R_LO_THR = 3
Const L_HI_THR = 4
Const R_HI_THR = 5
Const QUIT_NO = 0
Const QUIT_USER = 1
Const QUIT_CRASH = 2
Const QUIT_FUEL = 3
Const QUIT_WINNER = 4
Dim As Integer quit = 0
Dim As disc_object ship
Dim As thruster_type thruster(NUM_THRUSTERS - 1)
'const NUM_ASTEROID = 80
ReDim As astro_body asteroid(80 - 1)
'const NUM_HELIUM = 10
ReDim As astro_body helium(10 - 1)
Const As Single maxFuel = 1e6 'N*s
Dim As Single fuel = maxFuel
Const NUM_STARS = 150
Dim As star_type star(NUM_STARS-1)
Dim As bullet_type bullet
Dim As astro_body Ptr pAsteroid, pHelium
Dim As Integer nearestAsteroidToBulletId = -1
Dim As Integer nearestHeliumId
Dim As Integer nearestAsteroidId
Dim As Integer asteroidRemove = 0
ship.init(10, 1, 5, sgl2d(0, -50), RGB(127, 223, 0))
For i As Integer = 0 To UBound(asteroid)
asteroid(i).init(5 + 4 / (Rnd + 0.2), 1000, sgl2d((Rnd - 0.5) * 2000, (Rnd - 0.5) * 2000), RGB(Rnd * 64 + 127, Rnd * 64 + 95, 127))
Next
For i As Integer = 0 To UBound(helium)
helium(i).init(5 + 4 / (Rnd + 0.2), 1000, sgl2d((Rnd - 0.5) * 2000, (Rnd - 0.5) * 2000), RGB(255, 191, 0))
Next
For i As Integer = 0 To UBound(star)
star(i).init(sgl2d((Rnd - 0.5) * 4000, (Rnd - 0.5) * 4000), Rnd * 5 + 2, RGB(Rnd * 64 + 191, Rnd * 64 + 191, Rnd * 64 + 191))
Next
'force angle, force magnitude, polar thruster position
thruster(L_FW_THR).init(0.5 * pi, 1.2e4, -0.75 * pi, ship.radius)
thruster(R_FW_THR).init(0.5 * pi, 1.2e4, -0.25 * pi, ship.radius)
thruster(L_LO_THR).init(0.0 * pi, 8e3, -0.75 * pi, ship.radius)
thruster(R_LO_THR).init(1.0 * pi, 8e3, -0.25 * pi, ship.radius)
thruster(L_HI_THR).init(0.0 * pi, 8e3, +0.75 * pi, ship.radius)
thruster(R_HI_THR).init(1.0 * pi, 8e3, +0.25 * pi, ship.radius)
'intro text
Locate 10, 20: Print "HELIUM-3 SPACE RACE"
Locate 12, 20: Print "Scoop up all the helium-3 clouds as fast as possible."
Locate 13, 20: Print "Your ship needs helium-3 for its fusion powered trhusters."
Locate 14, 20: Print "Do not run out of it and do not collide with the asteroids."
Locate 15, 20: Print "Post your best time on the forum."
Locate 17, 20: Print "Press <ENTER> to start";
Locate 24, 20: Print "Controls:";
Locate 26, 20: Print " Fire: <SPACE>";
Locate 27, 20: Print " Forward thrusters: <UP>";
Locate 28, 20: Print " Rotation thrusters: <LEFT>, <RIGHT>";
Locate 29, 20: Print " Side thrusters: <A>, <D>";
Locate 30, 20: Print " Abort game: <ESC>";
waitForKey(K_ENTER)
Dim As Double tStart = Timer, tNow = tStart, tPrev = tNow, dt = 0
While quit = 0
'reset stuff
ship.lin_F = sgl2d(0, 0)
ship.ang_F = 0
For i As Integer = 0 To NUM_THRUSTERS - 1
thruster(i).active = 0
Next
If MultiKey(FB.SC_UP) Then
thruster(L_FW_THR).active = 1
thruster(R_FW_THR).active = 1
fuel -= thruster(L_FW_THR).polarForce.magnitude * dt
fuel -= thruster(R_FW_THR).polarForce.magnitude * dt
End If
If MultiKey(FB.SC_LEFT) Then
thruster(L_LO_THR).active = 1
thruster(R_HI_THR).active = 1
fuel -= thruster(L_LO_THR).polarForce.magnitude * dt
fuel -= thruster(R_HI_THR).polarForce.magnitude * dt
End If
If MultiKey(FB.SC_RIGHT) Then
thruster(R_LO_THR).active = 1
thruster(L_HI_THR).active = 1
fuel -= thruster(R_LO_THR).polarForce.magnitude * dt
fuel -= thruster(L_HI_THR).polarForce.magnitude * dt
End If
If MultiKey(FB.SC_A) Then
thruster(R_LO_THR).active = 1
thruster(R_HI_THR).active = 1
fuel -= thruster(R_LO_THR).polarForce.magnitude * dt
fuel -= thruster(R_HI_THR).polarForce.magnitude * dt
End If
If MultiKey(FB.SC_D) Then
thruster(L_LO_THR).active = 1
thruster(L_HI_THR).active = 1
fuel -= thruster(L_LO_THR).polarForce.magnitude * dt
fuel -= thruster(L_HI_THR).polarForce.magnitude * dt
End If
'~ if multikey(FB.SC_P) then
'~ sleep 5000,1 'for taking a screenshot
'~ end if
If MultiKey(FB.SC_SPACE) Then
If bullet.active = 0 Then
Dim As sgl2d vBullet = ship.lin_v + polarToCartesian(ship.angle + pi/2, 50)
bullet.init(ship.position, vBullet, 3.0, RGB(255, 0, 0))
fuel -= maxFuel * 0.05 'takes 5% of fuel
End If
End If
If MultiKey(FB.SC_ESCAPE) Then quit = QUIT_USER
For i As Integer = 0 To NUM_THRUSTERS - 1
'forces on body by active thrusters
If thruster(i).active > 0 Then
Dim As Single thrust = thruster(i).polarForce.magnitude
thruster(i).forceVector = polarToCartesian(ship.angle + thruster(i).polarForce.angle, thrust)
ship.lin_F += thruster(i).forceVector
ship.ang_F += cross(thruster(i).relPos, thruster(i).forceVector)
End If
Next
ship.update(dt) 'position and angle
sg.offset = ship.position
sg.scale = limit(100 / Len(ship.lin_v), 0.5, 2.0)
'do always for display
For i As Integer = 0 To NUM_THRUSTERS - 1
thruster(i).updatePosition(ship.position, ship.angle)
Next
For i As Integer = 0 To UBound(helium)
helium(i).rotation += 300 * RAD_PER_DEG * dt 'N * degrees / second
Next
nearestAsteroidId = findNearestBody(ship.position, asteroid())
pAsteroid = @asteroid(nearestAsteroidId)
If dist(ship.position, pAsteroid->position) < (ship.radius + pAsteroid->radius) Then
quit = QUIT_CRASH
End If
nearestHeliumId = findNearestBody(ship.position, helium())
If fuel <= 0 Then quit = QUIT_FUEL
If bullet.active = 1 Then
If tNow > bullet.EndTime Then
bullet.active = 0
Else
bullet.position += bullet.velocity * dt
nearestAsteroidToBulletId = findNearestBody(bullet.position, asteroid())
asteroidRemove = 1
End If
End If
'display
ScreenLock
sg.clearScreen(0)
'draw stars background
For i As Integer = 0 To UBound(star)
drawStar(star(i).position * 0.75 + ship.position * 0.25, star(i).size, star(i).colour)
Next
drawShip(ship)
'draw active thrusters
For i As Integer = 0 To NUM_THRUSTERS - 1
Dim As ULong c = IIf(i < 4, RGB(255, 255, 0), RGB(255, 255, 255))
If thruster(i).active > 0 Then
drawThruster(thruster(i).absPos, thruster(i).absPos - thruster(i).forceVector / 1e3, RGB(255, 63, 0)) 'thruster force indicator
End If
Next
'draw asteroids
For i As Integer = 0 To UBound(asteroid)
sg.drawCircleFilled(asteroid(i).position, asteroid(i).radius, asteroid(i).colour, 0)
Next
'draw helium 'clouds'
For i As Integer = 0 To UBound(helium)
drawHelium3(helium(i).position, helium(i).radius, helium(i).rotation, IIf(nearestHeliumId = i, RGB(191, 191, 255), helium(i).colour))
Next
Dim As sgl2d heliumPointer = normalise(ship.position - helium(nearestHeliumId).position)
drawArrow(ship.position, ship.position - heliumPointer * ship.radius * 2, RGB(191, 191, 255))
If bullet.active = 1 Then
sg.drawCircle(bullet.position, bullet.radius, bullet.colour)
End If
Draw String (8, 8 + 0 * 16), "Nearest helium distance [m]: " + Str(CInt(dist(ship.position, helium(nearestHeliumId).position)))
Draw String (8, 8 + 1 * 16), "Kinetic engergy [kJ]: " + Str(CInt(ship.getKineticEnergy() * 1e-3))
Draw String (8, 8 + 2 * 16), "Fuel remaining [%]: " + Str(CInt((fuel / maxFuel) * 100))
Draw String (8, 8 + 3 * 16), "Remaining helium3 clouds: " + Str(UBound(helium) + 1)
ScreenUnLock
'clean up after displaying
pHelium = @helium(nearestHeliumId)
If dist(ship.position, pHelium->position) < (ship.radius + pHelium->radius * 0.5) Then
If UBound(helium) > 0 Then
'remove form list
helium(nearestHeliumId) = helium(UBound(helium))
ReDim Preserve helium(UBound(helium) - 1)
fuel = maxFuel
Else
'last item
Erase helium
quit = QUIT_WINNER
End If
End If
'asteroid hit by bullet?
If nearestAsteroidToBulletId <> -1 Then
pAsteroid = @asteroid(nearestAsteroidToBulletId)
If dist(bullet.position, pAsteroid->position) < (bullet.radius + pAsteroid->radius) Then
'remove asteroid from list
If UBound(asteroid) > 0 Then
'remove form list
asteroid(nearestAsteroidToBulletId) = asteroid(UBound(asteroid))
ReDim Preserve asteroid(UBound(asteroid) - 1)
Else
'last item
Erase asteroid
End If
bullet.endTime = tNow + 0.1
'bullet.active = 0
End If
nearestAsteroidToBulletId = -1
End If
'time update
Sleep 1
tPrev = tNow
tNow = Timer
dt = tNow - tPrev
Wend
Select Case quit
Case QUIT_USER
Draw String (8, 8 + 6 * 16), "Abort by user"
Case QUIT_CRASH
ship.colour = RGB(233, 0, 0)
drawShip(ship)
Draw String (8, 8 + 6 * 16), "Ship crashed"
Case QUIT_FUEL
ship.colour = RGB(233, 191, 191)
drawShip(ship)
Draw String (8, 8 + 6 * 16), "Ship out of fuel"
Case QUIT_WINNER
Draw String (8, 8 + 6 * 16), "Well done all helium3 collected. Your time: " + Str(CInt(tNow - tStart)) + " seconds"
Case Else
End Select
Draw String (8, 8 + 7 * 16), "press <ENTER> to exit"
waitForKey(K_ENTER)
Screen 0
Print "End"