Initial commit

This commit is contained in:
Justin van der Leij 2018-01-25 15:19:31 +01:00
commit 58549d6b0a
14 changed files with 665 additions and 0 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

41
.gitignore vendored Normal file
View file

@ -0,0 +1,41 @@
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Justin van der Leij
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
README.md Normal file
View file

@ -0,0 +1 @@
# Fluid

9
conf.lua Normal file
View file

@ -0,0 +1,9 @@
function love.conf(t)
t.identity = "Platformer"
t.version = "0.10.2"
t.console = true
t.window.vsync = false
t.window.width = 720
t.window.height = 720
end

41
fluid/component.lua Normal file
View file

@ -0,0 +1,41 @@
local Component = {}
Component.__index = Component
--- Creates a new Component.
-- @param populate A function that populates the Bag with values
-- @param inherit States if the Bag should inherit the Component's functions
-- @return A Component object
function Component.new(populate, inherit)
local component = setmetatable({
__populate = populate,
__inherit = inherit,
}, Component)
if inherit then
component.__mt = {__index = component}
end
return component
end
-- Creates and initializes a new Bag.
-- @param ... The values passed to the populate function
-- @return A new initialized Bag
function Component:initialize(...)
if self.__populate then
local bag = {}
self.__populate(bag, ...)
if self.__inherit then
setmetatable(bag, self.__mt)
end
return bag
end
return true
end
return setmetatable(Component, {
__call = function(_, ...) return Component.new(...) end,
})

75
fluid/entity.lua Normal file
View file

@ -0,0 +1,75 @@
local Entity = {
entities = {},
}
Entity.__index = Entity
--- Creates and initializes a new Entity.
-- @return A new Entity
function Entity.new()
local e = setmetatable({
id = #Entity.entities + 1,
components = {},
systems = {},
keys = {},
instance = nil,
}, Entity)
Entity.entities[e.id] = e
return e
end
--- Gives an Entity a component with values.
-- @param component The Component to add
-- @param ... The values passed to the Component
-- @return self
function Entity:give(component, ...)
self.components[component] = component:initialize(...)
return self
end
--- Removes a component from an Entity.
-- @param component The Component to remove
-- @return self
function Entity:remove(component)
self.components[component] = nil
return self
end
--- Checks the Entity against the pools again.
-- @return self
function Entity:check()
self.instance:checkEntity(self)
return self
end
--- Removed an Entity from the instance.
-- @return self
function Entity:destroy()
Entity.entities[self.id] = nil
self.instance:destroyEntity(self)
return self
end
--- Gets a Component from the Entity
-- @param component The Component to get
-- @return The Bag from the Component
function Entity:get(component)
return self.components[component]
end
--- Returns true if the Entity has the Component
-- @params component The Component to check against
-- @return True if the entity has the Bag. False otherwise
function Entity:has(component)
return self.components[component] and true
end
return setmetatable(Entity, {
__call = function(_, ...) return Entity.new(...) end,
})

79
fluid/eventManager.lua Normal file
View file

@ -0,0 +1,79 @@
local EventManager = {}
EventManager.__index = EventManager
function EventManager.new()
local eventManager = setmetatable({
queue = {count = 0},
listeners = {},
}, EventManager)
return eventManager
end
function EventManager:push(event)
queue.count = queue.count + 1
queue[queue.count] = event
return self
end
function EventManager:emit(name, ...)
local listeners = self.listeners[name]
if listeners then
for i = 1, #listeners do
local listener = listeners[i]
listener[name](listener, ...)
end
end
return self
end
function EventManager:register(name, listener)
local listeners = self.listeners[name]
if not listeners then
listeners = {count = 0}
self.listeners[name] = listeners
end
listeners.count = listeners.count + 1
listeners[listeners.count] = listener
return self
end
function EventManager:deregister(name, listener)
local listeners = self.listeners[name]
if listeners then
for index, other in ipairs(listeners) do
if listener == other then
table.remove(listeners, index)
listeners.count = listeners.count - 1
return
end
end
end
return self
end
function EventManager:process()
local queue = self.queue
for i = 1, queue.count do
self:emit(queue[i])
queue[i] = nil
end
queue.count = 0
return self
end
return setmetatable(EventManager, {
__call = function(_, ...) return EventManager.new(...) end,
})

82
fluid/init.lua Normal file
View file

@ -0,0 +1,82 @@
local PATH = (...):gsub('%.init$', '')
local Fluid = {}
function Fluid.init(settings)
Fluid.entity = require(PATH..".entity")
Fluid.component = require(PATH..".component")
Fluid.system = require(PATH..".system")
Fluid.instance = require(PATH..".instance")
Fluid.eventManager = require(PATH..".eventManager")
if settings and settings.useEvents then
Fluid.instances = {}
Fluid.addInstance = function(instance)
table.insert(Fluid.instances, instance)
end
Fluid.removeInstance = function(instance)
for i, instance in ipairs(Fluid.instances) do
table.remove(Fluid.instances, i)
break
end
end
love.run = function()
if love.math then
love.math.setRandomSeed(os.time())
love.timer.step()
end
for _, instance in ipairs(Fluid.instances) do
instance:emit("load", arg)
end
if love.timer then love.timer.step() end
local dt = 0
while true do
if love.event then
love.event.pump()
for name, a, b, c, d, e, f in love.event.poll() do
for _, instance in ipairs(Fluid.instances) do
instance:emit(name, a, b, c, d, e, f)
end
if name == "quit" then
return a
end
end
end
if love.timer then
love.timer.step()
dt = love.timer.getDelta()
end
for _, instance in ipairs(Fluid.instances) do
instance:emit("update", dt)
end
if love.graphics and love.graphics.isActive() then
love.graphics.clear(love.graphics.getBackgroundColor())
love.graphics.origin()
for _, instance in ipairs(Fluid.instances) do
instance:emit("draw")
end
love.graphics.present()
end
if love.timer then love.timer.sleep(0.001) end
end
end
end
return Fluid
end
return Fluid

86
fluid/instance.lua Normal file
View file

@ -0,0 +1,86 @@
local PATH = (...):gsub('%.[^%.]+$', '')
local Pool = require(PATH..".pool")
local EventManager = require(PATH..".eventManager")
local Instance = {}
Instance.__index = Instance
function Instance.new()
local instance = setmetatable({
entities = Pool(),
eventManager = EventManager(),
systems = {},
namedSystems = {},
}, Instance)
return instance
end
function Instance:addEntity(e)
e.instance = self
self.entities:add(e)
self:checkEntity(e)
end
function Instance:checkEntity(e)
for _, system in ipairs(self.systems) do
if system:entityUpdated(e) then
e.systems[#e.systems + 1] = system
end
end
end
function Instance:destroyEntity(e)
self.entities:remove(e)
for _, system in ipairs(e.systems) do
system:remove(e)
end
end
function Instance:addSystem(system, eventName)
if not self.namedSystems[system] then
self.systems[#self.systems + 1] = system
self.namedSystems[system] = system
end
self.eventManager:register(eventName, system)
return self
end
function Instance:removeSystem(system)
for index, other in ipairs(self.systems) do
if system == other then
table.remove(self.systems, index)
end
end
self.namedSystems[system] = nil
return self
end
function Instance:emit(...)
self.eventManager:emit(...)
return self
end
function Instance:update(dt)
self:emit("update", dt)
return self
end
function Instance:draw()
self:emit("draw")
return self
end
return setmetatable(Instance, {
__call = function(_, ...) return Instance.new(...) end,
})

53
fluid/list.lua Normal file
View file

@ -0,0 +1,53 @@
local List = {}
local mt = {__index = List}
function List.new()
return setmetatable({
numerical = {},
named = {},
size = 0,
}, mt)
end
function List:clear()
self.numerical = {}
self.named = {}
self.size = 0
end
function List:add(obj)
local size = self.size + 1
self.numerical[size] = obj
self.named[obj] = size
self.size = size
end
function List:remove(obj)
local index = self.named[obj]
local size = self.size
if index == size then
self.numerical[size] = nil
else
local other = self.numerical[size]
self.numerical[index] = other
self.named[other] = index
end
self.named[obj] = nil
self.size = size - 1
end
function List:get(i)
return self.numerical[i]
end
function List:getIndex(obj)
return self.named[obj]
end
return setmetatable(List, {
__call = function() return List.new() end,
})

57
fluid/pool.lua Normal file
View file

@ -0,0 +1,57 @@
local Pool = {}
Pool.__index = Pool
function Pool.new(name, filter)
local pool = setmetatable({
__filter = filter,
__name = name,
}, Pool)
return pool
end
function Pool:eligible(e)
for _, component in ipairs(self.__filter) do
if not e.components[component] then
return false
end
end
return true
end
function Pool:add(e)
local key = #self + 1
self[key] = e
e.keys[self] = key
end
function Pool:has(e)
return e.keys[self] and true
end
function Pool:remove(e, pool)
local key = e.keys[self]
if key then
local count = #self
if key == count then
self[key] = nil
e.keys[self] = nil
else
local swap = self[count]
self[key] = swap
self[count] = nil
swap.keys[self] = key
end
return true
end
end
return setmetatable(Pool, {
__call = function(_, ...) return Pool.new(...) end,
})

118
fluid/system.lua Normal file
View file

@ -0,0 +1,118 @@
local PATH = (...):gsub('%.[^%.]+$', '')
local Component = require(PATH..".component")
local Pool = require(PATH..".pool")
local System = {}
System.__index = System
function System.new(...)
local system = setmetatable({
__all = {},
__pools = {},
}, System)
for _, filter in pairs({...}) do
local pool = system:buildPool(filter)
if not system[pool.__name] then
system[pool.__name] = pool
system.__pools[#system.__pools + 1] = pool
else
error("Pool with name '"..pool.__name.."' already exists.")
end
end
return system
end
function System:buildPool(pool)
local name = "pool"
local filter = {}
for i, v in ipairs(pool) do
if type(v) == "table" then
filter[#filter + 1] = v
elseif type(v) == "string" then
name = v
end
end
return Pool(name, filter)
end
function System:entityUpdated(e)
local systemHas = self:has(e)
for _, pool in ipairs(self.__pools) do
local poolHas = pool:has(e)
local eligible = pool:eligible(e)
if not poolHas and eligible then
pool:add(e)
self:entityAddedTo(e, pool)
self:tryAdd(e)
return true
elseif poolHas and not eligible then
pool:remove(e)
self:entityRemovedFrom(e, pool)
self:tryRemove(e)
return false
end
end
end
function System:tryAdd(e)
if not self:has(e) then
self.__all[e] = 0
self:entityAdded(e)
end
self.__all[e] = self.__all[e] + 1
end
function System:tryRemove()
if self:has(e) then
self.__all[e] = self.__all[e] - 1
if self.__all[e] == 0 then
self.__all[e] = nil
self:entityRemoved(e)
end
end
end
function System:remove(e)
if self:has(e) then
for _, pool in ipairs(self.__pools) do
if pool:has(e) then
pool:remove(e)
self:entityRemovedFrom(e, pool)
end
end
self.__all[e] = nil
self:entityRemoved(e)
end
end
function System:has(e)
return self.__all[e] and true
end
function System:entityAdded(e)
end
function System:entityAddedTo(e, pool)
end
function System:entityRemoved(e)
end
function System:entityRemovedFrom(e, pool)
end
return setmetatable(System, {
__call = function(_, ...) return System.new(...) end,
})

0
main.lua Normal file
View file