Compare commits
37 Commits
97de68e34b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a20b172af | ||
|
|
a01599c001 | ||
|
|
410c00dcd4 | ||
|
|
8edcbe2d9b | ||
|
|
fa62e1428b | ||
|
|
9be52e2b5f | ||
|
|
a3074acb3c | ||
|
|
59726dc2b7 | ||
|
|
f0a9c1acf9 | ||
|
|
1549976382 | ||
|
|
d20e5392f8 | ||
|
|
d359afaf97 | ||
|
|
11a46e6227 | ||
|
|
f670f6bc87 | ||
|
|
0486787b98 | ||
|
|
6ba4f4d1c9 | ||
|
|
918c63c535 | ||
|
|
6fa7dcbeef | ||
|
|
236e23177d | ||
|
|
4d94cc805d | ||
|
|
9c4b5431ee | ||
|
|
ba1c0f0c89 | ||
|
|
ef632d50ee | ||
|
|
5bcf25a461 | ||
|
|
1039479c47 | ||
|
|
62555b4526 | ||
|
|
a4af57ca6c | ||
|
|
5189bef537 | ||
|
|
eab4cbbcdc | ||
|
|
829963e080 | ||
|
|
82246dc0c6 | ||
|
|
3a5e0b395b | ||
|
|
feed65cf6d | ||
|
|
1883bcd78b | ||
|
|
3c1746d914 | ||
|
|
f091fba9f7 | ||
|
|
27f1dc71c0 |
|
Before Width: | Height: | Size: 92 B After Width: | Height: | Size: 92 B |
|
Before Width: | Height: | Size: 89 B After Width: | Height: | Size: 90 B |
|
Before Width: | Height: | Size: 88 B After Width: | Height: | Size: 88 B |
|
Before Width: | Height: | Size: 97 B After Width: | Height: | Size: 97 B |
@@ -10,6 +10,8 @@ function Animation:new(anim_data,speed)
|
|||||||
o.frame = 1
|
o.frame = 1
|
||||||
o.speed = speed or 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
|
||||||
@@ -49,6 +51,9 @@ 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 + self.speed
|
self.subframe = self.subframe + self.speed
|
||||||
@@ -56,6 +61,7 @@ function Animation:animate()
|
|||||||
if self.subframe > self.frames[self.frame]*game.framerate then
|
if self.subframe > self.frames[self.frame]*game.framerate then
|
||||||
self.subframe = self.subframe - self.frames[self.frame]*game.framerate
|
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
|
||||||
|
|||||||
@@ -77,3 +77,16 @@ function Camera:positionAt(x,y)
|
|||||||
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
@@ -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
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Collision = {}
|
Collision = class()
|
||||||
|
|
||||||
LoadedObjects.Collisions = {}
|
LoadedObjects.Collisions = {}
|
||||||
LoadedObjects.Platforms = {}
|
LoadedObjects.Platforms = {}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1,17 +1,37 @@
|
|||||||
assert(editor == nil)
|
assert(editor == nil)
|
||||||
editor = {
|
editor = {
|
||||||
|
active = false,
|
||||||
room_mode = false,
|
room_mode = false,
|
||||||
--palette_mode = false,
|
|
||||||
palette = {
|
palette = {
|
||||||
active = false,
|
active = false,
|
||||||
scroll = Point:new(0, 0),
|
scroll = Point:new(0, 0),
|
||||||
},
|
},
|
||||||
|
multiselect = {
|
||||||
|
active = false,
|
||||||
|
sweeping = false,
|
||||||
|
box = nil,
|
||||||
|
},
|
||||||
pan = { fixed = false, speed = 3 },
|
pan = { fixed = false, speed = 3 },
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepEditor()
|
function stepEditor()
|
||||||
|
|
||||||
animateTiles()
|
animateTiles()
|
||||||
|
|
||||||
|
local osweep = editor.multiselect.sweeping
|
||||||
|
editor.multiselect.sweeping = Keybind:checkDown(Keybind.editor.entity_select)
|
||||||
|
frameDebug("sweeping: "..tostring(editor.multiselect.sweeping))
|
||||||
|
if editor.multiselect.sweeping and not editor.multiselect.active then
|
||||||
|
print("multiselect enabled")
|
||||||
|
editor.multiselect.active = true
|
||||||
|
end
|
||||||
|
if not osweep and osweep ~= editor.multiselect.sweeping then
|
||||||
|
editor.multiselect.box = nil
|
||||||
|
end
|
||||||
|
if editor.multiselect.active then
|
||||||
|
doEditorMultiselect()
|
||||||
|
end
|
||||||
|
|
||||||
if Keybind:checkPressed(Keybind.editor.room_mode) then
|
if Keybind:checkPressed(Keybind.editor.room_mode) then
|
||||||
if love.keyboard.isDown("lshift") then
|
if love.keyboard.isDown("lshift") then
|
||||||
editor.room_mode = "delete"
|
editor.room_mode = "delete"
|
||||||
@@ -89,13 +109,6 @@ function stepEditor()
|
|||||||
end,
|
end,
|
||||||
}):activate()
|
}):activate()
|
||||||
end
|
end
|
||||||
|
|
||||||
if Keybind:checkPressed(Keybind.debug.editor) then
|
|
||||||
editor_mode = not editor_mode
|
|
||||||
deselectSpawns()
|
|
||||||
createTileObjects()
|
|
||||||
restartGame()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function scrollEditor(y)
|
function scrollEditor(y)
|
||||||
@@ -128,6 +141,10 @@ function drawEditor()
|
|||||||
if editor.palette.active 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()
|
||||||
@@ -204,7 +221,9 @@ function doEditorEdit()
|
|||||||
else
|
else
|
||||||
if Keybind:checkDown(Keybind.editor.entity_select) then
|
if Keybind:checkDown(Keybind.editor.entity_select) then
|
||||||
deselectSpawns()
|
deselectSpawns()
|
||||||
selectSpawns(mouse_x,mouse_y)
|
if editor.multiselect.box then
|
||||||
|
selectSpawns(editor.multiselect.box)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if Keybind:checkDown(Keybind.editor.entity_move) then
|
if Keybind:checkDown(Keybind.editor.entity_move) then
|
||||||
moveSpawns(mouse_x,mouse_y)
|
moveSpawns(mouse_x,mouse_y)
|
||||||
@@ -353,7 +372,21 @@ 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
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
Arrow = Entity:new()
|
Arrow = class(Entity, {
|
||||||
Arrow.type = "Arrow"
|
type = "Arrow",
|
||||||
|
display = Animation:new(animation.kupo.arrow),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
function Arrow:new(x,y,rotation,speed)
|
function Arrow:new(x,y,rotation,speed)
|
||||||
@@ -36,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
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
CursedBook = Entity:new()
|
CursedBook = class(Entity, {
|
||||||
CursedBook.type = "CursedBook"
|
type = "CursedBook",
|
||||||
CursedBook.display = Animation:new(animation.cursed_book.flying)
|
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)
|
||||||
@@ -28,10 +29,12 @@ function CursedBook:new(x,y)
|
|||||||
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
|
||||||
o:id()
|
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
|
||||||
@@ -67,6 +70,13 @@ function CursedBook:doLogic()
|
|||||||
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()
|
||||||
@@ -101,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
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
Decoration = Entity:new()
|
Decoration = class(Entity, {
|
||||||
Decoration.type = "Decoration"
|
type = "Decoration",
|
||||||
Decoration.display = nil
|
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.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
|
||||||
|
|
||||||
o:id()
|
if light_data then
|
||||||
|
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
|
||||||
@@ -29,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
|
|
||||||
|
|||||||
54
code/entities/decorations/candelabra.lua
Normal 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
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
Fairy = Entity:new()
|
Fairy = class(Entity, {
|
||||||
Fairy.type = "Fairy"
|
type = "Fairy",
|
||||||
Fairy.display = Animation:new(animation.fairy.flying)
|
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)
|
||||||
@@ -19,22 +20,23 @@ 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
|
||||||
|
|
||||||
o:id()
|
|
||||||
|
|
||||||
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.x = main_player.pos.x + main_player.target_offset.x
|
||||||
@@ -63,31 +65,19 @@ function Fairy:doLogic()
|
|||||||
|
|
||||||
local distance_x = self.target.x - self.pos.x
|
local distance_x = self.target.x - self.pos.x
|
||||||
local distance_y = self.target.y - self.pos.y
|
local distance_y = self.target.y - self.pos.y
|
||||||
local angle = getAngleFromVector(distance_x,distance_y)
|
local angle = getAngleFromVector(vector(distance_x,distance_y))
|
||||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||||
|
|
||||||
if distance < self.range then
|
if distance < self.range then
|
||||||
self.vel.x = self.vel.x * 0.9
|
local random_x = math.random(-1, 1)
|
||||||
self.vel.y = self.vel.y * 0.9
|
local random_y = math.random(-1, 1)
|
||||||
|
self.vel.x = self.vel.x * 0.9 + random_x/10
|
||||||
|
self.vel.y = self.vel.y * 0.9 + random_y/10
|
||||||
else
|
else
|
||||||
self.vel.x = math.cos(angle)*self.speed
|
local random_x = math.random(-6, 6)
|
||||||
self.vel.y = math.sin(angle)*self.speed
|
local random_y = math.random(-6, 6)
|
||||||
end
|
self.vel.x = math.cos(angle)*self.speed + random_x/10
|
||||||
self.particle_timer = self.particle_timer + 1
|
self.vel.y = math.sin(angle)*self.speed + random_y/10
|
||||||
if self.particle_timer >= self.particle_time then
|
|
||||||
self.particle_timer = 0
|
|
||||||
|
|
||||||
local particle_data = {
|
|
||||||
animation = animation.particle.simple,
|
|
||||||
animation_speed = 1,
|
|
||||||
sprite_tint = hex2rgb("#fed100"),
|
|
||||||
sprite_alpha_fade = true,
|
|
||||||
direction = angle-math.rad(180+math.random(60)-30),
|
|
||||||
speed = 0.8*(distance/50),
|
|
||||||
speed_increase = -0.01,
|
|
||||||
time = 0.75
|
|
||||||
}
|
|
||||||
Particle:new(self.pos.x,self.pos.y,particle_data)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,19 +85,45 @@ 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
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
HookAnchor = Entity:new()
|
HookAnchor = class(Entity, {
|
||||||
HookAnchor.type = "HookAnchor"
|
type = "HookAnchor",
|
||||||
HookAnchor.display = Animation:new(animation.fairy.flying)
|
display = Animation:new(animation.fairy.flying),
|
||||||
|
})
|
||||||
|
|
||||||
function HookAnchor:new(x,y,hook_distance)
|
function HookAnchor:new(x,y,hook_distance)
|
||||||
local o = Entity:new(x,y)
|
local o = Entity:new(x,y)
|
||||||
@@ -13,8 +14,6 @@ function HookAnchor:new(x,y,hook_distance)
|
|||||||
o:centerOffset(o.body)
|
o:centerOffset(o.body)
|
||||||
o:createBox(o.body)
|
o:createBox(o.body)
|
||||||
|
|
||||||
o:id()
|
|
||||||
|
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
return o
|
return o
|
||||||
@@ -36,10 +35,6 @@ function HookAnchor:drawBackground()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function HookAnchor:doPhysics()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Fairy:debug()
|
function Fairy:debug()
|
||||||
Entity.debug(self)
|
Entity.debug(self)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
Kupo = Entity:new()
|
Kupo = class(Entity, {
|
||||||
Kupo.type = "Kupo"
|
type = "Kupo",
|
||||||
Kupo.display = Animation:new(animation.kupo.body)
|
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)
|
||||||
@@ -27,10 +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
|
||||||
o:id()
|
light_data.shine_radius = 20
|
||||||
|
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
|
||||||
@@ -44,8 +48,9 @@ function Kupo:doLogic()
|
|||||||
self.target.y = main_player.pos.y - main_player.target_offset.y
|
self.target.y = main_player.pos.y - main_player.target_offset.y
|
||||||
local distance_x = self.target.x - self.pos.x
|
local distance_x = self.target.x - self.pos.x
|
||||||
local distance_y = self.target.y - self.pos.y
|
local distance_y = self.target.y - self.pos.y
|
||||||
|
|
||||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||||
local angle = getAngleFromVector(distance_x,distance_y)
|
local angle = getAngleFromVector(vector(distance_x,distance_y))
|
||||||
self.draw_bow = false
|
self.draw_bow = false
|
||||||
if distance <= self.range then
|
if distance <= self.range then
|
||||||
if self.hostile == true then
|
if self.hostile == true then
|
||||||
@@ -153,7 +158,3 @@ function Kupo:handleAnimation()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Kupo:doPhysics()
|
|
||||||
self:moveWithCollision()
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
LoadedObjects.Particles = {}
|
LoadedObjects.Particles = {}
|
||||||
|
Particle = class(Entity, {
|
||||||
Particle = Entity:new()
|
type = "Particle",
|
||||||
Particle.type = "Particle"
|
display = Animation:new(animation.particle.simple),
|
||||||
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)
|
||||||
@@ -10,19 +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_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 o.sprite_flip
|
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.time = particle_data.time or nil
|
||||||
if o.time ~= nil then o.time = o.time * game.framerate end
|
|
||||||
|
|
||||||
|
if o.time then
|
||||||
|
if particle_data.time_unit ~= nil
|
||||||
|
and particle_data.time_unit == "frames" then
|
||||||
|
o.time = o.time
|
||||||
|
else
|
||||||
|
o.time = o.time * game.framerate
|
||||||
|
end
|
||||||
|
end
|
||||||
o.timer = 0
|
o.timer = 0
|
||||||
|
|
||||||
o.vel = {
|
o.vel = {
|
||||||
@@ -30,44 +37,34 @@ 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,particle_data.animation_speed)
|
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)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- particle id handled differently from other entities
|
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()
|
||||||
@@ -77,34 +74,59 @@ function Particle:handleAnimation()
|
|||||||
self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
|
self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
|
||||||
end
|
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
|
|
||||||
-- move
|
|
||||||
self:moveWithCollision()
|
|
||||||
|
|
||||||
if self.light ~= nil then
|
|
||||||
self:adjustLight()
|
|
||||||
self.light.range = self.light_range * self.sprite_alpha/2
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.time ~= nil then
|
if self.time then
|
||||||
if self.timer >= self.time then self:kill() end
|
if self.timer >= self.time then self:kill() end
|
||||||
end
|
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
|
||||||
|
|
||||||
function Particle:debug()
|
function Particle:debug()
|
||||||
-- draw center CYAN
|
-- draw center CYAN
|
||||||
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
|
||||||
|
|
||||||
|
---------------
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
Player = Entity:new()
|
Player = class(Entity, {
|
||||||
Player.type = "Player"
|
type = "Player",
|
||||||
Player.display = Animation:new(animation.nancy.idle)
|
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)
|
||||||
@@ -41,9 +42,6 @@ function Player:new(x,y)
|
|||||||
o.walljump_nodrift_amount = 12
|
o.walljump_nodrift_amount = 12
|
||||||
o.walljump_impulse = { x = 2.5, y = 3.5 }
|
o.walljump_impulse = { x = 2.5, y = 3.5 }
|
||||||
|
|
||||||
-- light values
|
|
||||||
o.light_radius = 40 -- screen pixels
|
|
||||||
|
|
||||||
-- status
|
-- status
|
||||||
o.can_jump = true
|
o.can_jump = true
|
||||||
o.can_fall = true
|
o.can_fall = true
|
||||||
@@ -75,9 +73,12 @@ function Player:new(x,y)
|
|||||||
o:createBox(o.body,0,4,-1,-5)
|
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
|
||||||
o:id()
|
light_data.shine_radius = 20
|
||||||
|
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
|
||||||
@@ -155,7 +156,7 @@ function Player:doLogic()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- set dash values
|
-- set dash values
|
||||||
self.dashDirection = getAngleFromVector(horizontal, vertical)
|
self.dashDirection = getAngleFromVector(vector(horizontal, vertical))
|
||||||
self.dash_timer = math.floor(self.dash_time * game.framerate)
|
self.dash_timer = math.floor(self.dash_time * game.framerate)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -232,10 +233,10 @@ function Player:doPhysics()
|
|||||||
-- hook state
|
-- hook state
|
||||||
if self.is_hooked then
|
if self.is_hooked then
|
||||||
self.move_x = 0
|
self.move_x = 0
|
||||||
local hook = vector(self.pos.x, self.pos.y, self.hook_anchor.x, self.hook_anchor.y)
|
local hook = vector(self.hook_anchor.x - self.pos.x, self.hook_anchor.y - self.pos.y)
|
||||||
local dist = math.min(getVectorValue(hook), self.hook_distance)
|
local dist = math.min(getVectorValue(hook), self.hook_distance)
|
||||||
|
|
||||||
local hook_angle = getAngleFromVector(hook[1],hook[2])-math.rad(180)
|
local hook_angle = getAngleFromVector(hook)-math.rad(180)
|
||||||
|
|
||||||
if Keybind:checkDown(Keybind.move.right) then
|
if Keybind:checkDown(Keybind.move.right) then
|
||||||
hook_angle = hook_angle - self.hook_swing_speed
|
hook_angle = hook_angle - self.hook_swing_speed
|
||||||
@@ -251,7 +252,8 @@ function Player:doPhysics()
|
|||||||
animation_speed = 0,
|
animation_speed = 0,
|
||||||
sprite_tint = hex2rgb("#fed100"),
|
sprite_tint = hex2rgb("#fed100"),
|
||||||
sprite_alpha = 0.5,
|
sprite_alpha = 0.5,
|
||||||
time = 0.05,
|
time = 4,
|
||||||
|
time_unit = "frames",
|
||||||
sprite_flip = {
|
sprite_flip = {
|
||||||
x = self.sprite_flip.x,
|
x = self.sprite_flip.x,
|
||||||
y = self.sprite_flip.y
|
y = self.sprite_flip.y
|
||||||
@@ -263,8 +265,13 @@ function Player:doPhysics()
|
|||||||
local pos_y = self.hook_anchor.y + dist * math.sin(hook_angle)
|
local pos_y = self.hook_anchor.y + dist * math.sin(hook_angle)
|
||||||
self.vel.x = self.vel.x + pos_x - self.pos.x
|
self.vel.x = self.vel.x + pos_x - self.pos.x
|
||||||
self.vel.y = self.vel.y + pos_y - self.pos.y
|
self.vel.y = self.vel.y + pos_y - self.pos.y
|
||||||
self.pos.x = pos_x
|
|
||||||
self.pos.y = pos_y
|
self:moveX(
|
||||||
|
pos_x - self.pos.x
|
||||||
|
)
|
||||||
|
self:moveY(
|
||||||
|
pos_y - self.pos.y
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -275,24 +282,26 @@ function Player:doPhysics()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- horizontal collision
|
-- horizontal collision
|
||||||
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then
|
self.wall_hit = 0
|
||||||
self.pos.x = self.pos.x + self.vel.x
|
self:moveX(
|
||||||
self.wall_hit = 0
|
self.vel.x,
|
||||||
else
|
function()
|
||||||
self.wall_hit = math.sign(self.vel.x)
|
self.wall_hit = math.sign(self.vel.x)
|
||||||
self.vel.x = 0
|
self.vel.x = 0
|
||||||
end
|
end
|
||||||
|
)
|
||||||
|
|
||||||
-- vertical collision
|
-- vertical collision
|
||||||
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
|
self:moveY(
|
||||||
self.pos.y = self.pos.y + self.vel.y
|
self.vel.y,
|
||||||
else
|
function()
|
||||||
if self.vel.y > 0 then
|
if self.vel.y > 0 then
|
||||||
self.is_on_ground = true
|
self.is_on_ground = true
|
||||||
self.dash_count = self.dash_amount
|
self.dash_count = self.dash_amount
|
||||||
|
end
|
||||||
|
self.vel.y = 0
|
||||||
end
|
end
|
||||||
self.vel.y = 0
|
)
|
||||||
end
|
|
||||||
|
|
||||||
-- if u collision w hazard, respawn
|
-- if u collision w hazard, respawn
|
||||||
if self:isCollidingAt(self.pos.x, self.pos.y, LoadedObjects.Hazards) then
|
if self:isCollidingAt(self.pos.x, self.pos.y, LoadedObjects.Hazards) then
|
||||||
@@ -326,10 +335,10 @@ function Player:handleAnimation()
|
|||||||
elseif self.vel.y < 0 then
|
elseif self.vel.y < 0 then
|
||||||
self.body = self.body:change(animation.nancy.jump)
|
self.body = self.body:change(animation.nancy.jump)
|
||||||
self.mask = self.mask:change(self.mask_type.jump)
|
self.mask = self.mask:change(self.mask_type.jump)
|
||||||
elseif self.vel.x + self.move_x ~= 0 then
|
elseif self.vel.x + self.move_x ~= 0 and not self.is_hooked then
|
||||||
self.body = self.body:change(animation.nancy.run)
|
self.body = self.body:change(animation.nancy.run)
|
||||||
self.mask = self.mask:change(self.mask_type.run)
|
self.mask = self.mask:change(self.mask_type.run)
|
||||||
else
|
elseif not self.is_hooked then
|
||||||
self.body = self.body:change(animation.nancy.idle)
|
self.body = self.body:change(animation.nancy.idle)
|
||||||
self.mask = self.mask:change(self.mask_type.idle)
|
self.mask = self.mask:change(self.mask_type.idle)
|
||||||
end
|
end
|
||||||
|
|||||||
110
code/entity.lua
@@ -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,19 +23,13 @@ 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:id()
|
|
||||||
table.insert(LoadedObjects.Entities,self)
|
|
||||||
self.id = #LoadedObjects.Entities
|
|
||||||
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
|
||||||
@@ -66,27 +61,53 @@ function Entity:checkNearest(type,maxdistance)
|
|||||||
return return_entity
|
return return_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:doLogic()
|
function Entity:moveX(amount, func)
|
||||||
end
|
self.move_remainder.x = self.move_remainder.x + amount
|
||||||
|
local move = math.round(self.move_remainder.x)
|
||||||
function Entity:move()
|
if move ~= 0 then
|
||||||
self.pos.x = self.pos.x + self.vel.x
|
self.move_remainder.x = self.move_remainder.x - move
|
||||||
self.pos.y = self.pos.y + self.vel.y
|
local sign = math.sign(move)
|
||||||
end
|
while math.round(move) ~= 0 do
|
||||||
|
if not self:isCollidingAt(
|
||||||
function Entity:moveWithCollision()
|
self.pos.x + sign,
|
||||||
-- horizontal collision
|
self.pos.y,
|
||||||
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then
|
LoadedObjects.Collisions
|
||||||
self.pos.x = self.pos.x + self.vel.x
|
) then
|
||||||
else
|
self.pos.x = self.pos.x + sign
|
||||||
self.vel.x = 0
|
move = move - sign
|
||||||
|
if tostring(move) == "nan" then error() end
|
||||||
|
else
|
||||||
|
if func then
|
||||||
|
func()
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- vertical collision
|
function Entity:moveY(amount, func)
|
||||||
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
|
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)
|
||||||
else
|
if move ~= 0 then
|
||||||
self.vel.y = 0
|
self.move_remainder.y = self.move_remainder.y - move
|
||||||
|
local sign = math.sign(move)
|
||||||
|
while math.round(move) ~= 0 do
|
||||||
|
if not self:isCollidingAt(
|
||||||
|
self.pos.x,
|
||||||
|
self.pos.y + sign,
|
||||||
|
LoadedObjects.Collisions
|
||||||
|
) then
|
||||||
|
self.pos.y = self.pos.y + sign
|
||||||
|
move = move - sign
|
||||||
|
if tostring(move) == "nan" then error() end
|
||||||
|
else
|
||||||
|
if func then
|
||||||
|
func()
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,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
|
||||||
table.remove(LoadedObjects.Entities,self.id)
|
|
||||||
for _, e in pairs(LoadedObjects.Entities) do
|
|
||||||
if e.id > self.id then
|
|
||||||
e.id = e.id - 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:checkVisionLine(entity,range)
|
function Entity:checkVisionLine(entity,range)
|
||||||
@@ -120,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
|
||||||
@@ -227,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
|
||||||
@@ -277,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"
|
||||||
|
|||||||
@@ -53,10 +53,6 @@ function stepGame()
|
|||||||
initMenu("dialog",dialog_sequence.example)
|
initMenu("dialog",dialog_sequence.example)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Keybind:checkPressed(Keybind.debug.editor) then
|
|
||||||
editor_mode = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if Keybind:checkPressed(Keybind.debug.recording) then
|
if Keybind:checkPressed(Keybind.debug.recording) then
|
||||||
if DemoRecording then
|
if DemoRecording then
|
||||||
Demo:endRecord()
|
Demo:endRecord()
|
||||||
@@ -72,6 +68,10 @@ function stepGame()
|
|||||||
Demo:startPlayback()
|
Demo:startPlayback()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cleanDeadParticles()
|
||||||
|
cleanDeadEntities()
|
||||||
|
cleanDeadLights()
|
||||||
end
|
end
|
||||||
|
|
||||||
function drawGame()
|
function drawGame()
|
||||||
|
|||||||
@@ -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.circle_gradient:send("pos_x",- Camera.pos.x + light.pos.x)
|
|
||||||
shader.circle_gradient:send("pos_y",- Camera.pos.y + light.pos.y)
|
|
||||||
shader.circle_gradient:send("range",light.range)
|
|
||||||
shader.circle_gradient:send("scale",game.scale)
|
|
||||||
|
|
||||||
love.graphics.setShader(shader.circle_gradient)
|
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ Keybind.debug = {}
|
|||||||
Keybind.editor = {}
|
Keybind.editor = {}
|
||||||
Keybind.generic = {}
|
Keybind.generic = {}
|
||||||
|
|
||||||
|
function Keybind:isAvailable(action)
|
||||||
|
return not action.occupied
|
||||||
|
end
|
||||||
|
|
||||||
function Keybind:checkDown(action)
|
function Keybind:checkDown(action)
|
||||||
if DemoPlayback then
|
if DemoPlayback then
|
||||||
for _, demo_action in pairs(DemoAction[CurrentDemoFrame]) do
|
for _, demo_action in pairs(DemoAction[CurrentDemoFrame]) do
|
||||||
@@ -37,9 +41,11 @@ function Keybind:checkDown(action)
|
|||||||
if action.demo ~= nil then
|
if action.demo ~= nil then
|
||||||
Demo:recordAction(action.demo)
|
Demo:recordAction(action.demo)
|
||||||
end
|
end
|
||||||
|
action.occupied = true
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
action.occupied = false
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -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
|
|
||||||
table.remove(LoadedObjects.Lights,self.id)
|
|
||||||
for _, e in pairs(LoadedObjects.Lights) do
|
|
||||||
if e.id > self.id then
|
|
||||||
e.id = e.id - 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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
|
||||||
|
|
||||||
|
---------------
|
||||||
|
|||||||
@@ -8,20 +8,22 @@ function math.sign(x)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector(init_x, init_y, final_x, final_y)
|
function math.round(x)
|
||||||
local distance_x = final_x - init_x
|
return math.floor(x+0.5)
|
||||||
local distance_y = final_y - init_y
|
end
|
||||||
return {distance_x, distance_y}
|
|
||||||
|
function vector(x, y)
|
||||||
|
return {x = x, y = y}
|
||||||
end
|
end
|
||||||
|
|
||||||
function getVectorValue(vector)
|
function getVectorValue(vector)
|
||||||
return math.sqrt(vector[1] ^ 2 + vector[2] ^ 2)
|
return math.sqrt(vector.x ^ 2 + vector.y ^ 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function getAngleFromVector(x,y)
|
function getAngleFromVector(vector)
|
||||||
local reduce = 0
|
local reduce = 0
|
||||||
if x < 0 then
|
if vector.x < 0 then
|
||||||
reduce = math.rad(180)
|
reduce = math.rad(180)
|
||||||
end
|
end
|
||||||
return math.atan(y/x) - reduce
|
return math.atan(vector.y/vector.x) - reduce
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,10 +25,7 @@ function isThereObjectAt(x,y,objectType)
|
|||||||
for _, object in pairs(objectType) do
|
for _, object in pairs(objectType) do
|
||||||
if object.is_disabled then
|
if object.is_disabled then
|
||||||
-- Dont calculate if dissabled
|
-- Dont calculate if dissabled
|
||||||
elseif x >= object.from.x
|
elseif object:asRect():containsPoint(Point:new(x, y)) then
|
||||||
and x <= object.to.x
|
|
||||||
and y >= object.from.y
|
|
||||||
and y <= object.to.y then
|
|
||||||
object.is_colliding = true
|
object.is_colliding = true
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -36,14 +33,6 @@ function isThereObjectAt(x,y,objectType)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function isThereCollisionAt(x,y)
|
|
||||||
if x >= 0 and x < #CollisionTable
|
|
||||||
and y >= 0 and y < #CollisionTable[0] then
|
|
||||||
return CollisionTable[math.floor(y)][math.floor(x)]
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- flags
|
-- flags
|
||||||
function setCollisionFlags()
|
function setCollisionFlags()
|
||||||
local Check = {
|
local Check = {
|
||||||
|
|||||||
86
code/rect.lua
Normal 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
|
||||||
@@ -7,6 +7,7 @@ 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"
|
||||||
@@ -14,6 +15,7 @@ require "code/in_out"
|
|||||||
|
|
||||||
-- classes
|
-- classes
|
||||||
require "code/point"
|
require "code/point"
|
||||||
|
require "code/rect"
|
||||||
require "code/objects"
|
require "code/objects"
|
||||||
require "code/level"
|
require "code/level"
|
||||||
require "code/camera"
|
require "code/camera"
|
||||||
|
|||||||
31
code/serialize.lua
Normal 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
|
||||||
@@ -20,7 +20,11 @@ function deselectSpawns()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function selectSpawns(x,y)
|
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
|
for _, spawn in pairs(LoadedObjects.Spawns) do
|
||||||
|
|
||||||
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
|
local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
|
||||||
@@ -28,9 +32,9 @@ function selectSpawns(x,y)
|
|||||||
local top = spawn.args[2] - Camera.pos.y - offset_y
|
local top = spawn.args[2] - Camera.pos.y - offset_y
|
||||||
local right = spawn.args[1] - Camera.pos.x + offset_x
|
local right = spawn.args[1] - Camera.pos.x + offset_x
|
||||||
local bottom = spawn.args[2] - Camera.pos.y + offset_y
|
local bottom = spawn.args[2] - Camera.pos.y + offset_y
|
||||||
local x = (x / game.scale)
|
|
||||||
local y = (y / game.scale)
|
local spawn_rect = Rect:fromCoords(left, top, right, bottom)
|
||||||
if x >= left and y >= top and x <= right and y <= bottom then
|
if spawn_rect:overlapsRect(select_rect) then
|
||||||
spawn.selected = true
|
spawn.selected = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -47,10 +51,22 @@ function selectSpawns(x,y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function moveSpawns(x,y)
|
function moveSpawns(x,y)
|
||||||
|
local move_x = nil
|
||||||
|
local move_y = nil
|
||||||
for _, spawn in pairs(LoadedObjects.Spawns) do
|
for _, spawn in pairs(LoadedObjects.Spawns) do
|
||||||
if spawn.selected then
|
if spawn.selected then
|
||||||
spawn.args[1] = math.floor(x/game.scale)+Camera.pos.x
|
local difference_x = math.floor((x/game.scale)+Camera.pos.x) - spawn.args[1]
|
||||||
spawn.args[2] = math.floor(y/game.scale)+Camera.pos.y
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -72,6 +88,9 @@ function promptSpawnNew()
|
|||||||
for i=2, #result+1 do
|
for i=2, #result+1 do
|
||||||
print("arg #"..i-1)
|
print("arg #"..i-1)
|
||||||
args[i-1] = result[i]
|
args[i-1] = result[i]
|
||||||
|
if i < 4 then
|
||||||
|
args[i-1] = math.floor(args[i-1])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
args = {0,0}
|
args = {0,0}
|
||||||
@@ -225,7 +244,13 @@ function drawSpawns()
|
|||||||
)
|
)
|
||||||
|
|
||||||
if spawn.selected then
|
if spawn.selected then
|
||||||
local text = spawn.archetype.type.."\n---\nPosition\n["..spawn.args[1]..","..spawn.args[2].."]"
|
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
|
if #spawn.args > 2 then
|
||||||
text = text .. "\n---\nData:\n"
|
text = text .. "\n---\nData:\n"
|
||||||
for i=3, #spawn.args do
|
for i=3, #spawn.args do
|
||||||
|
|||||||
13
code/ui.lua
@@ -5,16 +5,19 @@ function addElement(self)
|
|||||||
self.id = #UIElement
|
self.id = #UIElement
|
||||||
end
|
end
|
||||||
|
|
||||||
function drawTextBox(text,x,y,color,background_color)
|
function drawTextBox(text,x,y,style)
|
||||||
local color = color or {1,1,1,1}
|
local style = style or {}
|
||||||
local background_color = background_color or {0,0,0,1}
|
|
||||||
local c1, c2, c3, a = love.graphics.getColor()
|
local c1, c2, c3, a = love.graphics.getColor()
|
||||||
local width = locale_font:getWidth(text)
|
local width = locale_font:getWidth(text)
|
||||||
local height = locale_font:getHeight(text)
|
local height = locale_font:getHeight(text)
|
||||||
local margin = 5
|
|
||||||
|
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
|
local lines = 1
|
||||||
for i in text:gmatch("\n") do
|
for i in text:gmatch("\n") do
|
||||||
lines = lines + 1
|
lines = lines + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.setColor(unpack(color))
|
love.graphics.setColor(unpack(color))
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ local function backspace(text)
|
|||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
Prompt = {
|
Prompt = class(nil, {
|
||||||
-- defaults for instance variables
|
-- defaults for instance variables
|
||||||
pos = { x = 10, y = 10 },
|
pos = { x = 10, y = 10 },
|
||||||
input = "",
|
input = "",
|
||||||
@@ -23,7 +23,7 @@ Prompt = {
|
|||||||
color = {1,1,1,1},
|
color = {1,1,1,1},
|
||||||
background_color = {0,0,0,1},
|
background_color = {0,0,0,1},
|
||||||
active_prompt = nil,
|
active_prompt = nil,
|
||||||
}
|
})
|
||||||
function Prompt:cancelActive()
|
function Prompt:cancelActive()
|
||||||
if Prompt.active_prompt then
|
if Prompt.active_prompt then
|
||||||
Prompt.active_prompt.canceled = true
|
Prompt.active_prompt.canceled = true
|
||||||
@@ -33,7 +33,6 @@ end
|
|||||||
function Prompt:new(o)
|
function Prompt:new(o)
|
||||||
o = o or {}
|
o = o or {}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -62,8 +61,10 @@ function Prompt:draw()
|
|||||||
self.name .. ": " .. self.input,
|
self.name .. ": " .. self.input,
|
||||||
self.pos.x,
|
self.pos.x,
|
||||||
self.pos.y,
|
self.pos.y,
|
||||||
self.color,
|
{
|
||||||
self.background_color
|
color = self.color,
|
||||||
|
background_color = self.background_color
|
||||||
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ return {
|
|||||||
name = "Dev Level",
|
name = "Dev Level",
|
||||||
tileset = tileset.library,
|
tileset = tileset.library,
|
||||||
properties = {
|
properties = {
|
||||||
darkness = false
|
darkness = true
|
||||||
},
|
},
|
||||||
tiles = {
|
tiles = {
|
||||||
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
@@ -32,7 +32,8 @@ return {
|
|||||||
spawns = {
|
spawns = {
|
||||||
{Fairy,{100,88}},
|
{Fairy,{100,88}},
|
||||||
{HookAnchor,{200,89,100}},
|
{HookAnchor,{200,89,100}},
|
||||||
{HookAnchor,{400,89,120}}
|
{HookAnchor,{400,89,120}},
|
||||||
|
{Candelabra,{328,297}}
|
||||||
},
|
},
|
||||||
rooms = {
|
rooms = {
|
||||||
{{96,64},{544,320}},
|
{{96,64},{544,320}},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ shader = {}
|
|||||||
shader.circle_gradient = 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.circle_gradient = 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;
|
||||||
}
|
}
|
||||||
|
|||||||
18
main.lua
@@ -6,9 +6,10 @@ function love.load()
|
|||||||
secs = 0
|
secs = 0
|
||||||
|
|
||||||
menu_type = "no"
|
menu_type = "no"
|
||||||
|
-- FIXME: this overrides a standard library!
|
||||||
debug = false
|
debug = false
|
||||||
debug_collision = false
|
debug_collision = false
|
||||||
editor_mode = false
|
--editor_mode = false
|
||||||
|
|
||||||
text_size = 1
|
text_size = 1
|
||||||
|
|
||||||
@@ -103,6 +104,15 @@ function love.update(dt)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Keybind:checkPressed(Keybind.debug.editor) then
|
||||||
|
if editor.active then
|
||||||
|
deselectSpawns()
|
||||||
|
createTileObjects()
|
||||||
|
restartGame()
|
||||||
|
end
|
||||||
|
editor.active = not editor.active
|
||||||
|
end
|
||||||
|
|
||||||
if love.keyboard.isDown("f7") then
|
if love.keyboard.isDown("f7") then
|
||||||
local test_prompt = Prompt:new({
|
local test_prompt = Prompt:new({
|
||||||
name = "test prompt",
|
name = "test prompt",
|
||||||
@@ -127,7 +137,7 @@ function love.update(dt)
|
|||||||
if menu_type ~= nil then stepMenu(menu_type) end
|
if menu_type ~= nil then stepMenu(menu_type) end
|
||||||
|
|
||||||
--editor
|
--editor
|
||||||
if editor_mode then
|
if editor.active then
|
||||||
stepEditor()
|
stepEditor()
|
||||||
else
|
else
|
||||||
stepGame()
|
stepGame()
|
||||||
@@ -136,7 +146,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function love.wheelmoved(_, y)
|
function love.wheelmoved(_, y)
|
||||||
if editor_mode then
|
if editor.active then
|
||||||
scrollEditor(y)
|
scrollEditor(y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -150,7 +160,7 @@ function love.draw()
|
|||||||
game_resize = false
|
game_resize = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if editor_mode then
|
if editor.active then
|
||||||
drawEditor()
|
drawEditor()
|
||||||
else
|
else
|
||||||
drawGame()
|
drawGame()
|
||||||
|
|||||||