created better map and tweaked player movement
This commit is contained in:
parent
a709e4f1c4
commit
6ae7e3b1a4
@ -3,6 +3,7 @@ function love.conf(t)
|
||||
|
||||
t.console = true
|
||||
|
||||
t.window.width = 854
|
||||
t.window.height = 480
|
||||
t.window.resizable = true
|
||||
t.window.width = 640 * 2
|
||||
t.window.height = 360 * 2
|
||||
end
|
||||
|
138
src/lib/center.lua
Normal file
138
src/lib/center.lua
Normal file
@ -0,0 +1,138 @@
|
||||
--[[
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Semyon Entsov <swalrus@yandex.ru>
|
||||
|
||||
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 center = {}
|
||||
|
||||
function center:setupScreen(width, height)
|
||||
self._WIDTH = width
|
||||
self._HEIGHT = height
|
||||
self._MAX_WIDTH = 0
|
||||
self._MAX_HEIGHT = 0
|
||||
self._MAX_RELATIVE_WIDTH = 0
|
||||
self._MAX_RELATIVE_HEIGHT = 0
|
||||
self._SCREEN_WIDTH = love.graphics.getWidth()
|
||||
self._SCREEN_HEIGHT = love.graphics.getHeight()
|
||||
self._BORDERS = {
|
||||
['t'] = 0,
|
||||
['r'] = 0,
|
||||
['b'] = 0,
|
||||
['l'] = 0
|
||||
}
|
||||
self:apply()
|
||||
return self
|
||||
end
|
||||
|
||||
function center:setBorders(top, right, bottom, left)
|
||||
self._BORDERS.t = top
|
||||
self._BORDERS.r = right
|
||||
self._BORDERS.b = bottom
|
||||
self._BORDERS.l = left
|
||||
end
|
||||
|
||||
function center:getScale()
|
||||
return self._SCALE
|
||||
end
|
||||
|
||||
function center:getOffsetX()
|
||||
return self._OFFSET_X
|
||||
end
|
||||
|
||||
function center:getOffsetY()
|
||||
return self._OFFSET_Y
|
||||
end
|
||||
|
||||
function center:setMaxWidth(width)
|
||||
self._MAX_WIDTH = width
|
||||
end
|
||||
|
||||
function center:setMaxHeight(height)
|
||||
self._MAX_HEIGHT = height
|
||||
end
|
||||
|
||||
function center:setMaxRelativeWidth(width)
|
||||
self._MAX_RELATIVE_WIDTH = width
|
||||
end
|
||||
|
||||
function center:setMaxRelativeHeight(height)
|
||||
self._MAX_RELATIVE_HEIGHT = height
|
||||
end
|
||||
|
||||
function center:resize(width, height)
|
||||
self._SCREEN_WIDTH = width
|
||||
self._SCREEN_HEIGHT = height
|
||||
self:apply()
|
||||
end
|
||||
|
||||
function center:apply()
|
||||
local available_width = self._SCREEN_WIDTH - self._BORDERS.l - self._BORDERS.r
|
||||
local available_height = self._SCREEN_HEIGHT - self._BORDERS.t - self._BORDERS.b
|
||||
local max_width = available_width
|
||||
local max_height = available_height
|
||||
if self._MAX_RELATIVE_WIDTH > 0 and available_width * self._MAX_RELATIVE_WIDTH < max_width then
|
||||
max_width = available_width * self._MAX_RELATIVE_WIDTH
|
||||
end
|
||||
if self._MAX_RELATIVE_HEIGHT > 0 and available_height * self._MAX_RELATIVE_HEIGHT < max_height then
|
||||
max_height = available_height * self._MAX_RELATIVE_HEIGHT
|
||||
end
|
||||
if self._MAX_WIDTH > 0 and self._MAX_WIDTH < max_width then
|
||||
max_width = self._MAX_WIDTH
|
||||
end
|
||||
if self._MAX_HEIGHT > 0 and self._MAX_HEIGHT < max_height then
|
||||
max_height = self._MAX_HEIGHT
|
||||
end
|
||||
if max_height / max_width > self._HEIGHT / self._WIDTH then
|
||||
self._CANVAS_WIDTH = max_width
|
||||
self._CANVAS_HEIGHT = self._CANVAS_WIDTH * (self._HEIGHT / self._WIDTH)
|
||||
else
|
||||
self._CANVAS_HEIGHT = max_height
|
||||
self._CANVAS_WIDTH = self._CANVAS_HEIGHT * (self._WIDTH / self._HEIGHT)
|
||||
end
|
||||
self._SCALE = self._CANVAS_HEIGHT / self._HEIGHT
|
||||
self._OFFSET_X = self._BORDERS.l + (available_width - self._CANVAS_WIDTH) / 2
|
||||
self._OFFSET_Y = self._BORDERS.t + (available_height - self._CANVAS_HEIGHT) / 2
|
||||
end
|
||||
|
||||
function center:start()
|
||||
love.graphics.push()
|
||||
love.graphics.translate(self._OFFSET_X, self._OFFSET_Y)
|
||||
love.graphics.scale(self._SCALE, self._SCALE)
|
||||
end
|
||||
|
||||
function center:finish()
|
||||
love.graphics.pop()
|
||||
end
|
||||
|
||||
function center:toGame(x, y, w, h)
|
||||
if not (self._OFFSET_X and self._OFFSET_Y and self._SCALE) then
|
||||
return x, y, w, h
|
||||
end
|
||||
|
||||
return (x - self._OFFSET_X) / self._SCALE,
|
||||
(y - self._OFFSET_Y) / self._SCALE,
|
||||
w and w / self._SCALE,
|
||||
h and h / self._SCALE
|
||||
end
|
||||
|
||||
return center
|
||||
|
@ -1,7 +1,11 @@
|
||||
local Gamestate = require("lib.hump.gamestate")
|
||||
local ScreenScaler = require("screen-scaler")
|
||||
pprint = require("lib.pprint")
|
||||
|
||||
PLAYER_SIZE = 20
|
||||
PLAYER_SIZE = 10
|
||||
|
||||
-- 640 x 360
|
||||
ScreenScaler.setVirtualDimensions(16 * 40, 9 * 40)
|
||||
|
||||
function love.load()
|
||||
love.math.setRandomSeed(love.timer.getTime())
|
||||
|
232
src/screen-scaler.lua
Normal file
232
src/screen-scaler.lua
Normal file
@ -0,0 +1,232 @@
|
||||
--- Module resposible for scaling screen and centering contents
|
||||
-- while respecting ratios.
|
||||
-- @module ScreenScaler
|
||||
local ScreenScaler = {}
|
||||
|
||||
-- This "Center" library will do most of the heavy lifting
|
||||
-- TODO: Removed this depedency, embed needed functionality
|
||||
local Center = require("lib.center")
|
||||
|
||||
local getRealDimensions = love.graphics.getDimensions
|
||||
|
||||
--- Set the "ideal" dimensions from which everything else will be scaled.
|
||||
-- @tparam number w virtual width
|
||||
-- @tparam number h virtual height
|
||||
function ScreenScaler.setVirtualDimensions(w, h)
|
||||
assert(type(w) == "number", "Expected width to be number")
|
||||
assert(type(h) == "number", "Expected height to be number")
|
||||
ScreenScaler.width, ScreenScaler.height = nil, nil
|
||||
|
||||
-- Setup library resposible for scaling the screen
|
||||
Center:setupScreen(w, h)
|
||||
|
||||
ScreenScaler.width, ScreenScaler.height = w, h
|
||||
end
|
||||
|
||||
--- Unsets virtual dimensions. Effectively disables scaler.
|
||||
function ScreenScaler.unsetVirtualDimensions()
|
||||
ScreenScaler.width = nil
|
||||
ScreenScaler.height = nil
|
||||
end
|
||||
|
||||
--- Get virtual dimensions.
|
||||
-- @return width, height
|
||||
function ScreenScaler.getVirtualDimensions()
|
||||
return ScreenScaler.width, ScreenScaler.height
|
||||
end
|
||||
|
||||
--- Returns true if scaler is enabled.
|
||||
-- @treturn boolean
|
||||
function ScreenScaler.isEnabled()
|
||||
return ScreenScaler.width ~= nil
|
||||
end
|
||||
|
||||
-- Overwrite default love.mouse functions to return position
|
||||
-- relative to scaled window
|
||||
do
|
||||
local getX = love.mouse.getX
|
||||
function love.mouse.getX()
|
||||
local x = getX()
|
||||
if not ScreenScaler.isEnabled() then
|
||||
return x
|
||||
end
|
||||
return (x - Center:getOffsetX()) / Center:getScale()
|
||||
end
|
||||
|
||||
local getY = love.mouse.getY
|
||||
function love.mouse.getY()
|
||||
local y = getY()
|
||||
if not ScreenScaler.isEnabled() then
|
||||
return y
|
||||
end
|
||||
return (y - Center:getOffsetY()) / Center:getScale()
|
||||
end
|
||||
|
||||
local getPosition = love.mouse.getPosition
|
||||
function love.mouse.getPosition()
|
||||
if ScreenScaler.isEnabled() then
|
||||
return Center:toGame(getPosition())
|
||||
else
|
||||
return getPosition()
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: add replacements for setX, setY, setPosition
|
||||
end
|
||||
|
||||
-- Overwrite default getDimensions, getWidth, getHeight
|
||||
-- to return virtual width and height if scaler is enabled
|
||||
do
|
||||
local getWidth = love.graphics.getWidth
|
||||
function love.graphics.getWidth()
|
||||
return ScreenScaler.width or getWidth()
|
||||
end
|
||||
|
||||
local getHeight = love.graphics.getHeight
|
||||
function love.graphics.getHeight()
|
||||
return ScreenScaler.height or getHeight()
|
||||
end
|
||||
|
||||
function love.graphics.getDimensions()
|
||||
return love.graphics.getWidth(), love.graphics.getHeight()
|
||||
end
|
||||
end
|
||||
|
||||
-- Adjust setScissor and intersectScissor function, so that they are relative
|
||||
-- to the scaled screen. By default these functions are unaffected by transformations
|
||||
do
|
||||
local setScissor = love.graphics.setScissor
|
||||
function love.graphics.setScissor(x, y, w, h)
|
||||
if x and ScreenScaler.isEnabled() then
|
||||
setScissor(Center:toGame(x, y, w, h))
|
||||
else
|
||||
setScissor(x, y, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
local intersectScissor = love.graphics.intersectScissor
|
||||
function love.graphics.intersectScissor(x, y, w, h)
|
||||
if x and ScreenScaler.isEnabled() then
|
||||
intersectScissor(Center:toGame(x, y, w, h))
|
||||
else
|
||||
intersectScissor(x, y, w, h)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function isInBounds(x, y)
|
||||
if not ScreenScaler.isEnabled() then return true end
|
||||
local w, h = ScreenScaler.getVirtualDimensions()
|
||||
return x >= 0 and x < w and y >= 0 and y < h
|
||||
end
|
||||
|
||||
-- Create event proccessors for converting normal screen coordinates
|
||||
-- to scaled screen coordinates
|
||||
-- If the user clicked out of bounds, it will not handled
|
||||
local eventPreProccessor = {}
|
||||
function eventPreProccessor.mousepressed(x, y, button, istouch, presses)
|
||||
x, y = Center:toGame(x, y)
|
||||
return isInBounds(x, y), x, y, button, istouch, presses
|
||||
end
|
||||
|
||||
function eventPreProccessor.mousereleased(x, y, button, istouch, presses)
|
||||
x, y = Center:toGame(x, y)
|
||||
return isInBounds(x, y), x, y, button, istouch, presses
|
||||
end
|
||||
|
||||
function eventPreProccessor.mousemoved(x, y, dx, dy, istouch)
|
||||
local scale = Center:getScale()
|
||||
x, y = Center:toGame(x, y)
|
||||
dx, dy = dx / scale, dy / scale
|
||||
return isInBounds(x, y), x, y, dx, dy, istouch, istouch
|
||||
end
|
||||
|
||||
function eventPreProccessor.wheelmoved(x, y)
|
||||
return isInBounds(love.mouse.getPosition()), x, y
|
||||
end
|
||||
|
||||
local function hideOutOfBounds()
|
||||
local r, g, b, a = love.graphics.getColor()
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
local w, h = getRealDimensions()
|
||||
|
||||
if Center._OFFSET_X ~= 0 then
|
||||
love.graphics.rectangle("fill", 0, 0, Center._OFFSET_X, h)
|
||||
love.graphics.rectangle("fill", Center._WIDTH*Center._SCALE+Center._OFFSET_X, 0, Center._OFFSET_X, h)
|
||||
end
|
||||
|
||||
if Center._OFFSET_Y ~= 0 then
|
||||
love.graphics.rectangle("fill", 0, 0, w, Center._OFFSET_Y)
|
||||
love.graphics.rectangle("fill", 0, Center._HEIGHT*Center._SCALE+Center._OFFSET_Y, w, Center._OFFSET_Y)
|
||||
end
|
||||
|
||||
love.graphics.setColor(r, g, b, a)
|
||||
end
|
||||
|
||||
-- Modify core game loop so that if scaler is enabled:
|
||||
-- * resize events are not handled
|
||||
-- * out of bounds mouse events are not handled
|
||||
-- * all drawing operations are centered
|
||||
function love.run()
|
||||
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
|
||||
|
||||
-- We don't want the first frame's dt to include time taken by love.load.
|
||||
if love.timer then love.timer.step() end
|
||||
|
||||
local dt = 0
|
||||
|
||||
-- Main loop time.
|
||||
return function()
|
||||
-- Process events.
|
||||
if love.event then
|
||||
love.event.pump()
|
||||
for name, a,b,c,d,e,f in love.event.poll() do
|
||||
if name == "quit" then
|
||||
if not love.quit or not love.quit() then
|
||||
return a or 0
|
||||
end
|
||||
end
|
||||
|
||||
if ScreenScaler.isEnabled() then
|
||||
if name == "resize" then
|
||||
Center:resize(a, b)
|
||||
goto continue
|
||||
elseif eventPreProccessor[name] then
|
||||
local success
|
||||
success, a, b, c, d, e, f = eventPreProccessor[name](a, b, c, d, e, f)
|
||||
if not success then goto continue end
|
||||
end
|
||||
end
|
||||
love.handlers[name](a, b, c, d, e, f)
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
|
||||
-- Update dt, as we'll be passing it to update
|
||||
if love.timer then dt = love.timer.step() end
|
||||
|
||||
-- Call update and draw
|
||||
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
|
||||
|
||||
if love.graphics and love.graphics.isActive() then
|
||||
love.graphics.origin()
|
||||
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||
|
||||
if love.draw then
|
||||
if ScreenScaler.isEnabled() then
|
||||
Center:start()
|
||||
love.draw()
|
||||
Center:finish()
|
||||
else
|
||||
love.draw()
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.present()
|
||||
end
|
||||
|
||||
if love.timer then love.timer.sleep(0.001) end
|
||||
end
|
||||
end
|
||||
|
||||
return ScreenScaler
|
@ -6,7 +6,7 @@ local rgb = require("helpers.rgb")
|
||||
local lerp = require("lib.lume").lerp
|
||||
local BoltMods = require("bolt-mods")
|
||||
|
||||
local BOLT_DIST_FROM_PLAYER = 40
|
||||
local BOLT_DIST_FROM_PLAYER = PLAYER_SIZE*2
|
||||
local BOLT_SIZE = 4
|
||||
|
||||
local DRAW_COLLIDERS = false
|
||||
@ -31,14 +31,24 @@ function MainState:enter()
|
||||
self.bolts = {}
|
||||
|
||||
self.obstacles = {}
|
||||
table.insert(self.obstacles, {{90, 90}, {100, 200}, {300, 300}, {200, 100}})
|
||||
table.insert(self.obstacles, {{390, 90}, {500, 200}, {500, 300}})
|
||||
table.insert(self.obstacles, {{450, 390}, {500, 200}, {500, 300}})
|
||||
table.insert(self.obstacles, {{750, 390}, {500, 200}, {500, 300}})
|
||||
table.insert(self.obstacles, {{750, 290}, {600, 200}, {600, 100}})
|
||||
table.insert(self.obstacles, {{550, 400}, {670, 500}, {500, 500}})
|
||||
table.insert(self.obstacles, {{700, 0}, {850, 200}, {850, 0}})
|
||||
table.insert(self.obstacles, {{250, 350}, {200, 500}, {300, 500}})
|
||||
do
|
||||
table.insert(self.obstacles, {{77, 2}, {6, 60}, {5, 5}})
|
||||
table.insert(self.obstacles, {{576, 357}, {639, 314}, {639, 357}})
|
||||
table.insert(self.obstacles, {{275, 101}, {395, 101}, {392, 55}, {281, 60}})
|
||||
table.insert(self.obstacles, {{271, 280}, {392, 277}, {392, 322}, {252, 320}})
|
||||
table.insert(self.obstacles, {{222, 115}, {248, 145}, {221, 176}, {192, 151}})
|
||||
table.insert(self.obstacles, {{435, 112}, {401, 142}, {426, 174}, {457, 142}})
|
||||
table.insert(self.obstacles, {{194, 229}, {246, 260}, {192, 262}})
|
||||
table.insert(self.obstacles, {{417, 260}, {466, 258}, {465, 226}})
|
||||
table.insert(self.obstacles, {{141, 148}, {136, 249}, {94, 246}, {105, 149}})
|
||||
table.insert(self.obstacles, {{216, 318}, {216, 359}, {134, 358}})
|
||||
table.insert(self.obstacles, {{435, 0}, {434, 52}, {541, 5}})
|
||||
table.insert(self.obstacles, {{507, 142}, {505, 247}, {554, 246}, {553, 138}})
|
||||
table.insert(self.obstacles, {{124, 104}, {219, 34}, {230, 64}, {166, 111}})
|
||||
table.insert(self.obstacles, {{429, 337}, {527, 282}, {504, 274}, {432, 312}})
|
||||
table.insert(self.obstacles, {{63, 292}, {78, 314}, {40, 315}})
|
||||
table.insert(self.obstacles, {{588, 92}, {565, 65}, {616, 66}})
|
||||
end
|
||||
|
||||
self.obstacle_colliders = {}
|
||||
for _, obstacle in ipairs(self.obstacles) do
|
||||
@ -83,10 +93,9 @@ end
|
||||
function MainState:start_match()
|
||||
self:stop_match()
|
||||
|
||||
local winw, winh = love.graphics.getDimensions()
|
||||
self:create_player("keyboard", Vec(50, 200))
|
||||
self:create_player("keyboard", Vec(60, 80))
|
||||
-- self:create_player("joystick", Vec(winw-50, 200))
|
||||
self:create_player("joystick", Vec(50, 300))
|
||||
self:create_player("joystick", Vec(600, 300))
|
||||
end
|
||||
|
||||
function MainState:update(dt)
|
||||
@ -121,9 +130,9 @@ function MainState:update(dt)
|
||||
end
|
||||
|
||||
local move_dir = player:get_move_dir()
|
||||
local acc = move_dir * 300
|
||||
local acc = move_dir * 1700
|
||||
player.vel = player.vel + acc * dt
|
||||
player.vel = player.vel * 0.98
|
||||
player.vel = player.vel * 0.8
|
||||
player.collider:setLinearVelocity(player.vel.x, player.vel.y)
|
||||
|
||||
if not player.has_bolt then
|
||||
@ -158,8 +167,13 @@ function MainState:update(dt)
|
||||
end
|
||||
|
||||
for _, player in ipairs(self.players) do
|
||||
player.pos.x = player.collider:getX()
|
||||
player.pos.y = player.collider:getY()
|
||||
local collider = player.collider
|
||||
player.pos.x = collider:getX()
|
||||
player.pos.y = collider:getY()
|
||||
|
||||
local velx, vely = collider:getLinearVelocity()
|
||||
player.vel.x = velx
|
||||
player.vel.y = vely
|
||||
end
|
||||
else
|
||||
self.victory_timer = (self.victory_timer or 0) + dt
|
||||
@ -183,9 +197,9 @@ end
|
||||
function MainState:create_player(controls, pos)
|
||||
local player = Player:new(controls, self.world, pos)
|
||||
player.bolt_mods = {
|
||||
BoltMods.mods.speed_bounce,
|
||||
-- BoltMods.mods.speed_bounce,
|
||||
BoltMods.mods.bouncy,
|
||||
BoltMods.mods.retain_speed,
|
||||
-- BoltMods.mods.retain_speed,
|
||||
}
|
||||
sort_bolt_mods(player.bolt_mods)
|
||||
player.collider.fixture:setUserData("player")
|
||||
@ -340,8 +354,6 @@ function MainState:draw()
|
||||
love.graphics.setColor(1, 1, 1)
|
||||
love.graphics.line(mx-cursor_size, my, mx+cursor_size, my)
|
||||
love.graphics.line(mx, my-cursor_size, mx, my+cursor_size)
|
||||
-- love.graphics.print(mx, 200, 10)
|
||||
-- love.graphics.print(my, 200, 40)
|
||||
|
||||
if DRAW_COLLIDERS then
|
||||
love.graphics.setColor(0.8, 0.1, 0.8)
|
||||
@ -350,7 +362,7 @@ function MainState:draw()
|
||||
|
||||
if #self.players == 1 then
|
||||
love.graphics.setColor(0.2, 1, 0.2)
|
||||
love.graphics.print("Victory!", 300, 200)
|
||||
love.graphics.print("Victory!", 150, 100)
|
||||
end
|
||||
end
|
||||
|
||||
|
95
src/states/map-editor.lua
Normal file
95
src/states/map-editor.lua
Normal file
@ -0,0 +1,95 @@
|
||||
local MapEditor = {}
|
||||
|
||||
function MapEditor:enter()
|
||||
self.obstacles = {}
|
||||
self.current_obstacle = {}
|
||||
self:from_clipboard()
|
||||
end
|
||||
|
||||
function MapEditor:keypressed(key)
|
||||
if key == "escape" then
|
||||
love.event.quit()
|
||||
self:refresh_clipboard()
|
||||
end
|
||||
end
|
||||
|
||||
function MapEditor:mousepressed(mx, my)
|
||||
mx = math.floor(mx)
|
||||
my = math.floor(my)
|
||||
if self.current_obstacle[1] then
|
||||
local origin_x, origin_y = self.current_obstacle[1][1], self.current_obstacle[1][2]
|
||||
local dist = ((origin_x-mx)^2 + (origin_y-my)^2)^0.5
|
||||
if dist < 10 then
|
||||
table.insert(self.obstacles, self.current_obstacle)
|
||||
self.current_obstacle = {}
|
||||
self:update_clipboard()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(self.current_obstacle, {mx, my})
|
||||
end
|
||||
|
||||
function MapEditor:update_clipboard()
|
||||
local lines = {}
|
||||
for _, obstacle in ipairs(self.obstacles) do
|
||||
local points = {}
|
||||
for _, point in ipairs(obstacle) do
|
||||
table.insert(points, ("{%d, %d}"):format(point[1], point[2]))
|
||||
end
|
||||
table.insert(lines, ("table.insert(self.obstacles, {%s})"):format(table.concat(points, ", ")))
|
||||
end
|
||||
|
||||
local text = table.concat(lines, "\n")
|
||||
love.system.setClipboardText(text)
|
||||
end
|
||||
|
||||
function MapEditor:from_clipboard()
|
||||
self.obstacles = {}
|
||||
self.current_obstacle = {}
|
||||
|
||||
local text = love.system.getClipboardText()
|
||||
for line in text:gmatch("%s*([^\n]+)%s*") do
|
||||
local points = line:match("^table%.insert%(self%.obstacles, {(.+)}%)$")
|
||||
if points then
|
||||
local obstacle = {}
|
||||
table.insert(self.obstacles, obstacle)
|
||||
for x, y in points:gmatch("{(%d+),%s*(%d+)}") do
|
||||
table.insert(obstacle, {tonumber(x), tonumber(y)})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MapEditor:draw_obstacle(obstacle)
|
||||
local n = #obstacle
|
||||
if n >= 2 then
|
||||
love.graphics.line(obstacle[1][1], obstacle[1][2], obstacle[n][1], obstacle[n][2])
|
||||
for i=1, n-1 do
|
||||
love.graphics.line(obstacle[i][1], obstacle[i][2], obstacle[i+1][1], obstacle[i+1][2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MapEditor:draw()
|
||||
for _, obstacle in ipairs(self.obstacles) do
|
||||
self:draw_obstacle(obstacle)
|
||||
end
|
||||
|
||||
do
|
||||
local obstacle = self.current_obstacle
|
||||
local n = #self.current_obstacle
|
||||
for i=1, n-1 do
|
||||
love.graphics.line(obstacle[i][1], obstacle[i][2], obstacle[i+1][1], obstacle[i+1][2])
|
||||
end
|
||||
if n > 0 then
|
||||
local mx, my = love.mouse.getPosition()
|
||||
mx = math.floor(mx)
|
||||
my = math.floor(my)
|
||||
local last_point = self.current_obstacle[n]
|
||||
love.graphics.line(last_point[1], last_point[2], mx, my)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return MapEditor
|
Loading…
Reference in New Issue
Block a user