function love.load() names = { "Ceres", "Pallas", "Vesta", "Hygiea", "Davida", "Interamnia", "Europa", "Eunomia", "Sylvia", "Psyche", "Euphrosyne", "Cybele", "Juno", "Bamberga", "Camilla", "Herculina", "Patientia", "Doris", "Amphitrite", "Hermione", "Diotima", "Egeria", "Eugenia", "Aurora", "Iris", "Alauda", "Palma", "Nemesis", "Bertha", "Hebe", "Freia", "Elektra", "Kalliope", "Aletheia", "Daphne", "Winchester", "Lachesis", "Pretoria", "Agamemnon", "Hilda", "Stereoskopia", "Prokne", "Aegle", "Elpis", "Siegena", "Diomedes", "Alexandra", "Chicago", "Gyptis", "Germania", "Aspasia", "Eunike", "Eleonora", "Juewa", "Parthenope", "Hispania", "Loreley", "Ino", "Julia", "Laetitia", "Merapi", "Kreusa", "Io", "Nuwa", "Hypatia", "Adeona", "Lomia", "Pales", "Sibylla", "Nemausa", } letters = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } lurker = { x = 100, y = 160, dX = 0, dY = 0, dR = 0, rotation = math.pi/2, fuel = 10, size = 10, scanDist = 40, scanning = false, thrust = 35, rotate = math.pi/2, thrusters = { left = false, right = false, forward = false, backward = false, rotate_left = false, rotate_right = false, }, img = love.graphics.newImage( 'images/sat.png' ), thrusterImg = love.graphics.newImage( 'images/thrust.png' ), scanImg = love.graphics.newImage( 'images/scancone.png' ) } collected = {} score = 0 scorebarImg = love.graphics.newImage( 'images/scorebar.png' ) planetImg = love.graphics.newImage( 'images/scanbar.png' ) intro = love.graphics.newImage( 'images/intro.png' ) outro = love.graphics.newImage( 'images/end.png' ) smallFont = love.graphics.newFont() largeFont = love.graphics.newFont( 22 ) love.graphics.setFont( smallFont ) markers = {} generateNewField() love.draw = intro_draw love.update = intro_update ready = false end function intro_update( dt ) if not love.keyboard.isDown( " " ) then ready = true end if love.keyboard.isDown( " " ) and ready then love.update = game_update love.draw = game_draw end end function intro_draw() love.graphics.draw( intro ) end function game_update( dt ) if lurker.fuel > 0 then lurkerControls( dt ) else noThrusters() end lurker.x = lurker.x + lurker.dX * dt lurker.y = lurker.y - lurker.dY * dt lurker.rotation = lurker.rotation + lurker.dR * dt -- can never be more than one anyway for k, v in ipairs( markers ) do v.y = v.y - 10*dt if v.y < 540 then table.remove( markers, k ) end end if checkLurkerDeath() then love.update = gameover_update love.draw = gameover_draw end checkLurkerPlanetScan( dt ) checkLurkerNextField() end function gameover_update( dt ) if love.keyboard.isDown( " " ) then love.load() end end function gameover_draw() love.graphics.draw( outro, 0, 0 ) love.graphics.setFont( largeFont ) local width = largeFont:getWidth( "Final score: " .. score ) love.graphics.print( "Final score: " .. score, 400 - width/2, 50 ) local width = largeFont:getWidth( "You have gathered valuable information on these planetoids:" ) love.graphics.print( "You have gathered valuable information on these planetoids:", 400 - width/2, 80 ) for k, v in ipairs( collected ) do local x = ((k-1)%5)*150+100 local y = math.ceil(k/5)*150+100 love.graphics.setColor( v.color ) love.graphics.circle( "fill", x, y, v.size ) love.graphics.setColor( 255,255,255,255 ) local width = largeFont:getWidth( v.name ) love.graphics.print( v.name, x - width/2, y + 75 ) for _k, spec in ipairs( v.specs ) do love.graphics.setColor( spec.color ) love.graphics.circle( "fill", x + spec.x, y + spec.y, spec.size ) end end love.graphics.setColor( 255,255,255,255 ) end function game_draw() drawBackground() drawLurker() drawPlanets() love.graphics.rectangle( "fill", 100, 580, (lurker.fuel)*70, 20 ) love.graphics.draw( scorebarImg, 0, 580 ) love.graphics.print( score, 30, 584 ) if lurker.fuel <= 0 then love.graphics.setColor( 0,0,0,255 ) love.graphics.rectangle( "fill", 100, 580, 700, 20 ) love.graphics.setColor( 255,255,255,255 ) love.graphics.print( "No more fuel. Hit 'R' to end, or watch the fate of your drifting satellite.", 120, 584 ) end love.graphics.setColor( 0, 255, 0, 255 ) for k, v in ipairs( markers ) do love.graphics.print( v.score, v.x, v.y ) end love.graphics.setColor( 255, 255, 255, 255 ) end function lurkerControls( dt ) if love.keyboard.isDown( 's' ) then lurker.fuel = lurker.fuel - dt lurker.dX = lurker.dX - lurker.thrust * math.cos( lurker.rotation ) * dt lurker.dY = lurker.dY - lurker.thrust * math.sin( lurker.rotation ) * dt lurker.thrusters.backward = true else lurker.thrusters.backward = false end if love.keyboard.isDown( 'w' ) then lurker.fuel = lurker.fuel - dt lurker.dX = lurker.dX - lurker.thrust * math.cos( lurker.rotation + math.pi ) * dt lurker.dY = lurker.dY - lurker.thrust * math.sin( lurker.rotation + math.pi ) * dt lurker.thrusters.forward = true else lurker.thrusters.forward = false end if love.keyboard.isDown( 'a' ) then lurker.fuel = lurker.fuel - dt lurker.dX = lurker.dX - lurker.thrust * math.cos( lurker.rotation - math.pi/2) * dt lurker.dY = lurker.dY - lurker.thrust * math.sin( lurker.rotation - math.pi/2) * dt lurker.thrusters.left = true else lurker.thrusters.left = false end if love.keyboard.isDown( 'd' ) then lurker.fuel = lurker.fuel - dt lurker.dX = lurker.dX - lurker.thrust * math.cos( lurker.rotation + math.pi/2 ) * dt lurker.dY = lurker.dY - lurker.thrust * math.sin( lurker.rotation + math.pi/2 ) * dt lurker.thrusters.right = true else lurker.thrusters.right = false end if love.keyboard.isDown( 'q' ) then lurker.fuel = lurker.fuel - dt lurker.dR = lurker.dR + lurker.rotate * dt lurker.thrusters.rotate_right = true else lurker.thrusters.rotate_right = false end if love.keyboard.isDown( 'e' ) then lurker.fuel = lurker.fuel - dt lurker.dR = lurker.dR - lurker.rotate * dt lurker.thrusters.rotate_left = true else lurker.thrusters.rotate_left = false end end function noThrusters() lurker.thrusters.rotate_left = false lurker.thrusters.rotate_right = false lurker.thrusters.forward = false lurker.thrusters.back = false lurker.thrusters.left = false lurker.thrusters.right = false end function drawPlanets() for k, planet in ipairs ( planets ) do love.graphics.setColor( planet.color ) love.graphics.circle( "fill", planet.x, planet.y, planet.size ) for k_, v in ipairs( planet.specs ) do love.graphics.setColor( v.color ) love.graphics.circle( "fill", planet.x + v.x, planet.y + v.y, v.size ) end love.graphics.setColor( 255, 255, 255, 255 ) love.graphics.draw( planetImg, planet.x, planet.y, 0, 1, 1, planetImg:getWidth()/2, planetImg:getHeight()/2 ) love.graphics.setColor( 0, 0, 0, 255 ) love.graphics.print( planet.score, planet.x, planet.y-13 ) love.graphics.setColor(0,0,0,255) for i = 1, math.floor( planet.timeScan * 4 ) do local notchX = math.floor( planet.x-16 + (i/planet.timeScan)*46/4) love.graphics.line( notchX, planet.y, notchX, planet.y+5) end if planet.scanned < planet.timeScan then love.graphics.setColor( 0, 0, 255, 255 ) else love.graphics.setColor( 0, 255, 0, 255 ) end love.graphics.rectangle( "fill", planet.x-16, planet.y, (planet.scanned / planet.timeScan) * 46, 15 ) love.graphics.setColor( 255, 255, 255, 255 ) end end function drawLurker() if lurker.scanning then local angle = math.atan2(lurker.scanning.x - lurker.x, lurker.scanning.y - lurker.y ) - math.pi/2 love.graphics.setColor( 0, 0, 255, 255 ) for i = -5, 5 do love.graphics.line( lurker.x, lurker.y, lurker.x + (lurker.size+40) * math.cos( angle - i*(math.pi/32) ), lurker.y - (lurker.size+40) * math.sin( angle - i*(math.pi/32) ) ) end love.graphics.setColor( 255, 255, 255, 255 ) end love.graphics.draw( lurker.img, lurker.x, lurker.y, -lurker.rotation, 1, 1, lurker.img:getWidth() / 2, lurker.img:getHeight() / 2 ) if lurker.thrusters.forward then love.graphics.draw( lurker.thrusterImg, lurker.x + 15 * math.cos( lurker.rotation + math.pi ), lurker.y - 15 * math.sin( lurker.rotation + math.pi ), -lurker.rotation, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end if lurker.thrusters.backward then love.graphics.draw( lurker.thrusterImg, lurker.x + 15 * math.cos( lurker.rotation ), lurker.y - 15 * math.sin( lurker.rotation ), -lurker.rotation + math.pi, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end if lurker.thrusters.right then love.graphics.draw( lurker.thrusterImg, lurker.x + 10 * math.cos( lurker.rotation + math.pi/2 ), lurker.y - 10 * math.sin( lurker.rotation + math.pi/2 ), -lurker.rotation + math.pi/2, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end if lurker.thrusters.left then love.graphics.draw( lurker.thrusterImg, lurker.x + 10 * math.cos( lurker.rotation - math.pi/2 ), lurker.y - 10 * math.sin( lurker.rotation - math.pi/2 ), -lurker.rotation - math.pi/2, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end if lurker.thrusters.rotate_left then love.graphics.draw( lurker.thrusterImg, lurker.x + 12 * math.cos( lurker.rotation + math.pi/4 ), lurker.y - 12 * math.sin( lurker.rotation + math.pi/4 ), -lurker.rotation - math.pi/4 - math.pi, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end if lurker.thrusters.rotate_right then love.graphics.draw( lurker.thrusterImg, lurker.x + 12 * math.cos( lurker.rotation - math.pi/4 ), lurker.y - 12 * math.sin( lurker.rotation - math.pi/4 ), -lurker.rotation + math.pi/4 - math.pi, 1, 1, lurker.thrusterImg:getWidth()/2, lurker.thrusterImg:getHeight()/2 ) end end function checkLurkerDeath() -- impacting a planet? for k, planet in ipairs( planets ) do if( math.sqrt( ( planet.x - lurker.x ) ^ 2 + ( planet.y - lurker.y ) ^ 2 ) < planet.size + lurker.size ) then return true end end -- outside of belt or returning? if lurker.y > 650 or lurker.y < -50 or lurker.x < -50 then return true end -- user quit? if love.keyboard.isDown( 'r' ) then return true end end function checkLurkerNextField() if lurker.x > 800 then lurker.x = 0 generateNewField() end end function generateNewField() planets = {} local function makeSpecs( size ) local specs = {} for i = 1, math.random( math.floor(size), math.floor(size*3) ) do local specSize = math.random( math.floor( size/8), math.floor( size/3 ) ) local rotation = math.random( -200, 200 ) * math.pi/100 local distance = math.random( 0, size ) if distance > size-specSize then distance = size-specSize end table.insert( specs, { x = math.cos( rotation ) * distance, y = math.sin( rotation ) * distance , dark = math.random( 5, 35 ), color = { math.random( 0, 255 ), math.random( 0, 255 ), math.random( 0, 255 ), math.random( 5, 35 ) }, size = specSize }) end return specs end for i = 1, math.random(4,10) do local value = math.random( 1, 10 ) * 5 local size = math.random( 32, 80 ) local planet = { x = math.random( 25, 775 ), y = math.random( 25, 575 ), size = size, mass = 0, color = { math.random( 0, 255 ), math.random( 0, 255 ), math.random( 0, 255 ), 255 }, score = value, scanned = 0, timeScan = math.random( 1, 4 ) * value / 40, name = makeName(), specs = makeSpecs( size ) } if checkClear( planet ) then table.insert( planets, planet ) end end stars = {} for i = 1, math.random( 200, 600 ) do table.insert( stars, { x = math.random( 5, 795 ), y = math.random( 5, 595 ), intensity = math.random( 30, 255 ), size = math.random( 1, 2 ) } ) end if #planets < 5 then generateNewField() end end function checkClear( planet ) for k, v in ipairs( planets ) do local dist = math.sqrt( ( v.x - planet.x )^2 + ( v.y - planet.y ) ^2 ) if dist < ( planet.size + v.size + 20 ) then return false end end dist = math.sqrt( ( lurker.x - planet.x )^2 + ( lurker.y - planet.y ) ^2 ) if dist < ( planet.size + lurker.size + 40 ) then return false end return true end function makeName() local basename = names[ math.random( 1, #names ) ] local number = math.random( 1, 20 ) local letter = '' if math.random(1,10) > 5 then letter = letters[ math.random( 1, #letters ) ] end return basename .. ' ' .. number .. letter end function checkLurkerPlanetScan( dt ) lurker.scanning = false for k, planet in ipairs( planets ) do if planet.scanned < planet.timeScan then local angle = math.atan2(planet.x - lurker.x, planet.y - lurker.y ) - math.pi/2 local angleDiff = ( angle - lurker.rotation) % (2*math.pi) local inRange = math.sqrt( ( planet.x - lurker.x ) ^ 2 + ( planet.y - lurker.y ) ^ 2 ) < planet.size + lurker.size + lurker.scanDist if inRange and ( angleDiff < math.pi/4 or angleDiff > math.pi*7/4 ) then planet.scanned = planet.scanned + dt lurker.scanning = planet if planet.scanned > planet.timeScan then score = score + planet.score floatingScoreMarker( planet.score ) table.insert( collected, { size = planet.size, color = planet.color, name = planet.name, specs = planet.specs }) end end end end end function floatingScoreMarker( score ) table.insert( markers, { x = 30, y = 564, score = score }) end function drawBackground() for k, v in ipairs( stars ) do love.graphics.setColor( 255,255,255, v.intensity ) love.graphics.circle( 'fill', v.x, v.y, v.size ) end love.graphics.setColor( 255, 255, 255, 255 ) end