Compare commits

..

49 Commits

Author SHA1 Message Date
binarycat
577b7576cf added level in new format to repo 2022-03-16 14:21:35 -04:00
binarycat
fa4b2c86b5 somewhat kinda got things working again 2022-03-16 13:54:25 -04:00
binarycat
e8cef497d4 reworking level loading logic 2022-03-16 13:54:25 -04:00
binarycat
b3a12305da trying to do chunked level loading 2022-03-16 13:54:24 -04:00
lustlion
236e23177d function to improve entities moving on collisions and fixed accordingly
made math.round()
changed vector() and fixed accordingly
2022-03-16 18:50:10 +01:00
binarycat
4d94cc805d serialization function 2022-03-15 20:16:35 -04:00
lustlion
9c4b5431ee fix adjusting select to camera 2022-03-13 10:47:17 +01:00
lustlion
ba1c0f0c89 getPoints and getCoords 2022-03-13 10:43:07 +01:00
lustlion
ef632d50ee multiselecting entities! 2022-03-13 10:38:20 +01:00
lustlion
5bcf25a461 fix typos and functions 2022-03-13 10:36:19 +01:00
lustlion
1039479c47 Keybinds can be occupied (when being checked down) 2022-03-13 09:57:44 +01:00
lustlion
62555b4526 improvement to moveSpawns so it can move multiple spawns correctly 2022-03-13 09:42:35 +01:00
lustlion
a4af57ca6c cleanup useless function 2022-03-13 09:34:34 +01:00
binarycat
5189bef537 cleanup 2022-03-12 14:06:55 -05:00
binarycat
eab4cbbcdc use Rect:containsPoint in isThereObjectAt 2022-03-12 13:56:16 -05:00
binarycat
829963e080 add Rect, begin work on multiselect 2022-03-12 13:17:52 -05:00
binarycat
82246dc0c6 multiselect region can be drawn with the right mouse button 2022-03-12 13:16:39 -05:00
lustlion
3a5e0b395b fix indentation and cleaning 2022-03-12 18:28:35 +01:00
lustlion
feed65cf6d floored coords when adding or moving entity spawns 2022-03-12 18:20:25 +01:00
lustlion
1883bcd78b drawTextBox to use style table instead of a lot of arguments 2022-03-12 18:20:06 +01:00
lustlion
3c1746d914 particles time to be handled in frames instead of seconds optionally 2022-03-12 18:19:07 +01:00
binarycat
f091fba9f7 change editor_mode to editor.active, minor refactor, and start work on multiselect 2022-03-12 11:46:45 -05:00
binarycat
27f1dc71c0 added Rect class 2022-03-12 11:12:29 -05:00
binarycat
97de68e34b removed last globals for editor palette 2022-03-11 16:04:38 -05:00
binarycat
719c6cc5af removed unused variable 2022-03-11 15:41:27 -05:00
binarycat
5f48756e2e cleaned up stepEditor() 2022-03-11 15:35:59 -05:00
binarycat
9c070e161f add camera smoothing 2022-03-11 14:51:14 -05:00
binarycat
4ae674f0a7 smooth camera 2022-03-11 14:49:58 -05:00
binarycat
362c7ea52d add Point.copy 2022-03-11 14:10:18 -05:00
binarycat
644b1a4828 require point.lua 2022-03-11 14:07:54 -05:00
binarycat
c0af34fd76 add Point.__tostring 2022-03-11 14:07:33 -05:00
binarycat
e648705e5b added Point class 2022-03-11 13:16:45 -05:00
lustlion
61b8aa883b added function to cancel active prompt added function to add new spawns from editor added keybind for that 2022-03-11 18:39:27 +01:00
binarycat
3d41699d8f fix indentation 2022-03-11 12:23:19 -05:00
lustlion
f7947af505 using drawTextBox for room editing 2022-03-11 15:46:45 +01:00
lustlion
222f4478ca using drawTextBox for editor info and spawn info
adjustement of keybinds
2022-03-11 15:44:52 +01:00
lustlion
f62ec3ea32 improvement to drawTextBox to account for newlines.
used drawTextBox in editor palette
2022-03-11 15:27:15 +01:00
lustlion
266bf10d13 moved the textinbox to a separate function, adjusted margin 2022-03-11 14:38:52 +01:00
lustlion
96b1e750e4 prompt box style, entity prompts improvement, killing entities and particles improvement 2022-03-11 13:04:36 +01:00
lustlion
8c8e4808ad update cursed book 2022-03-11 07:55:55 +01:00
lustlion
cb6623f29a fix particle but actualy true 2022-03-10 19:51:18 +01:00
lustlion
68fb258d26 fix particle 2022-03-10 19:50:22 +01:00
lustlion
ce66ab73d3 some fixes cursed book still crashes 2022-03-10 19:40:23 +01:00
lustlion
e575cb5725 hotfix 2022-03-10 19:38:02 +01:00
lustlion
6dd970c1d4 made the check for archetype better, fixed reposition into restart game 2022-03-10 18:37:19 +01:00
lustlion
dbfae2f74e you can now edit archetype and args of spawns in editor with "t" and "d" when selected, respectively 2022-03-10 18:23:47 +01:00
lustlion
93bfe0bda4 ability to move spawns in editor 2022-03-10 10:48:10 +01:00
lustlion
39b65571a0 more editor work on handling entity spawns 2022-03-10 10:21:10 +01:00
lustlion
6e76607030 bugfix and slide animation
- bugfix for hook swing not taking in consideration the length of rope
- bugfix for player hitbox size
- bugfix for fairy flight control system FCS
- added slide animation for wall slide and wall jump
2022-03-09 15:54:26 +01:00
40 changed files with 1163 additions and 470 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -15,6 +15,10 @@ function Animation:new(anim_data,speed)
return o return o
end end
function Animation:getCenteredOffset()
return self.imgs[1]:getWidth()/2, self.imgs[1]:getHeight()/2
end
function Animation:change(anim_data) function Animation:change(anim_data)
if anim_data.path == self.path if anim_data.path == self.path
then then

View File

@@ -1,36 +1,38 @@
Camera = { Camera = {
pos = {x = 0, y = 0}, pos = Point:new(0, 0),
width = 0, width = 0,
height = 0 height = 0,
speed = 4,
} }
function Camera:followPlayer(player) function Camera:followPlayer(player)
local pos = player.pos -- make sure we have the Point metatable self:moveTowards(pos)
local pos = Point.copy(player.pos)
local room = player:getCollidingAt(pos.x,pos.y,LoadedObjects.Rooms) local room = player:getCollidingAt(pos.x,pos.y,LoadedObjects.Rooms)
self:positionCenterAt(pos.x, pos.y) self:moveTowards(self:confineTo(room, pos))
self:confineTo(room)
end end
function Camera:confineTo(box) function Camera:confineTo(box, pos)
if box == nil then if box == nil then
--frameDebug("not in a room") --frameDebug("not in a room")
return return pos
end end
--frameDebug("in a room") --frameDebug("in a room")
local w = self.width/game.scale local w = self.width/game.scale
local h = self.height/game.scale local h = self.height/game.scale
local npos = pos - self:centerOffset()
-- bottom edge -- bottom edge
self.pos.y = math.min(self.pos.y+h, box.to.y)-h npos.y = math.min(npos.y+h, box.to.y)-h
-- right edge -- right edge
self.pos.x = math.min(self.pos.x+w, box.to.x)-w npos.x = math.min(npos.x+w, box.to.x)-w
-- top edge -- top edge
self.pos.y = math.max(self.pos.y, box.from.y) npos.y = math.max(npos.y, box.from.y)
-- left edge -- left edge
self.pos.x = math.max(self.pos.x, box.from.x) npos.x = math.max(npos.x, box.from.x)
return npos + self:centerOffset()
end end
function Camera:confineToLevel() function Camera:confineToLevel()
@@ -38,6 +40,32 @@ function Camera:confineToLevel()
self.pos.y = math.max(0,math.min(self.pos.y,LevelData.Height-self.height/game.scale)) self.pos.y = math.max(0,math.min(self.pos.y,LevelData.Height-self.height/game.scale))
end end
function Camera:moveTowards(pt)
--local pt = Point:new(x,y)
local diff = pt - self:center()
local dist = diff:abs()
local npos
if dist < self.speed then
npos = pt
else
frameDebug("camera at speed limit")
npos = self:center() + diff * (self.speed/dist)
frameDebug("dist = "..dist..", npos = "..tostring(npos))
end
self:positionCenterAt(npos.x, npos.y)
end
function Camera:size()
return Point:new(self.width, self.height)
end
function Camera:centerOffset()
return self:size()/game.scale/2
end
function Camera:center()
return self.pos + self:centerOffset()
end
function Camera:positionCenterAt(x,y) function Camera:positionCenterAt(x,y)
self.pos.x = x-self.width/game.scale/2 self.pos.x = x-self.width/game.scale/2
self.pos.y = y-self.height/game.scale/2 self.pos.y = y-self.height/game.scale/2
@@ -48,3 +76,17 @@ function Camera:positionAt(x,y)
self.pos.x = math.floor((x/self.width)*self.width) self.pos.x = math.floor((x/self.width)*self.width)
self.pos.y = math.floor((y/self.height)*self.height) self.pos.y = math.floor((y/self.height)*self.height)
end end
-- translate screen coordinates to game coordinates
function Camera:ptScreenToGame(pt)
return self.pos + pt
end
function Camera:mouseScreenPos()
return Point:new(love.mouse.getX(),love.mouse.getY()) / game.scale
end
-- return the mouse position as game coordinates
function Camera:mouseGamePos()
return self:ptScreenToGame(self:mouseScreenPos())
end

51
code/chunk.lua Normal file
View File

@@ -0,0 +1,51 @@
-- pieces of levels
Chunk = {all = {}}
Chunk.__index = Chunk
-- CLASS METHODS
-- box == nil for global chunks
function Chunk:new(filename, box)
local o = { filename = filename, box = box }
setmetatable(o, self)
self.all[o] = true
end
function Chunk:getExportList()
local r = {}
for chunk in pairs(self.all) do
table.insert(r, {chunk.filename, chunk.box})
end
return r
end
-- INSTANCE METHODS
function Chunk:containsPoint(pt)
return self.box == nil or self.box:containsPoint(pt)
end
function Chunk:load()
if self.loaded then
return
end
logPrint("loading chunk "..self.filename)
self.data = dofile(level_current.."/chunks/"..self.filename)
self.loaded = { rooms = {}, collisions = {} }
LevelTiles = self.data.tiles
indexLevelTiles()
optimizeTileObjects(self.loaded.collisions)
for _, v in ipairs(self.data.rooms or {}) do
local room = Collision:new(v[1],v[2],v[3],v[4])
table.insert(self.data.rooms, room)
table.insert(LoadedObjects.Rooms, room)
end
logPrint("loaded chunk with "..#self.loaded.collisions.." collisions")
end
function Chunk:save(chunkdir)
return love.filesystem.write(chunkdir.."/"..self.filename, "return "..serialize_lua_value(self.data))
end

View File

@@ -88,3 +88,7 @@ function Collision:draw(color)
love.graphics.setColor(0,1,90,0.5) love.graphics.setColor(0,1,90,0.5)
love.graphics.rectangle("line",self.from.x-Camera.pos.x, self.from.y-Camera.pos.y, self.width, self.height) love.graphics.rectangle("line",self.from.x-Camera.pos.x, self.from.y-Camera.pos.y, self.width, self.height)
end end
function Collision:asRect()
return Rect:fromCoords(self.from.x, self.from.y, self.to.x, self.to.y)
end

View File

@@ -1,12 +1,37 @@
assert(editor == nil) assert(editor == nil)
editor = { editor = {
active = false,
room_mode = false, room_mode = false,
palette_mode = false palette = {
active = false,
scroll = Point:new(0, 0),
},
multiselect = {
active = false,
sweeping = false,
box = nil,
},
pan = { fixed = false, speed = 3 },
} }
function stepEditor() function stepEditor()
editor.palette_mode = editor.palette_mode or false
animateTiles() animateTiles()
local osweep = editor.multiselect.sweeping
editor.multiselect.sweeping = Keybind:checkDown(Keybind.editor.entity_select)
frameDebug("sweeping: "..tostring(editor.multiselect.sweeping))
if editor.multiselect.sweeping and not editor.multiselect.active then
print("multiselect enabled")
editor.multiselect.active = true
end
if not osweep and osweep ~= editor.multiselect.sweeping then
editor.multiselect.box = nil
end
if editor.multiselect.active then
doEditorMultiselect()
end
if Keybind:checkPressed(Keybind.editor.room_mode) then if Keybind:checkPressed(Keybind.editor.room_mode) then
if love.keyboard.isDown("lshift") then if love.keyboard.isDown("lshift") then
editor.room_mode = "delete" editor.room_mode = "delete"
@@ -15,61 +40,33 @@ function stepEditor()
end end
editor.room_points = {} editor.room_points = {}
end end
if Keybind:checkPressed(Keybind.editor.palette_mode) then if Keybind:checkPressed(Keybind.editor.palette_mode) then
if editor.palette_mode then editor.palette.active = not editor.palette.active
editor.palette_mode = false
palette_scroll_x = nil
palette_scroll_y = nil
else
editor.palette_mode = true
palette_scroll_x = 0
palette_scroll_y = 0
end
end
if Keybind:checkPressed(Keybind.editor.palette_mode) then
if editor.palette_mode then
editor.palette_mode = false
palette_scroll_x = nil
palette_scroll_y = nil
else
editor.palette_mode = true
palette_scroll_x = 0
palette_scroll_y = 0
end
end end
if Keybind:checkPressed(Keybind.editor.palette_mode) then local cvel = Point:new(0, 0)
if editor.palette_mode then
editor.palette_mode = false
palette_scroll_x = nil
palette_scroll_y = nil
else
editor.palette_mode = true
palette_scroll_x = 0
palette_scroll_y = 0
end
end
-- TODO:
-- i changed this but i dont know what was to do here.
-- - made specific action keybinds
if Keybind:checkDown(Keybind.editor.left) then if Keybind:checkDown(Keybind.editor.left) then
Camera.pos.x = Camera.pos.x - 3 cvel.x = -1
end end
if Keybind:checkDown(Keybind.editor.right) then if Keybind:checkDown(Keybind.editor.right) then
Camera.pos.x = Camera.pos.x + 3 cvel.x = 1
end end
if Keybind:checkDown(Keybind.editor.up) then if Keybind:checkDown(Keybind.editor.up) then
Camera.pos.y = Camera.pos.y - 3 cvel.y = -1
end end
if Keybind:checkDown(Keybind.editor.down) then if Keybind:checkDown(Keybind.editor.down) then
Camera.pos.y = Camera.pos.y + 3 cvel.y = 1
end end
if editor.palette_mode then cvel = cvel * editor.pan.speed
if not editor.pan.fixed then
cvel = cvel / game.scale
end
Camera.pos = Camera.pos + cvel
if editor.palette.active then
if Keybind:checkPressed(Keybind.editor.palette_change) then if Keybind:checkPressed(Keybind.editor.palette_change) then
local next = false local next = false
local export = nil local export = nil
@@ -97,37 +94,32 @@ function stepEditor()
if Keybind:checkPressed(Keybind.editor.save) then if Keybind:checkPressed(Keybind.editor.save) then
Prompt:new({ Prompt:new({
name = "level name", name = "level name",
input = "unnamed", input = "unnamed",
func = function(name_prompt) func = function(name_prompt)
if name_prompt.canceled then return end if name_prompt.canceled then return end
Prompt:new({ Prompt:new({
name = "filename", name = "filename",
input = "level.lua", input = "unnamed_level",
func = function(file_prompt) func = function(file_prompt)
if file_prompt.canceled then return end if file_prompt.canceled then return end
exportLevel(name_prompt.input, file_prompt.input) exportLevel(name_prompt.input, file_prompt.input)
end, end,
}):activate() }):activate()
end, end,
}):activate() }):activate()
end end
if Keybind:checkPressed(Keybind.debug.editor) then
editor_mode = not editor_mode
createTileObjects()
end
end end
function scrollEditor(y) function scrollEditor(y)
if editor.palette_mode then if editor.palette.active then
local scr = editor.palette.scroll
if love.keyboard.isDown("lshift") then if love.keyboard.isDown("lshift") then
palette_scroll_y = palette_scroll_y + y scr.y = scr.y + y
else else
palette_scroll_x = palette_scroll_x + y scr.x = scr.x + y
end end
else else
local oscale = game.scale
game.scale = math.max(0.1,game.scale + y/16) game.scale = math.max(0.1,game.scale + y/16)
end end
end end
@@ -138,14 +130,21 @@ function drawEditor()
drawGridDisplay() drawGridDisplay()
drawGameworldForeground() drawGameworldForeground()
endGameworldDraw() endGameworldDraw()
doEditorEdit()
drawEditorRooms() drawEditorRooms()
drawSpawns()
doEditorEdit()
drawSelectingPaletteTile() drawSelectingPaletteTile()
if editor.palette_mode then if editor.palette.active then
doEditorPalette() doEditorPalette()
end end
if editor.multiselect.box ~= nil then
frameDebug("drawing multiselect "..tostring(editor.multiselect.box))
drawEditorMultiselect()
end
end end
function doEditorEdit() function doEditorEdit()
@@ -169,8 +168,14 @@ function doEditorEdit()
expand_v = vertical expand_v = vertical
end end
love.graphics.setColor(100, 100, 100, 0.8) love.graphics.setColor(100, 100, 100, 0.8)
love.graphics.print("> " .. horizontal .. ", " .. vertical .. "; " .. math.floor(mouse_x / game.scale + Camera.pos.x) .. ", " .. math.floor(mouse_y / game.scale + Camera.pos.y)) drawTextBox(
love.graphics.print("> " .. level_width .. "(" .. expand_h .. "), " .. level_height .. "(".. expand_v .. ")", 0, 10) "Coords: [" ..
horizontal .. "," .. vertical .. "] (tile)\t[" ..
math.floor(mouse_x / game.scale + Camera.pos.x) .. "," .. math.floor(mouse_y / game.scale + Camera.pos.y).."] (pixel)\n" ..
"Level size: [" .. level_width .. ", " .. level_height .. "] +(" .. expand_h .. "," .. expand_v .. ")",
0,
0
)
if editor.room_mode then if editor.room_mode then
local rx = horizontal * tile_properties.width local rx = horizontal * tile_properties.width
@@ -194,27 +199,47 @@ function doEditorEdit()
editor.room_points = {} editor.room_points = {}
end end
if editor.room_mode == "delete" then if editor.room_mode == "delete" then
love.graphics.print("Select room to delete", 0, 20) drawTextBox("Select room to delete", 0, 20)
elseif #editor.room_points == 0 then elseif #editor.room_points == 0 then
love.graphics.print("Select top left of new room", 0, 20) drawTextBox("Select top left of new room", 0, 20)
else else
love.graphics.print("Select bottom right of new room", 0, 20) drawTextBox("Select bottom right of new room", 0, 20)
end end
elseif not editor.palette_mode then elseif not editor.palette.active then
if LevelTiles[vertical] ~= nil if LevelTiles[vertical] ~= nil
and LevelTiles[vertical][horizontal] ~= nil and LevelTiles[vertical][horizontal] ~= nil
and love.keyboard.isDown("lshift") ~= true and love.keyboard.isDown("lshift") ~= true
and love.keyboard.isDown("lctrl") ~= true and love.keyboard.isDown("lctrl") ~= true
then then
if Keybind:checkDown(Keybind.generic.lclick) if selecting_tile ~= nil then
and selecting_tile ~= nil if Keybind:checkDown(Keybind.editor.tile_set) then
then setTile(vertical,horizontal,selecting_tile)
setTile(vertical,horizontal,selecting_tile) elseif Keybind:checkDown(Keybind.editor.tile_remove) then
elseif Keybind:checkDown(Keybind.generic.rclick) then setTile(vertical,horizontal,0)
setTile(vertical,horizontal,0) end
reloadLevelTiles()
else
if Keybind:checkDown(Keybind.editor.entity_select) then
deselectSpawns()
if editor.multiselect.box then
selectSpawns(editor.multiselect.box)
end
end
if Keybind:checkDown(Keybind.editor.entity_move) then
moveSpawns(mouse_x,mouse_y)
end
if Prompt.active_prompt == nil then
if Keybind:checkDown(Keybind.editor.entity_modify_archetype) then
promptSpawnArchetype()
elseif Keybind:checkDown(Keybind.editor.entity_modify_data) then
promptSpawnArgs()
elseif Keybind:checkDown(Keybind.editor.entity_remove) then
deleteSpawn()
elseif Keybind:checkDown(Keybind.editor.entity_new) then
promptSpawnNew()
end
end
end end
reloadLevelTiles()
elseif Keybind:checkPressed(Keybind.generic.lshift) then elseif Keybind:checkPressed(Keybind.generic.lshift) then
expandLevelCanvas(math.sign(expand_h),math.sign(expand_v)) expandLevelCanvas(math.sign(expand_h),math.sign(expand_v))
reloadLevelTiles() reloadLevelTiles()
@@ -245,27 +270,31 @@ function drawSelectingPaletteTile()
end end
function doEditorPalette() function doEditorPalette()
local width = LevelData.tileset:getPixelWidth()/tile_properties.width local width = LevelData.tileset:getPixelWidth()/tile_properties.width
local height = LevelData.tileset:getPixelHeight()/tile_properties.height local height = LevelData.tileset:getPixelHeight()/tile_properties.height
local mouse_x = love.mouse.getX()
local mouse_y = love.mouse.getY()
local hovering = nil
local hov_x = nil
local hov_y = nil
local output = ""
love.graphics.setColor(0,0,0,1) love.graphics.setColor(0,0,0,1)
love.graphics.rectangle( love.graphics.rectangle(
"fill", "fill",
(palette_scroll_x + 1) * (tile_properties.width+1), (editor.palette.scroll.x + 1) * (tile_properties.width+1),
(palette_scroll_y + 1) * (tile_properties.height+1), (editor.palette.scroll.y + 1) * (tile_properties.height+1),
1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width), 1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height) 1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height)
) )
love.graphics.setColor(1,1,1,1) love.graphics.setColor(1,1,1,1)
local position_x = 1 local position_x = 1
local position_y = 1 local position_y = 1
for i = 1, #TileIndex-width-1 do for i = 1, #TileIndex-width-1 do
local tile_x = (palette_scroll_x + position_x) * (tile_properties.width+1) local tile_x = (editor.palette.scroll.x + position_x) * (tile_properties.width+1)
local tile_y = (palette_scroll_y + position_y) * (tile_properties.height+1) local tile_y = (editor.palette.scroll.y + position_y) * (tile_properties.height+1)
love.graphics.draw( love.graphics.draw(
LevelData.tileset, LevelData.tileset,
@@ -276,18 +305,17 @@ function doEditorPalette()
1, 1,
1 1
) )
if Keybind:checkDown(Keybind.generic.lclick) then
local mouse_x = love.mouse.getX()
local mouse_y = love.mouse.getY()
if mouse_x > (tile_x) * game.scale if mouse_x > (tile_x) * game.scale
and mouse_x < (tile_x + tile_properties.width) * game.scale and mouse_x < (tile_x + tile_properties.width) * game.scale
and mouse_y > (tile_y) * game.scale and mouse_y > (tile_y) * game.scale
and mouse_y < (tile_y + tile_properties.height) * game.scale and mouse_y < (tile_y + tile_properties.height) * game.scale
then then
selecting_tile = position_x + ((position_y-1) * width) hovering = position_x + ((position_y-1) * width)
hov_x = tile_x
love.graphics.print(selecting_tile .. " | " .. tile_x .. ", " .. tile_y, 0, 20) hov_y = tile_y
if Keybind:checkDown(Keybind.generic.lclick) then
selecting_tile = hovering
end end
end end
@@ -318,17 +346,47 @@ function doEditorPalette()
love.graphics.rectangle( love.graphics.rectangle(
"line", "line",
(palette_scroll_x + 1) * (tile_properties.width+1), (editor.palette.scroll.x + 1) * (tile_properties.width+1),
(palette_scroll_y + 1) * (tile_properties.height+1), (editor.palette.scroll.y + 1) * (tile_properties.height+1),
1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width), 1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height) 1 + LevelData.tileset:getPixelHeight()* ((tile_properties.height+1) / tile_properties.height)
) )
local tile = "none"
if selecting_tile ~= nil then
tile = "#"..selecting_tile
end
output = output .. "Selected: " .. tile
if hovering ~= nil then
output = output .. " \nHovering: #".. hovering .. "\nImage coords: " .. hov_x .. ", " .. hov_y
end
drawTextBox(
output,
(editor.palette.scroll.x + 1+width) * (tile_properties.width+1),
(editor.palette.scroll.y + 1) * (tile_properties.height+1)
)
end end
function drawEditorRooms() function drawEditorRooms()
for _, room in pairs(LoadedObjects.Rooms) do for _, room in pairs(LoadedObjects.Rooms) do
love.graphics.setColor(0,0,100,1) love.graphics.setColor(0,0,1,1)
love.graphics.rectangle("line",room.from.x-Camera.pos.x, room.from.y-Camera.pos.y, room.width, room.height) room:asRect():draw("line")
end
end
function drawEditorMultiselect()
love.graphics.setColor(0,1,1,1)
editor.multiselect.box:draw("line")
end
function doEditorMultiselect()
local mousept = Camera:mouseGamePos()
if editor.multiselect.box == nil then
editor.multiselect.box = Rect:fromPoints(mousept, mousept)
elseif editor.multiselect.sweeping then
editor.multiselect.box.max = mousept
end end
end end

View File

@@ -36,20 +36,30 @@ function Arrow:drawBackground()
end end
function Arrow:doPhysics() function Arrow:doPhysics()
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then -- horizontal collision
self.pos.x = self.pos.x + self.vel.x self:moveX(
else self.vel.x,
self.stuck = true function()
end self.stuck = true
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then end
self.pos.y = self.pos.y + self.vel.y )
else
self.stuck = true if not self.stuck then
-- vertical collision
self:moveY(
self.vel.y,
function()
self.stuck = true
end
)
end end
if self.stuck then if self.stuck then
self.pos.x = self.pos.x + self.vel.x * (2/3) self.pos.x = self.pos.x + self.vel.x * (2/3)
self.pos.y = self.pos.y + self.vel.y * (2/3) self.pos.y = self.pos.y + self.vel.y * (2/3)
self.vel.x = 0 self.vel.x = 0
self.vel.y = 0 self.vel.y = 0
end end
self:adjustLight()
end end

View File

@@ -1,5 +1,6 @@
CursedBook = Entity:new() CursedBook = Entity:new()
CursedBook.type = "CursedBook" CursedBook.type = "CursedBook"
CursedBook.display = Animation:new(animation.cursed_book.flying)
function CursedBook:new(x,y) function CursedBook:new(x,y)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -21,13 +22,14 @@ function CursedBook:new(x,y)
-- animations -- animations
o.body = Animation:new(animation.cursed_book.spawn) o.body = Animation:new(animation.cursed_book.spawn)
o.body.speed = 0
o.sprite_tint = {0.7,0.7,0.7} o.sprite_tint = {0.7,0.7,0.7}
o:centerOffset(o.body) o:centerOffset(o.body)
o:createBox(o.body) o:createBox(o.body)
-- light -- light
o.light_range = 500 o.light_range = 500
o.light = Light:new(o.pos.x,o.pos.y,o.light_range,2,HEX2RGB("#fe00d1")) --o.light = Light:new(o.pos.x,o.pos.y,o.light_range,2,hex2rgb("#fe00d1"))
o:id() o:id()
@@ -37,18 +39,20 @@ function CursedBook:new(x,y)
end end
function CursedBook:doLogic() function CursedBook:doLogic()
print(self.status)
self.target.x = main_player.pos.x - main_player.target_offset.x self.target.x = main_player.pos.x - main_player.target_offset.x
self.target.y = main_player.pos.y - main_player.target_offset.y self.target.y = main_player.pos.y - main_player.target_offset.y
local distance_x = self.target.x - self.pos.x local distance_x = self.target.x - self.pos.x
local distance_y = self.target.y - self.pos.y local distance_y = self.target.y - self.pos.y
local angle = GetAngleFromVector(distance_x,distance_y) local angle = getAngleFromVector(distance_x,distance_y)
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
if self.status == 0 then if self.status == 0 then
if distance < self.spawn_range then if distance < self.spawn_range then
self.status = 1 self.status = 1
end end
elseif self.status == -1 then elseif self.status == 2 then
if distance < self.range then if distance < self.range then
self.vel.x = 0 self.vel.x = 0
self.vel.y = 0 self.vel.y = 0
@@ -58,21 +62,29 @@ function CursedBook:doLogic()
end end
elseif self.status == 2 then elseif self.status == 2 then
if distance < self.attack_range then if distance < self.attack_range then
self.status = 3 --self.status = 3
end end
elseif self.status == 4 then elseif self.status == 4 then
end end
if self.isFlying then
local random_x = math.random(-4, 4)/100
local random_y = math.random(-4, 4)/100
self.vel.x = self.vel.x + random_x
self.vel.y = self.vel.y + random_y
end
end end
function CursedBook:handleAnimation() function CursedBook:handleAnimation()
if self.status == 1 then if self.status == 1 then
if self.body.path == "assets/entities/cursed_book/spawn" then if self.body.path == "assets/entities/cursed_book/spawn" then
self.body.speed = 1/3 self.body.speed = 1
local tint = 0.7 + 0.3 * (self.body.frame-1)/self.body.frames local tint = 0.7 + 0.3 * (self.body.frame-1)/#self.body.frames
self.sprite_tint = {tint,tint,tint} self.sprite_tint = {tint,tint,tint}
if self.body.frame == self.body.frames then if self.body.frame == #self.body.frames then
self.status = 2 self.status = 2
self.isFlying = true
self.body = self.body:change(animation.cursed_book.flying) self.body = self.body:change(animation.cursed_book.flying)
self.sprite_tint = {1,1,1} self.sprite_tint = {1,1,1}
--self:getBoundingBox(self.body,2,2,-2,-2) --self:getBoundingBox(self.body,2,2,-2,-2)
@@ -82,9 +94,9 @@ function CursedBook:handleAnimation()
elseif self.status == 3 then elseif self.status == 3 then
if self.body.path == "assets/entities/cursed_book/flying" then if self.body.path == "assets/entities/cursed_book/flying" then
self.body = self.body:change(animation.cursed_book.attack_transition) self.body = self.body:change(animation.cursed_book.attack_transition)
self.body.speed = 1/3 self.body.speed = 1
self:centerOffset(self.body) --self:centerOffset(self.body)
if self.body.frame == self.body.frames then if self.body.frame == #self.body.frames then
self.status = 4 self.status = 4
self.body = self.body:change(animation.cursed_book.attack_loop) self.body = self.body:change(animation.cursed_book.attack_loop)
self:centerOffset(self.body) self:centerOffset(self.body)
@@ -96,15 +108,21 @@ function CursedBook:handleAnimation()
end end
function CursedBook:doPhysics() function CursedBook:doPhysics()
if self.isFlying then -- horizontal collision
local random_x = math.random(-4, 4)/100 self:moveX(
local random_y = math.random(-4, 4)/100 self.vel.x,
self.vel.x = self.vel.x + random_x function()
self.vel.y = self.vel.y + random_y self.vel.x = 0
end end
-- move )
-- vertical collision
self:moveWithCollision() self:moveY(
self.vel.y,
function()
self.vel.y = 0
end
)
-- final position
self:adjustLight() self:adjustLight()
end end
@@ -114,5 +132,5 @@ function CursedBook:debug()
love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.spawn_range) love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.spawn_range)
love.graphics.setColor(1,0,0) love.graphics.setColor(1,0,0)
love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.attack_range) love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.attack_range)
Entity.Debug(self) Entity.debug(self)
end end

View File

@@ -1,5 +1,6 @@
Decoration = Entity:new() Decoration = Entity:new()
Decoration.type = "Decoration" Decoration.type = "Decoration"
Decoration.display = nil
function Decoration:new(x,y,animation,light_radius) function Decoration:new(x,y,animation,light_radius)
local o = Entity:new(x,y) local o = Entity:new(x,y)

View File

@@ -1,5 +1,6 @@
Fairy = Entity:new() Fairy = Entity:new()
Fairy.type = "Fairy" Fairy.type = "Fairy"
Fairy.display = Animation:new(animation.fairy.flying)
function Fairy:new(x,y) function Fairy:new(x,y)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -10,7 +11,7 @@ function Fairy:new(x,y)
o.range = 20 o.range = 20
o.vision_range = 120 o.vision_range = 120
o.target = {x = x, y = y} o.target = {x = x, y = y}
o.hover_distance = 60 o.hover_distance = 40
-- animations -- animations
o.body = Animation:new(animation.fairy.flying) o.body = Animation:new(animation.fairy.flying)
@@ -33,7 +34,6 @@ function Fairy:new(x,y)
end end
function Fairy:doLogic() function Fairy:doLogic()
if self:checkVisionLine(main_player,self.vision_range) then if self:checkVisionLine(main_player,self.vision_range) then
self.target.x = main_player.pos.x + main_player.target_offset.x self.target.x = main_player.pos.x + main_player.target_offset.x
@@ -41,8 +41,8 @@ function Fairy:doLogic()
local below = 1 local below = 1
while not isThereObjectAt( while not isThereObjectAt(
self.target.x, self.pos.x,
self.target.y + below * game.scale, self.pos.y + below * game.scale,
LoadedObjects.Collisions LoadedObjects.Collisions
) do ) do
below = below + 1 below = below + 1
@@ -50,8 +50,8 @@ function Fairy:doLogic()
end end
local top = 1 local top = 1
while not isThereObjectAt( while not isThereObjectAt(
self.target.x, self.pos.x,
self.target.y - top * game.scale, self.pos.y - top * game.scale,
LoadedObjects.Collisions LoadedObjects.Collisions
) do ) do
top = top + 1 top = top + 1
@@ -62,31 +62,19 @@ function Fairy:doLogic()
local distance_x = self.target.x - self.pos.x local distance_x = self.target.x - self.pos.x
local distance_y = self.target.y - self.pos.y local distance_y = self.target.y - self.pos.y
local angle = getAngleFromVector(distance_x,distance_y) local angle = getAngleFromVector(vector(distance_x,distance_y))
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
if distance < self.range then if distance < self.range then
self.vel.x = self.vel.x * 0.9 local random_x = math.random(-1, 1)
self.vel.y = self.vel.y * 0.9 local random_y = math.random(-1, 1)
self.vel.x = self.vel.x * 0.9 + random_x/10
self.vel.y = self.vel.y * 0.9 + random_y/10
else else
self.vel.x = math.cos(angle)*self.speed local random_x = math.random(-6, 6)
self.vel.y = math.sin(angle)*self.speed local random_y = math.random(-6, 6)
end self.vel.x = math.cos(angle)*self.speed + random_x/10
self.particle_timer = self.particle_timer + 1 self.vel.y = math.sin(angle)*self.speed + random_y/10
if self.particle_timer >= self.particle_time then
self.particle_timer = 0
local particle_data = {
animation = animation.particle.simple,
animation_speed = 1,
sprite_tint = hex2rgb("#fed100"),
sprite_alpha_fade = true,
direction = angle-math.rad(180+math.random(60)-30),
speed = 0.8*(distance/50),
speed_increase = -0.01,
time = 0.75
}
Particle:new(self.pos.x,self.pos.y,particle_data)
end end
end end
@@ -94,19 +82,42 @@ function Fairy:handleAnimation()
self.body:animate() self.body:animate()
--if self:isCollidingWith(main_player) then self.sprite_tint = {1,0,0} else self.sprite_tint = {1,1,1} end --if self:isCollidingWith(main_player) then self.sprite_tint = {1,0,0} else self.sprite_tint = {1,1,1} end
self:draw(self.body) self:draw(self.body)
self.particle_timer = self.particle_timer + 1
if self.particle_timer >= self.particle_time then
local vector = vector(self.vel.x,self.vel.y)
local angle = getAngleFromVector(vector)
self.particle_timer = 0
local particle_data = {
animation = animation.particle.simple,
animation_speed = 1,
sprite_tint = hex2rgb("#fed100"),
sprite_alpha_fade = true,
direction = angle-math.rad(180+math.random(60)-30),
speed = 1,
speed_increase = -0.01,
time = 0.75
}
Particle:new(self.pos.x,self.pos.y,particle_data)
end
end end
function Fairy:doPhysics() function Fairy:doPhysics()
local random_x = math.random(-4, 4)/10 -- horizontal collision
local random_y = math.random(-4, 4)/10 self:moveX(
self.vel.x,
self.vel.x = self.vel.x + random_x function()
self.vel.y = self.vel.y + random_y self.vel.x = 0
end
self:moveWithCollision() )
self.vel.x = 0 -- vertical collision
self.vel.y = 0 self:moveY(
self.vel.y,
function()
self.vel.y = 0
end
)
-- final position
self:adjustLight() self:adjustLight()
end end

View File

@@ -1,5 +1,6 @@
HookAnchor = Entity:new() HookAnchor = Entity:new()
HookAnchor.type = "HookAnchor" HookAnchor.type = "HookAnchor"
HookAnchor.display = Animation:new(animation.fairy.flying)
function HookAnchor:new(x,y,hook_distance) function HookAnchor:new(x,y,hook_distance)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -35,10 +36,6 @@ function HookAnchor:drawBackground()
) )
end end
function HookAnchor:doPhysics()
end
function Fairy:debug() function Fairy:debug()
Entity.debug(self) Entity.debug(self)
end end

View File

@@ -1,5 +1,6 @@
Kupo = Entity:new() Kupo = Entity:new()
Kupo.type = "Kupo" Kupo.type = "Kupo"
Kupo.display = Animation:new(animation.kupo.body)
function Kupo:new(x,y) function Kupo:new(x,y)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -43,8 +44,9 @@ function Kupo:doLogic()
self.target.y = main_player.pos.y - main_player.target_offset.y self.target.y = main_player.pos.y - main_player.target_offset.y
local distance_x = self.target.x - self.pos.x local distance_x = self.target.x - self.pos.x
local distance_y = self.target.y - self.pos.y local distance_y = self.target.y - self.pos.y
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
local angle = getAngleFromVector(distance_x,distance_y) local angle = getAngleFromVector(vector(distance_x,distance_y))
self.draw_bow = false self.draw_bow = false
if distance <= self.range then if distance <= self.range then
if self.hostile == true then if self.hostile == true then
@@ -152,7 +154,3 @@ function Kupo:handleAnimation()
) )
end end
end end
function Kupo:doPhysics()
self:moveWithCollision()
end

View File

@@ -2,6 +2,7 @@ LoadedObjects.Particles = {}
Particle = Entity:new() Particle = Entity:new()
Particle.type = "Particle" Particle.type = "Particle"
Particle.display = Animation:new(animation.particle.simple)
function Particle:new(x,y,particle_data) function Particle:new(x,y,particle_data)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -20,8 +21,14 @@ function Particle:new(x,y,particle_data)
o.sprite_flip = particle_data.sprite_flip or o.sprite_flip o.sprite_flip = particle_data.sprite_flip or o.sprite_flip
o.time = particle_data.time or nil o.time = particle_data.time or nil
if o.time ~= nil then o.time = o.time * game.framerate end if o.time ~= nil then
if particle_data.time_unit ~= nil
and particle_data.time_unit == "frames" then
o.time = o.time
else
o.time = o.time * game.framerate
end
end
o.timer = 0 o.timer = 0
o.vel = { o.vel = {
@@ -82,26 +89,32 @@ function Particle:handleAnimation()
end end
end end
function Particle:doPhysics() function Particle:doLogic()
-- adjust speed -- adjust speed
if self.speed_increase ~= 0 then if self.speed_increase ~= 0 then
self.speed = self.speed + self.speed_increase self.speed = self.speed + self.speed_increase
self.vel.x = self.speed * math.cos(self.direction) self.vel.x = self.speed * math.cos(self.direction)
self.vel.y = self.speed * math.sin(self.direction) self.vel.y = self.speed * math.sin(self.direction)
end end
-- move
self:moveWithCollision()
if self.light ~= nil then
self:adjustLight()
self.light.range = self.light_range * self.sprite_alpha/2
end
if self.time ~= nil then if self.time ~= nil then
if self.timer >= self.time then self:kill() end if self.timer >= self.time then self:kill() end
end end
end end
function Particle:doPhysics()
-- horizontal collision
self:moveX(
self.vel.x
)
-- vertical collision
self:moveY(
self.vel.y
)
-- final position
self:adjustLight()
end
function Particle:debug() function Particle:debug()
-- draw center CYAN -- draw center CYAN
love.graphics.setColor(0,1,1) love.graphics.setColor(0,1,1)

View File

@@ -1,5 +1,6 @@
Player = Entity:new() Player = Entity:new()
Player.type = "Player" Player.type = "Player"
Player.display = Animation:new(animation.nancy.idle)
function Player:new(x,y) function Player:new(x,y)
local o = Entity:new(x,y) local o = Entity:new(x,y)
@@ -71,7 +72,7 @@ function Player:new(x,y)
o.mask = Animation:new(animation.moth_mask.idle) o.mask = Animation:new(animation.moth_mask.idle)
o:centerOffset(o.body) o:centerOffset(o.body)
o:createBox(o.body,0,3,-1,-3) o:createBox(o.body,0,4,-1,-5)
-- lights -- lights
o.light = Light:new(o.pos.x,o.pos.y,o.light_radius) o.light = Light:new(o.pos.x,o.pos.y,o.light_radius)
@@ -131,10 +132,13 @@ function Player:doLogic()
if self.dash_cooldown_timer == 0 if self.dash_cooldown_timer == 0
and not self.is_dashing and not self.is_dashing
and self.dash_count > 0 then and self.dash_count > 0 then
self:unhook() self:unhook()
self.nodrift_frames = 0
-- state player -- state player
self.is_dashing = true self.is_dashing = true
self.is_sliding = false
self.dash_count = self.dash_count - 1 self.dash_count = self.dash_count - 1
-- get dash direction -- get dash direction
@@ -151,7 +155,7 @@ function Player:doLogic()
end end
-- set dash values -- set dash values
self.dashDirection = getAngleFromVector(horizontal, vertical) self.dashDirection = getAngleFromVector(vector(horizontal, vertical))
self.dash_timer = math.floor(self.dash_time * game.framerate) self.dash_timer = math.floor(self.dash_time * game.framerate)
end end
else else
@@ -228,10 +232,10 @@ function Player:doPhysics()
-- hook state -- hook state
if self.is_hooked then if self.is_hooked then
self.move_x = 0 self.move_x = 0
local hook = vector(self.pos.x, self.pos.y, self.hook_anchor.x, self.hook_anchor.y) local hook = vector(self.hook_anchor.x - self.pos.x, self.hook_anchor.y - self.pos.y)
local dist = math.min(getVectorValue(hook), self.hook_distance) local dist = math.min(getVectorValue(hook), self.hook_distance)
local hook_angle = getAngleFromVector(hook[1],hook[2])-math.rad(180) local hook_angle = getAngleFromVector(hook)-math.rad(180)
if Keybind:checkDown(Keybind.move.right) then if Keybind:checkDown(Keybind.move.right) then
hook_angle = hook_angle - self.hook_swing_speed hook_angle = hook_angle - self.hook_swing_speed
@@ -247,7 +251,8 @@ function Player:doPhysics()
animation_speed = 0, animation_speed = 0,
sprite_tint = hex2rgb("#fed100"), sprite_tint = hex2rgb("#fed100"),
sprite_alpha = 0.5, sprite_alpha = 0.5,
time = 0.05, time = 4,
time_unit = "frames",
sprite_flip = { sprite_flip = {
x = self.sprite_flip.x, x = self.sprite_flip.x,
y = self.sprite_flip.y y = self.sprite_flip.y
@@ -259,8 +264,13 @@ function Player:doPhysics()
local pos_y = self.hook_anchor.y + dist * math.sin(hook_angle) local pos_y = self.hook_anchor.y + dist * math.sin(hook_angle)
self.vel.x = self.vel.x + pos_x - self.pos.x self.vel.x = self.vel.x + pos_x - self.pos.x
self.vel.y = self.vel.y + pos_y - self.pos.y self.vel.y = self.vel.y + pos_y - self.pos.y
self.pos.x = pos_x
self.pos.y = pos_y self:moveX(
pos_x - self.pos.x
)
self:moveY(
pos_y - self.pos.y
)
end end
@@ -271,24 +281,26 @@ function Player:doPhysics()
end end
-- horizontal collision -- horizontal collision
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then self.wall_hit = 0
self.pos.x = self.pos.x + self.vel.x self:moveX(
self.wall_hit = 0 self.vel.x,
else function()
self.wall_hit = math.sign(self.vel.x) self.wall_hit = math.sign(self.vel.x)
self.vel.x = 0 self.vel.x = 0
end end
)
-- vertical collision -- vertical collision
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then self:moveY(
self.pos.y = self.pos.y + self.vel.y self.vel.y,
else function()
if self.vel.y > 0 then if self.vel.y > 0 then
self.is_on_ground = true self.is_on_ground = true
self.dash_count = self.dash_amount self.dash_count = self.dash_amount
end
self.vel.y = 0
end end
self.vel.y = 0 )
end
-- if u collision w hazard, respawn -- if u collision w hazard, respawn
if self:isCollidingAt(self.pos.x, self.pos.y, LoadedObjects.Hazards) then if self:isCollidingAt(self.pos.x, self.pos.y, LoadedObjects.Hazards) then
@@ -312,18 +324,20 @@ function Player:handleAnimation()
elseif self.move_x ~= 0 then elseif self.move_x ~= 0 then
self.sprite_flip.x = math.sign(self.move_x) self.sprite_flip.x = math.sign(self.move_x)
end end
-- animation priority -- animation priority
if self.vel.y > 1.25 or self.is_sliding then if self.is_sliding then
self.body = self.body:change(animation.nancy.slide)
self.mask = self.mask:change(self.mask_type.slide)
elseif self.vel.y > 1.25 then
self.body = self.body:change(animation.nancy.fall) self.body = self.body:change(animation.nancy.fall)
self.mask = self.mask:change(self.mask_type.fall) self.mask = self.mask:change(self.mask_type.fall)
elseif self.vel.y < 0 then elseif self.vel.y < 0 then
self.body = self.body:change(animation.nancy.jump) self.body = self.body:change(animation.nancy.jump)
self.mask = self.mask:change(self.mask_type.jump) self.mask = self.mask:change(self.mask_type.jump)
elseif self.vel.x + self.move_x ~= 0 then elseif self.vel.x + self.move_x ~= 0 and not self.is_hooked then
self.body = self.body:change(animation.nancy.run) self.body = self.body:change(animation.nancy.run)
self.mask = self.mask:change(self.mask_type.run) self.mask = self.mask:change(self.mask_type.run)
else elseif not self.is_hooked then
self.body = self.body:change(animation.nancy.idle) self.body = self.body:change(animation.nancy.idle)
self.mask = self.mask:change(self.mask_type.idle) self.mask = self.mask:change(self.mask_type.idle)
end end

View File

@@ -5,6 +5,7 @@ function Entity:new(x,y)
local o = {} local o = {}
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.move_remainder = {x = 0, y = 0}
o.vel = {x = 0, y = 0} o.vel = {x = 0, y = 0}
o.direction = 0 o.direction = 0
@@ -38,21 +39,29 @@ end
function Entity:checkNearest(type,maxdistance) function Entity:checkNearest(type,maxdistance)
local return_entity = nil local return_entity = nil
local shortest = -1 local shortest = -1
local flag_variable_distance = false
if maxdistance == "hook_specific" then
flag_variable_distance = true
end
for _, entity in pairs(LoadedObjects.Entities) do for _, entity in pairs(LoadedObjects.Entities) do
if not type or entity.type == type then if not type or entity.type == type then
local distance_x = entity.pos.x - self.pos.x local distance_x = entity.pos.x - self.pos.x
local distance_y = entity.pos.y - self.pos.y local distance_y = entity.pos.y - self.pos.y
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
if maxdistance == "hook_specific" then maxdistance = entity.hook_distance end if flag_variable_distance then
maxdistance = entity.hook_distance
end
if not maxdistance or distance < maxdistance then if not maxdistance or distance < maxdistance then
if shortest == -1 or distance < shortest then if shortest == -1 or distance < shortest then
shortest = distance shortest = distance
return_entity = entity return_entity = entity
end end
print(shortest,maxdistance,distance)
end end
end end
end end
return return_entity return return_entity
@@ -61,26 +70,54 @@ end
function Entity:doLogic() function Entity:doLogic()
end end
function Entity:move() function Entity:moveX(amount, func)
self.pos.x = self.pos.x + self.vel.x self.move_remainder.x = self.move_remainder.x + amount
self.pos.y = self.pos.y + self.vel.y local move = math.round(self.move_remainder.x)
if move ~= 0 then
self.move_remainder.x = self.move_remainder.x - move
local sign = math.sign(move)
while math.round(move) ~= 0 do
if not self:isCollidingAt(
self.pos.x + sign,
self.pos.y,
LoadedObjects.Collisions
) then
self.pos.x = self.pos.x + sign
move = move - sign
if tostring(move) == "nan" then error() end
else
if func then
func()
end
break
end
end
end
end end
function Entity:moveWithCollision() function Entity:moveY(amount, func)
local r = false self.move_remainder.y = self.move_remainder.y + amount
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then local move = math.round(self.move_remainder.y)
self.pos.x = self.pos.x + self.vel.x if move ~= 0 then
else self.move_remainder.y = self.move_remainder.y - move
self.vel.x = 0 local sign = math.sign(move)
r = true while math.round(move) ~= 0 do
if not self:isCollidingAt(
self.pos.x,
self.pos.y + sign,
LoadedObjects.Collisions
) then
self.pos.y = self.pos.y + sign
move = move - sign
if tostring(move) == "nan" then error() end
else
if func then
func()
end
break
end
end
end end
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
self.pos.y = self.pos.y + self.vel.y
else
self.vel.y = 0
r = true
end
return r
end end
function Entity:adjustLight(x,y) function Entity:adjustLight(x,y)
@@ -97,12 +134,12 @@ function Entity:kill()
self.light:kill() self.light:kill()
end end
if self.id ~= nil then if self.id ~= nil then
table.remove(LoadedObjects.Entities,self.id)
for _, e in pairs(LoadedObjects.Entities) do for _, e in pairs(LoadedObjects.Entities) do
if e.id > self.id then if e.id > self.id then
e.id = e.id - 1 e.id = e.id - 1
end end
end end
table.remove(LoadedObjects.Entities,self.id)
end end
self = nil self = nil
end end
@@ -113,8 +150,9 @@ function Entity:checkVisionLine(entity,range)
local distance_x = target_x - self.pos.x local distance_x = target_x - self.pos.x
local distance_y = target_y - self.pos.y local distance_y = target_y - self.pos.y
local distance = vector(distance_x,distance_y)
local angle = getAngleFromVector(distance_x,distance_y) local angle = getAngleFromVector(distance)
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
local is_colliding = true local is_colliding = true
@@ -136,6 +174,7 @@ function Entity:checkVisionLine(entity,range)
end end
function Entity:draw(animation) function Entity:draw(animation)
if animation == nil then return end
local c1, c2, c3, a = love.graphics.getColor() local c1, c2, c3, a = love.graphics.getColor()
love.graphics.setColor(self.sprite_tint[1],self.sprite_tint[2],self.sprite_tint[3],self.sprite_alpha) love.graphics.setColor(self.sprite_tint[1],self.sprite_tint[2],self.sprite_tint[3],self.sprite_alpha)
animation:draw( animation:draw(
@@ -149,6 +188,7 @@ function Entity:draw(animation)
end end
function Entity:centerOffset(animation,x,y) function Entity:centerOffset(animation,x,y)
if animation == nil then return end
local x = x or 0 local x = x or 0
local y = y or 0 local y = y or 0
self.sprite_offset.x = animation.imgs[1]:getWidth()/2 + x self.sprite_offset.x = animation.imgs[1]:getWidth()/2 + x
@@ -156,6 +196,7 @@ function Entity:centerOffset(animation,x,y)
end end
function Entity:createBox(animation,top,left,bottom,right) function Entity:createBox(animation,top,left,bottom,right)
if animation == nil then return end
local left = left or 0 local left = left or 0
local right = right or 0 local right = right or 0
local top = top or 0 local top = top or 0
@@ -217,8 +258,9 @@ function Entity:checkVisionLineDebug(entity,range)
local distance_x = target_x - self.pos.x local distance_x = target_x - self.pos.x
local distance_y = target_y - self.pos.y local distance_y = target_y - self.pos.y
local distance = vector(distance_x,distance_y)
local angle = getAngleFromVector(distance_x,distance_y) local angle = getAngleFromVector(distance)
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
if distance < range then if distance < range then
@@ -267,6 +309,9 @@ function Entity:debug()
end end
end end
function Entity:doPhysics()
end
function Entity:handleAnimation() function Entity:handleAnimation()
end end

View File

@@ -1,3 +1,14 @@
function restartGame()
for _, entity in ipairs(LoadedObjects.Entities) do
if entity.light ~= nil then entity.light:kill() end
entity = nil
end
LoadedObjects.Entities = {}
LoadedObjects.Particles = {}
main_player = Player:new(75,50)
activateSpawns()
end
function stepGame() function stepGame()
setCollisionFlags() setCollisionFlags()
if menu_type == "no" then if menu_type == "no" then
@@ -33,13 +44,7 @@ function stepGame()
end end
if Keybind:checkPressed(Keybind.debug.reposition) then if Keybind:checkPressed(Keybind.debug.reposition) then
if not editor_mode then restartGame()
main_player.pos.x, main_player.pos.y = 75,50
end
for _, entity in pairs(LoadedObjects.Entities) do
if entity.id ~= main_player.id then entity:kill() end
end
activateSpawns()
end end
if Keybind:checkPressed(Keybind.debug.reload) then if Keybind:checkPressed(Keybind.debug.reload) then
@@ -48,10 +53,6 @@ function stepGame()
initMenu("dialog",dialog_sequence.example) initMenu("dialog",dialog_sequence.example)
end end
if Keybind:checkPressed(Keybind.debug.editor) then
editor_mode = true
end
if Keybind:checkPressed(Keybind.debug.recording) then if Keybind:checkPressed(Keybind.debug.recording) then
if DemoRecording then if DemoRecording then
Demo:endRecord() Demo:endRecord()

View File

@@ -20,7 +20,6 @@ function drawGameworldBackground()
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 then
local depth = TileData[LevelTiles[i][j].id].depth local depth = TileData[LevelTiles[i][j].id].depth
drawTile( drawTile(
LevelTiles[i][j], LevelTiles[i][j],

View File

@@ -1,90 +1,51 @@
function exportLevel(levelname, filename) function exportLevel(levelname, dirname)
love.filesystem.createDirectory("export") dirname = "export/"..dirname
filename = filename or "output.lua"
if string.sub(filename, 1, 1) ~= "/" then if love.filesystem.exists(dirname) then
filename = "export/"..filename -- TODO: prompt to overwrite
error("file already exists")
end
local ok = love.filesystem.createDirectory(dirname)
if not ok then
logPrint("error creating directory")
end end
exportFile = io.open(filename, "w+")
if exportFile then
logPrint("Exporting level \"".. levelname .. "\"...")
exportFile:write("return {")
logPrint("- level name") logPrint("Exporting level \"".. levelname .. "\"...")
exportFile:write("\n name = \"" .. levelname .. "\",") local exportTable = {}
exportTable.name = levelname
logPrint("- tileset") exportTable.tileset = "library"
for k, v in pairs(tileset) do exportTable.properties = LevelData.properties
if v == LevelData.tileset then --exportTable.tiles = LevelTiles
exportFile:write("\n tileset = tileset." .. k .. ",") --logPrint("- objects")
end --exportTable.objects = { spawns = {}, rooms = {} }
end --logPrint(" - spawns")
--for i, v in ipairs(LoadedObjects.Spawns) do
logPrint("- properties") --exportTable.objects.spawns = {v.archetype.name,{},v.args}
exportFile:write("\n properties = {") --end
logPrint(" - darkness: ".. tostring(LevelData.properties.darkness))
exportFile:write("\n darkness = " .. tostring(LevelData.properties.darkness)) --logPrint(" - rooms")
exportFile:write("\n },")
--for i, room in ipairs(LoadedObjects.Rooms) do
logPrint("- tiles") --- table.insert(exportTable.objects.rooms,{room:asRect():getCoords()})
exportFile:write("\n tiles = {") --end
local rows = #LevelTiles exportTable.chunks = Chunk:getExportList()
for i = 1, #LevelTiles do logPrint("Writing to file...")
if i > 1 then local ok, err = love.filesystem.write(dirname.."/level.lua", "return "..serialize_lua_value(exportTable))
exportFile:write(", ")
end if ok then
exportFile:write("\n { ") logPrint("Saving chunks...")
for j = 1, #LevelTiles[i] do local chunkdir = dirname.."/chunks"
if j ~= 1 then love.filesystem.createDirectory(chunkdir)
exportFile:write(", ") for chunk in pairs(Chunk.all) do
end local ok, err = chunk:save(chunkdir)
exportFile:write(tostring(LevelTiles[i][j].id)) if not ok then error(err) end
end end
exportFile:write("}") logPrint("Exporting complete.")
logPrint(" - row "..i.."/"..rows.." "..math.floor(100*((i-1)*100/rows))/100 .."%") else
end -- TODO: clean up created files
exportFile:write("\n },") logPrint("Exporting failed: "..err)
logPrint("- objects")
exportFile:write("\n objects = {")
logPrint(" - spawns")
exportFile:write("\n spawns = {")
for i, v in ipairs(LoadedObjects.Spawns) do
if i > 1 then
exportFile:write(",")
end
exportFile:write("\n {")
exportFile:write(v.archetype.type)
exportFile:write(",{")
for i=1, #v.args do
if i > 1 then
exportFile:write(",")
end
exportFile:write(v.args[i])
end
exportFile:write("}}")
end
exportFile:write("\n },")
logPrint(" - rooms")
exportFile:write("\n rooms = {")
for i, room in ipairs(LoadedObjects.Rooms) do
if i > 1 then
exportFile:write(",")
end
exportFile:write("\n {{")
exportFile:write(room.from.x)
exportFile:write(",")
exportFile:write(room.from.y)
exportFile:write("},{")
exportFile:write(room.to.x)
exportFile:write(",")
exportFile:write(room.to.y)
exportFile:write("}}")
end
exportFile:write("\n },")
exportFile:write("\n },")
logPrint("Exporting complete.")
exportFile:write("\n}")
exportFile:close()
end end
end end

View File

@@ -17,6 +17,10 @@ Keybind.debug = {}
Keybind.editor = {} Keybind.editor = {}
Keybind.generic = {} Keybind.generic = {}
function Keybind:isAvailable(action)
return not action.occupied
end
function Keybind:checkDown(action) function Keybind:checkDown(action)
if DemoPlayback then if DemoPlayback then
for _, demo_action in pairs(DemoAction[CurrentDemoFrame]) do for _, demo_action in pairs(DemoAction[CurrentDemoFrame]) do
@@ -37,9 +41,11 @@ function Keybind:checkDown(action)
if action.demo ~= nil then if action.demo ~= nil then
Demo:recordAction(action.demo) Demo:recordAction(action.demo)
end end
action.occupied = true
return true return true
end end
end end
action.occupied = false
return false return false
end end
end end
@@ -123,11 +129,19 @@ function Keybind:default()
Keybind.editor.down = { keys = {"down", "s"}} Keybind.editor.down = { keys = {"down", "s"}}
Keybind.editor.palette_change = { keys = {"f1"}} Keybind.editor.palette_change = { keys = {"f1"}}
Keybind.editor.save = { keys = {"f3"}} Keybind.editor.save = { keys = {"f3"}}
Keybind.editor.tile_set = { keys = {1}}
Keybind.editor.tile_remove = { keys = {2}}
Keybind.editor.entity_select = { keys = {1}}
Keybind.editor.entity_move = { keys = {2}}
Keybind.editor.entity_modify_archetype = { keys = {"t"}}
Keybind.editor.entity_modify_data = { keys = {"g"}}
Keybind.editor.entity_remove = { keys = {"delete"}}
Keybind.editor.entity_new = { keys = {"n"}}
-- Generic -- Generic
Keybind.generic.lclick = { keys = {1}} Keybind.generic.lclick = { keys = {1}}
Keybind.generic.rclick = { keys = {2}} Keybind.generic.rclick = { keys = {2}}
Keybind.generic.lshift = { keys = {"lshift"}} Keybind.generic.lshift = { keys = {"lshift"}}
Keybind.generic.alt = { keys = {"alt"}}
Keybind.generic.lctrl = { keys = {"lctrl"}} Keybind.generic.lctrl = { keys = {"lctrl"}}
end end

View File

@@ -1,7 +1,25 @@
function loadLevelTiles() function loadLevelTiles()
math.randomseed(3) math.randomseed(3)
LevelData = dofile("data/levels/"..level_current) level_current = "data/levels/level1"
LevelData = dofile(level_current.."/level.lua")
LoadedObjects.Collisions = {}
LoadedObjects.Platforms = {}
LoadedObjects.Ladders = {}
LoadedObjects.Hazards = {}
if type(LevelData.tileset) == "string" then
LevelData.tileset_name = LevelData.tileset
end
LevelData.tileset = tileset[LevelData.tileset_name]
getLevelTileData()
for _, v in ipairs(LevelData.chunks) do
Chunk:new(v[1], v[2])
end
local global_chunk = next(Chunk.all)
global_chunk:load()
LoadedObjects.Collisions = global_chunk.loaded.collisions
LevelTiles = global_chunk.data.tiles
--[[ --[[
on level format: on level format:
@@ -12,26 +30,26 @@ function loadLevelTiles()
overlay_depth = foreground/background overlay depth overlay_depth = foreground/background overlay depth
type = collision type type = collision type
]] ]]
getLevelTileData()
LevelTiles = LevelData.tiles
updateLevelDimensions() updateLevelDimensions()
indexLevelTiles() --
createTileObjects() --createTileObjects()
createRoomObjects() --createRoomObjects()
getSpawns() --getSpawns()
end end
function createRoomObjects() function createRoomObjects()
LoadedObjects.Rooms = {} LoadedObjects.Rooms = {}
for _, v in pairs(LevelData.objects.rooms) do for _, v in pairs(LevelData.objects.rooms) do
table.insert(LoadedObjects.Rooms, Collision:new(v[1][1],v[1][2],v[2][1],v[2][2])) table.insert(LoadedObjects.Rooms, Collision:new(v[1],v[2],v[3],v[4]))
end end
end end
function getSpawns() function getSpawns()
LoadedObjects.Spawns = {} LoadedObjects.Spawns = {}
for _, v in pairs(LevelData.objects.spawns) do for _, v in pairs(LevelData.objects.spawns) do
addSpawn(v[1],unpack(v[2])) --addSpawn(v[1],unpack(v[2]))
end end
end end
@@ -121,11 +139,8 @@ function reduceLevelCanvas(horizontal,vertical)
end end
function getLevelTileData() function getLevelTileData()
for k, v in pairs(tileset) do TileData = dofile("data/tileset/"..LevelData.tileset_name..".lua")
if v == LevelData.tileset then
TileData = dofile("data/tileset/"..k..".lua")
end
end
end end
function reloadLevelTiles() function reloadLevelTiles()
@@ -159,10 +174,10 @@ end
function indexLevelTiles() function indexLevelTiles()
TileIndex = {} TileIndex = {}
local this_tileset = LevelData.tileset
-- index from tileset -- index from tileset
local width = LevelData.tileset:getPixelWidth()/tile_properties.width local width = this_tileset:getPixelWidth()/tile_properties.width
local height = LevelData.tileset:getPixelHeight()/tile_properties.height local height = this_tileset:getPixelHeight()/tile_properties.height
for i = 0, height do for i = 0, height do
for j = 0, width do for j = 0, width do
TileIndex[i*width+j+1] = love.graphics.newQuad( TileIndex[i*width+j+1] = love.graphics.newQuad(
@@ -170,7 +185,7 @@ function indexLevelTiles()
i*tile_properties.height, i*tile_properties.height,
tile_properties.width, tile_properties.width,
tile_properties.height, tile_properties.height,
LevelData.tileset:getDimensions() this_tileset:getDimensions()
) )
end end
end end
@@ -220,6 +235,9 @@ end
function instanceTile(id) function instanceTile(id)
local tile = {} local tile = {}
if type(id) == "table" then
id = id.id
end
tile.id = id tile.id = id
local Properties = TileData[tile.id] local Properties = TileData[tile.id]
@@ -258,7 +276,7 @@ function drawGridDisplay()
end end
end end
function optimizeTileObjects() function optimizeTileObjects(dest)
logPrint("Optimizing Objects...") logPrint("Optimizing Objects...")
local unoptimized = 0 local unoptimized = 0
local isTileOptimized = {} local isTileOptimized = {}
@@ -270,8 +288,9 @@ function optimizeTileObjects()
end end
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 and TileData[LevelTiles[i][j].id] then
local type = TileData[LevelTiles[i][j].id].type local tile_dat = TileData[LevelTiles[i][j].id]
local type = tile_dat.type
if type == "whole" and not isTileOptimized[i][j] then if type == "whole" and not isTileOptimized[i][j] then
isTileOptimized[i][j] = true isTileOptimized[i][j] = true
local n = 1 local n = 1
@@ -337,29 +356,27 @@ function optimizeTileObjects()
base_x + tile_properties.width * tile_properties.scale * n, base_x + tile_properties.width * tile_properties.scale * n,
base_y + tile_properties.height * tile_properties.scale * m base_y + tile_properties.height * tile_properties.scale * m
) )
table.insert(LoadedObjects.Collisions,col) table.insert(dest,col)
end end
end end
end end
end end
logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions) --logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions)
end end
function createTileObjects() -- currently broken
LoadedObjects.Collisions = {} function createTileObjects(dest)
LoadedObjects.Platforms = {}
LoadedObjects.Ladders = {}
LoadedObjects.Hazards = {}
optimizeTileObjects()
optimizeTileObjects(dest.collisions)
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 then
local tile_dat = TileData[LevelTiles[i][j].id] or {}
local type = TileData[LevelTiles[i][j].id].type local type = tile_dat.type
local light = TileData[LevelTiles[i][j].id].light local light = tile_dat.light
local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height) local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height)
local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height) local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height)
@@ -372,6 +389,9 @@ function createTileObjects()
) )
end end
local col
local list = dest.collisions
-- wholes are handled in optimization now -- wholes are handled in optimization now
--[[if type == "whole" then --[[if type == "whole" then
local col = Collision:new( local col = Collision:new(
@@ -383,33 +403,33 @@ function createTileObjects()
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
else]]if type == "half_bottom" then else]]if type == "half_bottom" then
local col = Collision:new( col = Collision:new(
base_x, base_x,
base_y + tile_properties.height/2 * tile_properties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_top" then elseif type == "half_top" then
local col = Collision:new( col = Collision:new(
base_x, base_x,
base_y , base_y ,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height/2 * tile_properties.scale base_y + tile_properties.height/2 * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_right" then elseif type == "half_right" then
local col = Collision:new( col = Collision:new(
base_x + tile_properties.height/2 * tile_properties.scale, base_x + tile_properties.height/2 * tile_properties.scale,
base_y, base_y,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_left" then elseif type == "half_left" then
@@ -580,7 +600,8 @@ function createTileObjects()
end end
elseif type == "ladder_right" then -- TODO: fix ladders
--[[elseif type == "ladder_right" then
local ladder = Collision:new( local ladder = Collision:new(
base_x + (tile_properties.width-4)* tile_properties.scale, base_x + (tile_properties.width-4)* tile_properties.scale,
@@ -638,7 +659,7 @@ function createTileObjects()
) )
table.insert(LoadedObjects.Platforms,plat) table.insert(LoadedObjects.Platforms,plat)
elseif type == "bottom_hazard" then ]]elseif type == "bottom_hazard" then
local hazard = Collision:new( local hazard = Collision:new(
@@ -647,9 +668,10 @@ function createTileObjects()
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Hazards,hazard) list = dest.hazards
end end
table.insert(list, col)
end end
end end
end end

View File

@@ -26,12 +26,12 @@ end
function Light:kill() function Light:kill()
if self.id ~= nil then if self.id ~= nil then
table.remove(LoadedObjects.Lights,self.id)
for _, e in pairs(LoadedObjects.Lights) do for _, e in pairs(LoadedObjects.Lights) do
if e.id > self.id then if e.id > self.id then
e.id = e.id - 1 e.id = e.id - 1
end end
end end
table.remove(LoadedObjects.Lights,self.id)
end end
self = nil self = nil
end end

View File

@@ -8,20 +8,22 @@ function math.sign(x)
end end
end end
function vector(init_x, init_y, final_x, final_y) function math.round(x)
local distance_x = final_x - init_x return math.floor(x+0.5)
local distance_y = final_y - init_y end
return {distance_x, distance_y}
function vector(x, y)
return {x = x, y = y}
end end
function getVectorValue(vector) function getVectorValue(vector)
return math.sqrt(vector[1] ^ 2 + vector[2] ^ 2) return math.sqrt(vector.x ^ 2 + vector.y ^ 2)
end end
function getAngleFromVector(x,y) function getAngleFromVector(vector)
local reduce = 0 local reduce = 0
if x < 0 then if vector.x < 0 then
reduce = math.rad(180) reduce = math.rad(180)
end end
return math.atan(y/x) - reduce return math.atan(vector.y/vector.x) - reduce
end end

View File

@@ -25,10 +25,7 @@ function isThereObjectAt(x,y,objectType)
for _, object in pairs(objectType) do for _, object in pairs(objectType) do
if object.is_disabled then if object.is_disabled then
-- Dont calculate if dissabled -- Dont calculate if dissabled
elseif x >= object.from.x elseif object:asRect():containsPoint(Point:new(x, y)) then
and x <= object.to.x
and y >= object.from.y
and y <= object.to.y then
object.is_colliding = true object.is_colliding = true
return true return true
end end
@@ -36,14 +33,6 @@ function isThereObjectAt(x,y,objectType)
return false return false
end end
function isThereCollisionAt(x,y)
if x >= 0 and x < #CollisionTable
and y >= 0 and y < #CollisionTable[0] then
return CollisionTable[math.floor(y)][math.floor(x)]
end
return false
end
-- flags -- flags
function setCollisionFlags() function setCollisionFlags()
local Check = { local Check = {

37
code/point.lua Normal file
View File

@@ -0,0 +1,37 @@
Point = {}
Point.__index = Point
function Point:new(x, y)
local o = { x = x or 0, y = y or 0 }
setmetatable(o, self)
return o
end
function Point:__add(other)
return Point:new(self.x+other.x, self.y+other.y)
end
function Point:__sub(other)
return Point:new(self.x-other.x, self.y-other.y)
end
function Point:__mul(n)
return Point:new(self.x*n, self.y*n)
end
function Point:__div(n)
return Point:new(self.x/n, self.y/n)
end
-- absolute value, or the distance from the origin
function Point:abs()
return math.sqrt(self.x ^ 2 + self.y ^ 2)
end
function Point:__tostring()
return "("..self.x..","..self.y..")"
end
function Point:copy()
return Point:new(self.x, self.y)
end

86
code/rect.lua Normal file
View File

@@ -0,0 +1,86 @@
-- based of of plan9's Rectangle struct
-- rect.max is not counted as "in" the rectangle
Rect = {}
Rect.__index = Rect
function Rect:fromPoints(pt1, pt2)
local o = { min = pt1, max = pt2 }
setmetatable(o, self)
return o
end
function Rect:getPoints()
return self.min, self.max
end
function Rect:fromCoords(x1, y1, x2, y2)
return Rect:fromPoints(Point:new(x1, y1), Point:new(x2, y2))
end
function Rect:getCoords()
return self.min.x, self.min.y, self.max.x, self.max.y
end
-- clone refers to a deep copy
function Rect:clone()
return Rect:fromCoords(self.min.x, self.min.y, self.max.x, self.max.y)
end
-- make sure min and max refer to the correct corners
-- acts in place, returns self
function Rect:fix()
if self.min.x > self.max.x then
self.min.x, self.max.x = self.max.x, self.min.x
end
if self.min.y > self.max.y then
self.min.y, self.max.y = self.max.y, self.min.y
end
end
function Rect:width()
return self.max.x - self.min.x
end
function Rect:height()
return self.max.y - self.min.y
end
function Rect:size()
return Point:new(self:width(), self:height())
end
function Rect:__add(pt)
return Rect:fromPoints(self.min + pt, self.max + pt)
end
function Rect:corners()
return {
self.min:copy(), -- top left
Point:new(self.max.x, self.min.y), -- top right
Point:new(self.min.x, self.max.y), -- bottom left
self.max:copy(), -- bottom right
}
end
function Rect:containsPoint(pt)
return pt.x >= self.min.x
and pt.y >= self.min.y
and pt.x <= self.max.x
and pt.y <= self.max.y
end
function Rect:overlapsRect(other)
return self.min.x < other.max.x
and self.max.x > other.min.x
and self.min.y < other.max.y
and self.max.y > other.min.y
end
function Rect:draw(style)
love.graphics.rectangle(style, self.min.x - Camera.pos.x, self.min.y - Camera.pos.y, self:width(), self:height())
end
function Rect:__tostring()
return "Rect["..tostring(self.min).." "..tostring(self.max).."]"
end

View File

@@ -7,12 +7,16 @@ require "data/sfx"
require "code/locale" require "code/locale"
-- support functions -- support functions
require "code/serialize"
require "code/math" require "code/math"
require "code/draw" require "code/draw"
require "code/hex" require "code/hex"
require "code/in_out" require "code/in_out"
-- classes -- classes
require "code/point"
require "code/rect"
require "code/chunk"
require "code/objects" require "code/objects"
require "code/level" require "code/level"
require "code/camera" require "code/camera"

31
code/serialize.lua Normal file
View File

@@ -0,0 +1,31 @@
local function quote(str, lvl)
--lvl = lvl or
local rp = "]"..(lvl or "").."]"
if string.match(str, rp) then
return quote(str, (lvl or "") .. "=")
end
return "["..(lvl or "").."["..str..rp
end
function serialize_lua_value(val)
if type(val) == "number" then
return tostring(val)
elseif type(val) == "string" then
-- TODO: use different quotes if ']]' appears in the value
return quote(val)
elseif type(val) == "table" then
local r = "{"
for k, v in pairs(val) do
r = r .. "[ "..serialize_lua_value(k).." ]="..serialize_lua_value(v)..","
end
return r .. "}"
elseif val == nil then
return "nil"
elseif val == false then
return "false"
elseif val == true then
return "true"
end
error("serialization failed")
end

View File

@@ -10,6 +10,253 @@ end
function activateSpawns() function activateSpawns()
for _, spawn in pairs(LoadedObjects.Spawns) do for _, spawn in pairs(LoadedObjects.Spawns) do
spawn.archetype:new(unpack(spawn.args)) spawn.archetype:new(unpack(spawn.args))
end
end
function deselectSpawns()
for _, spawn in pairs(LoadedObjects.Spawns) do
spawn.selected = nil
end
end
function selectSpawns(rect)
local x, y = rect:getPoints()
local select_rect = Rect:fromPoints(x-{x=Camera.pos.x,y=Camera.pos.y},y-{x=Camera.pos.x,y=Camera.pos.y})
select_rect:fix()
for _, spawn in pairs(LoadedObjects.Spawns) do
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
local left = spawn.args[1] - Camera.pos.x - offset_x
local top = spawn.args[2] - Camera.pos.y - offset_y
local right = spawn.args[1] - Camera.pos.x + offset_x
local bottom = spawn.args[2] - Camera.pos.y + offset_y
local spawn_rect = Rect:fromCoords(left, top, right, bottom)
if spawn_rect:overlapsRect(select_rect) then
spawn.selected = true
end
if spawn.selected then
love.graphics.setColor(0,1,1,1)
else
love.graphics.setColor(0,1,0,1)
end
love.graphics.rectangle("fill",left-2,top-2,4,4)
love.graphics.rectangle("fill",right-2,bottom-2,4,4)
love.graphics.setColor(1,1,1,1)
end
end
function moveSpawns(x,y)
local move_x = nil
local move_y = nil
for _, spawn in pairs(LoadedObjects.Spawns) do
if spawn.selected then
local difference_x = math.floor((x/game.scale)+Camera.pos.x) - spawn.args[1]
local difference_y = math.floor((y/game.scale)+Camera.pos.y) - spawn.args[2]
if move_x == nil or Point.abs({x=difference_x,y=difference_y}) < Point.abs({x=move_x,y=move_y}) then
move_x = difference_x
move_y = difference_y
end
end
end
for _, spawn in pairs(LoadedObjects.Spawns) do
if spawn.selected then
spawn.args[1] = spawn.args[1] + move_x
spawn.args[2] = spawn.args[2] + move_y
end
end
end
function promptSpawnNew()
Prompt:cancelActive()
local text = ""
local prompt = Prompt:new({
name = "new spawn",
input = text,
func = function(prompt)
local f = loadstring("return {"..prompt.input.."}")
if f ~= nil then
local succ, result = pcall(f)
local arch = result[1]
local args = {}
if #result > 1 then
for i=2, #result+1 do
print("arg #"..i-1)
args[i-1] = result[i]
if i < 4 then
args[i-1] = math.floor(args[i-1])
end
end
else
args = {0,0}
end
print("new entity spawn --",succ)
if not succ
or checkArchetypeInvalid(arch)
then
print("invalid input for prompt "..prompt.name)
else
print("archetype: ",arch.type)
print("args: ",unpack(args))
addSpawn(arch, unpack(args))
end
else
print("invalid input for prompt "..prompt.name)
end
end,
})
prompt.pos.x = 0
prompt.pos.y = 10
prompt:activate()
end
function deleteSpawn()
for i=1, #LoadedObjects.Spawns do
if LoadedObjects.Spawns[i]
and LoadedObjects.Spawns[i].selected then
table.remove(LoadedObjects.Spawns,i)
break
end
end
end
function checkArchetypeInvalid(arch)
return type(arch) ~= "table" or type(arch.type) ~= "string"
end
function promptSpawnArchetype()
Prompt:cancelActive()
for _, spawn in pairs(LoadedObjects.Spawns) do
if spawn.selected then
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
local text = ""
for i=1, #spawn.args do
if i > 1 then text = text .. ", " end
text = text .. tostring(spawn.args[i])
end
local prompt = Prompt:new({
name = "archetype",
input = spawn.archetype.type,
spawn = spawn,
func = function(prompt)
print("return "..prompt.input)
local f = loadstring("return "..prompt.input)
if f ~= nil then
local succ, arch = pcall(f)
print("archetype changed --",succ)
print("from: ", spawn.archetype.type)
if not succ
or checkArchetypeInvalid(arch)
then
arch = spawn.archetype
end
print("to: ", arch.type)
spawn.archetype = arch
else
print("invalid input for prompt "..prompt.name)
end
end,
})
prompt.pos.x = (spawn.args[1]-4)*game.scale - Camera.pos.x - offset_x
prompt.pos.y = (spawn.args[2]-20)*game.scale - Camera.pos.y - offset_y
prompt:activate()
end
end
end
function checkArgsInvalid(args)
for _, arg in pairs(args) do
-- this is checking the args are not nil variables
if arg == nil
or arg == ""
then
return true
end
end
end
function promptSpawnArgs()
Prompt:cancelActive()
for _, spawn in pairs(LoadedObjects.Spawns) do
if spawn.selected then
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
local text = ""
for i=1, #spawn.args do
if i > 1 then text = text .. ", " end
text = text .. tostring(spawn.args[i])
end
local prompt = Prompt:new({
name = "args",
input = text,
func = function(prompt)
local f = loadstring("return {"..prompt.input.."}")
if f ~= nil then
local succ, args = pcall(f)
print("args changed --",succ)
print("from: ", unpack(args))
if not succ
or checkArgsInvalid(args)
then
args = spawn.args
end
print("to: ", unpack(args))
spawn.args = args
else
print("invalid input for prompt "..prompt.name)
end
end,
})
prompt.pos.x = (spawn.args[1]-4)*game.scale - Camera.pos.x - offset_x
prompt.pos.y = (spawn.args[2]-4)*game.scale - Camera.pos.y - offset_y
prompt:activate()
end
end
end
function drawSpawns()
for _, spawn in pairs(LoadedObjects.Spawns) do
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
love.graphics.setColor(1,1,1,1)
spawn.archetype.display:draw(
spawn.args[1] - Camera.pos.x - offset_x,
spawn.args[2] - Camera.pos.y - offset_y
)
if spawn.selected then
love.graphics.setColor(0,1,1,1)
else
love.graphics.setColor(0,1,0,1)
end
love.graphics.rectangle(
"line",
spawn.args[1] - Camera.pos.x - offset_x,
spawn.args[2] - Camera.pos.y - offset_y,
spawn.args[1] - Camera.pos.x + offset_x - (spawn.args[1] - Camera.pos.x - offset_x),
spawn.args[2] - Camera.pos.y + offset_y - (spawn.args[2] - Camera.pos.y - offset_y)
)
if spawn.selected then
local text = spawn.archetype.type.."\n---\nPosition\n["..spawn.args[1]..","..spawn.args[2].."]"
if #spawn.args > 2 then
text = text .. "\n---\nData:\n"
for i=3, #spawn.args do
if i > 3 then text = text .. ", " end
text = text .. tostring(spawn.args[i])
end
end
drawTextBox(
text,
spawn.args[1] - Camera.pos.x + 20,
spawn.args[2] - Camera.pos.y
)
end
end end
end end

View File

@@ -5,6 +5,40 @@ function addElement(self)
self.id = #UIElement self.id = #UIElement
end end
function drawTextBox(text,x,y,style)
local style = style or {}
local c1, c2, c3, a = love.graphics.getColor()
local width = locale_font:getWidth(text)
local height = locale_font:getHeight(text)
local color = style.color or {1,1,1,1}
local background_color = style.background_color or {0,0,0,1}
local margin = style.margin or 5
local lines = 1
for i in text:gmatch("\n") do
lines = lines + 1
end
love.graphics.setColor(unpack(color))
love.graphics.rectangle("fill",
x-1,
y-1,
width+margin*2+2,
height*lines+margin*2+2
)
love.graphics.setColor(unpack(background_color))
love.graphics.rectangle("fill",
x,
y,
width+margin*2,
height*lines+margin*2
)
love.graphics.setColor(unpack(color))
love.graphics.print(text, x+margin, y+margin)
love.graphics.setColor(c1,c2,c3,a)
end
require "code/ui/button" require "code/ui/button"
require "code/ui/dialog" require "code/ui/dialog"
require "code/ui/prompt" require "code/ui/prompt"

View File

@@ -4,12 +4,12 @@ local function backspace(text)
local byteoffset = utf8.offset(text, -1) local byteoffset = utf8.offset(text, -1)
if byteoffset then if byteoffset then
-- remove the last UTF-8 character. -- remove the last UTF-8 character.
-- string.sub operates on bytes rather than UTF-8 characters, -- string.sub operates on bytes rather than UTF-8 characters,
-- so we couldn't do string.sub(text, 1, -2). -- so we couldn't do string.sub(text, 1, -2).
return string.sub(text, 1, byteoffset - 1) return string.sub(text, 1, byteoffset - 1)
end end
return "" return ""
end end
@@ -20,9 +20,15 @@ Prompt = {
name = "input", name = "input",
canceled = false, canceled = false,
closing = false, closing = false,
color = {1,1,1,1},
background_color = {0,0,0,1},
active_prompt = nil, active_prompt = nil,
} }
function Prompt:cancelActive()
if Prompt.active_prompt then
Prompt.active_prompt.canceled = true
end
end
function Prompt:new(o) function Prompt:new(o)
o = o or {} o = o or {}
@@ -44,7 +50,7 @@ function Prompt:keypressed(key, scancode, isrepeat)
end end
function Prompt:update() function Prompt:update()
end end
function Prompt:textinput(text) function Prompt:textinput(text)
@@ -52,7 +58,15 @@ function Prompt:textinput(text)
end end
function Prompt:draw() function Prompt:draw()
love.graphics.print(self.name .. ": " .. self.input, self.pos.x, self.pos.y) drawTextBox(
self.name .. ": " .. self.input,
self.pos.x,
self.pos.y,
{
color = self.color,
background_color = self.background_color
}
)
end end
function Prompt:activate() function Prompt:activate()
@@ -65,4 +79,3 @@ local test_prompt = Prompt:new()
assert(test_prompt.name == "input") assert(test_prompt.name == "input")
test_prompt.name = "foobar" test_prompt.name = "foobar"
assert(Prompt.name == "input") assert(Prompt.name == "input")

View File

@@ -35,11 +35,11 @@ animation.cursed_book.flying = {
animation.cursed_book.spawn = { animation.cursed_book.spawn = {
path = "assets/entities/cursed_book/spawn", path = "assets/entities/cursed_book/spawn",
frames = { frames = {
0, 1/3,
0, 1/3,
0, 1/3,
0, 1/3,
0 1/3
} }
} }
@@ -140,6 +140,15 @@ animation.moth_mask.fall = {
1/8 1/8
} }
} }
animation.moth_mask.slide = {
path = "assets/entities/nancy/moth_mask/slide",
frames = {
1/8,
1/8,
1/8
}
}
animation.moth_mask.jump = { animation.moth_mask.jump = {
path = "assets/entities/nancy/moth_mask/jump", path = "assets/entities/nancy/moth_mask/jump",
frames = { frames = {
@@ -179,6 +188,14 @@ animation.nancy.fall = {
1/8 1/8
} }
} }
animation.nancy.slide = {
path = "assets/entities/nancy/slide",
frames = {
1/8,
1/8,
1/8
}
}
animation.nancy.jump = { animation.nancy.jump = {
path = "assets/entities/nancy/jump", path = "assets/entities/nancy/jump",
frames = { frames = {

View File

@@ -1,42 +0,0 @@
return {
name = "Dev Level",
tileset = tileset.library,
properties = {
darkness = false
},
tiles = {
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 13, 13, 13, 13, 13, 13, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
},
objects = {
spawns = {
{Fairy,{100,88}},
{HookAnchor,{200,89,100}},
{HookAnchor,{400,89,120}}
},
rooms = {
{{96,64},{544,320}},
{{0,0},{112,176}}
},
},
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
return {[ [[tileset]] ]=[[library]],[ [[chunks]] ]={[ 1 ]={[ 1 ]=[[global.lua]],},},[ [[name]] ]=[[unnamed]],[ [[properties]] ]={[ [[darkness]] ]=false,},}

View File

@@ -6,9 +6,10 @@ function love.load()
secs = 0 secs = 0
menu_type = "no" menu_type = "no"
-- FIXME: this overrides a standard library!
debug = false debug = false
debug_collision = false debug_collision = false
editor_mode = false --editor_mode = false
text_size = 1 text_size = 1
@@ -103,6 +104,15 @@ function love.update(dt)
return return
end end
if Keybind:checkPressed(Keybind.debug.editor) then
if editor.active then
deselectSpawns()
createTileObjects()
restartGame()
end
editor.active = not editor.active
end
if love.keyboard.isDown("f7") then if love.keyboard.isDown("f7") then
local test_prompt = Prompt:new({ local test_prompt = Prompt:new({
name = "test prompt", name = "test prompt",
@@ -127,7 +137,7 @@ function love.update(dt)
if menu_type ~= nil then stepMenu(menu_type) end if menu_type ~= nil then stepMenu(menu_type) end
--editor --editor
if editor_mode then if editor.active then
stepEditor() stepEditor()
else else
stepGame() stepGame()
@@ -136,7 +146,7 @@ end
function love.wheelmoved(_, y) function love.wheelmoved(_, y)
if editor_mode then if editor.active then
scrollEditor(y) scrollEditor(y)
end end
end end
@@ -150,7 +160,7 @@ function love.draw()
game_resize = false game_resize = false
end end
if editor_mode then if editor.active then
drawEditor() drawEditor()
else else
drawGame() drawGame()