Page 1 of 1

Love2D ECS?

Posted: Tue May 24, 2022 10:37 pm
by Seth144k
so i was wondering because all of the other libraries about ECS are really difficult to use, to try to make my own! anyways i got something up and running but i was wondering if I'm doing it right. i also would like their to just be entities and i dont have to call their load, update, and draw function inside of main.lua and have everything be done automatically. optionally i would like all entites to have their own collision tag to make collisions easier. if anyone knows how to solve this then please help!

Re: Love2D ECS?

Posted: Wed May 25, 2022 7:05 am
by togFox
What libraries have you tried/researched so far?

Re: Love2D ECS?

Posted: Wed May 25, 2022 4:35 pm
by ReFreezed
The main issue your code seem to have is that there are no arrays of entities or anything. The concept of an entity is that it's just "something/anything" in the game, i.e. a very generic concept. So we want to treat everything in a generic way, with ways to extend entities with entity-specific functionality.

Below is an example of a simple entity system. We have different types of entities, but when the system does things to the entities it treats them all the same way.

Code: Select all

--
-- Entity definitions.
--
local entityClasses = {}

entityClasses.wall = {} ; entityClasses.wall.__index = entityClasses.wall -- The __index thing is for metatables to work.
function entityClasses.wall:load(width, height)
	self.collisionType = "staticobject"
	self.width         = width
	self.height        = height
end
function entityClasses.wall:draw()  --[[...]]  end

entityClasses.player = {} ; entityClasses.player.__index = entityClasses.player
function entityClasses.player:load()
	self.collisionType = "character"
	self.health = 100
end
function entityClasses.player:update(dt)  --[[...]]  end
function entityClasses.player:draw()      --[[...]]  end

entityClasses.enemyRobot = {} ; entityClasses.enemyRobot.__index = entityClasses.enemyRobot
function entityClasses.enemyRobot:load()
	self.collisionType = "character"
	self.health        = 100
	self.armor         = 100
end
function entityClasses.enemyRobot:update(dt)  --[[...]]  end
function entityClasses.enemyRobot:draw()      --[[...]]  end

entityClasses.enemyBug = {} ; entityClasses.enemyBug.__index = entityClasses.enemyBug
function entityClasses.enemyBug:load()
	self.collisionType = "character"
	self.health        = 50
	self.isFlying      = true
end
function entityClasses.enemyBug:update(dt)  --[[...]]  end
function entityClasses.enemyBug:draw()      --[[...]]  end

--
-- Entity system.
--
local spawnedEntities = {}

local function spawnNewEntity(entityType, x, y, ...)
	local entityClass = entityClasses[entityType]
	local entity      = {type=entityType, x=x, y=y, collisionType="none"} -- All entities have these fields.
	setmetatable(entity, entityClass) -- Any field not present in entity (like the methods) will be retrieved from entityClass.__index.
	table.insert(spawnedEntities, entity)

	if entity.load then
		entity:load(...)
	end
end

local function callMethodOnEntities(methodName, ...)
	for _, entity in ipairs(spawnedEntities) do
		if entity[methodName] then
			entity[methodName](entity, ...)
		end
	end
end

--
-- LÖVE callbacks.
--
function love.load()
	spawnNewEntity("wall"      , 0 , 0 , 1, 100)
	spawnNewEntity("wall"      , 50, 0 , 1, 100)
	spawnNewEntity("player"    , 10, 20)
	spawnNewEntity("enemyRobot", 20, 20)
	spawnNewEntity("enemyBug"  , 25, 40)
end

function love.update(dt)
	callMethodOnEntities("update", dt)

	-- Collision handling.
	for _, entity in ipairs(spawnedEntities) do
		if entity.collisionType == "character" then
			-- (Collide with things...)
		end
	end
end

function love.draw()
	callMethodOnEntities("draw")
end
I'm not sure what you mean by "collision tag" but I'm assuming it's something that says what type of collision the entity should have, so I included something for that in the code.