fixed the camera so its motion is no longer tied to framerate
limited minimum and maximum zoom on camera changed point scaling so that cities get smaller when zooming in changed selection cursor to hollow circle changed capital cities to orange squares included data/earth/ directory so that files are loaded from there when they're not available in the mod folder when cities are hidden, hovering over travel nodes will display the travel node location (broken for now) when cities and travel nodes are hidden, hovering over ai markers will display their details made the information boxes more opaque changed border-calculating code so that it works with higher resolutions
|
@ -0,0 +1 @@
|
||||||
|
build/
|
34
ai.lua
|
@ -1,13 +1,27 @@
|
||||||
--Manage the AI nodes used by DEFCON.
|
--Manage the AI nodes used by DEFCON.
|
||||||
local t = {}
|
|
||||||
local bmp = require 'bmp'
|
local bmp = require 'bmp'
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
|
local locationQuery = require 'locationQuery'
|
||||||
|
|
||||||
|
local t = setmetatable( {}, {__index = locationQuery } )
|
||||||
local print = print
|
local print = print
|
||||||
|
|
||||||
|
local aiNode = {}
|
||||||
|
local mtAiNode = { __index = aiNode }
|
||||||
|
|
||||||
|
function aiNode:formatDisplayInfo()
|
||||||
|
return ([[AI NODE: %d
|
||||||
|
LONGITUDE: %3.2f
|
||||||
|
LATITUDE: %3.2f
|
||||||
|
ATTACKING: %s
|
||||||
|
]]):format( self.idx, self.x, self.y, tostring(self.attacking) )
|
||||||
|
end
|
||||||
|
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
local img, imgd = bmp.load( filename )
|
local img, imgd = bmp.load( filename )
|
||||||
local nodes = {
|
local nodes = {
|
||||||
visible = true,
|
visible = true,
|
||||||
|
all = {},
|
||||||
att = {},
|
att = {},
|
||||||
ptsAtt = {},
|
ptsAtt = {},
|
||||||
def = {},
|
def = {},
|
||||||
|
@ -16,15 +30,19 @@ function t.load( filename )
|
||||||
imgd = imgd }
|
imgd = imgd }
|
||||||
|
|
||||||
print( "=== Loading AI Markers: ===" )
|
print( "=== Loading AI Markers: ===" )
|
||||||
|
local idx = 1
|
||||||
for x = 0, 511 do
|
for x = 0, 511 do
|
||||||
for y = 0, 284 do
|
for y = 0, 284 do
|
||||||
local r, g = imgd:getPixel( x, 284 - y )
|
local r, g = imgd:getPixel( x, 284 - y )
|
||||||
if r > 0.5 or g > 0.5 then
|
if r > 0.5 or g > 0.5 then
|
||||||
local long = x * (360 / imgd:getWidth()) - 180
|
local long = x * (360 / imgd:getWidth()) - 180
|
||||||
local lat = y * (200 / img:getHeight()) - 100
|
local lat = y * (200 / img:getHeight()) - 100
|
||||||
local set = (r > 0.5) and nodes.att or nodes.def
|
local attacking = (r > 0.5)
|
||||||
set[#set + 1] = {x = long, y = lat}
|
local set = attacking and nodes.att or nodes.def
|
||||||
print( #set, long, lat )
|
local node = setmetatable( {x = long, y = lat, attacking = attacking, idx = idx}, mtAiNode )
|
||||||
|
nodes.all[ idx ] = node
|
||||||
|
set[#set + 1] = node
|
||||||
|
idx = idx + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -43,7 +61,13 @@ function t.load( filename )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable( nodes, {__index = t } )
|
nodes.all = locationQuery.New( nodes.all )
|
||||||
|
setmetatable( nodes, {__index = t } )
|
||||||
|
return nodes
|
||||||
|
end
|
||||||
|
|
||||||
|
function t.selectNearest( nodes, x, y )
|
||||||
|
return (nodes.all):getClosestPoint( x, y )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.draw( nodes )
|
function t.draw( nodes )
|
||||||
|
|
15
camera.lua
|
@ -20,12 +20,12 @@ function Camera.GetNodeCoordinate( x, y )
|
||||||
return tfNodes:inverseTransformPoint( x, y )
|
return tfNodes:inverseTransformPoint( x, y )
|
||||||
end
|
end
|
||||||
|
|
||||||
function Camera.Zoom( out )
|
function Camera.Zoom( delta )
|
||||||
local scale = out and 1.1 or 0.9
|
local scale = 1.0 + delta
|
||||||
tf:scale( scale, scale )
|
if Camera.zoom < 25.0 and delta > 0 or --zooming in
|
||||||
local x = Camera.x
|
Camera.zoom > 0.5 and delta < 0 then --zooming out
|
||||||
local y = Camera.y
|
return Camera.Set( Camera.x , Camera.y, Camera.w * scale, Camera.h * scale )
|
||||||
return Camera.Set( x, y, Camera.w * scale, Camera.h * scale )
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Camera.Translate( x, y )
|
function Camera.Translate( x, y )
|
||||||
|
@ -36,9 +36,8 @@ end
|
||||||
|
|
||||||
--In world coordinates: top left corner at x, y, extent of w, h.
|
--In world coordinates: top left corner at x, y, extent of w, h.
|
||||||
function Camera.Set( x, y, w, h )
|
function Camera.Set( x, y, w, h )
|
||||||
print( ("CAMERA: %3.2f %3.2f %3.2f %3.2f"):format(x, y, w, h) )
|
|
||||||
Camera.x, Camera.y, Camera.w, Camera.h = x, y, w, h
|
Camera.x, Camera.y, Camera.w, Camera.h = x, y, w, h
|
||||||
Camera.zoom = w / 360
|
Camera.zoom = w / 800
|
||||||
tf:reset()
|
tf:reset()
|
||||||
tf:scale( w / 360, -h / 200 )
|
tf:scale( w / 360, -h / 200 )
|
||||||
tf:translate( 180 - x, -y - 100 )
|
tf:translate( 180 - x, -y - 100 )
|
||||||
|
|
32
cities.lua
|
@ -23,26 +23,40 @@ function t.unlockSelection()
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.draw()
|
function t.draw()
|
||||||
if cities.visible then lg.points( points ) end
|
return lg.points( points )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.drawSelected( r )
|
function t.drawSelected( )
|
||||||
if not cities.visible then return end
|
|
||||||
local c = t.selected
|
local c = t.selected
|
||||||
if not c then return end
|
if not c then return end
|
||||||
lg.circle( "fill", c.x, c.y, r )
|
lg.circle( "line", c.x, c.y, 1.0 )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.drawCapitals()
|
function t.drawCapitals()
|
||||||
if cities.visible then lg.points( caps ) end
|
if cities.visible then lg.points( caps ) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.selectNearestCity(x, y)
|
function t.selectNearest( cities, x, y )
|
||||||
if not t.selectionLocked then t.selected = cities:getClosestPoint(x, y) end
|
return cities:getClosestPoint(x, y) --defer to locationQuery
|
||||||
|
end
|
||||||
|
|
||||||
|
local city = {}
|
||||||
|
local citymt = {__index = city}
|
||||||
|
function city:formatDisplayInfo()
|
||||||
|
return (
|
||||||
|
[[
|
||||||
|
NAME: %s
|
||||||
|
COUNTRY: %s
|
||||||
|
LONGITUDE: %3.2f
|
||||||
|
LATITUDE: %3.2f
|
||||||
|
POP: %d
|
||||||
|
CAPITAL: %s]]):format( self.name, self.country, self.x, self.y, self.pop, tostring(self.capital) )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
|
|
||||||
|
print( "=== LOADING CITIES. ===" )
|
||||||
|
|
||||||
cities = { visible = true, active = false }
|
cities = { visible = true, active = false }
|
||||||
local n = 1
|
local n = 1
|
||||||
local idxPts = 1
|
local idxPts = 1
|
||||||
|
@ -53,11 +67,11 @@ function t.load( filename )
|
||||||
local _, _, x, y, pop, capital = line:sub( 83 ):find( "(%g+)%s+(%g+)%s+(%g+)%s+(%g+)" )
|
local _, _, x, y, pop, capital = line:sub( 83 ):find( "(%g+)%s+(%g+)%s+(%g+)%s+(%g+)" )
|
||||||
if capital then --check against empty or malformed line
|
if capital then --check against empty or malformed line
|
||||||
x, y, pop, capital = tonumber( x ), tonumber( y ), tonumber( pop ), ( tonumber( capital ) > 0)
|
x, y, pop, capital = tonumber( x ), tonumber( y ), tonumber( pop ), ( tonumber( capital ) > 0)
|
||||||
local city = {
|
local city = setmetatable({
|
||||||
name = line:sub( 1, 39 ):gsub("%s+$",""),
|
name = line:sub( 1, 39 ):gsub("%s+$",""),
|
||||||
country = line:sub( 42, 82 ):gsub("%s+$",""),
|
country = line:sub( 42, 82 ):gsub("%s+$",""),
|
||||||
x = x, y = y, pop = pop, capital = capital
|
x = x, y = y, pop = pop, capital = capital
|
||||||
}
|
}, citymt )
|
||||||
cities[n] = city
|
cities[n] = city
|
||||||
n = n + 1
|
n = n + 1
|
||||||
|
|
||||||
|
@ -77,7 +91,7 @@ function t.load( filename )
|
||||||
cities = locationQuery.New( cities )
|
cities = locationQuery.New( cities )
|
||||||
setmetatable( getmetatable( cities ).__index, {__index = t } )
|
setmetatable( getmetatable( cities ).__index, {__index = t } )
|
||||||
|
|
||||||
print( "LOADED", filename, n )
|
print( "=== CITIES LOADED:", filename, n, "===" )
|
||||||
return cities
|
return cities
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
4
conf.lua
|
@ -11,7 +11,7 @@ function love.conf(t)
|
||||||
t.audio.mixwithsystem = true -- Keep background music playing when opening LOVE (boolean, iOS and Android only)
|
t.audio.mixwithsystem = true -- Keep background music playing when opening LOVE (boolean, iOS and Android only)
|
||||||
|
|
||||||
t.window.title = "dcEarth" -- The window title (string)
|
t.window.title = "dcEarth" -- The window title (string)
|
||||||
t.window.icon = "favicon.png" -- Filepath to an image to use as the window's icon (string)
|
t.window.icon = "icons/favicon.png" -- Filepath to an image to use as the window's icon (string)
|
||||||
t.window.width = 800 -- The window width (number)
|
t.window.width = 800 -- The window width (number)
|
||||||
t.window.height = 600 -- The window height (number)
|
t.window.height = 600 -- The window height (number)
|
||||||
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
||||||
|
@ -44,7 +44,7 @@ function love.conf(t)
|
||||||
t.modules.sound = false -- Enable the sound module (boolean)
|
t.modules.sound = false -- Enable the sound module (boolean)
|
||||||
t.modules.system = true -- Enable the system module (boolean)
|
t.modules.system = true -- Enable the system module (boolean)
|
||||||
t.modules.thread = false -- Enable the thread module (boolean)
|
t.modules.thread = false -- Enable the thread module (boolean)
|
||||||
t.modules.timer = false -- Enable the timer module (boolean), Disabling it will result 0 delta time in love.update
|
t.modules.timer = true -- Enable the timer module (boolean), Disabling it will result 0 delta time in love.update
|
||||||
t.modules.touch = false -- Enable the touch module (boolean)
|
t.modules.touch = false -- Enable the touch module (boolean)
|
||||||
t.modules.video = false -- Enable the video module (boolean)
|
t.modules.video = false -- Enable the video module (boolean)
|
||||||
t.modules.window = true -- Enable the window module (boolean)
|
t.modules.window = true -- Enable the window module (boolean)
|
||||||
|
|
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 428 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
@ -1,7 +1,6 @@
|
||||||
--Shitty acceleration structure: get closest point in set.
|
--Shitty acceleration structure: get closest point in set.
|
||||||
--Assumed to be in world coordinates: ( -180, 180 ) x ( -100, 100 )
|
--Assumed to be in world coordinates: ( -180, 180 ) x ( -100, 100 )
|
||||||
local t = {}
|
local t = {}
|
||||||
local hashes = {}
|
|
||||||
local math = math
|
local math = math
|
||||||
|
|
||||||
local hash = function( x, y, debug )
|
local hash = function( x, y, debug )
|
||||||
|
@ -9,9 +8,18 @@ local hash = function( x, y, debug )
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function t.getHashes( points )
|
||||||
|
return assert( points.hashes )
|
||||||
|
end
|
||||||
|
|
||||||
function t.getClosestPoint( points, x, y )
|
function t.getClosestPoint( points, x, y )
|
||||||
|
local hashes = t.getHashes( points )
|
||||||
local closePoints = hashes[hash( x, y )]
|
local closePoints = hashes[hash( x, y )]
|
||||||
if not closePoints then return end
|
|
||||||
|
if not closePoints then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local distance = math.huge
|
local distance = math.huge
|
||||||
local px, py, point
|
local px, py, point
|
||||||
for k, v in pairs(closePoints) do
|
for k, v in pairs(closePoints) do
|
||||||
|
@ -29,6 +37,7 @@ function t.getClosestPoint( points, x, y )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.Edit( points, point, x, y )
|
function t.Edit( points, point, x, y )
|
||||||
|
local hashes = t.getHashes( points )
|
||||||
local h = hashes[hash( point.x, point.y )]
|
local h = hashes[hash( point.x, point.y )]
|
||||||
if h then
|
if h then
|
||||||
for i, p in pairs(h) do
|
for i, p in pairs(h) do
|
||||||
|
@ -50,13 +59,21 @@ function t.Add( points, x, y )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.New( points )
|
function t.New( points )
|
||||||
|
local hashes = {}
|
||||||
for i = 1, #points do
|
for i = 1, #points do
|
||||||
local x, y = points[i].x, points[i].y
|
local x, y = points[i].x, points[i].y
|
||||||
local h = hash( x, y )
|
local h = hash( x, y )
|
||||||
hashes[h] = hashes[h] or {}
|
hashes[h] = hashes[h] or {}
|
||||||
hashes[h][#hashes[h] + 1] = points[i]
|
hashes[h][#hashes[h] + 1] = points[i]
|
||||||
end
|
end
|
||||||
return setmetatable( points, {__index = t } )
|
points.hashes = hashes
|
||||||
|
|
||||||
|
do
|
||||||
|
local count = 0
|
||||||
|
for k, v in pairs(hashes) do count = count + 1 end
|
||||||
|
print( "LOCATION QUERY. Points:", count )
|
||||||
|
end
|
||||||
|
return setmetatable( points, {__index = t} )
|
||||||
end
|
end
|
||||||
|
|
||||||
return t
|
return t
|
47
main.lua
|
@ -25,12 +25,12 @@ end
|
||||||
function love.update( dt )
|
function love.update( dt )
|
||||||
local tx, ty = 0, 0
|
local tx, ty = 0, 0
|
||||||
local moveCamera = false
|
local moveCamera = false
|
||||||
if love.keyboard.isScancodeDown( "w" ) then moveCamera = true; ty = ty + 1 end
|
if love.keyboard.isScancodeDown( "w" ) then moveCamera = true; ty = ty + 30 * dt end
|
||||||
if love.keyboard.isScancodeDown( "a" ) then moveCamera = true; tx = tx - 1 end
|
if love.keyboard.isScancodeDown( "a" ) then moveCamera = true; tx = tx - 30 * dt end
|
||||||
if love.keyboard.isScancodeDown( "s" ) then moveCamera = true; ty = ty - 1 end
|
if love.keyboard.isScancodeDown( "s" ) then moveCamera = true; ty = ty - 30 * dt end
|
||||||
if love.keyboard.isScancodeDown( "d" ) then moveCamera = true; tx = tx + 1 end
|
if love.keyboard.isScancodeDown( "d" ) then moveCamera = true; tx = tx + 30 * dt end
|
||||||
if love.keyboard.isScancodeDown( "q" ) then Camera.Zoom( true ) end
|
if love.keyboard.isScancodeDown( "q" ) then Camera.Zoom( dt ) end
|
||||||
if love.keyboard.isScancodeDown( "e" ) then Camera.Zoom( false ) end
|
if love.keyboard.isScancodeDown( "e" ) then Camera.Zoom( -dt ) end
|
||||||
if moveCamera then Camera.Translate( tx, ty ) end
|
if moveCamera then Camera.Translate( tx, ty ) end
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ function love.draw()
|
||||||
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
||||||
local h = love.graphics.getHeight() - 30
|
local h = love.graphics.getHeight() - 30
|
||||||
love.graphics.setColor( 0.2, 0.1, 0.1, 0.5 )
|
love.graphics.setColor( 0.2, 0.1, 0.1, 1.0 )
|
||||||
love.graphics.rectangle( "fill", 0, h, love.graphics.getWidth() / 2, 30 )
|
love.graphics.rectangle( "fill", 0, h, love.graphics.getWidth() / 2, 30 )
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
love.graphics.rectangle( "line", 0, h, love.graphics.getWidth() / 2, 30 )
|
love.graphics.rectangle( "line", 0, h, love.graphics.getWidth() / 2, 30 )
|
||||||
|
@ -94,30 +94,13 @@ function love.draw()
|
||||||
|
|
||||||
--Edit box.
|
--Edit box.
|
||||||
love.graphics.rectangle( "line", love.graphics.getWidth() / 2, h, love.graphics.getWidth() / 2, 30 )
|
love.graphics.rectangle( "line", love.graphics.getWidth() / 2, h, love.graphics.getWidth() / 2, 30 )
|
||||||
if map.loaded and map.cities.selected then
|
if map.selected then
|
||||||
local c = map.cities.selected
|
love.graphics.setColor( 0.2, 0.1, 0.1, 1.0 )
|
||||||
love.graphics.setColor( 0.2, 0.1, 0.1, 0.5 )
|
|
||||||
love.graphics.rectangle( "fill", 0, 0, 150 ,100 )
|
love.graphics.rectangle( "fill", 0, 0, 150 ,100 )
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
love.graphics.rectangle( "line", 0, 0, 150 ,100 )
|
love.graphics.rectangle( "line", 0, 0, 150 ,100 )
|
||||||
love.graphics.setColor( 1.2, 1.1, 1.1, 1.5 )
|
love.graphics.setColor( 1.2, 1.1, 1.1, 1.5 )
|
||||||
love.graphics.print( ("NAME: %s\nX: %3.2f\nY: %3.2f\nPOP: %d\nCAPITAL: %s\nCOUNTRY: %s"):format(c.name, c.x, c.y, c.pop, tostring(c.capital), c.country), 0, 0 )
|
love.graphics.print( map.selected:formatDisplayInfo(), 0, 0 )
|
||||||
elseif map.loaded and map.travelnodes.selected then
|
|
||||||
local c = map.travelnodes.selected
|
|
||||||
love.graphics.setColor( 0.2, 0.1, 0.1, 0.5 )
|
|
||||||
love.graphics.rectangle( "fill", 0, 0, 150 ,100 )
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
love.graphics.rectangle( "line", 0, 0, 150 ,100 )
|
|
||||||
love.graphics.setColor( 1.2, 1.1, 1.1, 1.5 )
|
|
||||||
love.graphics.print( ("Node: %d\nX: %3.2f\nY: %3.2f\n"):format(c.number, c.x, c.y) )
|
|
||||||
elseif map.loaded and map.ainodes.selectedNode then
|
|
||||||
local c = map.ainodes.selected
|
|
||||||
love.graphics.setColor( 0.2, 0.1, 0.1, 0.5 )
|
|
||||||
love.graphics.rectangle( "fill", 0, 0, 150 ,100 )
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
love.graphics.rectangle( "line", 0, 0, 150 ,100 )
|
|
||||||
love.graphics.setColor( 1.2, 1.1, 1.1, 1.5 )
|
|
||||||
love.graphics.print( ("Node: %d\nX: %3.2f\nY: %3.2f\noffensive: %s"):format(c.number, c.x, c.y, c.attack) )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -126,7 +109,7 @@ function love.resize(w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.wheelmoved(x, y)
|
function love.wheelmoved(x, y)
|
||||||
Camera.Zoom( (y > 0) and true or false )
|
Camera.Zoom( (y > 0) and 0.5 or -0.5 )
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.mousepressed( x, y, button, istouch, presses )
|
function love.mousepressed( x, y, button, istouch, presses )
|
||||||
|
@ -142,7 +125,13 @@ function love.mousepressed( x, y, button, istouch, presses )
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.mousemoved( x, y, dx, dy, istouch )
|
function love.mousemoved( x, y, dx, dy, istouch )
|
||||||
if map.loaded and map.cities.visible then map.cities.selectNearestCity( Camera.GetWorldCoordinate( x, y ) ) end
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
|
if map.loaded then
|
||||||
|
if map.cities.visible then map.selected = map.cities:selectNearest( wx, wy )
|
||||||
|
elseif map.travelnodes.visible then map.selected = map.travelnodes:selectNearest( wx, wy )
|
||||||
|
elseif map.ainodes.visible then map.selected = map.ainodes:selectNearest( wx, wy )
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ToggleVisibility( layer )
|
local function ToggleVisibility( layer )
|
||||||
|
|
25
map.lua
|
@ -2,8 +2,7 @@ local lg = love.graphics
|
||||||
local AI = require 'ai'
|
local AI = require 'ai'
|
||||||
local Cities = require 'cities'
|
local Cities = require 'cities'
|
||||||
local Lines = require 'lines'
|
local Lines = require 'lines'
|
||||||
local Nodes = require 'nodes'
|
local Nodes = require 'travelNodes'
|
||||||
local Bitmap = require 'bmp'
|
|
||||||
local Camera = require 'camera'
|
local Camera = require 'camera'
|
||||||
local Territory = require 'territory'
|
local Territory = require 'territory'
|
||||||
|
|
||||||
|
@ -79,20 +78,27 @@ function map.draw()
|
||||||
|
|
||||||
lg.replaceTransform( Camera.tf )
|
lg.replaceTransform( Camera.tf )
|
||||||
|
|
||||||
do --points
|
if map.selected then
|
||||||
|
lg.setColor( 1.0, 0.5, 0.5, 0.9 )
|
||||||
|
lg.setLineJoin( "miter" )
|
||||||
|
lg.setLineWidth( 1.0 / Camera.zoom )
|
||||||
|
lg.circle( "line", map.selected.x, map.selected.y, 0.2 + 1.0 / Camera.zoom )
|
||||||
|
end
|
||||||
|
|
||||||
|
if map.cities.visible then --points
|
||||||
|
|
||||||
lg.setColor( 1, 0, 0, 0.5 )
|
lg.setColor( 1, 0, 0, 0.5 )
|
||||||
lg.setPointSize( 0.5 * Camera.zoom )
|
lg.setPointSize( 5.0 )
|
||||||
map.cities.draw()
|
map.cities.draw()
|
||||||
|
|
||||||
lg.setColor( 1, 1, 1.0, 0.5 )
|
lg.setColor( 1, 1, 0.0, 0.5 )
|
||||||
lg.setPointSize( 1.0 * Camera.zoom )
|
|
||||||
map.cities.drawCapitals()
|
map.cities.drawCapitals()
|
||||||
|
|
||||||
lg.setColor( 1, 1, 1, 0.5 )
|
end
|
||||||
map.cities.drawSelected( 15.0 / Camera.zoom )
|
|
||||||
|
|
||||||
if map.ainodes.visible then map.ainodes:draw() end
|
if map.ainodes.visible then
|
||||||
|
lg.setPointSize( 5.0 )
|
||||||
|
map.ainodes:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
do --line stuff
|
do --line stuff
|
||||||
|
@ -122,6 +128,7 @@ function map.draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -109,8 +109,9 @@ function t.computeBorder( territory, threshold, key )
|
||||||
local border = territory[key]
|
local border = territory[key]
|
||||||
local n = 1
|
local n = 1
|
||||||
|
|
||||||
for x = 0, 511 do
|
local w, h = territory.imgd:getWidth() - 1, territory.imgd:getHeight() - 1
|
||||||
for y = 0, 284 do
|
for x = 0, w do
|
||||||
|
for y = 0, h do
|
||||||
--Bottom left, bottom right, and top right of pixel in image coordinates:
|
--Bottom left, bottom right, and top right of pixel in image coordinates:
|
||||||
local blx, bly = x, y + 1
|
local blx, bly = x, y + 1
|
||||||
local brx, bry = x + 1, y + 1
|
local brx, bry = x + 1, y + 1
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
--Manage the pathfinding nodes used by DEFCON.
|
--Manage the pathfinding nodes used by DEFCON.
|
||||||
--This is important for a mapping tool because the DEFCON client will not load a map unless
|
--This is important for a mapping tool because the DEFCON client will not load a map unless
|
||||||
--the pathfinding nodes form a connected graph.
|
--the pathfinding nodes form a connected graph.
|
||||||
local t = {}
|
|
||||||
local bmp = require 'bmp'
|
local bmp = require 'bmp'
|
||||||
|
local locationQuery = require 'locationQuery'
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
|
|
||||||
|
|
||||||
|
local t = setmetatable({}, {__index = locationQuery})
|
||||||
local isSailable
|
local isSailable
|
||||||
|
|
||||||
local function isConnected( startNode, endNode )
|
local function isConnected( startNode, endNode )
|
||||||
|
@ -25,15 +28,17 @@ local function isConnected( startNode, endNode )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.getClosest( nodes, x, y )
|
function t.selectNearest( nodes, x, y )
|
||||||
local d = math.huge
|
return (nodes.nodes):getClosestPoint( x, y )
|
||||||
local closestNode
|
end
|
||||||
for _, node in pairs( nodes.nodes ) do
|
|
||||||
local nx, ny = node.x, node.y
|
local travelNode = {}
|
||||||
local nd = (nx - x) * (nx - x) + (ny - y) * (ny - y)
|
local mtTravelNode = { __index = travelNode }
|
||||||
if nd < d then d = nd; closestNode = node end
|
|
||||||
end
|
function travelNode:formatDisplayInfo()
|
||||||
return closestNode
|
return ([[ TRAVEL NODE: %d
|
||||||
|
LONGITUDE: %3.2f
|
||||||
|
LATITUDE: %3.2f]]):format( self.idx, self.x, self.y )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.load( filename, sailable )
|
function t.load( filename, sailable )
|
||||||
|
@ -49,10 +54,10 @@ function t.load( filename, sailable )
|
||||||
if imgd:getPixel( x, 399 - y ) > 0 then
|
if imgd:getPixel( x, 399 - y ) > 0 then
|
||||||
local long = 360 * ( x - 800 ) / 800 - 360 / 2 + 360
|
local long = 360 * ( x - 800 ) / 800 - 360 / 2 + 360
|
||||||
local lat = 360 * ( 600 / 800 ) * ( 600 - y ) / 600 - 180
|
local lat = 360 * ( 600 / 800 ) * ( 600 - y ) / 600 - 180
|
||||||
nodes.nodes[n] = {x = long, y = lat}
|
nodes.nodes[n] = setmetatable({x = long, y = lat, idx = n}, mtTravelNode )
|
||||||
|
print( nodes.nodes[n]:formatDisplayInfo() )
|
||||||
nodes.points[ 2 * n - 1 ] = long
|
nodes.points[ 2 * n - 1 ] = long
|
||||||
nodes.points[ 2 * n ] = lat
|
nodes.points[ 2 * n ] = lat
|
||||||
print( n, long, lat )
|
|
||||||
n = n + 1
|
n = n + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -69,7 +74,9 @@ function t.load( filename, sailable )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( "=== Nodes Loaded ===" )
|
print( "=== Nodes Loaded ===" )
|
||||||
return setmetatable( nodes, {__index = t } )
|
nodes.nodes = locationQuery.New( nodes.nodes )
|
||||||
|
setmetatable( nodes, {__index = t} )
|
||||||
|
return nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
--Determine if graph has more than one connected component.
|
--Determine if graph has more than one connected component.
|
||||||
|
@ -78,9 +85,13 @@ function t.isConnected( nodes )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.draw( nodes )
|
function t.draw( nodes )
|
||||||
lg.setPointSize( 10 )
|
lg.setPointSize( 8 )
|
||||||
lg.setColor( 1, 1, 1, 0.5 )
|
lg.setColor( 1, 1, 1, 0.5 )
|
||||||
lg.points( nodes.points )
|
lg.points( nodes.points )
|
||||||
|
return t.drawConnections( nodes )
|
||||||
|
end
|
||||||
|
|
||||||
|
function t.drawConnections( nodes )
|
||||||
|
|
||||||
for i, connection in pairs( nodes.connections ) do
|
for i, connection in pairs( nodes.connections ) do
|
||||||
for j in pairs( connection ) do
|
for j in pairs( connection ) do
|
||||||
|
@ -88,9 +99,6 @@ function t.draw( nodes )
|
||||||
lg.line( ix, iy, fx, fy )
|
lg.line( ix, iy, fx, fy )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function t.drawConnections( nodes )
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|