Compare commits
10 Commits
af14ea661f
...
8f82a7e7f5
Author | SHA1 | Date | |
---|---|---|---|
8f82a7e7f5 | |||
|
20e4e459d2 | ||
|
c0e2572142 | ||
|
b5773d175c | ||
|
6c57a9d727 | ||
|
c3deb83608 | ||
|
b4fa1a6d84 | ||
|
da9e427512 | ||
|
013e24e285 | ||
|
793ecf575a |
3
ReadMe.md
Normal file
3
ReadMe.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
This repo is hosted at https://gitea.tangentfox.com/tangent/BSG and force-pushed to GitHub when commits are made.
|
||||||
|
|
||||||
|
Feel free to submit pull requests or whatever, but know that I would have to manage them over there.
|
12
ideas.txt
Normal file
12
ideas.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
1-4 on first dial, main dial
|
||||||
|
5-8 on second dial
|
||||||
|
|
||||||
|
1 Time orange
|
||||||
|
2 Ammo red
|
||||||
|
3 Fuel yellow
|
||||||
|
4 Supplies teal
|
||||||
|
|
||||||
|
5 Water blue
|
||||||
|
6 Food green
|
||||||
|
7 Metal silver
|
||||||
|
8 Ore brown
|
12
notes.txt
Normal file
12
notes.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
I'm sorry to disturb you Sir, but we got a priority one alert message from fleet headquarters. It .. was transmitted in the clear.
|
||||||
|
|
||||||
|
Attention all colonial units. Cylon attack underway. This is no drill.
|
||||||
|
|
||||||
|
Announce. Ignore.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Colonial Heavy 798
|
||||||
|
|
||||||
|
|
||||||
|
Hyperlight Jump
|
157
old/main.lua
Normal file
157
old/main.lua
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
local bsg = require "ships.bsg"
|
||||||
|
local viper = require "ships.viper"
|
||||||
|
|
||||||
|
local lg = love.graphics
|
||||||
|
|
||||||
|
local images = {}
|
||||||
|
local ships = {}
|
||||||
|
|
||||||
|
local hx, hy = lg.getWidth() / 2, lg.getHeight() / 2
|
||||||
|
|
||||||
|
local scale = 8
|
||||||
|
|
||||||
|
local selected
|
||||||
|
|
||||||
|
function love.load()
|
||||||
|
lg.setDefaultFilter("linear", "nearest", 1)
|
||||||
|
images.bsg = lg.newImage('img/bsg.png')
|
||||||
|
images.viper = lg.newImage('img/viper.png')
|
||||||
|
lg.setPointSize(10)
|
||||||
|
lg.setPointStyle("rough")
|
||||||
|
|
||||||
|
ships[1] = bsg()
|
||||||
|
for i=1,8 do
|
||||||
|
local v = viper()
|
||||||
|
table.insert(ships, v)
|
||||||
|
ships[1]:dock(v, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local timer = 0
|
||||||
|
function love.update(dt)
|
||||||
|
timer = timer + dt
|
||||||
|
if timer >= 33 then
|
||||||
|
timer = timer - 33
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawClock(x, y, r)
|
||||||
|
local time = math.floor(33 - timer)
|
||||||
|
if time == 0 then time = 33 end
|
||||||
|
|
||||||
|
local maxTime = 33
|
||||||
|
|
||||||
|
local segments = 33
|
||||||
|
local segmentRadius = math.pi*2 / segments
|
||||||
|
local dividerRadius = segmentRadius / 2
|
||||||
|
--local time = 33
|
||||||
|
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
for i=1,time do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*segmentRadius - math.pi/2, i*segmentRadius - dividerRadius - math.pi/2)
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r/1.15)
|
||||||
|
|
||||||
|
-- this looks cool and all, but it is the same function as the outer ring
|
||||||
|
-- instead, use this internal space for displaying things like fuel and water and supplies
|
||||||
|
--[[
|
||||||
|
segments = 12
|
||||||
|
segmentRadius = math.pi*2 / segments
|
||||||
|
dividerRadius = segmentRadius / segments * 2
|
||||||
|
time = math.floor(time/maxTime * segments) --33 -> 12 percentage = time/maxTime..multiply this by 12
|
||||||
|
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
for i=1,time do
|
||||||
|
lg.arc("fill", x, y, r/1.5, (i-1)*segmentRadius - math.pi/2, i*segmentRadius - dividerRadius - math.pi/2)
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r/2)
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--tmp, really each color-dependent section should do this itself!
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
end
|
||||||
|
|
||||||
|
local drawWheel = require "wheel";
|
||||||
|
|
||||||
|
function love.draw()
|
||||||
|
lg.translate(hx, hy)
|
||||||
|
|
||||||
|
for i=1,#ships do
|
||||||
|
lg.draw(images[ships[i].img], ships[i].x * scale, ships[i].y * scale, ships[i].rotation, scale, scale, ships[i].ox, ships[i].oy)
|
||||||
|
end
|
||||||
|
|
||||||
|
if selected then
|
||||||
|
lg.setColor(220, 180, 0)
|
||||||
|
lg.point(selected.x * scale, selected.y * scale)
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
end
|
||||||
|
|
||||||
|
--drawClock(-355, -145, 120)
|
||||||
|
drawWheel(-355, -145, 120, timer)
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.keypressed(key, unicode)
|
||||||
|
if key == "escape" then
|
||||||
|
love.event.quit()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pointInRadius(x, y, cx, cy, r)
|
||||||
|
cx = cx * scale + hx
|
||||||
|
cy = cy * scale + hy
|
||||||
|
local dx = x - cx
|
||||||
|
local dy = y - cy
|
||||||
|
return r * scale >= math.sqrt(dx * dx + dy * dy)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pointInAABB(x, y, cx, cy, s, r)
|
||||||
|
-- THIS IS HORRIBLY WRONG, FIX IT LATER
|
||||||
|
--[[
|
||||||
|
var x=((objects[i].x-objects[renderId].x)*Math.cos(rot)-(objects[i].y-objects[renderId].y)*Math.sin(rot))*scaleFactor;
|
||||||
|
var y=((objects[i].x-objects[renderId].x)*Math.sin(rot)+(objects[i].y-objects[renderId].y)*Math.cos(rot))*scaleFactor;
|
||||||
|
]]
|
||||||
|
local nx = (x - cx) * math.cos(r) - (y - cy) * math.sin(r)
|
||||||
|
local ny = (x - cx) * math.sin(r) + (y - cy) * math.cos(r)
|
||||||
|
x = nx
|
||||||
|
y = ny
|
||||||
|
cx = cx * scale + hx
|
||||||
|
cy = cy * scale + hy
|
||||||
|
return x >= cx - s.w * scale / 2 and x <= cx + s.w * scale / 2 and y >= cy - s.h * scale / 2 and y <= cy + s.h * scale / 2
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.mousepressed(x, y, button)
|
||||||
|
if button == "l" then
|
||||||
|
if selected then
|
||||||
|
-- find out where this actually is, now the ship selected is ordered to move to this point
|
||||||
|
selected.ship:moveTo(x * scale + hx, y * scale + hy)
|
||||||
|
else
|
||||||
|
for i=1,#ships do
|
||||||
|
if ships[i].selection.r then
|
||||||
|
if pointInRadius(x, y, ships[i].x, ships[i].y, ships[i].selection.r) then
|
||||||
|
-- selected
|
||||||
|
-- NOW CHECK IF HAS NODES AND IF WE ARE SELECTING A SHIP ON A NODE!
|
||||||
|
selected = {}
|
||||||
|
selected.ship = ships[i]
|
||||||
|
selected.x = ships[i].x
|
||||||
|
selected.y = ships[i].y
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if pointInAABB(x, y, ships[i].x, ships[i].y, ships[i].selection, ships[i].rotation) then
|
||||||
|
-- we are selecting it!
|
||||||
|
-- NOW CHECK IF HAS NODES AND IF WE ARE SELECTING A SHIP ON A NODE!
|
||||||
|
selected = {}
|
||||||
|
selected.ship = ships[i]
|
||||||
|
selected.x = ships[i].x
|
||||||
|
selected.y = ships[i].y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif button == "wd" then
|
||||||
|
scale = scale * 1.1
|
||||||
|
elseif button == "wu" then
|
||||||
|
scale = scale * 0.9
|
||||||
|
end
|
||||||
|
end
|
42
old/wheel.lua
Normal file
42
old/wheel.lua
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
local verticalOffset = math.pi/2
|
||||||
|
local maxTime = 60
|
||||||
|
|
||||||
|
local segments = 60
|
||||||
|
local segmentRadius = math.pi*2 / segments
|
||||||
|
|
||||||
|
local dividerRadius = segmentRadius / 2
|
||||||
|
|
||||||
|
local lg = love.graphics
|
||||||
|
|
||||||
|
local function drawWheel(x, y, r, time)
|
||||||
|
time = math.floor(33 - time)
|
||||||
|
if time == 0 then time = 33 end
|
||||||
|
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
for i=1,time do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*segmentRadius - verticalOffset, i*segmentRadius - dividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r/1.15)
|
||||||
|
|
||||||
|
-- this looks cool and all, but it is the same function as the outer ring
|
||||||
|
-- instead, use this internal space for displaying things like fuel and water and supplies
|
||||||
|
--[[
|
||||||
|
segments = 12
|
||||||
|
segmentRadius = math.pi*2 / segments
|
||||||
|
dividerRadius = segmentRadius / segments * 2
|
||||||
|
time = math.floor(time/maxTime * segments) --33 -> 12 percentage = time/maxTime..multiply this by 12
|
||||||
|
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
for i=1,time do
|
||||||
|
lg.arc("fill", x, y, r/1.5, (i-1)*segmentRadius - verticalOffset, i*segmentRadius - dividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r/2)
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--tmp, really each color-dependent section should do this itself!
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
end
|
||||||
|
|
||||||
|
return drawWheel
|
BIN
screenshots/Resources.png
Normal file
BIN
screenshots/Resources.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
screenshots/The Clock.png
Normal file
BIN
screenshots/The Clock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
369
src/hud.lua
Normal file
369
src/hud.lua
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
local r = 75
|
||||||
|
local edge = 5
|
||||||
|
|
||||||
|
local x = -480 + r + edge
|
||||||
|
local y = 270 - r - edge
|
||||||
|
|
||||||
|
local x2 = 480 - r - edge
|
||||||
|
local y2 = 270 - r - edge
|
||||||
|
|
||||||
|
local verticalOffset = math.pi/2
|
||||||
|
|
||||||
|
local timeSegments = 60
|
||||||
|
local timeSegmentRadius = math.pi*2 / timeSegments
|
||||||
|
local timeDividerRadius = timeSegmentRadius / 2
|
||||||
|
|
||||||
|
local lg = love.graphics
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local function brighten(color)
|
||||||
|
if color[cycle] == true then
|
||||||
|
if color[1] < 251 then
|
||||||
|
color[1] = color[1] + 5
|
||||||
|
else
|
||||||
|
color[1] = 255
|
||||||
|
end
|
||||||
|
if color[2] < 251 then
|
||||||
|
color[2] = color[2] + 5
|
||||||
|
else
|
||||||
|
color[2] = 255
|
||||||
|
end
|
||||||
|
if color[3] < 251 then
|
||||||
|
color[3] = color[3] + 5
|
||||||
|
else
|
||||||
|
color[3] = 255
|
||||||
|
end
|
||||||
|
if color[1] == 255 and color[2] == 255 and color[3] == 255 then
|
||||||
|
color[cycle] = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if color[1] > 4 then
|
||||||
|
color[1] = color[1] - 5
|
||||||
|
else
|
||||||
|
color[1] = 0
|
||||||
|
end
|
||||||
|
if color[2] > 4 then
|
||||||
|
color[2] = color[2] - 5
|
||||||
|
else
|
||||||
|
color[2] = 0
|
||||||
|
end
|
||||||
|
if color[3] > 4 then
|
||||||
|
color[3] = color[3] - 5
|
||||||
|
else
|
||||||
|
color[3] = 0
|
||||||
|
end
|
||||||
|
if color[1] == 0 and color[2] == 0 and color[3] == 0 then
|
||||||
|
color[cycle] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(color)
|
||||||
|
return color
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
return function(stats)
|
||||||
|
--[[ for seeing warnings
|
||||||
|
stats.ammo = 3
|
||||||
|
stats.fuel = 2
|
||||||
|
stats.supplies = 1
|
||||||
|
stats.water = 4
|
||||||
|
stats.food = 5
|
||||||
|
stats.metal = 1
|
||||||
|
stats.ore = 2
|
||||||
|
--]]
|
||||||
|
local tCalc = stats.time * 10
|
||||||
|
stats.time = math.floor(stats.time)
|
||||||
|
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
--local timeColor = {165, 52, 0, cycle = true}
|
||||||
|
lg.setColor(165, 52, 0)
|
||||||
|
if stats.time > 120 then
|
||||||
|
lg.setColor(255, 210, 110)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
--lg.setColor(40, 60, 100)
|
||||||
|
if tCalc%32 < 16 then
|
||||||
|
lg.setColor(165, 52, 0)
|
||||||
|
else
|
||||||
|
lg.setColor(0, 45, 145)
|
||||||
|
end
|
||||||
|
--lg.setColor(0, 45, 145)
|
||||||
|
for i=1,(stats.time-120)/5+1 do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
elseif stats.time > 60 then
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
lg.setColor(255, 210, 110)
|
||||||
|
for i=1,stats.time-60 do
|
||||||
|
--timeColor = brighten(timeColor)
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
elseif stats.time > 0 then
|
||||||
|
for i=1,stats.time do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i=0,stats.time+1,-1 do
|
||||||
|
lg.arc("fill", x, y, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r*4/5 + edge/2)
|
||||||
|
|
||||||
|
if stats.ammo < 2 then
|
||||||
|
if tCalc%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.ammo < 6 then
|
||||||
|
if tCalc%8 < 4 then
|
||||||
|
lg.setColor(255, 0, 0)
|
||||||
|
for i=1,stats.ammo do
|
||||||
|
lg.arc("fill", x, y, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(255, 0, 0)
|
||||||
|
for i=1,stats.ammo do
|
||||||
|
lg.arc("fill", x, y, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r*3/5 + edge/2)
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.fuel = 1
|
||||||
|
if stats.fuel < 2 then
|
||||||
|
if (tCalc+1)%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.fuel < 6 then
|
||||||
|
if (tCalc+1)%8 < 4 then
|
||||||
|
lg.setColor(255, 255, 0)
|
||||||
|
for i=1,stats.fuel do
|
||||||
|
lg.arc("fill", x, y, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(255, 255, 0)
|
||||||
|
for i=1,stats.fuel do
|
||||||
|
lg.arc("fill", x, y, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r*2/5 + edge/2)
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.supplies = 1
|
||||||
|
if stats.supplies < 2 then
|
||||||
|
if (tCalc+2)%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x, y, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.supplies < 6 then
|
||||||
|
if (tCalc+2)%8 < 4 then
|
||||||
|
lg.setColor(0, 255, 255)
|
||||||
|
for i=1,stats.supplies do
|
||||||
|
lg.arc("fill", x, y, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(0, 255, 255)
|
||||||
|
for i=1,stats.supplies do
|
||||||
|
lg.arc("fill", x, y, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x, y, r*1/5 + edge/2)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
1-4 on first dial, main dial
|
||||||
|
5-8 on second dial
|
||||||
|
|
||||||
|
1 Time orange
|
||||||
|
2 Ammo red
|
||||||
|
3 Fuel yellow
|
||||||
|
4 Supplies teal
|
||||||
|
|
||||||
|
5 Water blue
|
||||||
|
6 Food green
|
||||||
|
7 Metal silver
|
||||||
|
8 Ore brown
|
||||||
|
]]
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.water = 1
|
||||||
|
if stats.water < 2 then
|
||||||
|
if (tCalc+3)%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.water < 6 then
|
||||||
|
if (tCalc+3)%8 < 4 then
|
||||||
|
lg.setColor(0, 0, 255)
|
||||||
|
for i=1,stats.water do
|
||||||
|
lg.arc("fill", x2, y2, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(0, 0, 255)
|
||||||
|
for i=1,stats.water do
|
||||||
|
lg.arc("fill", x2, y2, r, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x2, y2, r*4/5 + edge/2)
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.food = 1
|
||||||
|
if stats.food < 2 then
|
||||||
|
if tCalc%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.food < 6 then
|
||||||
|
if tCalc%8 < 4 then
|
||||||
|
lg.setColor(0, 160, 0)
|
||||||
|
for i=1,stats.food do
|
||||||
|
lg.arc("fill", x2, y2, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(0, 160, 0)
|
||||||
|
for i=1,stats.food do
|
||||||
|
lg.arc("fill", x2, y2, r*4/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x2, y2, r*3/5 + edge/2)
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.metal = 1
|
||||||
|
if stats.metal < 2 then
|
||||||
|
if (tCalc+1)%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.metal < 6 then
|
||||||
|
if (tCalc+1)%8 < 4 then
|
||||||
|
lg.setColor(100, 100, 100)
|
||||||
|
for i=1,stats.metal do
|
||||||
|
lg.arc("fill", x2, y2, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(100, 100, 100)
|
||||||
|
for i=1,stats.metal do
|
||||||
|
lg.arc("fill", x2, y2, r*3/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x2, y2, r*2/5 + edge/2)
|
||||||
|
|
||||||
|
---[[tmp to see warnings]] stats.ore = 1
|
||||||
|
if stats.ore < 2 then
|
||||||
|
if (tCalc+2)%4 < 2 then
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(10, 20, 30)
|
||||||
|
for i=1,60 do
|
||||||
|
lg.arc("fill", x2, y2, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stats.ore < 7 then
|
||||||
|
if (tCalc+2)%8 < 4 then
|
||||||
|
lg.setColor(107, 66, 38)
|
||||||
|
for i=1,stats.ore do
|
||||||
|
lg.arc("fill", x2, y2, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lg.setColor(107, 66, 38)
|
||||||
|
for i=1,stats.ore do
|
||||||
|
lg.arc("fill", x2, y2, r*2/5 - edge/2, (i-1)*timeSegmentRadius - verticalOffset, i*timeSegmentRadius - timeDividerRadius - verticalOffset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lg.setColor(0, 0, 0)
|
||||||
|
lg.circle("fill", x2, y2, r*1/5 + edge/2)
|
||||||
|
|
||||||
|
--lg.setColor(255, 255, 255)
|
||||||
|
if stats.time < 0 then
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
elseif stats.time < 6 then
|
||||||
|
if tCalc%4 < 2 then
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
else
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
end
|
||||||
|
elseif stats.time < 31 then
|
||||||
|
if tCalc%8 < 4 then
|
||||||
|
lg.setColor(255, 102, 0)
|
||||||
|
else
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if tCalc%16 < 8 then
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
else
|
||||||
|
lg.setColor(255, 210, 110)
|
||||||
|
--lg.setColor(255, 102, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--stats.time = math.floor(stats.time)
|
||||||
|
local font = lg.getFont();
|
||||||
|
lg.print(stats.time, x - font:getWidth(stats.time)/2, y - font:getHeight()/2)
|
||||||
|
end
|
327
src/lib/inspect.lua
Normal file
327
src/lib/inspect.lua
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
local inspect ={
|
||||||
|
_VERSION = 'inspect.lua 3.0.0',
|
||||||
|
_URL = 'http://github.com/kikito/inspect.lua',
|
||||||
|
_DESCRIPTION = 'human-readable representations of tables',
|
||||||
|
_LICENSE = [[
|
||||||
|
MIT LICENSE
|
||||||
|
|
||||||
|
Copyright (c) 2013 Enrique García Cota
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
|
||||||
|
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
|
||||||
|
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
|
||||||
|
|
||||||
|
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||||
|
-- Otherwise, it returns a regular quoted string
|
||||||
|
local function smartQuote(str)
|
||||||
|
if str:match('"') and not str:match("'") then
|
||||||
|
return "'" .. str .. "'"
|
||||||
|
end
|
||||||
|
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||||
|
end
|
||||||
|
|
||||||
|
local controlCharsTranslation = {
|
||||||
|
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||||
|
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function escape(str)
|
||||||
|
local result = str:gsub("\\", "\\\\"):gsub("(%c)", controlCharsTranslation)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isIdentifier(str)
|
||||||
|
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isSequenceKey(k, length)
|
||||||
|
return type(k) == 'number'
|
||||||
|
and 1 <= k
|
||||||
|
and k <= length
|
||||||
|
and math.floor(k) == k
|
||||||
|
end
|
||||||
|
|
||||||
|
local defaultTypeOrders = {
|
||||||
|
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||||
|
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
local function sortKeys(a, b)
|
||||||
|
local ta, tb = type(a), type(b)
|
||||||
|
|
||||||
|
-- strings and numbers are sorted numerically/alphabetically
|
||||||
|
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||||
|
|
||||||
|
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||||
|
-- Two default types are compared according to the defaultTypeOrders table
|
||||||
|
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||||
|
elseif dta then return true -- default types before custom ones
|
||||||
|
elseif dtb then return false -- custom types after default ones
|
||||||
|
end
|
||||||
|
|
||||||
|
-- custom types are sorted out alphabetically
|
||||||
|
return ta < tb
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getNonSequentialKeys(t)
|
||||||
|
local keys, length = {}, #t
|
||||||
|
for k,_ in pairs(t) do
|
||||||
|
if not isSequenceKey(k, length) then table.insert(keys, k) end
|
||||||
|
end
|
||||||
|
table.sort(keys, sortKeys)
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getToStringResultSafely(t, mt)
|
||||||
|
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||||
|
local str, ok
|
||||||
|
if type(__tostring) == 'function' then
|
||||||
|
ok, str = pcall(__tostring, t)
|
||||||
|
str = ok and str or 'error: ' .. tostring(str)
|
||||||
|
end
|
||||||
|
if type(str) == 'string' and #str > 0 then return str end
|
||||||
|
end
|
||||||
|
|
||||||
|
local maxIdsMetaTable = {
|
||||||
|
__index = function(self, typeName)
|
||||||
|
rawset(self, typeName, 0)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local idsMetaTable = {
|
||||||
|
__index = function (self, typeName)
|
||||||
|
local col = setmetatable({}, {__mode = "kv"})
|
||||||
|
rawset(self, typeName, col)
|
||||||
|
return col
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local function countTableAppearances(t, tableAppearances)
|
||||||
|
tableAppearances = tableAppearances or setmetatable({}, {__mode = "k"})
|
||||||
|
|
||||||
|
if type(t) == 'table' then
|
||||||
|
if not tableAppearances[t] then
|
||||||
|
tableAppearances[t] = 1
|
||||||
|
for k,v in pairs(t) do
|
||||||
|
countTableAppearances(k, tableAppearances)
|
||||||
|
countTableAppearances(v, tableAppearances)
|
||||||
|
end
|
||||||
|
countTableAppearances(getmetatable(t), tableAppearances)
|
||||||
|
else
|
||||||
|
tableAppearances[t] = tableAppearances[t] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tableAppearances
|
||||||
|
end
|
||||||
|
|
||||||
|
local copySequence = function(s)
|
||||||
|
local copy, len = {}, #s
|
||||||
|
for i=1, len do copy[i] = s[i] end
|
||||||
|
return copy, len
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makePath(path, ...)
|
||||||
|
local keys = {...}
|
||||||
|
local newPath, len = copySequence(path)
|
||||||
|
for i=1, #keys do
|
||||||
|
newPath[len + i] = keys[i]
|
||||||
|
end
|
||||||
|
return newPath
|
||||||
|
end
|
||||||
|
|
||||||
|
local function processRecursive(process, item, path)
|
||||||
|
if item == nil then return nil end
|
||||||
|
|
||||||
|
local processed = process(item, path)
|
||||||
|
if type(processed) == 'table' then
|
||||||
|
local processedCopy = {}
|
||||||
|
local processedKey
|
||||||
|
|
||||||
|
for k,v in pairs(processed) do
|
||||||
|
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY))
|
||||||
|
if processedKey ~= nil then
|
||||||
|
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE))
|
||||||
|
setmetatable(processedCopy, mt)
|
||||||
|
processed = processedCopy
|
||||||
|
end
|
||||||
|
return processed
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Inspector = {}
|
||||||
|
local Inspector_mt = {__index = Inspector}
|
||||||
|
|
||||||
|
function Inspector:puts(...)
|
||||||
|
local args = {...}
|
||||||
|
local buffer = self.buffer
|
||||||
|
local len = #buffer
|
||||||
|
for i=1, #args do
|
||||||
|
len = len + 1
|
||||||
|
buffer[len] = tostring(args[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:down(f)
|
||||||
|
self.level = self.level + 1
|
||||||
|
f()
|
||||||
|
self.level = self.level - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:tabify()
|
||||||
|
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:alreadyVisited(v)
|
||||||
|
return self.ids[type(v)][v] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:getId(v)
|
||||||
|
local tv = type(v)
|
||||||
|
local id = self.ids[tv][v]
|
||||||
|
if not id then
|
||||||
|
id = self.maxIds[tv] + 1
|
||||||
|
self.maxIds[tv] = id
|
||||||
|
self.ids[tv][v] = id
|
||||||
|
end
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putKey(k)
|
||||||
|
if isIdentifier(k) then return self:puts(k) end
|
||||||
|
self:puts("[")
|
||||||
|
self:putValue(k)
|
||||||
|
self:puts("]")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putTable(t)
|
||||||
|
if t == inspect.KEY or t == inspect.METATABLE then
|
||||||
|
self:puts(tostring(t))
|
||||||
|
elseif self:alreadyVisited(t) then
|
||||||
|
self:puts('<table ', self:getId(t), '>')
|
||||||
|
elseif self.level >= self.depth then
|
||||||
|
self:puts('{...}')
|
||||||
|
else
|
||||||
|
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
||||||
|
|
||||||
|
local nonSequentialKeys = getNonSequentialKeys(t)
|
||||||
|
local length = #t
|
||||||
|
local mt = getmetatable(t)
|
||||||
|
local toStringResult = getToStringResultSafely(t, mt)
|
||||||
|
|
||||||
|
self:puts('{')
|
||||||
|
self:down(function()
|
||||||
|
if toStringResult then
|
||||||
|
self:puts(' -- ', escape(toStringResult))
|
||||||
|
if length >= 1 then self:tabify() end
|
||||||
|
end
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for i=1, length do
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:puts(' ')
|
||||||
|
self:putValue(t[i])
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,k in ipairs(nonSequentialKeys) do
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:tabify()
|
||||||
|
self:putKey(k)
|
||||||
|
self:puts(' = ')
|
||||||
|
self:putValue(t[k])
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if mt then
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:tabify()
|
||||||
|
self:puts('<metatable> = ')
|
||||||
|
self:putValue(mt)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if #nonSequentialKeys > 0 or mt then -- result is multi-lined. Justify closing }
|
||||||
|
self:tabify()
|
||||||
|
elseif length > 0 then -- array tables have one extra space before closing }
|
||||||
|
self:puts(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
self:puts('}')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putValue(v)
|
||||||
|
local tv = type(v)
|
||||||
|
|
||||||
|
if tv == 'string' then
|
||||||
|
self:puts(smartQuote(escape(v)))
|
||||||
|
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
|
||||||
|
self:puts(tostring(v))
|
||||||
|
elseif tv == 'table' then
|
||||||
|
self:putTable(v)
|
||||||
|
else
|
||||||
|
self:puts('<',tv,' ',self:getId(v),'>')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
function inspect.inspect(root, options)
|
||||||
|
options = options or {}
|
||||||
|
|
||||||
|
local depth = options.depth or math.huge
|
||||||
|
local newline = options.newline or '\n'
|
||||||
|
local indent = options.indent or ' '
|
||||||
|
local process = options.process
|
||||||
|
|
||||||
|
if process then
|
||||||
|
root = processRecursive(process, root, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
local inspector = setmetatable({
|
||||||
|
depth = depth,
|
||||||
|
buffer = {},
|
||||||
|
level = 0,
|
||||||
|
ids = setmetatable({}, idsMetaTable),
|
||||||
|
maxIds = setmetatable({}, maxIdsMetaTable),
|
||||||
|
newline = newline,
|
||||||
|
indent = indent,
|
||||||
|
tableAppearances = countTableAppearances(root)
|
||||||
|
}, Inspector_mt)
|
||||||
|
|
||||||
|
inspector:putValue(root)
|
||||||
|
|
||||||
|
return table.concat(inspector.buffer)
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||||
|
|
||||||
|
return inspect
|
182
src/lib/middleclass.lua
Normal file
182
src/lib/middleclass.lua
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
local middleclass = {
|
||||||
|
_VERSION = 'middleclass v3.0.1',
|
||||||
|
_DESCRIPTION = 'Object Orientation for Lua',
|
||||||
|
_URL = 'https://github.com/kikito/middleclass',
|
||||||
|
_LICENSE = [[
|
||||||
|
MIT LICENSE
|
||||||
|
|
||||||
|
Copyright (c) 2011 Enrique García Cota
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
|
||||||
|
local function _setClassDictionariesMetatables(aClass)
|
||||||
|
local dict = aClass.__instanceDict
|
||||||
|
dict.__index = dict
|
||||||
|
|
||||||
|
local super = aClass.super
|
||||||
|
if super then
|
||||||
|
local superStatic = super.static
|
||||||
|
setmetatable(dict, super.__instanceDict)
|
||||||
|
setmetatable(aClass.static, { __index = function(_,k) return dict[k] or superStatic[k] end })
|
||||||
|
else
|
||||||
|
setmetatable(aClass.static, { __index = function(_,k) return dict[k] end })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _setClassMetatable(aClass)
|
||||||
|
setmetatable(aClass, {
|
||||||
|
__tostring = function() return "class " .. aClass.name end,
|
||||||
|
__index = aClass.static,
|
||||||
|
__newindex = aClass.__instanceDict,
|
||||||
|
__call = function(self, ...) return self:new(...) end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _createClass(name, super)
|
||||||
|
local aClass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict={} }
|
||||||
|
aClass.subclasses = setmetatable({}, {__mode = "k"})
|
||||||
|
|
||||||
|
_setClassDictionariesMetatables(aClass)
|
||||||
|
_setClassMetatable(aClass)
|
||||||
|
|
||||||
|
return aClass
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _createLookupMetamethod(aClass, name)
|
||||||
|
return function(...)
|
||||||
|
local method = aClass.super[name]
|
||||||
|
assert( type(method)=='function', tostring(aClass) .. " doesn't implement metamethod '" .. name .. "'" )
|
||||||
|
return method(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _setClassMetamethods(aClass)
|
||||||
|
for _,m in ipairs(aClass.__metamethods) do
|
||||||
|
aClass[m]= _createLookupMetamethod(aClass, m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _setDefaultInitializeMethod(aClass, super)
|
||||||
|
aClass.initialize = function(instance, ...)
|
||||||
|
return super.initialize(instance, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function _includeMixin(aClass, mixin)
|
||||||
|
assert(type(mixin)=='table', "mixin must be a table")
|
||||||
|
for name,method in pairs(mixin) do
|
||||||
|
if name ~= "included" and name ~= "static" then aClass[name] = method end
|
||||||
|
end
|
||||||
|
if mixin.static then
|
||||||
|
for name,method in pairs(mixin.static) do
|
||||||
|
aClass.static[name] = method
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if type(mixin.included)=="function" then mixin:included(aClass) end
|
||||||
|
aClass.__mixins[mixin] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local Object = _createClass("Object", nil)
|
||||||
|
|
||||||
|
Object.static.__metamethods = { '__add', '__call', '__concat', '__div', '__ipairs', '__le',
|
||||||
|
'__len', '__lt', '__mod', '__mul', '__pairs', '__pow', '__sub',
|
||||||
|
'__tostring', '__unm'}
|
||||||
|
|
||||||
|
function Object.static:allocate()
|
||||||
|
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
||||||
|
return setmetatable({ class = self }, self.__instanceDict)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object.static:new(...)
|
||||||
|
local instance = self:allocate()
|
||||||
|
instance:initialize(...)
|
||||||
|
return instance
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object.static:subclass(name)
|
||||||
|
assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
|
||||||
|
assert(type(name) == "string", "You must provide a name(string) for your class")
|
||||||
|
|
||||||
|
local subclass = _createClass(name, self)
|
||||||
|
_setClassMetamethods(subclass)
|
||||||
|
_setDefaultInitializeMethod(subclass, self)
|
||||||
|
self.subclasses[subclass] = true
|
||||||
|
self:subclassed(subclass)
|
||||||
|
|
||||||
|
return subclass
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object.static:subclassed(other) end
|
||||||
|
|
||||||
|
function Object.static:isSubclassOf(other)
|
||||||
|
return type(other) == 'table' and
|
||||||
|
type(self) == 'table' and
|
||||||
|
type(self.super) == 'table' and
|
||||||
|
( self.super == other or
|
||||||
|
type(self.super.isSubclassOf) == 'function' and
|
||||||
|
self.super:isSubclassOf(other)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object.static:include( ... )
|
||||||
|
assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
|
||||||
|
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object.static:includes(mixin)
|
||||||
|
return type(mixin) == 'table' and
|
||||||
|
type(self) == 'table' and
|
||||||
|
type(self.__mixins) == 'table' and
|
||||||
|
( self.__mixins[mixin] or
|
||||||
|
type(self.super) == 'table' and
|
||||||
|
type(self.super.includes) == 'function' and
|
||||||
|
self.super:includes(mixin)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Object:initialize() end
|
||||||
|
|
||||||
|
function Object:__tostring() return "instance of " .. tostring(self.class) end
|
||||||
|
|
||||||
|
function Object:isInstanceOf(aClass)
|
||||||
|
return type(self) == 'table' and
|
||||||
|
type(self.class) == 'table' and
|
||||||
|
type(aClass) == 'table' and
|
||||||
|
( aClass == self.class or
|
||||||
|
type(aClass.isSubclassOf) == 'function' and
|
||||||
|
self.class:isSubclassOf(aClass)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function middleclass.class(name, super, ...)
|
||||||
|
super = super or Object
|
||||||
|
return super:subclass(name, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
middleclass.Object = Object
|
||||||
|
|
||||||
|
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
|
||||||
|
|
||||||
|
return middleclass
|
252
src/main.lua
252
src/main.lua
@@ -1,106 +1,216 @@
|
|||||||
local bsg = require "ships.bsg"
|
--tmp
|
||||||
local viper = require "ships.viper"
|
local inspect = require "lib.inspect"
|
||||||
|
|
||||||
local lg = love.graphics
|
local lg = love.graphics
|
||||||
|
|
||||||
local images = {}
|
|
||||||
local ships = {}
|
|
||||||
|
|
||||||
local hx, hy = lg.getWidth() / 2, lg.getHeight() / 2
|
local hx, hy = lg.getWidth() / 2, lg.getHeight() / 2
|
||||||
|
local scale = 2
|
||||||
|
|
||||||
local scale = 8
|
local images = {}
|
||||||
|
local fleet = {}
|
||||||
|
|
||||||
|
local hud = require "hud"
|
||||||
|
|
||||||
|
local bsg = require "ships.bsg"
|
||||||
|
local viper = require "ships.viper"
|
||||||
|
|
||||||
|
--tmp
|
||||||
local selected
|
local selected
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
lg.setDefaultFilter("linear", "nearest", 1)
|
lg.setDefaultFilter("linear", "nearest", 1)
|
||||||
images.bsg = lg.newImage('img/bsg.png')
|
images.bsg = lg.newImage('img/bsg.png')
|
||||||
images.viper = lg.newImage('img/viper.png')
|
images.viper = lg.newImage('img/viper.png')
|
||||||
|
--tmp
|
||||||
lg.setPointSize(10)
|
lg.setPointSize(10)
|
||||||
lg.setPointStyle("rough")
|
--lg.setPointStyle("rough") --WAS REMOVED IN 0.10, FIND ITS REPLACEMENT
|
||||||
|
|
||||||
ships[1] = bsg()
|
fleet[1] = bsg()
|
||||||
for i=1,8 do
|
for i=1,8 do
|
||||||
local v = viper()
|
local v = viper()
|
||||||
table.insert(ships, v)
|
table.insert(fleet, v)
|
||||||
ships[1]:dock(v, i)
|
fleet[1]:dock(v, i)
|
||||||
|
v.engineStatus = "off"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local timer = 0
|
||||||
|
local stats = {
|
||||||
|
time = 60,
|
||||||
|
ammo = 40,
|
||||||
|
fuel = 55,
|
||||||
|
supplies = 10,
|
||||||
|
water = 30,
|
||||||
|
food = 40,
|
||||||
|
metal = 60,
|
||||||
|
ore = 24
|
||||||
|
}
|
||||||
|
local function getStats()
|
||||||
|
local ammo = 0
|
||||||
|
local fuel = 0
|
||||||
|
local supplies = 0
|
||||||
|
local water = 0
|
||||||
|
local food = 0
|
||||||
|
local metal = 0
|
||||||
|
local ore = 0
|
||||||
|
|
||||||
|
local maxAmmo = 0
|
||||||
|
local maxFuel = 0
|
||||||
|
local maxSupplies = 0
|
||||||
|
local maxWater = 0
|
||||||
|
local maxFood = 0
|
||||||
|
local maxMetal = 0
|
||||||
|
local maxOre = 0
|
||||||
|
|
||||||
|
for i=1,#fleet do
|
||||||
|
ammo = ammo + fleet[i].Resources.ammo
|
||||||
|
fuel = fuel + fleet[i].Resources.fuel
|
||||||
|
supplies = supplies + fleet[i].Resources.supplies
|
||||||
|
water = water + fleet[i].Resources.water
|
||||||
|
food = food + fleet[i].Resources.food
|
||||||
|
metal = metal + fleet[i].Resources.metal
|
||||||
|
ore = ore + fleet[i].Resources.ore
|
||||||
|
|
||||||
|
maxAmmo = maxAmmo + fleet[i].Resources.maxAmmo
|
||||||
|
maxFuel = maxFuel + fleet[i].Resources.maxFuel
|
||||||
|
maxSupplies = maxSupplies + fleet[i].Resources.maxSupplies
|
||||||
|
maxWater = maxWater + fleet[i].Resources.maxWater
|
||||||
|
maxFood = maxFood + fleet[i].Resources.maxFood
|
||||||
|
maxMetal = maxMetal + fleet[i].Resources.maxMetal
|
||||||
|
maxOre = maxOre + fleet[i].Resources.maxOre
|
||||||
|
end
|
||||||
|
|
||||||
|
ammo = ammo * 60 / maxAmmo
|
||||||
|
fuel = fuel * 60 / maxFuel
|
||||||
|
supplies = supplies * 60 / maxSupplies
|
||||||
|
water = water * 60 / maxWater
|
||||||
|
food = food * 60 / maxFood
|
||||||
|
metal = metal * 60 / maxMetal
|
||||||
|
ore = ore * 60 / maxOre
|
||||||
|
|
||||||
|
if ammo > 0 and ammo < 1 then
|
||||||
|
ammo = 1
|
||||||
|
end
|
||||||
|
if fuel > 0 and fuel < 1 then
|
||||||
|
fuel = 1
|
||||||
|
end
|
||||||
|
if supplies > 0 and supplies < 1 then
|
||||||
|
supplies = 1
|
||||||
|
end
|
||||||
|
if water > 0 and water < 1 then
|
||||||
|
water = 1
|
||||||
|
end
|
||||||
|
if food > 0 and food < 1 then
|
||||||
|
food = 1
|
||||||
|
end
|
||||||
|
if metal > 0 and metal < 1 then
|
||||||
|
metal = 1
|
||||||
|
end
|
||||||
|
if ore > 0 and ore < 1 then
|
||||||
|
ore = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
ammo = math.floor(ammo),
|
||||||
|
fuel = math.floor(fuel),
|
||||||
|
supplies = math.floor(supplies),
|
||||||
|
water = math.floor(water),
|
||||||
|
food = math.floor(food),
|
||||||
|
metal = math.floor(metal),
|
||||||
|
ore = math.floor(ore)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
local timing = -33
|
||||||
|
local paused = false
|
||||||
|
function love.update(dt)
|
||||||
|
if paused then return end
|
||||||
|
dt = dt --* 10 --temporary accelerated
|
||||||
|
timer = timer + dt
|
||||||
|
if timer >= 1 then
|
||||||
|
timer = timer - 1
|
||||||
|
--stat = current * 60 / max
|
||||||
|
stats = getStats()
|
||||||
|
--[[
|
||||||
|
stats = {
|
||||||
|
time = math.random(0, 60),
|
||||||
|
ammo = math.random(0, 60),
|
||||||
|
fuel = math.random(0, 60),
|
||||||
|
supplies = math.random(0, 60),
|
||||||
|
water = math.random(0, 60),
|
||||||
|
food = math.random(0, 60),
|
||||||
|
metal = math.random(0, 60),
|
||||||
|
ore = math.random(0, 60)
|
||||||
|
}
|
||||||
|
--]]
|
||||||
|
--[[
|
||||||
|
stats = {
|
||||||
|
time = 0,
|
||||||
|
ammo = 0,
|
||||||
|
fuel = 0,
|
||||||
|
supplies = 0,
|
||||||
|
water = 0,
|
||||||
|
food = 0,
|
||||||
|
metal = 0,
|
||||||
|
ore = 0
|
||||||
|
}
|
||||||
|
--]]
|
||||||
|
end
|
||||||
|
|
||||||
|
timing = timing + dt
|
||||||
|
--[[
|
||||||
|
if timing >= 121 then
|
||||||
|
timing = timing -181+60-33
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
stats.time = timing --TMP ?
|
||||||
|
|
||||||
|
for i=1,#fleet do
|
||||||
|
fleet[i]:update(dt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.draw()
|
function love.draw()
|
||||||
lg.translate(hx, hy)
|
lg.translate(hx, hy)
|
||||||
|
|
||||||
for i=1,#ships do
|
lg.setColor(255, 255, 255)
|
||||||
lg.draw(images[ships[i].img], ships[i].x * scale, ships[i].y * scale, ships[i].rotation, scale, scale, ships[i].ox, ships[i].oy)
|
for i=1,#fleet do
|
||||||
|
lg.draw(images[fleet[i].img], fleet[i].x * scale, fleet[i].y * scale, fleet[i].rotation, scale, scale, fleet[i].ox, fleet[i].oy)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--tmp
|
||||||
if selected then
|
if selected then
|
||||||
lg.setColor(220, 180, 0)
|
lg.setColor(220, 180, 0)
|
||||||
lg.point(selected.x * scale, selected.y * scale)
|
lg.point(selected.x * scale, selected.y * scale)
|
||||||
lg.setColor(255, 255, 255)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
hud(stats)
|
||||||
|
|
||||||
|
---[[temporary, raw Resource stats of Galactica
|
||||||
|
local r = fleet[1].Resources
|
||||||
|
lg.setColor(255, 255, 255)
|
||||||
|
lg.print("Ammo: " .. math.floor(r.ammo/r.maxAmmo*100) .. "% " .. r.ammo, -300, -200)
|
||||||
|
lg.print("Fuel: " .. math.floor(r.fuel/r.maxFuel*100) .. "% " .. r.fuel, -300, -190)
|
||||||
|
lg.print("Supplies: " .. math.floor(r.supplies/r.maxSupplies*100) .. "% " .. r.supplies, -300, -180)
|
||||||
|
lg.print("Food: " .. math.floor(r.food/r.maxFood*100) .. "% " .. r.food, -300, -170)
|
||||||
|
lg.print("Water: " .. math.floor(r.water/r.maxWater*100) .. "% " .. r.water, -300, -160)
|
||||||
|
lg.print("Metal: " .. math.floor(r.metal/r.maxMetal*100) .. "% " .. r.metal, -300, -150)
|
||||||
|
lg.print("Ore: " .. math.floor(r.ore/r.maxOre*100) .. "% " .. r.ore, -300, -140)
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--[[tmp, printing total time as hours/minutes/seconds]]
|
||||||
|
lg.print("Time elapsed: " .. math.floor(timing/60/60) .. ":" .. math.floor(timing/60)%60 .. ":" .. math.floor(timing)%60, -300, -120)
|
||||||
|
local result = 0
|
||||||
|
for i=2,#fleet do
|
||||||
|
result = result + fleet[i].Resources.fuel
|
||||||
|
end
|
||||||
|
lg.print("Viper fuel: " .. result, -300, -110)
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.keypressed(key, unicode)
|
function love.keypressed(key, unicode)
|
||||||
if key == "escape" then
|
if key == "escape" then
|
||||||
love.event.quit()
|
love.event.quit()
|
||||||
end
|
elseif key == " " then
|
||||||
end
|
paused = not paused
|
||||||
|
|
||||||
local function pointInRadius(x, y, cx, cy, r)
|
|
||||||
cx = cx * scale + hx
|
|
||||||
cy = cy * scale + hy
|
|
||||||
local dx = x - cx
|
|
||||||
local dy = y - cy
|
|
||||||
return r * scale >= math.sqrt(dx * dx + dy * dy)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pointInAABB(x, y, cx, cy, s, r)
|
|
||||||
-- THIS IS HORRIBLY WRONG, FIX IT LATER
|
|
||||||
--[[
|
|
||||||
var x=((objects[i].x-objects[renderId].x)*Math.cos(rot)-(objects[i].y-objects[renderId].y)*Math.sin(rot))*scaleFactor;
|
|
||||||
var y=((objects[i].x-objects[renderId].x)*Math.sin(rot)+(objects[i].y-objects[renderId].y)*Math.cos(rot))*scaleFactor;
|
|
||||||
]]
|
|
||||||
local nx = (x - cx) * math.cos(r) - (y - cy) * math.sin(r)
|
|
||||||
local ny = (x - cx) * math.sin(r) + (y - cy) * math.cos(r)
|
|
||||||
x = nx
|
|
||||||
y = ny
|
|
||||||
cx = cx * scale + hx
|
|
||||||
cy = cy * scale + hy
|
|
||||||
return x >= cx - s.w * scale / 2 and x <= cx + s.w * scale / 2 and y >= cy - s.h * scale / 2 and y <= cy + s.h * scale / 2
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.mousepressed(x, y, button)
|
|
||||||
if button == "l" then
|
|
||||||
if selected then
|
|
||||||
-- find out where this actually is, now the ship selected is ordered to move to this point
|
|
||||||
selected.ship:moveTo(x * scale + hx, y * scale + hy)
|
|
||||||
else
|
|
||||||
for i=1,#ships do
|
|
||||||
if ships[i].selection.r then
|
|
||||||
if pointInRadius(x, y, ships[i].x, ships[i].y, ships[i].selection.r) then
|
|
||||||
-- selected
|
|
||||||
-- NOW CHECK IF HAS NODES AND IF WE ARE SELECTING A SHIP ON A NODE!
|
|
||||||
selected = {}
|
|
||||||
selected.ship = ships[i]
|
|
||||||
selected.x = ships[i].x
|
|
||||||
selected.y = ships[i].y
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if pointInAABB(x, y, ships[i].x, ships[i].y, ships[i].selection, ships[i].rotation) then
|
|
||||||
-- we are selecting it!
|
|
||||||
-- NOW CHECK IF HAS NODES AND IF WE ARE SELECTING A SHIP ON A NODE!
|
|
||||||
selected = {}
|
|
||||||
selected.ship = ships[i]
|
|
||||||
selected.x = ships[i].x
|
|
||||||
selected.y = ships[i].y
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif button == "wd" then
|
|
||||||
scale = scale * 1.1
|
|
||||||
elseif button == "wu" then
|
|
||||||
scale = scale * 0.9
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -1,11 +1,35 @@
|
|||||||
return function(x, y, rotation)
|
local class = require "lib.middleclass"
|
||||||
local self = {}
|
|
||||||
|
|
||||||
|
local Node = class('Node')
|
||||||
|
|
||||||
|
function Node:initialize(x, y, rotation)
|
||||||
self.x = x or 0
|
self.x = x or 0
|
||||||
self.y = y or 0
|
self.y = y or 0
|
||||||
self.rotation = rotation or 0
|
self.rotation = rotation or 0
|
||||||
|
|
||||||
self.docked = false
|
self.dockedShip = false
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--TODO docking needs to check distance between ships and only allow
|
||||||
|
-- docking when close enough
|
||||||
|
function Node:dock(Ship)
|
||||||
|
if self.dockedShip or Ship.dockedTo then
|
||||||
|
error("Attempted to dock to Node with something already docked to it!")
|
||||||
|
else
|
||||||
|
self.dockedShip = Ship
|
||||||
|
Ship.dockedTo = self
|
||||||
|
|
||||||
|
Ship:setPosition(self.x, self.y, self.rotation)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Node:undock()
|
||||||
|
if not self.dockedShip then
|
||||||
|
error("Attempted to undock a ship from a Node with no docked ship.")
|
||||||
|
else
|
||||||
|
self.dockedShip.dockedTo = false
|
||||||
|
self.dockedShip = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Node
|
||||||
|
74
src/ships/Resources.lua
Normal file
74
src/ships/Resources.lua
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
local resourceConsumptionMultiplier = 500 --does not apply to ammo or crew
|
||||||
|
|
||||||
|
local class = require "lib.middleclass"
|
||||||
|
|
||||||
|
local Resources = class('Resources')
|
||||||
|
|
||||||
|
function Resources:initialize()
|
||||||
|
self.ammo = 0
|
||||||
|
self.fuel = 0
|
||||||
|
self.supplies = 0
|
||||||
|
self.water = 0
|
||||||
|
self.food = 0
|
||||||
|
self.metal = 0
|
||||||
|
self.ore = 0
|
||||||
|
self.crew = 0
|
||||||
|
|
||||||
|
self.missiles = 0
|
||||||
|
self.nukes = 0
|
||||||
|
|
||||||
|
self.maxAmmo = 0
|
||||||
|
self.maxFuel = 0
|
||||||
|
self.maxSupplies = 0
|
||||||
|
self.maxWater = 0
|
||||||
|
self.maxFood = 0
|
||||||
|
self.maxMetal = 0
|
||||||
|
self.maxOre = 0
|
||||||
|
self.maxCrew = 0
|
||||||
|
|
||||||
|
self.ammoUse = 0
|
||||||
|
self.fuelUseOff = 0
|
||||||
|
self.fuelUseIdle = 0
|
||||||
|
self.fuelUseMoving = 0
|
||||||
|
self.fuelUseJump = 0
|
||||||
|
self.suppliesUse = 0
|
||||||
|
self.waterUse = 0
|
||||||
|
self.foodUse = 0
|
||||||
|
self.metalUse = 0
|
||||||
|
self.oreUse = 0
|
||||||
|
self.crewUse = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function Resources:update(dt, engineStatus)
|
||||||
|
self.ammo = self.ammo - self.ammoUse * dt
|
||||||
|
if engineStatus == "off" then
|
||||||
|
self.fuel = self.fuel - self.fuelUseOff * dt * resourceConsumptionMultiplier
|
||||||
|
elseif engineStatus == "idle" then
|
||||||
|
self.fuel = self.fuel - self.fuelUseIdle * dt * resourceConsumptionMultiplier
|
||||||
|
elseif engineStatus == "moving" then
|
||||||
|
self.fuel = self.fuel - self.fuelUseMoving * dt * resourceConsumptionMultiplier
|
||||||
|
else
|
||||||
|
error("Invalid engineStatus!")
|
||||||
|
end
|
||||||
|
self.supplies = self.supplies - self.suppliesUse * dt * resourceConsumptionMultiplier
|
||||||
|
self.water = self.water - self.waterUse * dt * resourceConsumptionMultiplier
|
||||||
|
self.food = self.food - self.foodUse * dt * resourceConsumptionMultiplier
|
||||||
|
self.metal = self.metal - self.metalUse * dt * resourceConsumptionMultiplier
|
||||||
|
self.ore = self.ore - self.oreUse * dt * resourceConsumptionMultiplier
|
||||||
|
self.crew = self.crew - self.crewUse * dt
|
||||||
|
|
||||||
|
--TODO check if running out of anything, and do whatever is appropriate
|
||||||
|
end
|
||||||
|
|
||||||
|
function Resources:maxEverything()
|
||||||
|
self.ammo = self.maxAmmo
|
||||||
|
self.fuel = self.maxFuel
|
||||||
|
self.supplies = self.maxSupplies
|
||||||
|
self.water = self.maxWater
|
||||||
|
self.food = self.maxFood
|
||||||
|
self.metal = self.maxMetal
|
||||||
|
self.ore = self.maxOre
|
||||||
|
self.crew = self.maxCrew
|
||||||
|
end
|
||||||
|
|
||||||
|
return Resources
|
86
src/ships/Ship.lua
Normal file
86
src/ships/Ship.lua
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
local class = require "lib.middleclass"
|
||||||
|
|
||||||
|
local Resources = require "ships.Resources"
|
||||||
|
|
||||||
|
local Ship = class('Ship')
|
||||||
|
|
||||||
|
function Ship:initialize(x, y, rotation)
|
||||||
|
self.img = ""
|
||||||
|
--offsets
|
||||||
|
self.ox = 0
|
||||||
|
self.oy = 0
|
||||||
|
|
||||||
|
self.x = x or 0
|
||||||
|
self.y = y or 0
|
||||||
|
self.destination = {
|
||||||
|
x = x or 0,
|
||||||
|
y = y or 0
|
||||||
|
}
|
||||||
|
self.rotation = rotation or 0
|
||||||
|
|
||||||
|
self.selection = {}
|
||||||
|
|
||||||
|
self.node = {}
|
||||||
|
|
||||||
|
self.dockedTo = false
|
||||||
|
|
||||||
|
self.engineStatus = "idle"
|
||||||
|
self.Resources = Resources()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:dock(targetShip, nodeIndex)
|
||||||
|
if self.node[nodeIndex] then
|
||||||
|
self.node[nodeIndex]:dock(targetShip)
|
||||||
|
else
|
||||||
|
error("Ship attempted to dock to non-existent Node.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:undock(nodeIndex)
|
||||||
|
if self.node[nodeIndex] then
|
||||||
|
self.node[nodeIndex]:undock()
|
||||||
|
else
|
||||||
|
--find which node "nodeIndex" is docked to
|
||||||
|
for i=1,#self.node do
|
||||||
|
if self.node[i].dockedShip == nodeIndex then
|
||||||
|
self.node[i]:undock()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("Ship attempted to undock from non-existent Node.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:dockTo(targetShip, nodeIndex)
|
||||||
|
if targetShip.node[nodeIndex] then
|
||||||
|
targetShip.node[nodeIndex]:dock(self)
|
||||||
|
else
|
||||||
|
error("Ship attempted to dock to non-existent Node.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:undockFromParent()
|
||||||
|
self.dockedTo:undock(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:setPosition(x, y, rotation)
|
||||||
|
self.x = x or self.x
|
||||||
|
self.y = y or self.y
|
||||||
|
self.rotation = rotation or self.rotation
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:moveTo(x, y)
|
||||||
|
if self.dockedTo then
|
||||||
|
self:undockFromParent()
|
||||||
|
end
|
||||||
|
self.destination.x = x
|
||||||
|
self.destination.y = y
|
||||||
|
end
|
||||||
|
|
||||||
|
function Ship:update(dt)
|
||||||
|
self.Resources:update(dt, self.engineStatus)
|
||||||
|
--check our speed, see how far along the "line" we can go, go there
|
||||||
|
-- if reached destination ... WELL SHIT DEST NEEDS TO BE ABLE TO KNOW IF IS SHIP OR WHATEVER
|
||||||
|
end
|
||||||
|
|
||||||
|
return Ship
|
@@ -1,18 +1,22 @@
|
|||||||
local Node = require "ships.Node"
|
math.randomseed(os.time())
|
||||||
|
math.random() math.random()
|
||||||
|
|
||||||
local ninety = 90 * math.pi / 180
|
local ninety = 90 * math.pi / 180
|
||||||
|
|
||||||
return function(x, y, rotation)
|
local class = require "lib.middleclass"
|
||||||
local self = {}
|
|
||||||
|
|
||||||
|
local Ship = require "ships.Ship"
|
||||||
|
local Node = require "ships.Node"
|
||||||
|
|
||||||
|
local BSG = class('BSG', Ship)
|
||||||
|
|
||||||
|
function BSG:initialize(x, y, rotation)
|
||||||
|
Ship.initialize(self, x, y, rotation)
|
||||||
self.img = "bsg"
|
self.img = "bsg"
|
||||||
|
--offsets
|
||||||
self.ox = 31.5
|
self.ox = 31.5
|
||||||
self.oy = 67
|
self.oy = 67
|
||||||
|
|
||||||
self.x = x or 0
|
|
||||||
self.y = y or 0
|
|
||||||
self.rotation = rotation or 0
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
self.selection = {
|
self.selection = {
|
||||||
w = 54,
|
w = 54,
|
||||||
@@ -34,31 +38,50 @@ return function(x, y, rotation)
|
|||||||
Node(-23, 16.5, -ninety)
|
Node(-23, 16.5, -ninety)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dock = function(self, ship, node)
|
self.Resources.maxAmmo = 1000000
|
||||||
if self.node[node].docked or ship.isDocked then return false end
|
self.Resources.maxFuel = 1300000
|
||||||
|
self.Resources.maxSupplies = 40000
|
||||||
|
--what the fuck are jp's ?
|
||||||
|
-- http://www.traditionaloven.com/culinary-arts/cooking/shortening/convert-japanese-cup-measure-of-shortening-to-fluid-ounce-floz-shortening.html
|
||||||
|
-- From show "10 mil JPs water lost, almost 60%"
|
||||||
|
self.Resources.maxWater = 16000000
|
||||||
|
self.Resources.maxFood = 51000
|
||||||
|
self.Resources.maxMetal = 80000
|
||||||
|
--self.Resources.maxOre = 0
|
||||||
|
self.Resources.maxCrew = 5100
|
||||||
|
|
||||||
ship.x = self.node[node].x
|
self.Resources.ammo = math.random(100, 1300)
|
||||||
ship.y = self.node[node].y
|
self.Resources.fuel = math.random(496000, 512000)
|
||||||
ship.rotation = self.node[node].rotation
|
self.Resources.supplies = math.random(18000,21000)
|
||||||
|
self.Resources.water = math.random(14186500, 14989900)
|
||||||
|
self.Resources.food = math.random(34700, 39200)
|
||||||
|
self.Resources.metal = math.random(19200,21600)
|
||||||
|
--self.Resources.ore = 0
|
||||||
|
self.Resources.crew = math.random(2870, 2960)
|
||||||
|
|
||||||
self.node[node].docked = ship
|
self.Resources.missiles = math.random(5, 11)
|
||||||
ship.isDocked = true
|
--self.Resources.nukes = 0
|
||||||
ship.dockedTo = self
|
|
||||||
ship.dockedNode = node
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
self.undock = function(self, node)
|
--self.Resources.ammoUse = 0
|
||||||
if not self.node[node].docked then return false end
|
-- a year is 31,556,900 seconds
|
||||||
|
-- for 17 mil water to last ?
|
||||||
local ship = self.node[node].docked
|
-- How about 1 water per second?
|
||||||
ship.isDocked = false
|
-- 195 days
|
||||||
ship.dockedTo = false
|
self.Resources.fuelUseIdle = 0.04
|
||||||
ship.dockedNode = false
|
self.Resources.fuelUseMoving = 0.54
|
||||||
self.node[node].docked = false
|
self.Resources.fuelUseJump = 4000
|
||||||
|
self.Resources.suppliesUse = 0.0013
|
||||||
return ship
|
self.Resources.waterUse = 1
|
||||||
end
|
-- 45k civs = 82+85+119+304 (590) tons food
|
||||||
|
-- 2.5 mil JPs water
|
||||||
return self
|
-- these are per week numbers
|
||||||
|
-- 604800 seconds, 4.13 water per second
|
||||||
|
-- 1 ton = 2000 pounds
|
||||||
|
-- 1180000 pounds / sec = 1.95 food per second
|
||||||
|
self.Resources.foodUse = 0.099
|
||||||
|
--self.Resources.metalUse = 0.002 -- this # assumes normal repairs, which I'm ignoring for this
|
||||||
|
--self.Resources.oreUse = 0
|
||||||
|
--self.Resources.crewUse = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return BSG
|
||||||
|
@@ -1,20 +1,16 @@
|
|||||||
return function(x, y, rotation)
|
local class = require "lib.middleclass"
|
||||||
local self = {}
|
|
||||||
|
|
||||||
|
local Ship = require "ships.Ship"
|
||||||
|
|
||||||
|
local Viper = class('Viper', Ship)
|
||||||
|
|
||||||
|
function Viper:initialize(x, y, rotation)
|
||||||
|
Ship.initialize(self, x, y, rotation)
|
||||||
self.img = "viper"
|
self.img = "viper"
|
||||||
|
--offsets
|
||||||
self.ox = 4.5
|
self.ox = 4.5
|
||||||
self.oy = 7.5
|
self.oy = 7.5
|
||||||
|
|
||||||
self.x = x or 0
|
|
||||||
self.y = y or 0
|
|
||||||
self.rotation = rotation or 0
|
|
||||||
|
|
||||||
self.destination = {
|
|
||||||
x = x or 0,
|
|
||||||
y = y or 0
|
|
||||||
}
|
|
||||||
self.isMoving = false
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
self.selection = {
|
self.selection = {
|
||||||
w = 9,
|
w = 9,
|
||||||
@@ -25,24 +21,15 @@ return function(x, y, rotation)
|
|||||||
r = 5
|
r = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
--self.node = false
|
self.Resources.maxAmmo = 1800 --10 shots per second? 5s per barrel
|
||||||
self.isDocked = false
|
self.Resources.maxFuel = 30000 --86400s = 1day, x = 1/2 day's thrust
|
||||||
self.dockedTo = false
|
self.Resources.maxCrew = 1
|
||||||
self.dockedNode = false
|
|
||||||
|
|
||||||
self.moveTo = function(self, x, y)
|
self.Resources.ammo = math.random(0, 20)
|
||||||
if self.isDocked then
|
self.Resources.fuel = math.random(120, 1500)
|
||||||
self.dockedTo:undock(self.dockedNode)
|
|
||||||
end
|
|
||||||
self.destination.x = x
|
|
||||||
self.destination.y = y
|
|
||||||
self.isMoving = true
|
|
||||||
end
|
|
||||||
|
|
||||||
self.update = function(self, dt)
|
self.Resources.fuelUseIdle = 0.09
|
||||||
-- check if moving, check our speed, see how far along the "line" we can go, go there
|
self.Resources.fuelUseMoving = 0.76
|
||||||
-- if reached destination ... WELL SHIT DEST NEEDS TO BE ABLE TO KNOW IF IS SHIP OR WHATEVER
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return Viper
|
||||||
|
Reference in New Issue
Block a user