From 8eed23c87da48167ed2337f5d6026ce5018225d8 Mon Sep 17 00:00:00 2001 From: wan-may Date: Fri, 28 Jul 2023 02:17:00 -0300 Subject: [PATCH] Feverish coding binge tonight. Mouseover to find nearest city and display information. Camera movement via arrow keys and scroll wheel. Status bar displaying mouse location in world and window coordinates. --- bmp.lua | 18 ++++++++++-- camera.lua | 40 ++++++++++++++++++++++++++ cities.lua | 37 ++++++++++++++++++++---- conf.lua | 51 +++++++++++++++++++++++++++++++++ data/earth/cities.dat | 2 +- favicon.png | Bin 0 -> 8539 bytes locationQuery.lua | 65 ++++++++++++++++++++++++++++++++++++++++++ main.lua | 61 +++++++++++++++++++++++++++++++++++---- map.lua | 40 ++++++++++++++++---------- nodes.lua | 26 +++++++++++++++-- scratch.lua | 2 ++ territory.lua | 42 +++++++++++++++++++++++++++ 12 files changed, 352 insertions(+), 32 deletions(-) create mode 100644 camera.lua create mode 100644 conf.lua create mode 100644 favicon.png create mode 100644 locationQuery.lua create mode 100644 scratch.lua create mode 100644 territory.lua diff --git a/bmp.lua b/bmp.lua index 450b05c..961739f 100644 --- a/bmp.lua +++ b/bmp.lua @@ -1,5 +1,19 @@ --Load and save the bmp formats used by DEFCON. -local bmp = {} +local t = {} +local lfs = love.filesystem +--FFI bit-twiddling stuff. +local ffi = require 'ffi' +local bit = require 'bit' -return bmp \ No newline at end of file +function t.load( filename ) + local bytes, size = lfs.read( filename ) + + print( "LOADED", filename, size) +end + +function t.save( data, format ) + +end + +return t \ No newline at end of file diff --git a/camera.lua b/camera.lua new file mode 100644 index 0000000..3fafcfa --- /dev/null +++ b/camera.lua @@ -0,0 +1,40 @@ +local tf = love.math.newTransform() +local lg = assert( love.graphics ) +local Camera = { x = 0, y = 0, w = 360, h = 200, zoom = 1, tf = tf } + +function Camera.GetWorldCoordinate( x, y ) + return tf:inverseTransformPoint( x, y ) +end + +function Camera.Zoom( out ) + local scale = out and 1.1 or 0.9 + tf:scale( scale, scale ) + local x = Camera.x + local y = Camera.y + return Camera.Set( x, y, Camera.w * scale, Camera.h * scale ) +end + +function Camera.Translate( x, y ) + x = x or 0 + y = y or 0 + return Camera.Set( Camera.x + x, Camera.y + y, Camera.w, Camera.h) +end + +--In world coordinates: top left corner at x, y, extent of 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.zoom = w / 360 + tf:reset() + tf:scale( w / 360, -h / 200 ) + tf:translate( 180 - x, -y - 100 ) +end + +function Camera.Resize( w, h ) + w, h = math.min( w, h * 360 / 200 ), math.min( h, w * 200 / 360 ) + return Camera.Set( Camera.x, Camera.y, w, h ) +end + +Camera.Resize( lg.getDimensions() ) + +return Camera \ No newline at end of file diff --git a/cities.lua b/cities.lua index c3dca75..1892cfd 100644 --- a/cities.lua +++ b/cities.lua @@ -1,31 +1,52 @@ --Load and save the fixed width plaintext data used by DEFCON. local t = {} local io = io +local math = math local table = table local tonumber = tonumber local lfs = love.filesystem local lg = love.graphics +local locationQuery = require 'locationQuery' local cities local points = {} local caps = {} +t.selectedCity = nil + function t.draw() lg.points( points ) end +function t.drawSelected( r ) + local c = t.selectedCity + if not c then return end + lg.circle( "fill", c.x, c.y, r ) +end + function t.drawCapitals() lg.points( caps ) end +function t.selectNearestCity(x, y) + t.selectedCity = cities:getClosestPoint(x, y) + + if t.selectedCity then + local city = t.selectedCity + print( "SELECTED CITY", city.x, city.y, city.name, city.pop, city.capital) + else + print( "NO SELECTED CITY" ) + end +end + function t.load( filename ) cities = {} - local n = 0 + local n = 1 local idxPts = 1 local idxCaps = 1 - for line in assert( io.lines( filename ), "Error: could not open cities.dat" ) do - n = n + 1 + for line in assert( lfs.lines( filename ), "Error: could not open cities.dat" ) do + local _, _, x, y, pop, capital = line:sub( 83 ):find( "(%g+)%s+(%g+)%s+(%g+)%s+(%g+)" ) x, y, pop, capital = tonumber( x ), tonumber( y ), tonumber( pop ), ( tonumber( capital ) > 0) local city = { @@ -33,7 +54,8 @@ function t.load( filename ) country = line:sub( 42, 82 ):gsub("%s+$",""), x = x, y = y, pop = pop, capital = capital } - cities[n] = city + cities[n] = city + n = n + 1 points[idxPts], points[idxPts + 1] = x, y idxPts = idxPts + 2 @@ -44,9 +66,12 @@ function t.load( filename ) end end + --Multiple inheritance. + cities = locationQuery.New( cities ) + setmetatable( getmetatable( cities ).__index, {__index = t } ) + print( "LOADED", filename, n ) - - return setmetatable( cities, {__index = t } ) + return cities end function t.save( cities, filename ) diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..92c8889 --- /dev/null +++ b/conf.lua @@ -0,0 +1,51 @@ +function love.conf(t) + t.identity = "dcEarth" -- The name of the save directory (string) + t.appendidentity = true -- Search files in source directory before save directory (boolean) + t.version = "11.3" -- The LÖVE version this game was made for (string) + t.console = true -- Attach a console (boolean, Windows only) + t.accelerometerjoystick = true -- Enable the accelerometer on iOS and Android by exposing it as a Joystick (boolean) + t.externalstorage = false -- True to save files (and read from the save directory) in external storage on Android (boolean) + t.gammacorrect = false -- Enable gamma-correct rendering, when supported by the system (boolean) + + t.audio.mic = false -- Request and use microphone capabilities in Android (boolean) + 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.icon = "favicon.png" -- Filepath to an image to use as the window's icon (string) + t.window.width = 800 -- The window width (number) + t.window.height = 600 -- The window height (number) + t.window.borderless = false -- Remove all border visuals from the window (boolean) + t.window.resizable = true -- Let the window be user-resizable (boolean) + t.window.minwidth = 1 -- Minimum window width if the window is resizable (number) + t.window.minheight = 1 -- Minimum window height if the window is resizable (number) + t.window.fullscreen = false -- Enable fullscreen (boolean) + t.window.fullscreentype = "desktop" -- Choose between "desktop" fullscreen or "exclusive" fullscreen mode (string) + t.window.vsync = 0 -- Vertical sync mode (number) + t.window.msaa = 0 -- The number of samples to use with multi-sampled antialiasing (number) + t.window.depth = nil -- The number of bits per sample in the depth buffer + t.window.stencil = nil -- The number of bits per sample in the stencil buffer + t.window.display = 1 -- Index of the monitor to show the window in (number) + t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean) + t.window.usedpiscale = true -- Enable automatic DPI scaling when highdpi is set to true as well (boolean) + t.window.x = nil -- The x-coordinate of the window's position in the specified display (number) + t.window.y = nil -- The y-coordinate of the window's position in the specified display (number) + + t.modules.audio = true -- Enable the audio module (boolean) + t.modules.data = true -- Enable the data module (boolean) + t.modules.event = true -- Enable the event module (boolean) + t.modules.font = true -- Enable the font module (boolean) + t.modules.graphics = true -- Enable the graphics module (boolean) + t.modules.image = true -- Enable the image module (boolean) + t.modules.joystick = false -- Enable the joystick module (boolean) + t.modules.keyboard = true -- Enable the keyboard module (boolean) + t.modules.math = true -- Enable the math module (boolean) + t.modules.mouse = true -- Enable the mouse module (boolean) + t.modules.physics = false -- Enable the physics module (boolean) + t.modules.sound = true -- Enable the sound module (boolean) + t.modules.system = true -- Enable the system module (boolean) + t.modules.thread = true -- Enable the thread module (boolean) + 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.video = false -- Enable the video module (boolean) + t.modules.window = true -- Enable the window module (boolean) +end \ No newline at end of file diff --git a/data/earth/cities.dat b/data/earth/cities.dat index 26cc1ff..84b9829 100644 --- a/data/earth/cities.dat +++ b/data/earth/cities.dat @@ -1,4 +1,4 @@ -Cambridge United Kingdom 6.166700 35.566700 106673 0 +Cambridge United Kingdom 6.166700 35.566700 106673 0 Gloucester United Kingdom 6.666700 36.366699 108150 0 Hastings/Bexhill United Kingdom 5.400000 36.183300 112080 0 Slough United Kingdom 13.250000 -8.833300 106882 0 diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..018fb5db6cc5187a77107af97b52f4a01e9a6e21 GIT binary patch literal 8539 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 V{oN3LTIm1)002ovPDHLkV1m0jVm$x= literal 0 HcmV?d00001 diff --git a/locationQuery.lua b/locationQuery.lua new file mode 100644 index 0000000..d677f22 --- /dev/null +++ b/locationQuery.lua @@ -0,0 +1,65 @@ +--Shitty acceleration structure: get closest point in set. +--Assumed to be in world coordinates: ( -180, 180 ) x ( -100, 100 ) +local t = {} +local hashes = {} +local math = math + +local hash = function( x, y, debug ) + local s = "h"..("%2d%2d"):format(math.floor( 0.5 + (180 + x) / 10 ), math.floor( 0.5 + (100 + y) / 10 ) ) + if debug then print( "HASH: ", s, x, y) end + return s +end + +function t.getClosestPoint( points, x, y ) + local closePoints = hashes[hash( x, y )] + if not closePoints then return end + local distance = math.huge + local px, py, point + for k, v in pairs(closePoints) do + + px, py = v.x, v.y + local d = (x - px) * (x - px) + (y - py) * (y - py) + if d < distance then + distance = d + point = v + end + + end + + print( #closePoints, distance ) + + return point +end + +function t.Edit( points, point, x, y ) + local h = hashes[hash( point.x, point.y )] + if h then + for i, p in pairs(h) do + if p == point then + table.remove( h, i ) + break + end + end + end + + table.insert( hashes[ hash( x, y ) ], point ) + point.x = x + point.y = y + +end + +function t.Add( points ) + +end + +function t.New( points ) + for i = 1, #points do + local x, y = points[i].x, points[i].y + local h = hash( x, y ) + hashes[h] = hashes[h] or {} + hashes[h][#hashes[h] + 1] = points[i] + end + return setmetatable( points, {__index = t } ) +end + +return t \ No newline at end of file diff --git a/main.lua b/main.lua index d49f13c..04ef67a 100644 --- a/main.lua +++ b/main.lua @@ -1,29 +1,78 @@ local love = assert( love, "This tool requires LOVE: love2d.org" ) local map = require 'map' local SAVEDIRECTORY = "out/" +local Camera = require 'camera' +local wasKeyPressed function love.load() + local lfs = assert( love.filesystem ) lfs.setIdentity( "dcearth", false ) assert( lfs.createDirectory( SAVEDIRECTORY.."data/earth" )) assert( lfs.createDirectory( SAVEDIRECTORY.."data/graphics" )) map.load() + + + love.graphics.setNewFont( 12, "mono" ) end -local canvas = love.graphics.newCanvas() function love.update( dt ) - love.graphics.setCanvas( canvas ) - map.draw() - love.graphics.setCanvas() + local tx, ty = 0, 0 + local moveCamera = false + if love.keyboard.isScancodeDown( "w" ) then moveCamera = true; ty = ty + 1 end + if love.keyboard.isScancodeDown( "a" ) then moveCamera = true; tx = tx - 1 end + if love.keyboard.isScancodeDown( "s" ) then moveCamera = true; ty = ty - 1 end + if love.keyboard.isScancodeDown( "d" ) then moveCamera = true; tx = tx + 1 end + if moveCamera then Camera.Translate( tx, ty ) end + + end + function love.draw() - love.graphics.draw( canvas ) + love.graphics.push( "all" ) + map.draw() + love.graphics.pop() + + --Status bar. + local x, y = love.mouse.getPosition() + local wx, wy = Camera.GetWorldCoordinate( x, y ) + local h = love.graphics.getHeight() - 30 + love.graphics.setColor( 0.2, 0.1, 0.1, 0.5 ) + love.graphics.rectangle( "fill", 0, h, love.graphics.getWidth() / 2, 30 ) + love.graphics.setColor( 1, 1, 1, 1 ) + love.graphics.rectangle( "line", 0, h, love.graphics.getWidth() / 2, 30 ) + love.graphics.print(("SCREEN\t%d\t%d\nWORLD \t%5.2f\t%5.2f"):format(x, y, wx, wy), 0, h) + + --Edit box. + love.graphics.rectangle( "line", love.graphics.getWidth() / 2, h, love.graphics.getWidth() / 2, 30 ) + if map.cities.selectedCity then + local c = map.cities.selectedCity + 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 ) + end +end + +function love.resize(w, h) + Camera.Resize( w, h ) +end + +function love.wheelmoved(x, y) + Camera.Zoom( (y > 0) and true or false ) +end + +function love.mousepressed( x, y, button, istouch, presses ) + local wx, wy = Camera.GetWorldCoordinate( x, y ) + print( ("MOUSE\tx %f\ty %f\twx %f\twy %f"):format(x, y, wx, wy) ) +end + +function love.mousemoved( x, y, dx, dy, istouch ) + map.cities.selectNearestCity( Camera.GetWorldCoordinate( x, y ) ) end function love.keypressed(key) - if key == "s" then + if key == "l" then -- To open a file or folder, "file://" must be prepended to the path. love.system.openURL("file://"..love.filesystem.getSaveDirectory()) end + wasKeyPressed = true end diff --git a/map.lua b/map.lua index a08fd9a..c483f55 100644 --- a/map.lua +++ b/map.lua @@ -1,7 +1,9 @@ local lg = love.graphics local Cities = require 'cities' local Lines = require 'lines' +local Nodes = require 'nodes' local Bitmap = require 'bmp' +local Camera = require 'camera' local map = { coastlines = false, @@ -26,41 +28,49 @@ function map.load() map.coastlines = Lines.load( "data/earth/coastlines.dat" ) map.coastlinesLow = Lines.load( "data/earth/coastlines-low.dat" ) map.international = Lines.load( "data/earth/international.dat" ) + map.travelnodes = Nodes.load( "data/earth/travel_nodes.bmp" ) end function map.draw() lg.clear( 0, 0, 0, 1 ) do --all this stuff is drawn in world coordinates, ( -180, 180 ) x ( -100, 100 ) - lg.push( "transform" ) - lg.scale( lg.getCanvas():getDimensions() ) - lg.scale( 1 / 360, - 1 / 200 ) - lg.translate( 180, -100 ) - - + + lg.replaceTransform( Camera.tf ) do --points lg.setColor( 1, 0, 0, 0.5 ) - lg.setPointSize( 2 ) - map.cities:draw() + lg.setPointSize( 0.5 * Camera.zoom ) + map.cities.draw() - lg.setColor( 1, 0, 0, 1.0 ) - lg.setPointSize( 4 ) - map.cities:drawCapitals() + lg.setColor( 1, 1, 1.0, 0.5 ) + lg.setPointSize( 1.0 * Camera.zoom ) + map.cities.drawCapitals() + + lg.setColor( 1, 0, 1, 0.5 ) + map.cities.drawSelected( 22.0 / Camera.zoom ) end do --line stuff lg.setColor(1, 1, 1, 0.2 ) - lg.setLineWidth( 0.2 ) + + lg.setLineJoin( "miter" ) + lg.setLineWidth( 0.2 / Camera.zoom ) map.international:draw() - lg.setColor(1, 1, 1, 1 ) - lg.setLineWidth( 0.3 ) + lg.setColor(1, 1, 1, 0.5 ) map.coastlines:draw() map.coastlinesLow:draw() + + --International Date Line + lg.line( -180, -100, -180, 100 ) + lg.line( 180, -100, 180, 100 ) + lg.line( -180, 90, 180, 90 ) + lg.line( -180, -90, 180, -90 ) + lg.line( -180, 100, 180, 100 ) + lg.line( -180, -100, 180, -100 ) end - lg.pop( ) end end diff --git a/nodes.lua b/nodes.lua index f42e45c..30cbc19 100644 --- a/nodes.lua +++ b/nodes.lua @@ -1,7 +1,29 @@ --Manage the pathfinding nodes used by DEFCON. --This is important for a mapping tool because the DEFCON client will not load a map unless --the pathfinding nodes form a connected graph. -local nodes = {} +local t = {} +local bmp = require 'bmp' +function t.load( filename ) + local nodes = { points = {}, connections = {}, img = bmp.load( filename ) } + + return setmetatable( nodes, {__index = t } ) +end -return nodes \ No newline at end of file +function t.isConnected( nodes ) + +end + +function t.draw( nodes ) + +end + +function t.drawConnections( nodes ) + +end + +function t.save( nodes, filename ) + +end + +return t \ No newline at end of file diff --git a/scratch.lua b/scratch.lua new file mode 100644 index 0000000..39c2b53 --- /dev/null +++ b/scratch.lua @@ -0,0 +1,2 @@ +local jit = require 'jit' +for k, v in pairs( jit.opt ) do print(k , v ) end \ No newline at end of file diff --git a/territory.lua b/territory.lua new file mode 100644 index 0000000..5d79516 --- /dev/null +++ b/territory.lua @@ -0,0 +1,42 @@ +local t = {} +local bmp = require 'bmp' + +function t.load( filename, name ) + local territory = { img = bmp.load( filename ) } + return setmetatable( territory, {__index = t } ) +end + +--World space coordinate. +function t.isValid( x, y ) + +end + +function t.getPixel( territory, x, y ) + --ZERO INDEXED + return territory.img[math.floor( 512 * ( x + 180 ) / 360 ) ][ math.floor( 285 * ( y + 100 ) / 200 ) ] +end + +--[[ +0 +20 -- once sailable.bmp is brighter than this, the area is traversable by ships +60 -- once sailable.bmp and territory.bmp are brighter than this, ships can be placed here +130 -- if territory.bmp is brighter than this and sailable is darker than 60, structures are placeable. + +SO: + SAILABLE: 0 (not), 21 (traverse not place), 61 ( traverse and place ) + TERRITORY: 131 ( place land if sailable <= 60 ), 61 ( place sea ), 0 +]] + +function t.draw( nodes ) + +end + +function t.drawConnections( nodes ) + +end + +function t.save( nodes, filename ) + +end + +return t \ No newline at end of file