OOP (Object-Oriented Programming) in short:
-
Encapsulation – bundling data and methods that operate on it into objects, controlling access.
-
Abstraction – hiding implementation details, showing only the necessary interface.
-
Inheritance – creating new classes based on existing ones, reusing and extending functionality.
-
Polymorphism – the ability of different classes to be treated through a common interface, with behavior depending on the actual type.
-
Modularity - the property of a system that has been decomposed into internally cohesive but loosely coupled modules.
Thats what you currently do, i did improve for lua by my script and thats what Josh wants to destroy for no real reasons instead of doing what i did internally in the Engine.
About OOP.lua:
It starts before main.lua as script from "Source\Start" and add global functions that allow you to do Inheritance and Interfaces for tables, including components.
CreateClass("className", BaseClass) - it needed to make table support interfaces and add parent table if needed to use its variables and methods
component:AddInterface("interfaceName") - to add interface's variables and methods. Could be several of them per class.
To use in component you just need to do:
Monster = CreateClass("Monster") Monster:AddInterface("Killable")
Interface scripts should be in Source\Interfaces folder
To make one do something like that inside script:
return CreateInterface("Killable", { health = 100, team = 0, Kill = function(self) end, IsDead = function(self) return self.health <= 0 end, DamageEffect = function(self, amount, attacker) end, Damage = function(self, amount, attacker) if self:IsDead() then return end self.health = MoveTowards(self.health, 0, amount) self:DamageEffect() if self:IsDead() then self:Kill() end end })
CreateInterface(name, members) - name of interface and vars with functions inside of {}
You can make function implementation inside of functions there and use self as self of component, including interface functions and variables
Or you can leave function body empty: "DamageEffect = function(self, amount, attacker) end"
You can check if entity interface in a very simple way:
GetComponentByInterface(entity, "Killable")
So for example checking and doing damage for entity in bullet component will looks like that:
local pickinfo = world:Pick(pos, nextpos, 0.0, true, Bullet.PickFilter, self.owner) local killable = GetComponentByInterface(pickinfo.entity, "Killable") if killable then killable:Damage(self.damage, entity) end
No loops or removing component requires to make proper OOP code already.
For comparison it looked like that before in Josh code:
if type(pickinfo.entity.health) == "number" then pickinfo.entity.health = pickinfo.entity.health - self.damage for n = 1, #pickinfo.entity.components do if type(pickinfo.entity.components[n].Damage) == "function" then pickinfo.entity.components[n]:Damage(self.damage, entity) end if pickinfo.entity.health <= 0 and type(pickinfo.entity.components[n].Kill) == "function" then pickinfo.entity.components[n]:Kill() end end end
And his way requiring copy pasting same functions and vars in every component that you want to make killable or usable for example.
And it will not looks much better after removing components anyway:
if type(pickinfo.entity.health) == "number" then pickinfo.entity.health = pickinfo.entity.health - self.damage if type(pickinfo.entity.Damage) == "function" then pickinfo.entity:Damage(self.damage, entity) end if pickinfo.entity.health <= 0 and type(pickinfo.entity.components[n].Kill) == "function" then pickinfo.entity:Kill() end end
And even if Josh add Damage and health members in every entity (which is just silly), it will be same for anything else and in same time you will loose the most basic thing of modern engines as Component system without getting any real advantages.
Source code: https://github.com/Dreikblack/OOP-FPS-Template
0 Comments
Recommended Comments
There are no comments to display.