Compare commits

...

76 Commits

Author SHA1 Message Date
lustlion
9a20b172af fix fix
last commit
2022-03-17 11:53:48 +01:00
lustlion
a01599c001 fix last commit 2022-03-17 11:52:58 +01:00
lustlion
410c00dcd4 Replaced the id system with a simple flag for deletion 2022-03-17 11:46:10 +01:00
binarycat
8edcbe2d9b use class() in more places 2022-03-16 21:01:04 -04:00
lustlion
fa62e1428b swapped obsolete supertype for getAncestors() 2022-03-17 01:40:35 +01:00
binarycat
9be52e2b5f real real bugfix 2022-03-16 20:38:57 -04:00
binarycat
a3074acb3c real bugfix 2022-03-16 20:36:45 -04:00
binarycat
59726dc2b7 bugfix 2022-03-16 20:34:23 -04:00
lustlion
f0a9c1acf9 added getAncestors() 2022-03-17 01:26:59 +01:00
binarycat
1549976382 add class() for easy definition of classes 2022-03-16 19:59:42 -04:00
lustlion
d20e5392f8 Decoration now acts as parent for specific decorations better.
added candelabra decoration.
2022-03-17 00:39:47 +01:00
lustlion
d359afaf97 fixed all entities instanced an entity when grabbing functions from parent Entity. now it just sets metatable 2022-03-17 00:39:18 +01:00
lustlion
11a46e6227 spawns now also display archetype* on drawing the data
*to be replaced with actual parent once the class thing is implemented?
2022-03-17 00:38:08 +01:00
lustlion
f670f6bc87 Changes on Lights
- adjusted lights so they are called to do something, instead of it 
being handled on game world 
- lights has only coordinate arguments + a table with all other optional 
ones.
- renamed a lot of lights components to radius instaed of range, as it 
was agreed before elsewhere
2022-03-17 00:37:14 +01:00
lustlion
0486787b98 changed particle png to be white so it can be tinted 2022-03-17 00:33:52 +01:00
lustlion
6ba4f4d1c9 animations now have a flag for when they update their img frame 2022-03-17 00:33:36 +01:00
binarycat
918c63c535 removed file on the wrong branch 2022-03-16 14:37:19 -04:00
binarycat
6fa7dcbeef add missing file 2022-03-16 14:33:35 -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
lustlion
9ada88f4f5 fix infinite range hook bug 2022-03-09 06:27:13 +01:00
lustlion
a230d3ed06 fixed anim speed 2022-03-09 06:06:55 +01:00
lustlion
d3796a0204 improvements to particles and animation can now have variable speed 2022-03-09 06:04:36 +01:00
lustlion
e8242f6564 i had accidentally commented out a line of the level tiles
sorry ?? XD
2022-03-08 09:41:15 +01:00
lustlion
0acbfd5e9d more naming convention
now there are spawn objects!
now entity spawns are loaded from level!
now entity spawns are saved to level!
2022-03-08 09:34:51 +01:00
lustlion
a8ffae726f fix offset in creating rooms 2022-03-07 04:22:10 +01:00
lustlion
59a21aa655 now rooms are saved with level 2022-03-07 04:10:55 +01:00
lustlion
081fd99d04 fix editor not being able to exit 2022-03-07 03:58:01 +01:00
lustlion
5c9fc39fad added specific action keybinds to the editor 2022-03-06 16:33:45 +01:00
lustlion
05bf757ea5 naming conventions act 2: the end 2022-03-06 09:35:45 +01:00
binarycat
edd064c2fd improve Prompt and use it to ask for level and file name when exporting 2022-03-05 14:29:01 -05:00
binarycat
8cfc6a9d18 cleaned up file stuff in ExportLevel 2022-03-05 14:00:27 -05:00
binarycat
70958c5762 add Prompt 2022-03-05 13:46:33 -05:00
56 changed files with 2073 additions and 1037 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 B

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 B

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 97 B

View File

@@ -1,6 +1,6 @@
Animation = {} Animation = {}
function Animation:new(anim_data) function Animation:new(anim_data,speed)
local o = {} local o = {}
o.path = anim_data.path o.path = anim_data.path
@@ -8,12 +8,19 @@ function Animation:new(anim_data)
o.imgs = anim_data.imgs o.imgs = anim_data.imgs
o.subframe = 0 o.subframe = 0
o.frame = 1 o.frame = 1
o.speed = speed or 1
o.was_updated = false
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
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
@@ -44,13 +51,17 @@ end
-- to linearly animate -- to linearly animate
function Animation:animate() function Animation:animate()
if self.was_updated then
self.was_updated = false
end
if self.frames[self.frame] ~= 0 then if self.frames[self.frame] ~= 0 then
-- try to animate -- try to animate
self.subframe = self.subframe + current_dt self.subframe = self.subframe + self.speed
if self.subframe > self.frames[self.frame] then if self.subframe > self.frames[self.frame]*game.framerate then
self.subframe = self.subframe - self.frames[self.frame] self.subframe = self.subframe - self.frames[self.frame]*game.framerate
self.frame = self.frame + 1 self.frame = self.frame + 1
self.was_updated = true
end end
-- cycle -- cycle

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

17
code/class.lua Normal file
View File

@@ -0,0 +1,17 @@
function class(super, self)
assert(super == nil or super.__index == super)
self = self or {}
self.__index = self
setmetatable(self, super)
return self
end
function getAncestors(self)
local family = self
local list = {}
while family ~= nil do
family = getmetatable(family)
table.insert(list,family)
end
return list
end

View File

@@ -1,4 +1,4 @@
Collision = {} Collision = class()
LoadedObjects.Collisions = {} LoadedObjects.Collisions = {}
LoadedObjects.Platforms = {} LoadedObjects.Platforms = {}
@@ -10,10 +10,10 @@ LoadedObjects.Rooms = {}
--[[ --[[
Collision Collision
[bool flag] isDisabled [bool flag] is_disabled
> if true used for collision > if true used for collision
[bool flag] isColliding [bool flag] is_colliding
> if true, this collision is colliding > if true, this collision is colliding
[vec2 position] from - x, y [vec2 position] from - x, y
@@ -31,7 +31,7 @@ LoadedObjects.Rooms = {}
-- can also be called with only ox and oy, where they become the width and height instead -- can also be called with only ox and oy, where they become the width and height instead
function Collision:new(ox,oy,tx,ty) function Collision:new(ox,oy,tx,ty)
local o = {isColliding = false, isDisabled = false} local o = {is_colliding = false, is_disabled = false}
if tx ~= nil and ty ~= nil then if tx ~= nil and ty ~= nil then
o.from = {x = ox, y = oy} o.from = {x = ox, y = oy}
@@ -48,7 +48,6 @@ function Collision:new(ox,oy,tx,ty)
end end
setmetatable(o, self) setmetatable(o, self)
self.__index = self
return o return o
end end
@@ -77,7 +76,7 @@ function Collision:containsPoint(x, y)
end end
function Collision:draw(color) function Collision:draw(color)
if self.isColliding == true then if self.is_colliding == true then
love.graphics.setColor(0,1,0,0.5) love.graphics.setColor(0,1,0,0.5)
elseif color == 1 then elseif color == 1 then
love.graphics.setColor(1,0,0,0.5) love.graphics.setColor(1,0,0,0.5)
@@ -88,3 +87,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

@@ -8,21 +8,19 @@ function debugUI()
love.graphics.print(light.pos.x,light.pos.x,light.pos.y+40) love.graphics.print(light.pos.x,light.pos.x,light.pos.y+40)
end end
love.graphics.print("time: ".. tostring(math.floor(100*game.secondsSinceStart)/100) .." fps: "..fps_current, 10*textScale, 0*textScale, 0, textScale) love.graphics.print("time: ".. tostring(math.floor(100*game.seconds_since_start)/100) .." fps: "..fps_current, 10*text_size, 0*text_size, 0, text_size)
love.graphics.print(--[["CPUtime: "..checkCPUTime("total")..", CPU: "..(math.floor(checkCPUTime("get")*10000)/100).."%,]] "memoryUsage: "..memoryUsage.."kB", 10*textScale, 20*textScale, 0, textScale) love.graphics.print(--[["CPUtime: "..checkCPUTime("total")..", CPU: "..(math.floor(checkCPUTime("get")*10000)/100).."%,]] "memory_usage: "..memory_usage.."kB", 10*text_size, 20*text_size, 0, text_size)
love.graphics.setColor(1,1,1) love.graphics.setColor(1,1,1)
-- lots of variables -- lots of variables
love.graphics.print("LoadedObjects",10*textScale,40*textScale, 0, textScale) love.graphics.print("LoadedObjects",10*text_size,40*text_size, 0, text_size)
local i = 1 local i = 1
for k, v in pairs(LoadedObjects) do for k, v in pairs(LoadedObjects) do
if type(v) == "table" then if type(v) == "table" then
love.graphics.print("<"..k.."> ".. #v,10*textScale,(40+(10*i))*textScale, 0, textScale) love.graphics.print("<"..k.."> ".. #v,10*text_size,(40+(10*i))*text_size, 0, text_size)
i = i + 1 i = i + 1
end end
end end
-- player isOnGroundCheck
--love.graphics.main_Player
love.graphics.setColor(1,0,0) love.graphics.setColor(1,0,0)
end end
@@ -34,7 +32,7 @@ end
function debugEntities() function debugEntities()
love.graphics.setScale(game.scale) love.graphics.setScale(game.scale)
for _, particle in pairs(LoadedParticles) do for _, particle in pairs(LoadedObjects.Particles) do
particle:debug() particle:debug()
end end
for _, enty in pairs(LoadedObjects.Entities) do for _, enty in pairs(LoadedObjects.Entities) do

View File

@@ -37,8 +37,8 @@ function Demo:startRecord()
os.execute( "mkdir \"./demos\"" ) os.execute( "mkdir \"./demos\"" )
DemoFile = io.open("demos/play_demo.lua", "w+") DemoFile = io.open("demos/play_demo.lua", "w+")
--DemoFile = io.open("demo/mothbackDemo_"..os.date("%Y-%m-%d_%H-%M-%S")..".lua", "w+") --DemoFile = io.open("demo/mothbackDemo_"..os.date("%Y-%m-%d_%H-%M-%S")..".lua", "w+")
DemoFile:write("main_Player.pos.x = "..main_Player.pos.x.."\n") DemoFile:write("main_player.pos.x = "..main_player.pos.x.."\n")
DemoFile:write("main_Player.pos.y = "..main_Player.pos.y.."\n") DemoFile:write("main_player.pos.y = "..main_player.pos.y.."\n")
DemoFile:write("DemoAction = {\n") DemoFile:write("DemoAction = {\n")
DemoRecording = true DemoRecording = true
CurrentDemoFrame = 1 CurrentDemoFrame = 1

View File

@@ -1,10 +1,38 @@
assert(editor == nil) assert(editor == nil)
editor = { room_mode = false } editor = {
active = false,
room_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()
palette = palette or false
AnimateTiles() animateTiles()
if Keybind:CheckPressed(Keybind.editor.room_mode) then
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 love.keyboard.isDown("lshift") then if love.keyboard.isDown("lshift") then
editor.room_mode = "delete" editor.room_mode = "delete"
else else
@@ -12,34 +40,34 @@ 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) then editor.palette.active = not editor.palette.active
if palette then
palette = false
palette_scroll_x = nil
palette_scroll_y = nil
else
palette = true
palette_scroll_x = 0
palette_scroll_y = 0
end
end
-- TODO:
if love.keyboard.isDown('a',"left") then
Camera.pos.x = Camera.pos.x - 3/game.scale
end
if love.keyboard.isDown('d',"right") then
Camera.pos.x = Camera.pos.x + 3/game.scale
end
if love.keyboard.isDown("up", "w") then
Camera.pos.y = Camera.pos.y - 3/game.scale
end
if love.keyboard.isDown("down", "s") then
Camera.pos.y = Camera.pos.y + 3/game.scale
end end
if palette then
if Keybind:CheckPressed(Keybind.debug.debug) then local cvel = Point:new(0, 0)
if Keybind:checkDown(Keybind.editor.left) then
cvel.x = -1
end
if Keybind:checkDown(Keybind.editor.right) then
cvel.x = 1
end
if Keybind:checkDown(Keybind.editor.up) then
cvel.y = -1
end
if Keybind:checkDown(Keybind.editor.down) then
cvel.y = 1
end
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
local next = false local next = false
local export = nil local export = nil
for k, v in pairs(tileset) do for k, v in pairs(tileset) do
@@ -59,30 +87,39 @@ function stepEditor()
if next then if next then
LevelData.tileset = export LevelData.tileset = export
end end
LevelGetTileData() getLevelTileData()
LevelIndexTiles() indexLevelTiles()
end end
end end
if Keybind:CheckPressed(Keybind.debug.reload) then if Keybind:checkPressed(Keybind.editor.save) then
ExportLevel("test") Prompt:new({
end name = "level name",
input = "unnamed",
if Keybind:CheckPressed(Keybind.debug.editor) then func = function(name_prompt)
editor_mode = false if name_prompt.canceled then return end
TileCreateObjects() Prompt:new({
name = "filename",
input = "level.lua",
func = function(file_prompt)
if file_prompt.canceled then return end
exportLevel(name_prompt.input, file_prompt.input)
end,
}):activate()
end,
}):activate()
end end
end end
function scrollEditor(y) function scrollEditor(y)
if palette 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
@@ -93,47 +130,60 @@ function drawEditor()
drawGridDisplay() drawGridDisplay()
drawGameworldForeground() drawGameworldForeground()
endGameworldDraw() endGameworldDraw()
doEditorEdit()
drawEditorRooms() drawEditorRooms()
drawSpawns()
doEditorEdit()
drawSelectingPaletteTile() drawSelectingPaletteTile()
if palette 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()
local mouse_x = love.mouse.getX() local mouse_x = love.mouse.getX()
local mouse_y = love.mouse.getY() local mouse_y = love.mouse.getY()
local horizontal = 1+math.floor(((mouse_x/game.scale) / tileProperties.width) + (Camera.pos.x / tileProperties.width)) local horizontal = 1+math.floor(((mouse_x/game.scale) / tile_properties.width) + (Camera.pos.x / tile_properties.width))
local vertical = 1+math.floor(((mouse_y/game.scale) / tileProperties.height) + (Camera.pos.y / tileProperties.height)) local vertical = 1+math.floor(((mouse_y/game.scale) / tile_properties.height) + (Camera.pos.y / tile_properties.height))
local expand_h = 0 local expand_h = 0
local expand_v = 0 local expand_v = 0
local LevelWidth = LevelGetTileWidth() local level_width = getLevelTileWidth()
local LevelHeight = LevelGetTileHeight() local level_height = getLevelTileHeight()
if horizontal > LevelWidth then if horizontal > level_width then
expand_h = horizontal-LevelWidth expand_h = horizontal-level_width
elseif horizontal < 0 then elseif horizontal < 0 then
expand_h = horizontal expand_h = horizontal
end end
if vertical > LevelHeight then if vertical > level_height then
expand_v = vertical-LevelHeight expand_v = vertical-level_height
elseif vertical < 0 then elseif vertical < 0 then
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("> " .. LevelWidth .. "(" .. expand_h .. "), " .. LevelHeight .. "(".. 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 * tileProperties.width local rx = horizontal * tile_properties.width
local ry = vertical * tileProperties.height local ry = vertical * tile_properties.height
local r = editor.room_points local r = editor.room_points
if Keybind:CheckPressed(Keybind.generic.rclick) then if Keybind:checkPressed(Keybind.generic.rclick) then
editor.room_points = {} editor.room_points = {}
elseif Keybind:CheckPressed(Keybind.generic.lclick) then elseif Keybind:checkPressed(Keybind.generic.lclick) then
if editor.room_mode == "delete" then if editor.room_mode == "delete" then
for i, room in ipairs(LoadedObjects.Rooms) do for i, room in ipairs(LoadedObjects.Rooms) do
if room:containsPoint(rx, ry) then if room:containsPoint(rx, ry) then
@@ -145,37 +195,57 @@ function doEditorEdit()
end end
end end
if #editor.room_points == 2 then if #editor.room_points == 2 then
table.insert(LoadedObjects.Rooms, Collision:new(r[1].x,r[1].y,r[2].x,r[2].y)) table.insert(LoadedObjects.Rooms, Collision:new(r[1].x-tile_properties.width,r[1].y-tile_properties.height,r[2].x,r[2].y))
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 palette 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
LevelReloadTiles() elseif Keybind:checkPressed(Keybind.generic.lshift) then
expandLevelCanvas(math.sign(expand_h),math.sign(expand_v))
elseif Keybind:CheckPressed(Keybind.generic.lshift) then reloadLevelTiles()
LevelExpandCanvas(math.sign(expand_h),math.sign(expand_v)) elseif Keybind:checkPressed(Keybind.generic.lctrl) then
LevelReloadTiles() reduceLevelCanvas(math.sign(expand_h),math.sign(expand_v))
elseif Keybind:CheckPressed(Keybind.generic.lctrl) then reloadLevelTiles()
LevelReduceCanvas(math.sign(expand_h),math.sign(expand_v))
LevelReloadTiles()
end end
end end
end end
@@ -185,10 +255,10 @@ function drawSelectingPaletteTile()
local mouse_x = love.mouse.getX() local mouse_x = love.mouse.getX()
local mouse_y = love.mouse.getY() local mouse_y = love.mouse.getY()
local horizontal = math.floor(((mouse_x/game.scale) / tileProperties.width) + (Camera.pos.x / tileProperties.width)) local horizontal = math.floor(((mouse_x/game.scale) / tile_properties.width) + (Camera.pos.x / tile_properties.width))
local vertical = math.floor(((mouse_y/game.scale) / tileProperties.height) + (Camera.pos.y / tileProperties.height)) local vertical = math.floor(((mouse_y/game.scale) / tile_properties.height) + (Camera.pos.y / tile_properties.height))
local draw_x = tileProperties.width * horizontal - Camera.pos.x local draw_x = tile_properties.width * horizontal - Camera.pos.x
local draw_y = tileProperties.height * vertical - Camera.pos.y local draw_y = tile_properties.height * vertical - Camera.pos.y
love.graphics.draw( love.graphics.draw(
LevelData.tileset, LevelData.tileset,
@@ -200,27 +270,31 @@ function drawSelectingPaletteTile()
end end
function doEditorPalette() function doEditorPalette()
local width = LevelData.tileset:getPixelWidth()/tile_properties.width
local width = LevelData.tileset:getPixelWidth()/tileProperties.width local height = LevelData.tileset:getPixelHeight()/tile_properties.height
local height = LevelData.tileset:getPixelHeight()/tileProperties.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) * (tileProperties.width+1), (editor.palette.scroll.x + 1) * (tile_properties.width+1),
(palette_scroll_y + 1) * (tileProperties.height+1), (editor.palette.scroll.y + 1) * (tile_properties.height+1),
1 + LevelData.tileset:getPixelWidth() * ((tileProperties.width+1) / tileProperties.width), 1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
1 + LevelData.tileset:getPixelHeight()* ((tileProperties.height+1) / tileProperties.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) * (tileProperties.width+1) local tile_x = (editor.palette.scroll.x + position_x) * (tile_properties.width+1)
local tile_y = (palette_scroll_y + position_y) * (tileProperties.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,
@@ -231,22 +305,21 @@ 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 + tileProperties.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 + tileProperties.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
if Keybind:CheckDown(Keybind.generic.rclick) then if Keybind:checkDown(Keybind.generic.rclick) then
selecting_tile = nil selecting_tile = nil
end end
@@ -256,8 +329,8 @@ function doEditorPalette()
"line", "line",
tile_x, tile_x,
tile_y, tile_y,
tileProperties.width, tile_properties.width,
tileProperties.height tile_properties.height
) )
love.graphics.setColor(1,1,1,1) love.graphics.setColor(1,1,1,1)
end end
@@ -273,17 +346,47 @@ function doEditorPalette()
love.graphics.rectangle( love.graphics.rectangle(
"line", "line",
(palette_scroll_x + 1) * (tileProperties.width+1), (editor.palette.scroll.x + 1) * (tile_properties.width+1),
(palette_scroll_y + 1) * (tileProperties.height+1), (editor.palette.scroll.y + 1) * (tile_properties.height+1),
1 + LevelData.tileset:getPixelWidth() * ((tileProperties.width+1) / tileProperties.width), 1 + LevelData.tileset:getPixelWidth() * ((tile_properties.width+1) / tile_properties.width),
1 + LevelData.tileset:getPixelHeight()* ((tileProperties.height+1) / tileProperties.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

@@ -1,10 +1,12 @@
Arrow = Entity:new() Arrow = class(Entity, {
type = "Arrow",
display = Animation:new(animation.kupo.arrow),
})
function Arrow:new(x,y,rotation,speed) function Arrow:new(x,y,rotation,speed)
local o = Entity:new(x,y) local o = Entity:new(x,y)
o.type = "arrow"
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.speed = speed or 10 o.speed = speed or 10
o.sprite_rotation = rotation or 0 o.sprite_rotation = rotation or 0
@@ -24,8 +26,7 @@ function Arrow:new(x,y,rotation,speed)
to = {x = 0.5, y = 0.5} -- gameworld pixels to = {x = 0.5, y = 0.5} -- gameworld pixels
} }
table.insert(LoadedObjects.Entities,o) o:id()
o.id = #LoadedObjects.Entities
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -37,20 +38,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,9 +1,11 @@
CursedBook = Entity:new() CursedBook = class(Entity, {
type = "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)
o.type = "cursed_book"
-- behaviour -- behaviour
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.speed = 0.01 o.speed = 0.01
@@ -21,16 +23,18 @@ 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 local light_data = {}
o.light = Light:new(o.pos.x,o.pos.y,o.light_range,2,HEX2RGB("#fe00d1")) light_data.radius = 500
light_data.shine_radius = 0
table.insert(LoadedObjects.Entities,o) light_data.flicker = nil
o.id = #LoadedObjects.Entities light_data.color = nil
o.light = Light:new(o.pos.x,o.pos.y,light_data)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -38,18 +42,20 @@ function CursedBook:new(x,y)
end end
function CursedBook:doLogic() function CursedBook:doLogic()
self.target.x = main_Player.pos.x - main_Player.target_offset.x print(self.status)
self.target.y = main_Player.pos.y - main_Player.target_offset.y self.target.x = main_player.pos.x - main_player.target_offset.x
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
@@ -59,21 +65,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)
@@ -83,9 +97,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)
@@ -97,15 +111,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
@@ -115,5 +135,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,24 +1,23 @@
Decoration = Entity:new() Decoration = class(Entity, {
type = "Decoration",
supertype = Entity.type,
display = Animation:new(animation.particle.simple),
})
function Decoration:new(x,y,animation,light_radius) function Decoration:new(x,y,animation,light_data)
local o = Entity:new(x,y) local o = Entity:new(x,y)
o.type = "decoration"
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
-- animations if animation then
o.body = Animation:new(animation) o.body = Animation:new(animation)
o:centerOffset(o.body) o:centerOffset(o.body)
o:createBox(o.body) o:createBox(o.body)
if light_radius ~= nil then
o.light_radius = light_radius
o.light = Light:new(o.pos.x,o.pos.y,o.light_radius)
end end
table.insert(LoadedObjects.Entities,o) if light_data then
o.id = #LoadedObjects.Entities o.light = Light:new(o.pos.x,o.pos.y,light_data)
end
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -30,5 +29,4 @@ function Decoration:handleAnimation()
self:draw(self.body) self:draw(self.body)
end end
function Decoration:doPhysics() require "code/entities/decorations/candelabra"
end

View File

@@ -0,0 +1,54 @@
Candelabra = class(Decoration, {
type = "Candelabra",
display = Animation:new(animation.decoration.candelabra),
})
function Candelabra:new(x,y)
local light_data = {}
light_data.radius = 100
light_data.color = hex2rgb("#fed100")
local o = Decoration:new(x,y,animation.decoration.candelabra,light_data)
o.particle_rate = 5
o.particle_count = 0
setmetatable(o, self)
self.__index = self
return o
end
function Candelabra:handleAnimation()
if self.body.was_updated then
self.particle_count = self.particle_count + 1
while self.particle_count >= self.particle_rate do
local pos = math.floor(math.random(1,3))-2
local particle_data = {}
particle_data.animation = animation.particle.simple
particle_data.sprite_tint = hex2rgb("#ffffff")
particle_data.sprite_alpha_fade = true
particle_data.direction = -math.rad(90)
particle_data.speed = 0.5 + math.random(2)*0.005
particle_data.time = 0.5+math.random(0.5)
particle_data.animation_speed = 1/particle_data.time
particle_data.func = function(self)
--COSINE WAVE FUNCTION
--init variables and constants
self.t = self.t or 0
self.phase = self.phase or math.random(2*math.pi)
local dt = 0.5
local amplitude = 0.5
local frequency = 0.5/game.framerate
--calc
self.t = self.t + dt
self:moveX(amplitude*math.cos(2*math.pi*frequency*self.t+self.phase))
end
Particle:new(self.pos.x+pos*5,self.pos.y-3,particle_data)
self.particle_count = self.particle_count - self.particle_rate
end
end
Decoration.handleAnimation(self)
end

View File

@@ -1,17 +1,18 @@
Fairy = Entity:new() Fairy = class(Entity, {
type = "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)
o.type = "fairy"
-- behaviour -- behaviour
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.speed = 1.4 o.speed = 1.4
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)
@@ -19,32 +20,32 @@ function Fairy:new(x,y)
o:createBox(o.body) o:createBox(o.body)
-- light -- light
o.light_radius = 80 local light_data = {}
o.light = Light:new(o.pos.x,o.pos.y,o.light_radius,nil,HEX2RGB("#fed100")) light_data.radius = 80
light_data.shine_radius = 80
light_data.flicker = nil
light_data.color = hex2rgb("#fed100")
o.light = Light:new(o.pos.x,o.pos.y,light_data)
-- timer -- timer
o.particle_timer = 0 o.particle_timer = 0
o.particle_time = 5 o.particle_time = 5
table.insert(LoadedObjects.Entities,o)
o.id = #LoadedObjects.Entities
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
return o return o
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.y = main_player.pos.y + main_player.target_offset.y
self.target.x = main_Player.pos.x + main_Player.target_offset.x
self.target.y = main_Player.pos.y + main_Player.target_offset.y
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
@@ -52,8 +53,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
@@ -64,52 +65,69 @@ 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,
sprite_tint = HEX2RGB("#fed100"),
direction = angle-math.rad(180+math.random(60)-30),
speed = 0.8*(distance/50),
speed_increase = -0.01,
}
Particle:new(self.pos.x,self.pos.y,particle_data)
end end
end end
function Fairy:handleAnimation() 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 = {}
particle_data.animation = animation.particle.simple
particle_data.animation_speed = 1
particle_data.sprite_tint = hex2rgb("#fed100")
particle_data.sprite_alpha_fade = true
particle_data.direction = angle-math.rad(180+math.random(60)-30)
particle_data.speed = 1
particle_data.time = 0.75
particle_data.func = function(self)
self.speed = self.speed - 0.01
self.vel.x = self.speed * math.cos(self.direction)
self.vel.y = self.speed * math.sin(self.direction)
end
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
function Fairy:debug() function Fairy:debug()
Entity.debug(self) Entity.debug(self)
self:checkVisionLineDebug(main_Player,self.vision_range) self:checkVisionLineDebug(main_player,self.vision_range)
end end

View File

@@ -1,21 +1,19 @@
HookAnchor = Entity:new() HookAnchor = class(Entity, {
type = "HookAnchor",
display = Animation:new(animation.fairy.flying),
})
function HookAnchor:new(x,y,hookDistance) function HookAnchor:new(x,y,hook_distance)
local o = Entity:new(x,y) local o = Entity:new(x,y)
o.type = "hook_anchor"
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.hookDistance = hookDistance or 100 o.hook_distance = hook_distance or 100
-- animations -- animations
o.body = Animation:new(animation.fairy.flying) o.body = Animation:new(animation.fairy.flying)
o:centerOffset(o.body) o:centerOffset(o.body)
o:createBox(o.body) o:createBox(o.body)
table.insert(LoadedObjects.Entities,o)
o.id = #LoadedObjects.Entities
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
return o return o
@@ -33,14 +31,10 @@ function HookAnchor:drawBackground()
"fill", "fill",
-Camera.pos.x + self.pos.x, -Camera.pos.x + self.pos.x,
-Camera.pos.y + self.pos.y, -Camera.pos.y + self.pos.y,
self.hookDistance self.hook_distance
) )
end end
function HookAnchor:doPhysics()
end
function Fairy:debug() function Fairy:debug()
Entity.debug(self) Entity.debug(self)
end end

View File

@@ -1,10 +1,11 @@
Kupo = Entity:new() Kupo = class(Entity, {
type = "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)
o.type = "kupo"
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.speed = 20 o.speed = 20
o.range = 200 o.range = 200
@@ -27,11 +28,13 @@ function Kupo:new(x,y)
o.bow_aim_frames = 8 o.bow_aim_frames = 8
o.hostile = true o.hostile = true
o.light_radius = o.range/2 -- light values
o.light = Light:new(o.pos.x,o.pos.y,o.light_radius) local light_data = {}
light_data.radius = 100
table.insert(LoadedObjects.Entities,o) light_data.shine_radius = 20
o.id = #LoadedObjects.Entities light_data.flicker = nil
light_data.color = nil
o.light = Light:new(o.pos.x,o.pos.y,light_data)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -41,12 +44,13 @@ end
function Kupo:doLogic() function Kupo:doLogic()
self:adjustLight(self.target_offset.x,self.target_offset.y) self:adjustLight(self.target_offset.x,self.target_offset.y)
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 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
@@ -143,7 +147,7 @@ function Kupo:handleAnimation()
if self.vel.x ~= 0 then self.sprite_flip.x = math.sign(self.vel.x) end if self.vel.x ~= 0 then self.sprite_flip.x = math.sign(self.vel.x) end
self.body:animate() self.body:animate()
self:Draw(self.body) self:draw(self.body)
if self.draw_bow == true then if self.draw_bow == true then
self.bow:drawFrame( self.bow:drawFrame(
@@ -154,7 +158,3 @@ function Kupo:handleAnimation()
) )
end end
end end
function Kupo:doPhysics()
self:moveWithCollision()
end

View File

@@ -1,5 +1,8 @@
Particle = Entity:new()
LoadedObjects.Particles = {} LoadedObjects.Particles = {}
Particle = class(Entity, {
type = "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)
@@ -7,18 +10,26 @@ function Particle:new(x,y,particle_data)
o.pos = {x = x, y = y} o.pos = {x = x, y = y}
o.speed = particle_data.speed or 0 o.speed = particle_data.speed or 0
o.direction = particle_data.direction or o.direction o.direction = particle_data.direction or 0
o.sprite_rotation = particle_data.sprite_rotation or o.sprite_rotation o.sprite_rotation = particle_data.sprite_rotation or 0
o.sprite_offset = particle_data.sprite_offset or o.sprite_offset o.sprite_offset = particle_data.sprite_offset or vector(0,0)
o.sprite_scale = particle_data.sprite_scale or o.sprite_scale o.sprite_scale = particle_data.sprite_scale or vector(1,1)
o.sprite_tint = particle_data.sprite_tint or o.sprite_tint o.sprite_tint = particle_data.sprite_tint or {1,1,1}
o.sprite_alpha = particle_data.sprite_alpha or o.sprite_alpha o.sprite_alpha = particle_data.sprite_alpha or 1
o.sprite_alpha_fade = particle_data.sprite_alpha_fade or false
o.sprite_alpha_base = o.sprite_alpha o.sprite_alpha_base = o.sprite_alpha
o.sprite_flip = particle_data.sprite_flip or vector(1,1)
o.func = particle_data.func or nil
o.time = particle_data.time or nil
o.sprite_flip = particle_data.sprite_flip or o.sprite_flip if o.time then
o.animation_active = particle_data.animation_active or false if particle_data.time_unit ~= nil
and particle_data.time_unit == "frames" then
o.time = 0.5 o.time = o.time
else
o.time = o.time * game.framerate
end
end
o.timer = 0 o.timer = 0
o.vel = { o.vel = {
@@ -26,71 +37,79 @@ function Particle:new(x,y,particle_data)
y = o.speed * math.sin(o.direction) y = o.speed * math.sin(o.direction)
} }
o.speed_increase = particle_data.speed_increase or 0 if particle_data.light then
local light_data = {}
if particle_data.light ~= nil then light_data.radius = particle_data.light
o.light_range = particle_data.light light_data.shine_radius = particle_data.light_shine or nil
local flicker = particle_data.light_flicker or nil light_data.flicker = particle_data.light_flicer or nil
local color = particle_data.light_color or nil light_data.color = particle_data.light_color or nil
o.light = Light:new(o.pos.x,o.pos.y,o.light_range,flicker,color) o.light = Light:new(o.pos.x,o.pos.y,light_data)
end end
-- animations -- animations
if particle_data.animation ~= nil then if particle_data.animation then
o.body = Animation:new(particle_data.animation) o.body = Animation:new(particle_data.animation,particle_data.animation_speed)
o:centerOffset(o.body) o:centerOffset(o.body)
o:createBox(o.body) o:createBox(o.body)
if not o.animation_active then
o.body.speed = 0
end
end end
table.remove(LoadedObjects.Entities,#LoadedObjects.Entities)
table.insert(LoadedObjects.Particles,o) table.insert(LoadedObjects.Particles,o)
o.id = #LoadedObjects.Particles
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
return o return o
end end
function Particle:kill() function Particle:kill()
if self.light ~= nil then if self.light then
self.light:kill() self.light:kill()
end end
if self.id ~= nil then self.dead = true
for _, e in pairs(LoadedObjects.Particles) do
if e.id > self.id then
e.id = e.id - 1
end
end
table.remove(LoadedObjects.Particles,self.id)
end
self = nil
end end
function Particle:handleAnimation() function Particle:handleAnimation()
self.timer = self.timer + current_dt self.timer = self.timer + 1
self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
if self.light ~= nil then if self.sprite_alpha_fade ~= false then
self:adjustLight() self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
self.light.range = self.light_range * self.sprite_alpha/2
end end
if self.sprite_alpha < 0 then self:kill() end
if self.body ~= nil then if self.body then
self.body:animate() self.body:animate()
self:draw(self.body) self:draw(self.body)
end end
end end
function Particle:doPhysics() function Particle:doLogic()
-- adjust speed if self.func then
if self.speed_increase ~= 0 then self:func()
self.speed = self.speed + self.speed_increase
self.vel.x = self.speed * math.cos(self.direction)
self.vel.y = self.speed * math.sin(self.direction)
end end
-- move
self:moveWithCollision() if self.time then
if self.timer >= self.time then self:kill() end
end
end
function cleanDeadParticles()
for i=1, #LoadedObjects.Particles do
part = LoadedObjects.Particles[i]
if part.kill then
table.remove(LoadedObjects.Particles,i)
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 end
function Particle:debug() function Particle:debug()
@@ -98,3 +117,16 @@ function Particle:debug()
love.graphics.setColor(0,1,1) love.graphics.setColor(0,1,1)
love.graphics.circle("fill", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, 1) love.graphics.circle("fill", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, 1)
end end
---------------
function cleanDeadParticles()
for i=1, #LoadedObjects.Particles do
part = LoadedObjects.Particles[i]
if part and part.dead then
table.remove(LoadedObjects.Particles,i)
end
end
end
---------------

View File

@@ -1,68 +1,65 @@
Player = Entity:new() Player = class(Entity, {
type = "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)
o.type = "player"
-- physics -- physics
o.moveSpeed = 1.3 -- gameworld pixels o.zero_speed = 0.01 -- gameworld pixels
o.zeroSpeed = 0.01 -- gameworld pixels
o.move_x = 0 -- gameworld pixels o.move_x = 0 -- gameworld pixels
o.noDriftFrames = 0 -- frames o.move_speed = 1.3 -- gameworld pixels
o.airFriction = 0.01 -- gameworld pixels o.nodrift_frames = 0 -- frames
o.groundFriction = 0.3 -- gameworld pixels
o.jumpImpulse = 3.5 -- gameworld pixels o.air_friction = 0.01 -- gameworld pixels
o.ground_friction = 0.3 -- gameworld pixels
o.wall_friction = 0.3 -- gameworld pixels
o.coyoteValue = 5 -- frames o.jump_impulse = 3.5 -- gameworld pixels
o.coyoteAmount = 5 -- int
o.coyote_value = 5 -- frames
o.coyote_amount = 5 -- int
o.dashCooldownTime = 0.1 -- seconds
o.dashCooldownTimer = 0 -- seconds
-- dash values -- dash values
o.dashTimer = 0 -- seconds o.dash_timer = 0 -- seconds
o.dashTime = 0.15 -- seconds o.dash_time = 0.15 -- seconds
o.dashDistance = 40 -- gameworld pixels o.dash_distance = 40 -- gameworld pixels
o.dashSpeed = o.dashDistance / (o.dashTime*60) -- pixels o.dash_speed = o.dash_distance / (o.dash_time*60) -- pixels
o.dashCount = 1 -- int o.dash_count = 1 -- int
o.dashAmount = 10 -- int o.dash_amount = 10 -- int
o.dash_cooldown_time = 0.1 -- seconds
o.dash_cooldown_timer = 0 -- seconds
-- hook values -- hook values
o.hookSwingSpeed = math.rad(0.05) o.hook_swing_speed = math.rad(0.05)
o.hookAnchor = { o.hook_anchor = nil
x = nil,
y = nil
}
-- walljump values -- walljump values
o.walljumpNoDriftAmount = 12 o.walljump_nodrift_amount = 12
o.walljumpImpulse = { x = 2.5, y = 3.5 } o.walljump_impulse = { x = 2.5, y = 3.5 }
o.walljumpFriction = 0.3 -- gameworld pixels
-- light values
o.light_radius = 40 -- screen pixels
-- status -- status
o.canJump = true o.can_jump = true
o.canFall = true o.can_fall = true
o.canFriction = true o.can_friction = true
o.canHook = true o.can_hook = true
o.canWalljump = true o.can_walljump = true
o.isDashing = false o.is_dashing = false
o.isHooked = false o.is_hooked = false
o.isSliding = false o.is_sliding = false
o.isJumping = false o.is_jumping = false
o.isOnGround = false o.is_on_ground = false
o.isOnLadder = false o.is_on_ladder = false
o.maskType = animation.moth_mask o.mask_type = animation.moth_mask
o.wallHit = 0 o.wall_hit = 0
o.anchorRespawn = { o.respawn_anchor = {
x = o.pos.x, x = o.pos.x,
y = o.pos.y y = o.pos.y
} }
@@ -71,14 +68,17 @@ function Player:new(x,y)
o.target_offset = {x = 0, y = 0} o.target_offset = {x = 0, y = 0}
o.body = Animation:new(animation.nancy.idle) o.body = Animation:new(animation.nancy.idle)
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) local light_data = {}
light_data.radius = 40
table.insert(LoadedObjects.Entities,o) light_data.shine_radius = 20
o.id = #LoadedObjects.Entities light_data.flicker = nil
light_data.color = nil
o.light = Light:new(o.pos.x,o.pos.y,light_data)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -86,67 +86,69 @@ function Player:new(x,y)
end end
function Player:doLogic() function Player:doLogic()
self:adjustLight(self.target_offset.x,self.target_offset.y)
-- reset coyoteValue -- reset coyote_value
if self.isOnGround then if self.is_on_ground then
self.coyoteValue = self.coyoteAmount self.coyote_value = self.coyote_amount
elseif self.coyoteValue > 0 then elseif self.coyote_value > 0 then
self.coyoteValue = self.coyoteValue - 1 self.coyote_value = self.coyote_value - 1
end end
-- not dashing, normal movment -- not dashing, normal movment
if self.dashTimer <= 0 then if self.dash_timer <= 0 then
-- horizontal movement -- horizontal movement
if not self.isHooked then if not self.is_hooked then
if self.noDriftFrames > 0 then if self.nodrift_frames > 0 then
self.move_x = 0 self.move_x = 0
elseif Keybind:CheckDown(Keybind.move.left) then elseif Keybind:checkDown(Keybind.move.left) then
self.move_x = -1 self.move_x = -1
self.vel.x = math.min(self.vel.x, -self.moveSpeed) self.vel.x = math.min(self.vel.x, -self.move_speed)
elseif Keybind:CheckDown(Keybind.move.right) then elseif Keybind:checkDown(Keybind.move.right) then
self.move_x = 1 self.move_x = 1
self.vel.x = math.max(self.vel.x, self.moveSpeed) self.vel.x = math.max(self.vel.x, self.move_speed)
end end
end end
-- jump if on ground (coyotevalue) or if 0 -- jump if on ground (coyotevalue) or if 0
if self.canJump and Keybind:CheckPressed(Keybind.move.jump) then if self.can_jump and Keybind:checkPressed(Keybind.move.jump) then
if self.canWalljump and self.wallHit ~= 0 then if self.can_walljump and self.wall_hit ~= 0 then
self.isSliding = false self.is_sliding = false
self.vel.y = -self.walljumpImpulse.y self.vel.y = -self.walljump_impulse.y
self.vel.x = -self.walljumpImpulse.x * self.wallHit self.vel.x = -self.walljump_impulse.x * self.wall_hit
self.move_x = 0 self.move_x = 0
self.sprite_flip.x = -self.sprite_flip.x self.sprite_flip.x = -self.sprite_flip.x
self.noDriftFrames = self.walljumpNoDriftAmount self.nodrift_frames = self.walljump_nodrift_amount
elseif self.coyoteValue > 0 then elseif self.coyote_value > 0 then
self.vel.y = -self.jumpImpulse self.vel.y = -self.jump_impulse
self.coyoteValue = 0 self.coyote_value = 0
end end
end end
end end
-- dash timer -- dash timer
self.dashCooldownTimer = math.max(0,self.dashCooldownTimer - current_dt) self.dash_cooldown_timer = math.max(0,self.dash_cooldown_timer - current_dt)
-- try to dash -- try to dash
if Keybind:CheckDown(Keybind.move.dash) then if Keybind:checkDown(Keybind.move.dash) then
if self.dashCooldownTimer == 0 if self.dash_cooldown_timer == 0
and not self.isDashing and not self.is_dashing
and self.dashCount > 0 then and self.dash_count > 0 then
self:unhook() self:unhook()
self.nodrift_frames = 0
-- state player -- state player
self.isDashing = true self.is_dashing = true
self.dashCount = self.dashCount - 1 self.is_sliding = false
self.dash_count = self.dash_count - 1
-- get dash direction -- get dash direction
local vertical = 0 local vertical = 0
if Keybind:CheckDown(Keybind.move.down) then vertical = vertical + 1 end if Keybind:checkDown(Keybind.move.down) then vertical = vertical + 1 end
if Keybind:CheckDown(Keybind.move.up) then vertical = vertical - 1 end if Keybind:checkDown(Keybind.move.up) then vertical = vertical - 1 end
local horizontal = 0 local horizontal = 0
if Keybind:CheckDown(Keybind.move.right) then horizontal = horizontal + 1 end if Keybind:checkDown(Keybind.move.right) then horizontal = horizontal + 1 end
if Keybind:CheckDown(Keybind.move.left) then horizontal = horizontal - 1 end if Keybind:checkDown(Keybind.move.left) then horizontal = horizontal - 1 end
-- if no direction, then dash forward -- if no direction, then dash forward
if horizontal == 0 and vertical == 0 then if horizontal == 0 and vertical == 0 then
@@ -154,23 +156,23 @@ function Player:doLogic()
end end
-- set dash values -- set dash values
self.dashDirection = GetAngleFromVector(horizontal, vertical) self.dashDirection = getAngleFromVector(vector(horizontal, vertical))
self.dashTimer = math.floor(self.dashTime * game.framerate) self.dash_timer = math.floor(self.dash_time * game.framerate)
end end
else else
-- not dashing! -- not dashing!
self.isDashing = false self.is_dashing = false
end end
if self.canHook and Keybind:CheckPressed(Keybind.move.hook) then if self.can_hook and Keybind:checkPressed(Keybind.move.hook) then
if self.isHooked then if self.is_hooked then
self:unhook() self:unhook()
else else
local anchor = self:checkNearest("hook_anchor",self.hookDistance) local anchor = self:checkNearest("HookAnchor","hook_specific")
if anchor then if anchor then
self.isHooked = true self.is_hooked = true
self.hookDistance = anchor.hookDistance self.hook_distance = anchor.hook_distance
self.hookAnchor = { self.hook_anchor = {
x = anchor.pos.x, x = anchor.pos.x,
y = anchor.pos.y y = anchor.pos.y
} }
@@ -180,73 +182,78 @@ function Player:doLogic()
end end
function Player:doPhysics() function Player:doPhysics()
if self.dashTimer <= 0 then if self.dash_timer <= 0 then
if self.isOnGround then if self.is_on_ground then
self.vel.x = self.vel.x * (1-self.groundFriction) self.vel.x = self.vel.x * (1-self.ground_friction)
else else
self.vel.x = self.vel.x * (1-self.airFriction) self.vel.x = self.vel.x * (1-self.air_friction)
end end
self.isSliding = false self.is_sliding = false
if self.wallHit == 0 then if self.wall_hit == 0 then
self.vel.y = self.vel.y * (1-self.airFriction) self.vel.y = self.vel.y * (1-self.air_friction)
elseif self.noDriftFrames ~= self.walljumpNoDriftAmount then elseif self.nodrift_frames ~= self.walljump_nodrift_amount then
self.isSliding = true self.is_sliding = true
self.vel.y = self.vel.y * (1-self.walljumpFriction) self.vel.y = self.vel.y * (1-self.wall_friction)
end end
if math.abs(self.vel.x) < self.zeroSpeed then self.vel.x = 0 end if math.abs(self.vel.x) < self.zero_speed then self.vel.x = 0 end
end end
-- reset state -- reset state
self.canFall = true self.can_fall = true
self.isOnGround = false self.is_on_ground = false
-- adjust timers -- adjust timers
self.dashTimer = self.dashTimer - 1 self.dash_timer = self.dash_timer - 1
self.noDriftFrames = self.noDriftFrames - 1 self.nodrift_frames = self.nodrift_frames - 1
-- DASH STATE -- DASH STATE
if self.dashTimer > 0 then if self.dash_timer > 0 then
self.canFall = false self.can_fall = false
-- dash particle -- dash particle
local particle_data = { local particle_data = {
animation = self.body, animation = self.body,
sprite_tint = HEX2RGB("#fed100"), animation_speed = 0,
sprite_tint = hex2rgb("#fed100"),
sprite_alpha = 0.5, sprite_alpha = 0.5,
time = 0.2,
sprite_flip = { sprite_flip = {
x = self.sprite_flip.x, x = self.sprite_flip.x,
y = self.sprite_flip.y y = self.sprite_flip.y
} }
} }
Particle:new(self.pos.x,self.pos.y,particle_data) Particle:new(self.pos.x,self.pos.y,particle_data)
self.dashCooldownTimer = self.dashCooldownTime self.dash_cooldown_timer = self.dash_cooldown_time
-- dash movement -- dash movement
self.vel.x = self.dashSpeed * math.cos(self.dashDirection) self.vel.x = self.dash_speed * math.cos(self.dashDirection)
self.vel.y = self.dashSpeed * math.sin(self.dashDirection) self.vel.y = self.dash_speed * math.sin(self.dashDirection)
end end
-- hook state -- hook state
if self.isHooked then if self.is_hooked then
self.move_x = 0 self.move_x = 0
local hook = Vector(self.pos.x, self.pos.y, self.hookAnchor.x, self.hookAnchor.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.hookDistance) 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.hookSwingSpeed hook_angle = hook_angle - self.hook_swing_speed
end end
if Keybind:CheckDown(Keybind.move.left) then if Keybind:checkDown(Keybind.move.left) then
hook_angle = hook_angle + self.hookSwingSpeed hook_angle = hook_angle + self.hook_swing_speed
end end
local particle_data = { local particle_data = {
animation = self.body, animation = self.body,
sprite_tint = HEX2RGB("#fed100"), animation_speed = 0,
sprite_tint = hex2rgb("#fed100"),
sprite_alpha = 0.5, sprite_alpha = 0.5,
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
@@ -254,75 +261,86 @@ function Player:doPhysics()
} }
Particle:new(self.pos.x,self.pos.y,particle_data) Particle:new(self.pos.x,self.pos.y,particle_data)
local pos_x = self.hookAnchor.x + dist * math.cos(hook_angle) local pos_x = self.hook_anchor.x + dist * math.cos(hook_angle)
local pos_y = self.hookAnchor.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
if self.canFall then if self.can_fall then
-- not in dash -- not in dash
self.dashTimer = 0 self.dash_timer = 0
self.vel.y = self.vel.y + gravity self.vel.y = self.vel.y + gravity
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.wallHit = 0 self.vel.x,
else function()
self.wallHit = 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.isOnGround = true self.is_on_ground = true
self.dashCount = self.dashAmount 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
self:respawn() self:respawn()
end end
self:adjustLight(self.target_offset.x,self.target_offset.y)
end end
function Player:respawn() function Player:respawn()
self.pos.x = self.anchorRespawn.x self.pos.x = self.respawn_anchor.x
self.pos.y = self.anchorRespawn.y self.pos.y = self.respawn_anchor.y
end end
function Player:handleAnimation() function Player:handleAnimation()
-- flip sprite to look in the direction is moving -- flip sprite to look in the direction is moving
if self.isHooked then if self.is_hooked then
if self.vel.x ~= 0 then if self.vel.x ~= 0 then
self.sprite_flip.x = math.sign(self.vel.x) self.sprite_flip.x = math.sign(self.vel.x)
end end
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.isSliding 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.maskType.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.maskType.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.maskType.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.maskType.idle) self.mask = self.mask:change(self.mask_type.idle)
end end
-- special case: idle animation gets slower by time -- special case: idle animation gets slower by time
@@ -332,30 +350,31 @@ function Player:handleAnimation()
end end
end end
if self.isHooked then if self.is_hooked then
love.graphics.line( love.graphics.line(
-Camera.pos.x + self.pos.x, -Camera.pos.x + self.pos.x,
-Camera.pos.y + self.pos.y, -Camera.pos.y + self.pos.y,
-Camera.pos.x + self.hookAnchor.x, -Camera.pos.x + self.hook_anchor.x,
-Camera.pos.y + self.hookAnchor.y -Camera.pos.y + self.hook_anchor.y
) )
end end
self.body:animate() self.body:animate()
self:draw(self.body) self:draw(self.body)
if self.dashCount > 0 then if self.dash_count > 0 then
self:draw(self.mask) self:draw(self.mask)
end end
self.move_x = 0 self.move_x = 0
end end
function Player:unhook() function Player:unhook()
self.isHooked = false self.is_hooked = false
self.hookAnchor = nil self.hook_anchor = nil
self.hook_distance = nil
end end
function Player:debug() function Player:debug()
Entity.debug(self) Entity.debug(self)
love.graphics.print("wallHit: "..self.wallHit) love.graphics.print("wall_hit: "..self.wall_hit)
end end

View File

@@ -1,10 +1,11 @@
Entity = {class = "Entity"}
LoadedObjects.Entities = {} LoadedObjects.Entities = {}
Entity = class(nil, {type = "Entity"})
function Entity:new(x,y) 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
@@ -22,58 +23,92 @@ function Entity:new(x,y)
o.sprite_tint = {1,1,1} o.sprite_tint = {1,1,1}
o.sprite_alpha = 1 o.sprite_alpha = 1
o.sprite_flip = { x = 1, y = 1} o.sprite_flip = { x = 1, y = 1}
o.illuminated = false
table.insert(LoadedObjects.Entities,o)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
return o return o
end 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 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
end end
function Entity:doLogic() function Entity:moveX(amount, func)
self.move_remainder.x = self.move_remainder.x + amount
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:move() function Entity:moveY(amount, func)
self.pos.x = self.pos.x + self.vel.x self.move_remainder.y = self.move_remainder.y + amount
self.pos.y = self.pos.y + self.vel.y local move = math.round(self.move_remainder.y)
end if move ~= 0 then
self.move_remainder.y = self.move_remainder.y - move
function Entity:moveWithCollision() local sign = math.sign(move)
local r = false while math.round(move) ~= 0 do
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then if not self:isCollidingAt(
self.pos.x = self.pos.x + self.vel.x self.pos.x,
else self.pos.y + sign,
self.vel.x = 0 LoadedObjects.Collisions
r = true ) 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)
@@ -89,15 +124,7 @@ function Entity:kill()
if self.light ~= nil then if self.light ~= nil then
self.light:kill() self.light:kill()
end end
if self.id ~= nil then self.dead = true
for _, e in pairs(LoadedObjects.Entities) do
if e.id > self.id then
e.id = e.id - 1
end
end
table.remove(LoadedObjects.Entities,self.id)
end
self = nil
end end
function Entity:checkVisionLine(entity,range) function Entity:checkVisionLine(entity,range)
@@ -106,8 +133,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
@@ -129,6 +157,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(
@@ -142,6 +171,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
@@ -149,6 +179,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
@@ -174,7 +205,7 @@ function Entity:getCollidingAt(x,y,object)
and y + self.box.from.y < collision.to.y and y + self.box.from.y < collision.to.y
and y + self.box.to.y > collision.from.y and y + self.box.to.y > collision.from.y
then then
collision.isColliding = true collision.is_colliding = true
return collision return collision
end end
end end
@@ -210,8 +241,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
@@ -260,12 +292,31 @@ function Entity:debug()
end end
end end
function Entity:doLogic()
end
function Entity:doPhysics()
end
function Entity:handleAnimation() function Entity:handleAnimation()
end end
function Entity:drawBackground() function Entity:drawBackground()
end end
---------------
function cleanDeadEntities()
for i=1, #LoadedObjects.Entities do
enty = LoadedObjects.Entities[i]
if enty and enty.dead then
table.remove(LoadedObjects.Entities,i)
end
end
end
---------------
require "code/entities/kupo" require "code/entities/kupo"
require "code/entities/arrow" require "code/entities/arrow"
require "code/entities/decoration" require "code/entities/decoration"

View File

@@ -1,7 +1,18 @@
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
for _, particle in pairs(LoadedParticles) do for _, particle in pairs(LoadedObjects.Particles) do
particle:doLogic() particle:doLogic()
end end
for _, enty in pairs(LoadedObjects.Entities) do for _, enty in pairs(LoadedObjects.Entities) do
@@ -16,12 +27,12 @@ function stepGame()
enty:doPhysics() enty:doPhysics()
end end
AnimateTiles() animateTiles()
Camera:followPlayer(main_Player) Camera:followPlayer(main_player)
--Camera:positionCenterAt(main_Player.pos.x, main_Player.pos.y) --Camera:positionCenterAt(main_player.pos.x, main_player.pos.y)
--camera:positionAt(main_Player.pos.x, main_Player.pos.y,game.width,game.height) --camera:positionAt(main_player.pos.x, main_player.pos.y,game.width,game.height)
if Keybind:CheckPressed(Keybind.debug.debug) then if Keybind:checkPressed(Keybind.debug.debug) then
if debug then if debug then
debug = false debug = false
debug_collision = true debug_collision = true
@@ -32,23 +43,17 @@ function stepGame()
end end
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 = 16,-10
end
end end
if Keybind:CheckPressed(Keybind.debug.reload) then if Keybind:checkPressed(Keybind.debug.reload) then
MenuClear() clearMenu()
menu_type = "dialog" menu_type = "dialog"
MenuInit("dialog",DialogSequence.Example) initMenu("dialog",dialog_sequence.example)
end end
if Keybind:CheckPressed(Keybind.debug.editor) then if Keybind:checkPressed(Keybind.debug.recording) then
editor_mode = true
end
if Keybind:CheckPressed(Keybind.debug.recording) then
if DemoRecording then if DemoRecording then
Demo:endRecord() Demo:endRecord()
else else
@@ -56,13 +61,17 @@ function stepGame()
end end
end end
if Keybind:CheckPressed(Keybind.debug.playback) then if Keybind:checkPressed(Keybind.debug.playback) then
if DemoPlayback then if DemoPlayback then
Demo:endPlayback() Demo:endPlayback()
else else
Demo:startPlayback() Demo:startPlayback()
end end
end end
cleanDeadParticles()
cleanDeadEntities()
cleanDeadLights()
end end
function drawGame() function drawGame()
@@ -88,7 +97,7 @@ function drawGame()
endGameworldDraw() endGameworldDraw()
-- hud -- hud
textScale = 1 text_size = 1
-- debug -- debug
if debug then debugUI() end if debug then debugUI() end

View File

@@ -22,10 +22,10 @@ function drawGameworldBackground()
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],
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x, tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.width) - Camera.pos.x,
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y, tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height) - Camera.pos.y,
"background" "background"
) )
@@ -61,10 +61,10 @@ function drawGameworldForeground()
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],
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x, tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.width) - Camera.pos.x,
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y, tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height) - Camera.pos.y,
"foreground" "foreground"
) )
@@ -79,19 +79,7 @@ function drawGameworldDarkness()
love.graphics.setBlendMode("replace") love.graphics.setBlendMode("replace")
love.graphics.setColor(0,0,0,0) love.graphics.setColor(0,0,0,0)
for _, light in pairs(LoadedObjects.Lights) do for _, light in pairs(LoadedObjects.Lights) do
if light.range ~= 0 then light:drawClear()
local position = {
x = (light.pos.x - Camera.pos.x) / game.scale,
y = (light.pos.y - Camera.pos.y) / game.scale
}
local range = (light.range + light.flicker_value) / game.scale
love.graphics.circle(
"fill",
position.x,
position.y,
range
)
end
end end
Canvas.Darkness:endDrawing() Canvas.Darkness:endDrawing()
Canvas.Darkness:draw() Canvas.Darkness:draw()
@@ -99,23 +87,7 @@ end
function drawGameworldLights() function drawGameworldLights()
for _, light in pairs(LoadedObjects.Lights) do for _, light in pairs(LoadedObjects.Lights) do
if light.range ~= 0 then light:drawShine()
love.graphics.setColor(light.color[1],light.color[2],light.color[3],1)
Shader.RadiusGradient:send("pos_x",- Camera.pos.x + light.pos.x)
Shader.RadiusGradient:send("pos_y",- Camera.pos.y + light.pos.y)
Shader.RadiusGradient:send("range",light.range)
Shader.RadiusGradient:send("scale",game.scale)
love.graphics.setShader(Shader.RadiusGradient)
love.graphics.circle(
"fill",
- Camera.pos.x + light.pos.x,
- Camera.pos.y + light.pos.y,
light.range
)
love.graphics.setShader()
end
end end
end end

View File

@@ -1,15 +1,15 @@
function HEX2RGB(color) function hex2rgb(color)
local r1 = HEX2DEX(color:sub(2,2)) local r1 = hex2dec(color:sub(2,2))
local r2 = HEX2DEX(color:sub(3,3)) local r2 = hex2dec(color:sub(3,3))
local g1 = HEX2DEX(color:sub(4,4)) local g1 = hex2dec(color:sub(4,4))
local g2 = HEX2DEX(color:sub(5,5)) local g2 = hex2dec(color:sub(5,5))
local b1 = HEX2DEX(color:sub(6,6)) local b1 = hex2dec(color:sub(6,6))
local b2 = HEX2DEX(color:sub(7,7)) local b2 = hex2dec(color:sub(7,7))
return {(r1*16 + r2)/255, (g1*16 + g2)/255, (b1*16 + b2)/255} return {(r1*16 + r2)/255, (g1*16 + g2)/255, (b1*16 + b2)/255}
end end
function HEX2DEX(hex) function hex2dec(hex)
if hex == "0" then return 0 if hex == "0" then return 0
elseif hex == "1" then return 1 elseif hex == "1" then return 1
elseif hex == "2" then return 2 elseif hex == "2" then return 2

View File

@@ -1,51 +1,88 @@
function ExportLevel(levelname, filename) function exportLevel(levelname, filename)
os.execute( "mkdir \"./export\"" ) love.filesystem.createDirectory("export")
filename = filename or "output.lua" filename = filename or "output.lua"
filename = "export/"..filename if string.sub(filename, 1, 1) ~= "/" then
filename = "export/"..filename
end
exportFile = io.open(filename, "w+") exportFile = io.open(filename, "w+")
if exportFile then if exportFile then
logPrint("Exporting level \"".. levelname .. "\"...") logPrint("Exporting level \"".. levelname .. "\"...")
exportFile:write("return {") exportFile:write("return {")
logPrint("- level name") logPrint("- level name")
exportFile:write("\n name = \"" .. levelname .. "\",") exportFile:write("\n name = \"" .. levelname .. "\",")
logPrint("- tileset") logPrint("- tileset")
for k, v in pairs(tileset) do for k, v in pairs(tileset) do
if v == LevelData.tileset then if v == LevelData.tileset then
exportFile:write("\n tileset = tileset." .. k .. ",") exportFile:write("\n tileset = tileset." .. k .. ",")
end
end
logPrint("- properties")
exportFile:write("\n properties = {")
exportFile:write("\n darkness = true")
exportFile:write("\n },")
logPrint("- tiles")
exportFile:write("\n tiles = {")
local rows = #LevelTiles
for i = 1, #LevelTiles do
exportFile:write("\n { ")
for j = 1, #LevelTiles[i] do
if j ~= 1 then
exportFile:write(", ")
end end
exportFile:write(tostring(LevelTiles[i][j].id))
end end
exportFile:write("}")
if i ~= #LevelTiles then logPrint("- properties")
exportFile:write(", ") exportFile:write("\n properties = {")
logPrint(" - darkness: ".. tostring(LevelData.properties.darkness))
exportFile:write("\n darkness = " .. tostring(LevelData.properties.darkness))
exportFile:write("\n },")
logPrint("- tiles")
exportFile:write("\n tiles = {")
local rows = #LevelTiles
for i = 1, #LevelTiles do
if i > 1 then
exportFile:write(", ")
end
exportFile:write("\n { ")
for j = 1, #LevelTiles[i] do
if j ~= 1 then
exportFile:write(", ")
end
exportFile:write(tostring(LevelTiles[i][j].id))
end
exportFile:write("}")
logPrint(" - row "..i.."/"..rows.." "..math.floor(100*((i-1)*100/rows))/100 .."%")
end end
logPrint(" - Row "..i.."/"..rows.." "..math.floor(100*((i-1)*100/rows))/100 .."%") exportFile:write("\n },")
end logPrint("- objects")
exportFile:write("\n },") exportFile:write("\n objects = {")
logPrint(" - spawns")
logPrint("- objects") exportFile:write("\n spawns = {")
exportFile:write("\n objects = {}") for i, v in ipairs(LoadedObjects.Spawns) do
if i > 1 then
logPrint("Exporting complete.") 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:write("\n}")
exportFile:close() exportFile:close()
end end
@@ -63,22 +100,6 @@ function scandir(directory)
return t return t
end end
--[[
return {
name = "level1",
tileset = tileset.library,
tiles = {
{13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13},
{ 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, 5,25,26, 6,25,26, 7, 0, 5,25,26, 7, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 5,37,38, 6,37,38, 7, 0, 5,37,38, 7, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 5,37,38, 6,37,38, 7, 0, 5,37,38, 7, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 5,49,50, 6,49,50, 7, 0, 5,49,50, 7, 0, 0, 0, 0, 0, 0},
{ 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 = {}
}
]]
if logging then if logging then
-- Make log stuff -- Make log stuff
os.execute( "mkdir \"./logs\"" ) os.execute( "mkdir \"./logs\"" )

View File

@@ -17,7 +17,11 @@ Keybind.debug = {}
Keybind.editor = {} Keybind.editor = {}
Keybind.generic = {} Keybind.generic = {}
function Keybind:CheckDown(action) function Keybind:isAvailable(action)
return not action.occupied
end
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
if demo_action == action.demo then if demo_action == action.demo then
@@ -37,15 +41,18 @@ 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
function Keybind:CheckPressed(action) -- relies on being called exactly once per frame to be accurate.
if Keybind:CheckDown(action) then function Keybind:checkPressed(action)
if Keybind:checkDown(action) then
if not action.pressed then if not action.pressed then
action.pressed = true action.pressed = true
return true return true
@@ -56,7 +63,7 @@ function Keybind:CheckPressed(action)
return false return false
end end
function Keybind:CheckCollision(cat, key) function Keybind:checkCollision(cat, key)
for _, action in pairs(cat) do for _, action in pairs(cat) do
for _, keyname in pairs(action.keys) do for _, keyname in pairs(action.keys) do
if key == keyname then return true end if key == keyname then return true end
@@ -65,19 +72,30 @@ function Keybind:CheckCollision(cat, key)
return false return false
end end
function Keybind:AddKey(action, key) function Keybind:addKey(action, key)
table.insert(action.keys, key) table.insert(action.keys, key)
end end
function Keybind:ChangeKey(action, position, key) function Keybind:changeKey(action, position, key)
action.keys[position] = key action.keys[position] = key
end end
function Keybind:RemoveKeys(action) function Keybind:removeKeys(action)
action.keys = {} action.keys = {}
end end
function Keybind:Default() -- this prolly should be used by Prompt:keypressed()
function Keybind:hasKey(action, key)
for _, v in pairs(action.keys) do
if v == key then
return true
end
end
return false
end
function Keybind:default()
--Menu --Menu
Keybind.menu.pause.keys = {"escape"} Keybind.menu.pause.keys = {"escape"}
Keybind.menu.confirm.keys = {"z", "space", 1} Keybind.menu.confirm.keys = {"z", "space", 1}
@@ -98,17 +116,34 @@ function Keybind:Default()
Keybind.debug.editor = { keys = {"f4"}} Keybind.debug.editor = { keys = {"f4"}}
Keybind.debug.recording = { keys = {"f5"}} Keybind.debug.recording = { keys = {"f5"}}
Keybind.debug.playback = { keys = {"f6"}} Keybind.debug.playback = { keys = {"f6"}}
Keybind.debug.respawn = { keys = {"f8"}}
-- Editor -- Editor
Keybind.editor.palette = { keys = {"tab"}} Keybind.editor.palette_mode = { keys = {"tab"}}
Keybind.editor.room_mode = { keys = {"r"}} Keybind.editor.room_mode = { keys = {"r"}}
Keybind.editor.entity_mode = { keys = {"e"}}
Keybind.editor.properties_mode = { keys = {"p"}}
Keybind.editor.left = { keys = {"left", "a"}}
Keybind.editor.right = { keys = {"right", "d"}}
Keybind.editor.up = { keys = {"up", "w"}}
Keybind.editor.down = { keys = {"down", "s"}}
Keybind.editor.palette_change = { keys = {"f1"}}
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
-- Set default values at start -- Set default values at start
Keybind:Default() Keybind:default()

View File

@@ -1,6 +1,6 @@
function LevelLoadTiles() function loadLevelTiles()
math.randomseed(3) math.randomseed(3)
LevelData = dofile("data/levels/"..currLevel) LevelData = dofile("data/levels/"..level_current)
--[[ --[[
on level format: on level format:
@@ -12,19 +12,34 @@ function LevelLoadTiles()
overlay_depth = foreground/background overlay depth overlay_depth = foreground/background overlay depth
type = collision type type = collision type
]] ]]
LevelGetTileData() getLevelTileData()
LevelTiles = LevelData.tiles LevelTiles = LevelData.tiles
LevelUpdateDimensions() updateLevelDimensions()
LevelIndexTiles() indexLevelTiles()
TileCreateObjects() createTileObjects()
createRoomObjects()
getSpawns()
end end
function createRoomObjects()
LoadedObjects.Rooms = {}
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]))
end
end
function LevelExpandCanvas(horizontal,vertical) function getSpawns()
LoadedObjects.Spawns = {}
for _, v in pairs(LevelData.objects.spawns) do
addSpawn(v[1],unpack(v[2]))
end
end
function expandLevelCanvas(horizontal,vertical)
local horizontal = horizontal or 0 local horizontal = horizontal or 0
local vertical = vertical or 0 local vertical = vertical or 0
local h = LevelGetTileWidth() local h = getLevelTileWidth()
local v = LevelGetTileHeight() local v = getLevelTileHeight()
-- get new canvas size -- get new canvas size
local newCanvasH = h + math.abs(horizontal) local newCanvasH = h + math.abs(horizontal)
@@ -35,7 +50,7 @@ function LevelExpandCanvas(horizontal,vertical)
for i = 1, newCanvasV do for i = 1, newCanvasV do
ExpandedLevel[i] = {} ExpandedLevel[i] = {}
for j = 1, newCanvasH do for j = 1, newCanvasH do
ExpandedLevel[i][j] = InstanceTile(0) ExpandedLevel[i][j] = instanceTile(0)
end end
end end
@@ -53,7 +68,7 @@ function LevelExpandCanvas(horizontal,vertical)
-- get data from old canvas to new canvas -- get data from old canvas to new canvas
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
ExpandedLevel[i+expand_v][j+expand_h] = InstanceTile(LevelTiles[i][j].id) ExpandedLevel[i+expand_v][j+expand_h] = instanceTile(LevelTiles[i][j].id)
end end
end end
@@ -62,11 +77,11 @@ function LevelExpandCanvas(horizontal,vertical)
end end
function LevelReduceCanvas(horizontal,vertical) function reduceLevelCanvas(horizontal,vertical)
local horizontal = horizontal or 0 local horizontal = horizontal or 0
local vertical = vertical or 0 local vertical = vertical or 0
local h = LevelGetTileWidth() local h = getLevelTileWidth()
local v = LevelGetTileHeight() local v = getLevelTileHeight()
-- get new canvas size -- get new canvas size
local newCanvasH = h - math.abs(horizontal) local newCanvasH = h - math.abs(horizontal)
@@ -77,7 +92,7 @@ function LevelReduceCanvas(horizontal,vertical)
for i = 1, newCanvasV do for i = 1, newCanvasV do
ExpandedLevel[i] = {} ExpandedLevel[i] = {}
for j = 1, newCanvasH do for j = 1, newCanvasH do
ExpandedLevel[i][j] = InstanceTile(0) ExpandedLevel[i][j] = instanceTile(0)
end end
end end
@@ -95,17 +110,17 @@ function LevelReduceCanvas(horizontal,vertical)
-- get data from old canvas to new canvas -- get data from old canvas to new canvas
for i = 1, #ExpandedLevel do for i = 1, #ExpandedLevel do
for j = 1, #ExpandedLevel[i] do for j = 1, #ExpandedLevel[i] do
ExpandedLevel[i][j] = InstanceTile(LevelTiles[i+expand_v][j+expand_h].id) ExpandedLevel[i][j] = instanceTile(LevelTiles[i+expand_v][j+expand_h].id)
end end
end end
-- use new canvas -- use new canvas
LevelTiles = ExpandedLevel LevelTiles = ExpandedLevel
LevelExpandCanvas() expandLevelCanvas()
end end
function LevelGetTileData() function getLevelTileData()
for k, v in pairs(tileset) do for k, v in pairs(tileset) do
if v == LevelData.tileset then if v == LevelData.tileset then
TileData = dofile("data/tileset/"..k..".lua") TileData = dofile("data/tileset/"..k..".lua")
@@ -113,20 +128,20 @@ function LevelGetTileData()
end end
end end
function LevelReloadTiles() function reloadLevelTiles()
LevelUpdateDimensions() updateLevelDimensions()
end end
function LevelUpdateDimensions() function updateLevelDimensions()
LevelData.Width = LevelGetWidth() LevelData.Width = getLevelWidth()
LevelData.Height = LevelGetHeight() LevelData.Height = getLevelHeight()
end end
function LevelGetTileHeight() function getLevelTileHeight()
return #LevelTiles return #LevelTiles
end end
function LevelGetTileWidth() function getLevelTileWidth()
local width = 0 local width = 0
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
if width < #LevelTiles[i] then width = #LevelTiles[i] end if width < #LevelTiles[i] then width = #LevelTiles[i] end
@@ -134,42 +149,42 @@ function LevelGetTileWidth()
return width return width
end end
function LevelGetHeight() function getLevelHeight()
return LevelGetTileHeight() * tileProperties.height return getLevelTileHeight() * tile_properties.height
end end
function LevelGetWidth() function getLevelWidth()
return LevelGetTileWidth() * tileProperties.width return getLevelTileWidth() * tile_properties.width
end end
function LevelIndexTiles() function indexLevelTiles()
TileIndex = {} TileIndex = {}
-- index from tileset -- index from tileset
local width = LevelData.tileset:getPixelWidth()/tileProperties.width local width = LevelData.tileset:getPixelWidth()/tile_properties.width
local height = LevelData.tileset:getPixelHeight()/tileProperties.height local height = LevelData.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(
j*tileProperties.width, j*tile_properties.width,
i*tileProperties.height, i*tile_properties.height,
tileProperties.width, tile_properties.width,
tileProperties.height, tile_properties.height,
LevelData.tileset:getDimensions() LevelData.tileset:getDimensions()
) )
end end
end end
TileDataInitialize() initTileData()
-- instance level tiles according to the Properties -- instance level tiles according to the Properties
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
SetTile(i,j,LevelTiles[i][j]) setTile(i,j,LevelTiles[i][j])
end end
end end
end end
function TileDataInitialize() function initTileData()
for _, Properties in pairs(TileData) do for _, Properties in pairs(TileData) do
if Properties.animation ~= nil then if Properties.animation ~= nil then
Properties.tileset = love.graphics.newImage("assets/terrain/"..Properties.animation..".png") Properties.tileset = love.graphics.newImage("assets/terrain/"..Properties.animation..".png")
@@ -178,18 +193,18 @@ function TileDataInitialize()
Properties.current_subimage = 1 Properties.current_subimage = 1
local tileset = Properties.tileset local tileset = Properties.tileset
local width = tileset:getPixelWidth()/tileProperties.width local width = tileset:getPixelWidth()/tile_properties.width
local height = tileset:getPixelHeight()/tileProperties.height local height = tileset:getPixelHeight()/tile_properties.height
local image_count = 0 local image_count = 0
for i = 0, height-1 do for i = 0, height-1 do
for j = 0, width-1 do for j = 0, width-1 do
local quad = local quad =
love.graphics.newQuad( love.graphics.newQuad(
j*tileProperties.width, j*tile_properties.width,
i*tileProperties.height, i*tile_properties.height,
tileProperties.width, tile_properties.width,
tileProperties.height, tile_properties.height,
tileset:getDimensions() tileset:getDimensions()
) )
image_count = image_count + 1 image_count = image_count + 1
@@ -202,7 +217,7 @@ function TileDataInitialize()
end end
end end
function InstanceTile(id) function instanceTile(id)
local tile = {} local tile = {}
tile.id = id tile.id = id
@@ -225,8 +240,8 @@ function InstanceTile(id)
return tile return tile
end end
function SetTile(i,j,id) function setTile(i,j,id)
LevelTiles[i][j] = InstanceTile(id) LevelTiles[i][j] = instanceTile(id)
end end
function drawGridDisplay() function drawGridDisplay()
@@ -234,16 +249,16 @@ function drawGridDisplay()
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
love.graphics.rectangle( love.graphics.rectangle(
"line", "line",
tileProperties.scale * (j * tileProperties.width + (levelProperties.offset.x - tileProperties.width)) - Camera.pos.x, tile_properties.scale * (j * tile_properties.width + (level_properties.offset.x - tile_properties.width)) - Camera.pos.x,
tileProperties.scale * (i * tileProperties.height + (levelProperties.offset.y - tileProperties.height)) - Camera.pos.y, tile_properties.scale * (i * tile_properties.height + (level_properties.offset.y - tile_properties.height)) - Camera.pos.y,
tileProperties.scale * tileProperties.width, tile_properties.scale * tile_properties.width,
tileProperties.scale * tileProperties.height tile_properties.scale * tile_properties.height
) )
end end
end end
end end
function TileOptimizeObjects() function optimizeTileObjects()
logPrint("Optimizing Objects...") logPrint("Optimizing Objects...")
local unoptimized = 0 local unoptimized = 0
local isTileOptimized = {} local isTileOptimized = {}
@@ -313,14 +328,14 @@ function TileOptimizeObjects()
logPrint("- Group size: "..m.."x"..n) logPrint("- Group size: "..m.."x"..n)
unoptimized = unoptimized + m * n unoptimized = unoptimized + m * n
local base_x = tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.height) local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height)
local base_y = tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height)
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale * n, base_x + tile_properties.width * tile_properties.scale * n,
base_y + tileProperties.height * tileProperties.scale * m base_y + tile_properties.height * tile_properties.scale * m
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
end end
@@ -331,13 +346,13 @@ function TileOptimizeObjects()
logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions) logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions)
end end
function TileCreateObjects() function createTileObjects()
LoadedObjects.Collisions = {} LoadedObjects.Collisions = {}
LoadedObjects.Platforms = {} LoadedObjects.Platforms = {}
LoadedObjects.Ladders = {} LoadedObjects.Ladders = {}
LoadedObjects.Hazards = {} LoadedObjects.Hazards = {}
TileOptimizeObjects() optimizeTileObjects()
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
@@ -345,14 +360,14 @@ function TileCreateObjects()
local type = TileData[LevelTiles[i][j].id].type local type = TileData[LevelTiles[i][j].id].type
local light = TileData[LevelTiles[i][j].id].light local light = TileData[LevelTiles[i][j].id].light
local base_x = tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.height) local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height)
local base_y = tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height)
if light ~= 0 and light ~= nil then if light ~= 0 and light ~= nil then
CreateLight( CreateLight(
base_x + tileProperties.width/2 * tileProperties.scale, base_x + tile_properties.width/2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
light light
) )
end end
@@ -362,17 +377,17 @@ function TileCreateObjects()
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
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( local col = Collision:new(
base_x, base_x,
base_y + tileProperties.height/2 * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -381,18 +396,18 @@ function TileCreateObjects()
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y , base_y ,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
elseif type == "half_right" then elseif type == "half_right" then
local col = Collision:new( local col = Collision:new(
base_x + tileProperties.height/2 * tileProperties.scale, base_x + tile_properties.height/2 * tile_properties.scale,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -401,17 +416,17 @@ function TileCreateObjects()
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.height/2 * tileProperties.scale, base_x + tile_properties.height/2 * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
elseif type == "platform" then elseif type == "platform" then
local plat = Collision:new( local plat = Collision:new(
base_x, base_x,
base_y + tileProperties.scale * 2, base_y + tile_properties.scale * 2,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2 base_y + tile_properties.height/4 * tile_properties.scale + tile_properties.scale * 2
) )
table.insert(LoadedObjects.Platforms,plat) table.insert(LoadedObjects.Platforms,plat)
@@ -420,9 +435,9 @@ function TileCreateObjects()
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x, base_x,
base_y + k * tileProperties.scale - tileProperties.scale, base_y + k * tile_properties.scale - tile_properties.scale,
base_x + k * 2 * tileProperties.scale, base_x + k * 2 * tile_properties.scale,
base_y + k * tileProperties.scale base_y + k * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -430,9 +445,9 @@ function TileCreateObjects()
-- fill lower half -- fill lower half
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y + tileProperties.height/2 * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -441,9 +456,9 @@ function TileCreateObjects()
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x, base_x,
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale - tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale + k * tile_properties.scale - tile_properties.scale,
base_x + k * 2 * tileProperties.scale, base_x + k * 2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale + k * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -454,9 +469,9 @@ function TileCreateObjects()
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x, base_x,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale - tile_properties.scale + k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale - (k-1) * 2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale - tile_properties.scale + k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -465,8 +480,8 @@ function TileCreateObjects()
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -475,9 +490,9 @@ function TileCreateObjects()
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x, base_x,
base_y - tileProperties.scale + k * tileProperties.scale, base_y - tile_properties.scale + k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale - (k-1) * 2 * tile_properties.scale,
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale base_y - tile_properties.scale + k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -487,10 +502,10 @@ function TileCreateObjects()
for k = 1, 8 do for k = 1, 8 do
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x + (k-8) * -2 * tileProperties.scale, base_x + (k-8) * -2 * tile_properties.scale,
base_y - tileProperties.scale + k * tileProperties.scale, base_y - tile_properties.scale + k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale base_y - tile_properties.scale + k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -498,9 +513,9 @@ function TileCreateObjects()
-- fill lower half -- fill lower half
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y + tileProperties.height/2 * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -508,10 +523,10 @@ function TileCreateObjects()
for k = 1, 8 do for k = 1, 8 do
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x + (k-8) * -2 * tileProperties.scale, base_x + (k-8) * -2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale - tile_properties.scale + k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale - tile_properties.scale + k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -521,10 +536,10 @@ function TileCreateObjects()
for k = 1, 8 do for k = 1, 8 do
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x + (k-8) * -2 * tileProperties.scale, base_x + (k-8) * -2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale - k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale - k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -534,10 +549,10 @@ function TileCreateObjects()
for k = 1, 8 do for k = 1, 8 do
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x + (k-8) * -2 * tileProperties.scale, base_x + (k-8) * -2 * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale, base_y + tile_properties.height/2 * tile_properties.scale + tile_properties.height/2 * tile_properties.scale - k * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale + tile_properties.height/2 * tile_properties.scale - k * tile_properties.scale + tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -546,8 +561,8 @@ function TileCreateObjects()
local col = Collision:new( local col = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/2 * tileProperties.scale base_y + tile_properties.height/2 * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
@@ -557,9 +572,9 @@ function TileCreateObjects()
-- do ramp owo -- do ramp owo
local slope = Collision:new( local slope = Collision:new(
base_x, base_x,
base_y + k * tileProperties.scale - tileProperties.scale, base_y + k * tile_properties.scale - tile_properties.scale,
base_x + k * tileProperties.scale, base_x + k * tile_properties.scale,
base_y + k * tileProperties.scale base_y + k * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,slope) table.insert(LoadedObjects.Collisions,slope)
@@ -568,28 +583,28 @@ function TileCreateObjects()
elseif type == "ladder_right" then elseif type == "ladder_right" then
local ladder = Collision:new( local ladder = Collision:new(
base_x + (tileProperties.width-4)* tileProperties.scale, base_x + (tile_properties.width-4)* tile_properties.scale,
base_y, base_y,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Ladders,ladder) table.insert(LoadedObjects.Ladders,ladder)
elseif type == "ladder_platform_right" then elseif type == "ladder_platform_right" then
local ladder = Collision:new( local ladder = Collision:new(
base_x + (tileProperties.width-4)* tileProperties.scale, base_x + (tile_properties.width-4)* tile_properties.scale,
base_y + tileProperties.scale * 2, base_y + tile_properties.scale * 2,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Ladders,ladder) table.insert(LoadedObjects.Ladders,ladder)
local plat = Collision:new( local plat = Collision:new(
base_x, base_x,
base_y + tileProperties.scale * 2, base_y + tile_properties.scale * 2,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2 base_y + tile_properties.height/4 * tile_properties.scale + tile_properties.scale * 2
) )
table.insert(LoadedObjects.Platforms,plat) table.insert(LoadedObjects.Platforms,plat)
@@ -599,8 +614,8 @@ function TileCreateObjects()
local ladder = Collision:new( local ladder = Collision:new(
base_x, base_x,
base_y, base_y,
base_x + tileProperties.scale * 4, base_x + tile_properties.scale * 4,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Ladders,ladder) table.insert(LoadedObjects.Ladders,ladder)
@@ -609,17 +624,17 @@ function TileCreateObjects()
local ladder = Collision:new( local ladder = Collision:new(
base_x, base_x,
base_y + tileProperties.scale * 2, base_y + tile_properties.scale * 2,
base_x + tileProperties.scale * 4, base_x + tile_properties.scale * 4,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Ladders,ladder) table.insert(LoadedObjects.Ladders,ladder)
local plat = Collision:new( local plat = Collision:new(
base_x, base_x,
base_y + tileProperties.scale * 2, base_y + tile_properties.scale * 2,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2 base_y + tile_properties.height/4 * tile_properties.scale + tile_properties.scale * 2
) )
table.insert(LoadedObjects.Platforms,plat) table.insert(LoadedObjects.Platforms,plat)
@@ -628,9 +643,9 @@ function TileCreateObjects()
local hazard = Collision:new( local hazard = Collision:new(
base_x, base_x,
base_y + tileProperties.height * 12/16 * tileProperties.scale, base_y + tile_properties.height * 12/16 * tile_properties.scale,
base_x + tileProperties.width * tileProperties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tileProperties.height * tileProperties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Hazards,hazard) table.insert(LoadedObjects.Hazards,hazard)
@@ -641,7 +656,7 @@ function TileCreateObjects()
--CreateCollisionTable() --CreateCollisionTable()
end end
function AnimateTiles() function animateTiles()
for _, Properties in pairs(TileData) do for _, Properties in pairs(TileData) do
if Properties ~= nil then if Properties ~= nil then
if Properties.animation ~= nil then if Properties.animation ~= nil then
@@ -661,40 +676,7 @@ function AnimateTiles()
end end
end end
function CreateCollisionTable() function drawTile(tile,x,y,depth)
-- init table
CollisionTable = {}
for j=0, 16*LevelGetTileHeight()-1 do
CollisionTable[j] = {}
for i=0, 16*LevelGetTileWidth()-1 do
CollisionTable[j][i] = false
end
end
for _, collision in pairs(LoadedObjects.Collisions) do
for ci=0, math.floor(collision.width)-1 do
for cj=0, math.floor(collision.height)-1 do
print(ci..","..cj)
CollisionTable[collision.from.y+cj][collision.from.x+ci] = true
end
end
end
end
function DrawColisionTable()
for j=1, #CollisionTable do
for i=1, #CollisionTable[j] do
if CollisionTable[j][i] then
love.graphics.setColor(0,1,0,1)
else
love.graphics.setColor(1,0,0,1)
end
love.graphics.points(i,j)
end
end
end
function DrawTile(tile,x,y,depth)
local Properties = TileData[tile.id] local Properties = TileData[tile.id]
if Properties ~= nil then if Properties ~= nil then
@@ -707,8 +689,8 @@ function DrawTile(tile,x,y,depth)
x, x,
y, y,
0, 0,
tileProperties.scale, tile_properties.scale,
tileProperties.scale tile_properties.scale
) )
end end
elseif Properties.depth == depth then elseif Properties.depth == depth then
@@ -720,8 +702,8 @@ function DrawTile(tile,x,y,depth)
x, x,
y, y,
0, 0,
tileProperties.scale, tile_properties.scale,
tileProperties.scale tile_properties.scale
) )
end end
else else
@@ -731,8 +713,8 @@ function DrawTile(tile,x,y,depth)
x, x,
y, y,
0, 0,
tileProperties.scale, tile_properties.scale,
tileProperties.scale tile_properties.scale
) )
end end
end end
@@ -747,8 +729,8 @@ function DrawTile(tile,x,y,depth)
x, x,
y, y,
0, 0,
tileProperties.scale, tile_properties.scale,
tileProperties.scale tile_properties.scale
) )
else else
love.graphics.draw( love.graphics.draw(
@@ -757,8 +739,8 @@ function DrawTile(tile,x,y,depth)
x, x,
y, y,
0, 0,
tileProperties.scale, tile_properties.scale,
tileProperties.scale tile_properties.scale
) )
end end
end end

View File

@@ -1,41 +1,30 @@
Light = {} Light = class(nil, {
type = "Light"
})
LoadedObjects.Lights = {} LoadedObjects.Lights = {}
function Light:new(x,y,range,flicker,color,lum) function Light:new(x,y,data)
local o = {} local o = {}
o.pos = { o.pos = {
x = x, x = x,
y = y y = y
} }
o.range = range o.radius = data.radius
o.lum = lum or 1 o.shine_radius = data.shine_radius or 0
o.color = color or {1,1,1} o.lum = data.lum or 1
o.flicker_amount = flicker or 2 o.color = data.color or {1,1,1}
o.flicker_amount = data.flicker or 2
o.flicker_value = 0 o.flicker_value = 0
o.dim = 0 o.dim = 0
o.flicker_time = 60/12 o.flicker_time = 60/12
o.flicker_timer = 0 o.flicker_timer = 0
table.insert(LoadedObjects.Lights,o)
o.id = #LoadedObjects.Lights
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
table.insert(LoadedObjects.Lights,o)
return o return o
end end
function Light:kill()
if self.id ~= nil then
for _, e in pairs(LoadedObjects.Lights) do
if e.id > self.id then
e.id = e.id - 1
end
end
table.remove(LoadedObjects.Lights,self.id)
end
self = nil
end
function Light:flicker() function Light:flicker()
self.flicker_timer = self.flicker_timer + 1 self.flicker_timer = self.flicker_timer + 1
@@ -45,3 +34,56 @@ function Light:flicker()
self.flicker_value = math.min(math.max(self.flicker_value, -self.flicker_amount), self.flicker_amount) self.flicker_value = math.min(math.max(self.flicker_value, -self.flicker_amount), self.flicker_amount)
end end
end end
function Light:drawClear()
if self.radius ~= 0 then
local position = {
x = (self.pos.x - Camera.pos.x) / game.scale,
y = (self.pos.y - Camera.pos.y) / game.scale
}
local radius = (self.radius + self.flicker_value) / game.scale
love.graphics.circle(
"fill",
position.x,
position.y,
radius
)
end
end
function Light:drawShine()
if self.radius ~= 0 then
love.graphics.setColor(self.color[1],self.color[2],self.color[3],1)
shader.circle_gradient:send("pos_x",- Camera.pos.x + self.pos.x)
shader.circle_gradient:send("pos_y",- Camera.pos.y + self.pos.y)
shader.circle_gradient:send("radius",self.shine_radius)
shader.circle_gradient:send("scale",game.scale)
love.graphics.setShader(shader.circle_gradient)
love.graphics.circle(
"fill",
- Camera.pos.x + self.pos.x,
- Camera.pos.y + self.pos.y,
self.radius
)
love.graphics.setShader()
end
end
function Light:kill()
self.dead = true
end
---------------
function cleanDeadLights()
for i=1, #LoadedObjects.Lights do
light = LoadedObjects.Lights[i]
if light and light.dead then
table.remove(LoadedObjects.Lights,i)
end
end
end
---------------

View File

@@ -1,4 +1,4 @@
function LocaleLoad(ISO639) function loadLocale(ISO639)
local ISO639 = ISO639 or "ENG" local ISO639 = ISO639 or "ENG"
dofile("data/locale/"..ISO639..".lua") dofile("data/locale/"..ISO639..".lua")
dofile("data/dialog_sequences.lua") dofile("data/dialog_sequences.lua")

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
return {distance_x, distance_y}
end end
function GetVectorValue(vector) function vector(x, y)
return math.sqrt(vector[1] ^ 2 + vector[2] ^ 2) return {x = x, y = y}
end end
function GetAngleFromVector(x,y) function getVectorValue(vector)
return math.sqrt(vector.x ^ 2 + vector.y ^ 2)
end
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

@@ -1,24 +1,24 @@
function MenuDraw(menu) function drawMenu(menu)
local font = love.graphics.getFont() local font = love.graphics.getFont()
love.graphics.setFont(LocaleFont) love.graphics.setFont(locale_font)
-- reset scale -- reset scale
love.graphics.setScale() love.graphics.setScale()
if menu == "pause" then if menu == "pause" then
MenuDrawPauseScreen() drawMenuPauseScreen()
elseif menu == "dialog" then elseif menu == "dialog" then
MenuDrawDialog() drawMenuDialog()
end end
for _, element in pairs(UIElement) do for _, element in pairs(UIElement) do
element:Draw() element:draw()
end end
love.graphics.setFont(font) love.graphics.setFont(font)
end end
function MenuDrawPauseScreen() function drawMenuPauseScreen()
-- Parameters -- Parameters
local pauseWidth = 640 local pauseWidth = 640
local pauseHeight = 480 local pauseHeight = 480
@@ -32,10 +32,10 @@ function MenuDrawPauseScreen()
love.graphics.rectangle("fill", pauseX, pauseY, pauseWidth, pauseHeight) love.graphics.rectangle("fill", pauseX, pauseY, pauseWidth, pauseHeight)
end end
function MenuDrawDialog() function drawMenuDialog()
end end
function MenuStep(menu) function stepMenu(menu)
-- first get mouse -- first get mouse
local mouse_x, mouse_y = love.mouse.getPosition() local mouse_x, mouse_y = love.mouse.getPosition()
for _, element in pairs(UIElement) do for _, element in pairs(UIElement) do
@@ -47,98 +47,98 @@ function MenuStep(menu)
end end
if menu == 0 then if menu == 0 then
elseif menu == "pause" then elseif menu == "pause" then
MenuStepPauseScreen() stepMenuPauseScreen()
elseif menu == "dialog" then elseif menu == "dialog" then
MenuStepDialog() stepMenuDialog()
end end
end end
function MenuStepPauseScreen() function stepMenuPauseScreen()
if PauseResume:getVariable() == true then if pause_resume:getVariable() == true then
PauseResume = nil pause_resume = nil
PauseOptions = nil pause_options = nil
PauseExit = nil pause_exit = nil
MenuExit() exitMenu()
elseif PauseExit:getVariable() == true then elseif pause_exit:getVariable() == true then
love.event.quit() love.event.quit()
end end
end end
function MenuStepDialog() function stepMenuDialog()
if DialogContainer.value >= DialogContainer.target_value then if dialog_container.value >= dialog_container.target_value then
DialogContainer = nil dialog_container = nil
MenuExit() exitMenu()
end end
end end
function MenuClear() function clearMenu()
for _, element in pairs(UIElement) do for _, element in pairs(UIElement) do
element = nil element = nil
end end
UIElement = {} UIElement = {}
end end
function MenuExit(to) function exitMenu(to)
MenuClear() clearMenu()
local to = to or "no" local to = to or "no"
menu_type = to menu_type = to
end end
function MenuInit(menu,parameter) function initMenu(menu,parameter)
-- main menu -- main menu
if menu == "pause" then if menu == "pause" then
MenuInitPauseScreen() initMenuPauseScreen()
elseif menu == "dialog" then elseif menu == "dialog" then
if parameter == nil then if parameter == nil then
parameter = DialogSequence.Example parameter = dialog_sequence.Example
end end
MenuInitDialog(parameter) initMenuDialog(parameter)
end end
end end
function MenuInitDialog(parameter) function initMenuDialog(parameter)
DialogContainer = interfaceDialog:new() dialog_container = InterfaceDialog:new()
DialogContainer:loadSequence(parameter) dialog_container:loadSequence(parameter)
end end
function MenuInitPauseScreen() function initMenuPauseScreen()
local buttonStandard = {width = 200, height = 30, separation = 10} local button_standard = {width = 200, height = 30, separation = 10}
-- elements -- elements
PauseResume = interfaceButton:new( pause_resume = InterfaceButton:new(
game.width/2, game.width/2,
game.height/2-buttonStandard.height-buttonStandard.separation, game.height/2-button_standard.height-button_standard.separation,
buttonStandard.width, button_standard.width,
buttonStandard.height, button_standard.height,
{false,true}, {false,true},
1, 1,
{ {
text = Locale.ui.pause_screen_resume, text = locale.ui.pause_screen_resume,
color = {0,0,0.5}, color = {0,0,0.5},
color2 = {1,1,1} color2 = {1,1,1}
} }
) )
PauseOptions = interfaceButton:new( pause_options = InterfaceButton:new(
game.width/2, game.width/2,
game.height/2, game.height/2,
buttonStandard.width, button_standard.width,
buttonStandard.height, button_standard.height,
{false,true}, {false,true},
1, 1,
{ {
text = Locale.ui.pause_screen_options, text = locale.ui.pause_screen_options,
color = {0,0,0.5}, color = {0,0,0.5},
color2 = {1,1,1} color2 = {1,1,1}
} }
) )
PauseExit = interfaceButton:new( pause_exit = InterfaceButton:new(
game.width/2, game.width/2,
game.height/2+buttonStandard.height+buttonStandard.separation, game.height/2+button_standard.height+button_standard.separation,
buttonStandard.width, button_standard.width,
buttonStandard.height, button_standard.height,
{false,true}, {false,true},
1, 1,
{ {
text = Locale.ui.pause_screen_exit, text = locale.ui.pause_screen_exit,
color = {0,0,0.5}, color = {0,0,0.5},
color2 = {1,1,1} color2 = {1,1,1}
} }

View File

@@ -7,8 +7,8 @@ function LoadedObjects.drawCollisions()
end end
for _, platform in pairs(LoadedObjects.Platforms) do for _, platform in pairs(LoadedObjects.Platforms) do
if platform.disable == true then platform:Draw(2) end if platform.is_disabled == true then platform:Draw(2) end
if platform.disable == false then platform:Draw(1) end if platform.is_disabled == false then platform:Draw(1) end
end end
for _, ladder in pairs(LoadedObjects.Ladders) do for _, ladder in pairs(LoadedObjects.Ladders) do
@@ -23,27 +23,16 @@ end
-- returns true if theres a collision at that point -- returns true if theres a collision at that point
function isThereObjectAt(x,y,objectType) function isThereObjectAt(x,y,objectType)
for _, object in pairs(objectType) do for _, object in pairs(objectType) do
if object.disable 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 object.is_colliding = true
and y >= object.from.y
and y <= object.to.y then
object.isColliding = true
return true return true
end end
end end
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 = {
@@ -54,21 +43,21 @@ function setCollisionFlags()
} }
for _, type in pairs(Check) do for _, type in pairs(Check) do
for _, object in pairs(type) do for _, object in pairs(type) do
object.isColliding = false object.is_colliding = false
end end
end end
for _, platform in pairs(LoadedObjects.Platforms) do for _, platform in pairs(LoadedObjects.Platforms) do
if main_Player.pos.y < platform.from.y then if main_player.pos.y < platform.from.y then
platform.disable = false platform.is_disabled = false
else else
platform.disable = true platform.is_disabled = true
end end
end end
for _, platform in pairs(LoadedObjects.Hazards) do for _, platform in pairs(LoadedObjects.Hazards) do
if main_Player.isOnGround then if main_player.isOnGround then
platform.disable = true platform.is_disabled = true
else else
platform.disable = false platform.is_disabled = false
end end
end end
end end

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

View File

@@ -8,7 +8,7 @@ function Queue:new()
return o return o
end end
function Queue:Enqueue(item) function Queue:enqueue(item)
local elem = {item = item} local elem = {item = item}
if self.head == nil then if self.head == nil then
self.head = elem self.head = elem
@@ -22,12 +22,12 @@ function Queue:Enqueue(item)
return return
end end
function Queue:Empty() function Queue:empty()
return self.tail == nil return self.tail == nil
end end
function Queue:Dequeue() function Queue:dequeue()
if self:Empty() then if self:empty() then
return nil return nil
end end
@@ -41,9 +41,9 @@ function Queue:Dequeue()
end end
local tq1 = Queue:new() local tq1 = Queue:new()
tq1:Enqueue(5) tq1:enqueue(5)
assert(tq1.head.item == 5) assert(tq1.head.item == 5)
assert(tq1:Dequeue() == 5) assert(tq1:dequeue() == 5)
-- queue that keeps a rolling tally of its arguments -- queue that keeps a rolling tally of its arguments
AvgQueue = {} AvgQueue = {}
@@ -58,7 +58,7 @@ function AvgQueue:new(n, initial)
local x = initial / n local x = initial / n
for _ = 1,n do for _ = 1,n do
o.queue:Enqueue(x) o.queue:enqueue(x)
end end
setmetatable(o, self) setmetatable(o, self)
@@ -66,9 +66,9 @@ function AvgQueue:new(n, initial)
return o return o
end end
function AvgQueue:Push(item) function AvgQueue:push(item)
local x = item/self.n local x = item/self.n
self.avg = self.avg + x - self.queue:Dequeue() self.avg = self.avg + x - self.queue:dequeue()
self.queue:Enqueue(x) self.queue:enqueue(x)
return self.avg return self.avg
end 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,15 @@ require "data/sfx"
require "code/locale" require "code/locale"
-- support functions -- support functions
require "code/class"
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/objects" require "code/objects"
require "code/level" require "code/level"
require "code/camera" require "code/camera"
@@ -22,6 +25,7 @@ require "code/queue"
-- objects -- objects
require "code/entity" require "code/entity"
require "code/spawn"
require "code/canvas" require "code/canvas"
require "code/collision" require "code/collision"
require "code/lights" require "code/lights"

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

268
code/spawn.lua Normal file
View File

@@ -0,0 +1,268 @@
LoadedObjects.Spawns = {}
function addSpawn(archetype, ...)
local o = {
archetype = archetype,
args = {...}
}
table.insert(LoadedObjects.Spawns, o)
end
function activateSpawns()
for _, spawn in pairs(LoadedObjects.Spawns) do
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("
local ancestors = getAncestors(spawn.archetype)
for i=1, #ancestors do
if i > 1 then text = text .. ", " end
text = text .. ancestors[i].type
end
text = text ..")\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

View File

@@ -1,9 +1,44 @@
UIElement = {} UIElement = {}
function AddElement(self) function addElement(self)
table.insert(UIElement,self) table.insert(UIElement,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"

View File

@@ -39,7 +39,7 @@ function InterfaceButton:new(x,y,w,h,table_values,value,style)
scale_proportion = 1.5 scale_proportion = 1.5
} }
AddElement(o) addElement(o)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -71,7 +71,7 @@ function InterfaceButton:checkMouse(mouse_x, mouse_y)
end end
end end
function InterfaceButton:Draw() function InterfaceButton:draw()
local c1, c2, c3, a = love.graphics.getColor() local c1, c2, c3, a = love.graphics.getColor()
love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha) love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha)

View File

@@ -29,7 +29,7 @@ function InterfaceDialog:new(style)
scale_proportion = 1 scale_proportion = 1
} }
AddElement(o) addElement(o)
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
@@ -65,7 +65,7 @@ function InterfaceDialog:checkConfirm()
end end
end end
function InterfaceDialog:Draw() function InterfaceDialog:draw()
local c1, c2, c3, a = love.graphics.getColor() local c1, c2, c3, a = love.graphics.getColor()
love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha) love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha)

80
code/ui/prompt.lua Normal file
View File

@@ -0,0 +1,80 @@
local utf8 = require("utf8")
local function backspace(text)
local byteoffset = utf8.offset(text, -1)
if byteoffset then
-- remove the last UTF-8 character.
-- string.sub operates on bytes rather than UTF-8 characters,
-- so we couldn't do string.sub(text, 1, -2).
return string.sub(text, 1, byteoffset - 1)
end
return ""
end
Prompt = class(nil, {
-- defaults for instance variables
pos = { x = 10, y = 10 },
input = "",
name = "input",
canceled = false,
closing = false,
color = {1,1,1,1},
background_color = {0,0,0,1},
active_prompt = nil,
})
function Prompt:cancelActive()
if Prompt.active_prompt then
Prompt.active_prompt.canceled = true
end
end
function Prompt:new(o)
o = o or {}
setmetatable(o, self)
return o
end
function Prompt:keypressed(key, scancode, isrepeat)
if key == "backspace" then
self.input = backspace(self.input)
elseif key == "return" or key == "kpenter" or key == "escape" then
if key == "escape" then
self.canceled = true
end
self.closing = true
self:func()
end
end
function Prompt:update()
end
function Prompt:textinput(text)
self.input = self.input .. text
end
function Prompt:draw()
drawTextBox(
self.name .. ": " .. self.input,
self.pos.x,
self.pos.y,
{
color = self.color,
background_color = self.background_color
}
)
end
function Prompt:activate()
Prompt.active_prompt = self
love.keyboard.setTextInput(true)
end
-- demonstration of how default values work
local test_prompt = Prompt:new()
assert(test_prompt.name == "input")
test_prompt.name = "foobar"
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,7 +1,7 @@
DialogSequence = {} dialog_sequence = {}
DialogSequence.Example = { dialog_sequence.example = {
{Locale.dialogue.example[1],Locale.name.fairy}, {locale.dialogue.example[1],locale.name.fairy},
{Locale.dialogue.example[2],Locale.name.chaos}, {locale.dialogue.example[2],locale.name.chaos},
{Locale.dialogue.example[3],Locale.name.life} {locale.dialogue.example[3],locale.name.life}
} }

View File

@@ -1,5 +1,5 @@
return { return {
name = "test", name = "Dev Level",
tileset = tileset.library, tileset = tileset.library,
properties = { properties = {
darkness = true darkness = true
@@ -24,9 +24,20 @@ return {
{ 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, 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, 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, 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, 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}},
{Candelabra,{328,297}}
},
rooms = {
{{96,64},{544,320}},
{{0,0},{112,176}}
},
}, },
objects = {}
} }

View File

@@ -1,16 +1,16 @@
LocaleFont = love.graphics.getFont() locale_font = love.graphics.getFont()
Locale = {} locale = {}
Locale.ui = {} locale.ui = {}
Locale.ui.pause_screen_resume = "Resume" locale.ui.pause_screen_resume = "Resume"
Locale.ui.pause_screen_options = "Options" locale.ui.pause_screen_options = "Options"
Locale.ui.pause_screen_exit = "Exit" locale.ui.pause_screen_exit = "Exit"
Locale.name = {} locale.name = {}
Locale.name.fairy = "Ozy" locale.name.fairy = "Ozy"
Locale.name.chaos = "Aelato" locale.name.chaos = "Aelato"
Locale.name.life = "Olidia" locale.name.life = "Olidia"
Locale.dialogue = {} locale.dialogue = {}
Locale.dialogue.example = {"Hello!","Duh.","Lol"} locale.dialogue.example = {"Hello!","Duh.","Lol"}

View File

@@ -1,16 +1,16 @@
LocaleFont = love.graphics.newFont("assets/ui/fonts/heon.ttf",18) locale_font = love.graphics.newFont("assets/ui/fonts/heon.ttf",18)
Locale = {} locale = {}
Locale.ui = {} locale.ui = {}
Locale.ui.pause_screen_resume = "" locale.ui.pause_screen_resume = ""
Locale.ui.pause_screen_options = "" locale.ui.pause_screen_options = ""
Locale.ui.pause_screen_exit = "" locale.ui.pause_screen_exit = ""
Locale.name = {} locale.name = {}
Locale.name.fairy = "" locale.name.fairy = ""
Locale.name.chaos = "" locale.name.chaos = ""
Locale.name.life = "" locale.name.life = ""
Locale.dialogue = {} locale.dialogue = {}
Locale.dialogue.example = {"","",""} locale.dialogue.example = {"","",""}

View File

@@ -1,8 +1,8 @@
Shader = {} shader = {}
Shader.RadiusGradient = love.graphics.newShader[[ shader.circle_gradient = love.graphics.newShader[[
uniform float pos_x; uniform float pos_x;
uniform float pos_y; uniform float pos_y;
uniform float range; uniform float radius;
uniform float scale; uniform float scale;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){
@@ -12,11 +12,13 @@ Shader.RadiusGradient = love.graphics.newShader[[
float distance_x = pos_x - screen_coords.x / scale; float distance_x = pos_x - screen_coords.x / scale;
float distance_y = pos_y - screen_coords.y / scale; float distance_y = pos_y - screen_coords.y / scale;
float distance = sqrt( pow(distance_x,2) + pow(distance_y,2) ) ; float distance = sqrt( pow(distance_x,2) + pow(distance_y,2) ) ;
if (distance < range){ if (distance < radius){
float alpha = 1-(5*distance/range); float alpha = 1-(5*distance/radius);
if (pixel.a > alpha){ if (pixel.a > alpha){
pixel.a = alpha; pixel.a = alpha;
} }
} else {
pixel.a = 0;
} }
return pixel * color * color; return pixel * color * color;
} }

View File

@@ -1,4 +1,4 @@
levelProperties = { level_properties = {
pos = { pos = {
x = 0, x = 0,
y = 0 y = 0
@@ -15,7 +15,7 @@ tileset = {
library = love.graphics.newImage("assets/tileset/library.png") library = love.graphics.newImage("assets/tileset/library.png")
} }
tileProperties = { tile_properties = {
width = 16, width = 16,
height = 16, height = 16,
scale = 1, scale = 1,

118
main.lua
View File

@@ -1,15 +1,17 @@
function love.load() function love.load()
logging = true logging = true
loveMemUsage = collectgarbage("count") local love_mem_usage = collectgarbage("count")
loveInitLog = "love: "..loveMemUsage.." kB, time: "..os.clock().." seconds" local love_init_log = "love: "..love_mem_usage.." kB, time: "..os.clock().." seconds"
arrow = 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
textScale = 1 text_size = 1
love.graphics.setColor(1,1,1) love.graphics.setColor(1,1,1)
@@ -17,7 +19,7 @@ function love.load()
love.graphics.setDefaultFilter("nearest") -- good pixel love.graphics.setDefaultFilter("nearest") -- good pixel
game = { game = {
secondsSinceStart = 0, seconds_since_start = 0,
scale = 2, scale = 2,
width = love.graphics.getWidth(), width = love.graphics.getWidth(),
height = love.graphics.getHeight(), height = love.graphics.getHeight(),
@@ -29,77 +31,113 @@ function love.load()
fps_history = AvgQueue:new(30,60) fps_history = AvgQueue:new(30,60)
logPrint(loveInitLog) logPrint(love_init_log)
loveInitLog = nil love_init_log = nil
Camera.width = game.width Camera.width = game.width
Camera.height = game.height Camera.height = game.height
levelList = scandir("./data/levels") level_list = scandir("./data/levels")
levelNum = 1 level_current_num = 1
currLevel = levelList[levelNum] level_current = level_list[level_current_num]
logPrint("currLevel: "..currLevel) logPrint("level_current: "..level_current)
LoadedParticles = {}
LevelLoadTiles() loadLevelTiles()
language = "ENG" language = "ENG"
LocaleLoad(language) loadLocale(language)
gravity = 0.14 gravity = 0.14
-- Debug and log stuff -- Debug and log stuff
memoryUsage, dtcount = 0, 0 memory_usage, dtcount = 0, 0
logPrint("mothback: "..collectgarbage("count").." kB, Loading time: "..os.clock().." seconds") logPrint("mothback: "..collectgarbage("count").." kB, Loading time: "..os.clock().." seconds")
main_Player = Player:new(75,50) main_player = Player:new(75,50)
--Kupo:new(100,150)
--Kupo:new(300,150)
HookAnchor:new(200,89)
HookAnchor:new(400,89)
Fairy:new(200,88)
--CursedBook:new(180,68)
activateSpawns()
--love.audio.play(music.placeholder) --love.audio.play(music.placeholder)
end end
function love.textinput(text)
if Prompt.active_prompt then
Prompt.active_prompt:textinput(text)
end
end
function love.keypressed(...)
if Prompt.active_prompt then
Prompt.active_prompt:keypressed(...)
end
end
function love.update(dt) function love.update(dt)
-- audio update -- audio update
love.audio.update() love.audio.update()
-- fps counter -- fps counter
fps_current = fps_history:Push(1/dt) fps_current = fps_history:push(1/dt)
current_dt = dt current_dt = dt
game.secondsSinceStart = game.secondsSinceStart + dt game.seconds_since_start = game.seconds_since_start + dt
if DemoRecording or DemoPlayback then Demo:step() end if DemoRecording or DemoPlayback then Demo:step() end
-- things per second -- things per second
dtcount = dtcount + dt dtcount = dtcount + dt
game.seconds_since_start = game.seconds_since_start + dt
if dtcount >= 1 then if dtcount >= 1 then
if secs == nil then secs = 0 end
secs = secs + 1 secs = secs + 1
dtcount = dtcount - 1 dtcount = dtcount - 1
if debug or logging then if debug or logging then
memoryUsage = math.floor(collectgarbage("count")) memory_usage = math.floor(collectgarbage("count"))
end end
logWrite("Second "..secs..": "..memoryUsage.." kB") logWrite("Second "..secs..": "..memory_usage.." kB")
end
if Prompt.active_prompt then
-- try to stop the keypress that closed the menu from spilling into the rest of the game
Keybind:checkPressed(Keybind.menu.pause)
if Prompt.active_prompt.closing then
Prompt.active_prompt = nil
else
Prompt.active_prompt:update()
end
return
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
local test_prompt = Prompt:new({
name = "test prompt",
func = function(prompt)
print("test prompt got input: "..prompt.input)
end,
})
test_prompt:activate()
end end
--keypressed --keypressed
if Keybind:CheckPressed(Keybind.menu.pause) then if Keybind:checkPressed(Keybind.menu.pause) then
if do_pause then if do_pause then
do_pause = false do_pause = false
else else
menu_type = "pause" menu_type = "pause"
MenuInit(menu_type) initMenu(menu_type)
end end
end end
--MenuStep --MenuStep
if menu_type ~= nil then MenuStep(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()
@@ -108,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
@@ -122,17 +160,21 @@ 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()
end end
if menu_type ~= nil then MenuDraw(menu_type) end if menu_type ~= nil then drawMenu(menu_type) end
love.graphics.print(game.scale,10,40) love.graphics.print(game.scale,10,40)
if DemoRecording or DemoPlayback then Demo:draw() end if DemoRecording or DemoPlayback then Demo:draw() end
if Prompt.active_prompt then
Prompt.active_prompt:draw()
end
frameDebugFlush() frameDebugFlush()
end end