Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require("lovedebug")
- local gamera = require "gamera" -- camera modifier, important.
- local lume = require "lume" -- Useful functions, mostly random table stuff.
- local flux = require "flux" -- Animations and tweening
- local timer = require "hump.timer" -- obviously used for timers. Simple and functional.
- -- general variables
- math.randomseed(os.time()) -- makes things actually random. Super useful line.
- local mainWidth, mainHeight = love.graphics.getDimensions() -- grabs the screen dimensions. Useful.
- local modeNum = 1 -- technical variable, controls modeName.
- local modeName -- the string name of the current mode. locate mouseModeSwitch() to see list.
- local preload = true
- -- grid variables
- local grid = {} -- stores the entire grid
- local initGrid = true -- initializes the "invisible" grid coords into tGrid.
- local gridPos = {}
- local mouseGridX, mouseGridY = nil, nil -- keep nil, not empty. Some code relies on ensuring these have values and will crash otherwise.
- local loadedTiles = {}
- local gridSizeX, gridSizeY = 50, 50 -- grid size. Likely keep 50,50. Maybe change based on planet size and other things later, like certain techs.
- local terrain = {} -- placed tiles
- local gridValuesLoaded = false
- local initialPlacement = true -- waits for the initial tile placement.
- local debugGrid = false -- controls whether or not the grid is visible.
- -- screen variables
- local moveVariable = 50 -- the initial moving speed for WASD movement.
- local screenScale = 1 -- set the initial zoom to 1x
- -- soul variables
- local playerList = {}
- local interactDist = 3 -- how far they can check when pathfinding
- -- pathfinding variables
- local xPathSign, yPathSign = "none" -- whether to go up or down with signs
- local testPath = {}
- local path = {} -- the real path to take
- local function screenSize() -- setup the gamera world based upon the current grid.
- sWidth, sHeight = (gridSizeX * 64)*1.25, (gridSizeY * 64)*1.25 -- calculate the size taken by full pixels, modified to look nice on edges. (25% increase)
- xTop = 0 -- start at 0, don't head negative. Makes things difficult.
- xBot = sHeight -- modified height from above equation.
- yTop = 0
- yBot = sWidth
- cam = gamera.new(xTop,yTop,xBot,yBot)
- left, top, width, height = cam:getWorld() -- width = right, height = bottom
- startX, startY = sWidth/2, sHeight/2
- cam:setPosition(startX, startY) -- set the center point of the camera to the center of the world.
- end
- local function gridLoad() -- creates a [x][y] format numbered list to iterate and assign variables to (keep first, everything relies upon this)
- if preload then
- for x=1, gridSizeX do
- grid[x] = {}
- for y=1, gridSizeY do
- grid[x][y] = { x = 0, y = 0, img = "none"}
- if x == gridSizeX and y == gridSizeY then
- preload = false
- end
- end
- end
- end
- end
- local function mouseModeSwitch() -- detects when you hit the mode key, triggers only once, and changes modeName to the proper variable.
- function love.keypressed(key)
- if key == "m" then -- mode cycle. move to something easier on release.
- if modeNum < 3 then -- # == number of available modes, listed at bottom of this function.
- modeNum = modeNum + 1
- else
- modeNum = 1
- end
- elseif key == "o" then -- testing key for values. Remove in public releases.
- debugGrid = true
- elseif key == "p" then -- testing key for values. Remove in public releases.
- debugGrid = false
- elseif key == "t" then -- testing key for values. Remove in public releases.
- end
- end
- if modeNum == 1 then
- modeName = "land"
- elseif modeNum == 2 then
- modeName = "souls"
- elseif modeNum == 3 then
- modeName = "build"
- end
- end
- local function screenMove(dt) -- allows the use of WASD and arrow keys for screen movement.
- local camXPos, camYPos = cam:getPosition() -- finds the center of the visible screen, tracks boundaries.
- local moveMin = 50 -- the minimum movement speed. Tweak as needed.
- local moveMax = 300 -- the max movement speed. Tweak as needed.
- if love.keyboard.isDown('w') then
- if moveVariable < moveMax then -- if the current movement speed is under the maximum, go down a line and increase it by 1 every delta frame.
- moveVariable = moveVariable + 1
- end
- if love.keyboard.isDown('a') then
- cam:setPosition(camXPos - moveVariable * dt, camYPos - moveVariable * dt) -- detect if another specified key is being pressed at the same time as W.
- elseif love.keyboard.isDown('d') then
- cam:setPosition(camXPos + moveVariable * dt, camYPos - moveVariable * dt)
- else
- cam:setPosition(camXPos, camYPos - moveVariable * dt) -- changes the position based upon moveVariable and delta time to run similarly on all systems.
- end
- elseif love.keyboard.isDown('s') then -- keep 'w' and 's' first, so they trigger first. keeps it from having to run every option, keep it as the two main directions.
- if moveVariable < moveMax then
- moveVariable = moveVariable + 1
- end
- if love.keyboard.isDown('a') then
- cam:setPosition(camXPos - moveVariable * dt, camYPos + moveVariable * dt)
- elseif love.keyboard.isDown('d') then
- cam:setPosition(camXPos + moveVariable * dt, camYPos + moveVariable * dt)
- else
- cam:setPosition(camXPos, camYPos + moveVariable * dt)
- end
- elseif love.keyboard.isDown('d') then
- if moveVariable < moveMax then
- moveVariable = moveVariable + 1
- end
- cam:setPosition(camXPos + moveVariable * dt, camYPos)
- elseif love.keyboard.isDown('a') then
- if moveVariable < moveMax then
- moveVariable = moveVariable + 1
- end
- cam:setPosition(camXPos - moveVariable * dt, camYPos)
- elseif love.keyboard.isDown('c') then -- center the camera.
- cam:setPosition(sWidth/2, sHeight/2)
- else
- if moveVariable > moveMin then
- moveVariable = moveVariable - 5 -- ensures the movement doesn't come to a full stop, it'll ease back down.
- end
- end
- end
- local function screenZoom()
- function love.wheelmoved(x, y) -- records mouse wheel movement. Possibly add a keypress to this later.
- scaleMin = .6 -- minimum zoom
- scaleMax = 2.4 -- maximum zoom
- if y > 0 then -- mouse wheel forward. wheel moved returns a positive or negative value.
- if scaleMax > screenScale then
- screenScale = screenScale + 0.2 -- modifies screenScale with every wheel movement.
- cam:setScale(screenScale)
- end
- elseif y < 0 then
- if scaleMin < screenScale then
- screenScale = screenScale - 0.2
- cam:setScale(screenScale)
- end
- end
- end
- end
- local function visualAssets() -- loads in all the visual assets (only in a function for organization).
- tileg1 = love.graphics.newImage('assets/grass1.png')
- tilegrid = love.graphics.newImage('assets/grid.png')-- first grass texture caching
- playerex = love.graphics.newImage('assets/ExamplePlayer.png')
- farmerex = love.graphics.newImage('assets/farmer.png')
- debugtile = love.graphics.newImage('assets/fulltile.png')
- block_width = tileg1:getWidth()
- block_height = tileg1:getHeight()
- block_depth = tileg1:getHeight()/2 -- the height of the back of the block
- end
- function love.load()
- small = love.graphics.newFont(8) -- differently sized fonts. May have to modify for localization later.
- medium = love.graphics.newFont(12)
- large = love.graphics.newFont(16)
- love.graphics.setDefaultFilter( 'nearest', 'nearest' ) -- keeps things from being blurry when zooming.
- screenSize() -- sets the screen size in accordance to the function.
- visualAssets() -- loads in all the visual assets.
- end
- local function mousePos()
- local x, y = love.mouse.getPosition()
- xM, yM = cam:toWorld(math.floor(x),math.floor(y))
- end
- local function closestPoint () -- assigns the closest point (modified) to mouseGridX/Y.
- local gridCompare = 25 -- how many pixels out constitutes association.
- for xMi = 1, gridSizeX do
- for yMi = 1, gridSizeY do
- if xM - gridCompare <= grid[xMi][yMi].x and grid[xMi][yMi].x <= xM + gridCompare then
- if yM - gridCompare <= grid[xMi][yMi].y and grid[xMi][yMi].y <= yM + gridCompare then
- mouseGridX, mouseGridY = xMi, yMi -- the minus 1 is due to the size of the texture, not a code glitch. Work around this.
- return
- end
- end
- end
- end
- end
- function love.update(dt)
- gridLoad() -- create the listings within tGrid
- mouseModeSwitch() -- Change the mouse mode.
- screenMove(dt) -- WASD
- screenZoom() -- Zooming
- mousePos() -- locate and record mouse world positions.
- closestPoint() -- tracks the closest grid location.
- end
- local function gridXY() -- optionally draw the grid points, record their world x and y as values attached to the grid[x][y] function.
- if preload == false then -- after the grid loading function finishes
- love.graphics.setFont(small)
- for x = 1,gridSizeX do -- iterate over #gridSizeX in tGrid, same for Y. Will record over every possible value.
- for y = 1,gridSizeY do
- gridX = (sWidth/2) -- find world width
- gridY = (sHeight/2) -- find world height
- if debugGrid then
- love.graphics.print((x.." "..y), gridX + ((y-x) * (block_width / 2)), gridY + ((x+y) * (block_depth / 2)) - (block_depth * (gridSizeY / 2))) -- this and next 2 lines are optional, draws grid
- love.graphics.setColor(255,255,255)
- love.graphics.circle("fill", gridX + ((y-x) * (block_width / 2)), gridY + ((x+y) * (block_depth / 2)) - (block_depth * (gridSizeY / 2)), 2.5, 25)
- end
- grid[x][y] = {x = (gridX + ((y-x) * (block_width / 2))), -- add x value to [x][y].x
- y = (gridY + ((x+y) * (block_depth / 2)) - (block_depth * (gridSizeY / 2))), -- add y value to [x][y].y
- t = "none"} -- add a terrain value to grid
- end
- end
- end
- end
- local function plotCheck(plotA) -- checks to see if a plot is occupied, and if so, by what.
- for i, plotB in ipairs(terrain) do
- if plotA.x == plotB.x and plotA.y == plotB.y then -- if there is a matching tile in terrain, move on
- if plotA.img == tileg1 then -- remember to change this based upon the grass tile's name! (if current tile is grass, move)
- if plotB.img == tilegrid then -- if placed tile is grid, move on.
- plotB.img = tileg1 -- change grid to grass
- return false -- uhh, look into.
- end
- else
- return false -- just a catch if current tile isn't grass.
- end
- end
- end
- end
- local function gridCheck (gridX, gridY) -- checks to see if there's a grid (for use with tilePlacement())
- for i, plotB in ipairs(terrain) do
- if grid[gridX][gridY].x - 32 == plotB.x and grid[gridX][gridY].y - 16 == plotB.y then
- if plotB.img ~= tilegrid then
- --print("wasn't grid")
- return false, "grid"
- elseif plotB.img == tilegrid then
- return true
- end
- else
- --print("no tiles around")
- end
- end
- return false
- end
- local function tilePlacement (mGridX, mGridY) -- places the "star pattern" around any terrain.
- if not initialPlacement then -- initial tiles have been placed.
- if gridCheck(mGridX, mGridY) == false then
- --print("not a grid")
- return false
- end
- end
- if mGridX ~= 1 then--mGridY ~= 1 and mGridX ~= 1 then -- to ensure that these pieces aren't placed if they're on the edge.
- terrain1 = {img = tilegrid, x = grid[mGridX - 1][mGridY - 0].x - 32, y = grid[mGridX - 1][mGridY - 0].y - 16, imgN = "tilegrid"} -- top right -> ^
- grid[mGridX - 1][mGridY - 0].img = "tilegrid"
- if plotCheck(terrain1) ~= false and mGridX ~= 1 then
- table.insert(terrain, terrain1)
- end
- end
- if mGridY ~= 1 then
- terrain2 = {img = tilegrid, x = grid[mGridX - 0][mGridY - 1].x - 32, y = grid[mGridX - 0][mGridY - 1].y - 16, imgN = "tilegrid"} -- top left <- ^
- grid[mGridX - 0][mGridY - 1].img = "tilegrid"
- if plotCheck(terrain2) ~= false then
- table.insert(terrain, terrain2)
- end
- end
- terrain3 = {img = tileg1, x = grid[mGridX][mGridY].x - 32, y = grid[mGridX][mGridY].y - 16, imgN = "tileg1"} -- middle--print(grid[25][25].x.." "..grid[25][25].y)
- grid[mGridX][mGridY].img = "tileg1"
- if plotCheck(terrain3) ~= false then
- table.insert(terrain, terrain3)
- end
- if mGridX ~= gridSizeX then
- terrain4 = {img = tilegrid, x = grid[mGridX + 1][mGridY + 0].x - 32, y = grid[mGridX + 1][mGridY + 0].y - 16, imgN = "tilegrid"} -- bottom left <- v
- grid[mGridX + 1][mGridY - 0].img = "tilegrid"
- if plotCheck(terrain4) ~= false then
- table.insert(terrain, terrain4)
- end
- end
- if mGridY ~= gridSizeY then
- terrain5 = {img = tilegrid, x = grid[mGridX + 0][mGridY + 1].x - 32, y = grid[mGridX + 0][mGridY + 1].y - 16, imgN = "tilegrid"} -- bottom right -> v
- grid[mGridX - 0][mGridY + 1].img = "tilegrid"
- if plotCheck(terrain5) ~= false then
- table.insert(terrain, terrain5)
- end
- end
- end
- function love.mousepressed(x, y, button, istouch) -- the singular mouse-detection function. Handles everything from UI to building.
- if mouseGridX and mouseGridY ~= nil then
- if button == 1 then
- if modeName == "land" then
- print("Land-ho!"..modeName)
- tilePlacement(mouseGridX, mouseGridY)
- return
- end
- end
- end
- end
- local function sortDrawTerrain() -- ensures that lower tiles overlap higher tiles, then draws the tiles.
- local function ySorting (a, b )
- return a.y < b.y
- end
- table.sort(terrain, ySorting)
- for i, plot in ipairs(terrain) do -- draws the terrain
- if modeName == "land" then -- draw everything.
- love.graphics.draw(plot.img, plot.x, plot.y)
- else
- if plot.img ~= tilegrid then -- if not land mode, exclude grids from being drawn.
- love.graphics.draw(plot.img, plot.x, plot.y)
- end
- end
- end
- end
- local function initialPlace() -- place the initial tiles in the center of the map.
- if initialPlacement then
- tilePlacement(gridSizeX/2,gridSizeY/2)
- initialPlacement = false
- end
- end
- local function pathFinder(startGrX, startGrY, finishGrX, finishGrY) -- the pathfinding module. Much of this is still on paper, and hasn't actually been created due to not knowing how to transmit the info
- local startX, startY, finishX, finishY = grid[startGrX][startGrY].x, grid[startGrX][startGrY].y, grid[finishGrX][finishGrY].x, grid[finishGrX][finishGrY].y -- get the actual x,y coords
- local xTiles, yTiles = finishGrX - startGrX, finishGrY - startGrY
- if lume.sign(xTiles) == 1 then
- xPathSign = "add" -- head down v
- else
- xPathSign = "sub" -- head up ^ (negative number found)
- end
- if lume.sign(yTiles) == 1 then
- yPathSign = "add"
- else
- yPathSign = "sub"
- end
- end -- find difference between start and finish, find if it's positive or negative, attempt to ease the way through by iterating through terrain, and finding if there's a possible connection.
- function love.draw(dt) -- place anything screen locked outside of cam:draw, preferably below so it loads sooner.
- cam:draw(function(l,t,w,h) -- gamera world locked.
- gridXY() -- record .x and .y into tGrid
- sortDrawTerrain()
- initialPlace()
- end)
- love.graphics.setFont(medium)
- love.graphics.print("Use 'm' to cycle the mode. Currently: "..modeName, 5, 5) -- temporary way to visualize the current mode
- love.graphics.print("Use 'WASD' to move the camera, 'c' to center it", 5, 20) -- temporary way to visualize the current mode
- love.graphics.print("Your current zoom level is "..screenScale.."x", 5, 35) -- temporary way to visualize the current mode
- love.graphics.print("Your mouse coords are: "..math.floor(xM).." "..math.floor(yM), 5, 50) -- temporary way to visualize the current mode
- if mouseGridX ~= nil then
- love.graphics.print("The closest point is "..mouseGridX..","..mouseGridY, 5, 65) -- temporary way to visualize the current position on the grid
- if grid[mouseGridX][mouseGridY].img ~= nil then
- love.graphics.print("The closest point's image is "..grid[mouseGridX][mouseGridY].img, 5, 80) -- temporary way to visualize the current tile's image
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment