Object systems or LÖVE should have one

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Object systems or LÖVE should have one

Post by Hexenhammer »

Almost every time I download a LÖVE game here and look at the source it contains an object system (i.e. something which adds OOP constructs to Lua).. but unfortunately not always the same one.

I think the fact that LÖVE games are made with different object systems hurts the community because it needlessly increases the difficulty of understanding other people's code. Also some people use absolutely horrible systems..

You can implement a perfectly adequate system with a small amount of Lua code so adding one would not meaningfully increase the size of LÖVE. I thus would like to suggest the addition of a default object system to LÖVE. I don't care whether the devs choose an existing one or write a new one, as long as it is easy to understand and efficient. The primary target audience of LÖVE must be considered here. Efficient because it will be used for real-time games and easy to understand because many/most LÖVE users are not professional programmers or even just experienced amateurs. It is amazing how many C++ class features one can implement in Lua .. resist the temptation.

A related suggestion would be the addition of a container lib written in Lua. Again this requires very little code because of the high-level nature of Lua. I found myself writing my own container classes for my game.. which is just ridiculous. Lua tables are powerful but using them for everything does not lead to good code. You might argue that hobby coders shouldn't be bothered with countless data structures and I would even agree. I don't suggest making the other LÖVE functions depend on them. I suggest adding them as an optional component for advanced users e.g. like the physics libs or the pixel shaders. Thus far I have successfully ignored the very existence of those! :crazy:

At least data structures commonly used in games should be added e.g. priority queue (pathfinding), matrix/multi-dimensional array (grid-based games), vector/one-dimensional array (pretty much everywhere), ..

Before someone points out that Lua tables include vector-like behavior as a subset: the issue is that Lua tables don't have methods. LÖVE in general uses OOP syntax i.e. you get objects and call their methods. It feels wrong to switch to old procedural style - i.e. you pass objects to functions which operate on them - to work with tables. Also the Lua table library is minimalist, you could certainly add some functions there. Personally I love functional-like constructs however I don't want to suggest adding them because that would make things unnecessary confusing for most LÖVE users. There should be one way to do things and we are not going to get rid of loops, so having both loops and map/filter/reduce would be evil complexity bloat in case of LÖVE.

Damn, that was a long post :o

P.S.: For your general amusement here is some code from my current project. I wrote my own object system, container lib, etc. Unfortunately that means other LÖVErs cannot copypasta my code.. or even just understand it :death:

Area.lua

Code: Select all

-- Area class

--[[

== Size

The area size is fixed because it is more efficient to reuse the same area
object again and again than to continuously create and destroy areas of
different sizes. Thus we use one Area object whose size equals the size
of the largest supported area. To create the illusion of differently sized
areas we use View objects to limit how much of the area is visible

== Map

The area map has three layers: actor, item, terrain (see AreaCell.lua)

  actor:    an entity with AI

  item:     an entity without AI

  terrain:  an immutable entity without AI
            when terrain "changes" it is simply replaced by different terrain

== Actors

In addition to the map the area has a container containing references to
all actors within the area. We can use it to quickly iterate over all of
them

--]]



-- Dependencies
require "Lib.Gex"

local Class       = require "Lib.Class"
local Dimensions  = require "Lib.Dimensions"
local Matrix      = require "Lib.Matrix"

local AreaCell    = require "System.AreaCell"



local Area = Class.Singleton({

  -- Map of the area
  map     = Matrix(Dimensions(64, 64)),

  -- Contains references to all actors within the area
  actors  = Vector()

})



-- Initialization
Area.Initialization = function(self)

  self.map:Fill(AreaCell)

end



-- Clears the area
Area.Clear = function(self)

  self.map:Apply(AreaCell.Clear)

  self.actors:Clear()

end



return Class.Finalize(Area)
AreaCell.lua

Code: Select all

-- Area cell class

--[[

We implement map layers through multi-layer map cells.
See Area.lua for details about these layers

--]]



-- Dependencies
require "Lib.Gex"

local Class = require "Lib.Class"



local AreaCell = Class.UniqueObjects({

  -- Entities in the cell
  actor   = false,
  item    = false,
  terrain = false

})



-- Clears the area cell
AreaCell.Clear = function(self)

  self.actor    = false
  self.item     = false
  self.terrain  = false

end



return Class.Finalize(AreaCell)

Code: Select all

-- Rope class

-- Dependencies
require "Lib.Gex"

local Class   = require "Lib.Class"
local String  = require "Lib.String"
local Vector  = require "Lib.Vector"



local Rope = Class.Extends(Vector)



-- Adds a fragment
Rope.Add = function(self, fragment)

  self[#self + 1] = String(fragment)

end



-- To string
Rope.ToString = function(self)

  return table.concat(self)

end



-- To string + clear
Rope.Yield = function(self)

  local yield = self:ToString()

  self:Clear()

  return yield

end



return Class.Finalize(Rope)
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Object systems or LÖVE should have one

Post by Inny »

The thing about Lua, since this is really a Lua question, is that Lua isn't a Classical Object Oriented system. Lua is a Prototypical Object Oriented system. Lua has provided objects (tables) and a way to link them (__index) and it's up to you to figure out how to do it. This isn't very different from how Javascript works. So, the reason everyone has their own object system in their games is because everyone rolls their own, because everyone disagrees on how to use tables and metatables to simulate classical inheritance. And of course, some people (like myself) don't even believe that classical inheritance is necessary, nor productive. And, for Gaming, there's been a major movement towards composition of objects in a system called "Entity-Component", which is a specialization of the Gang Of Four Strategy Pattern.

Personally, I'm a fan of "Mixins" and shallow inheritance, meaning that you produce a class by adding functions to it, and then there's little or no inheritance between classes, just instantiation. I was playing with a bunch of Entity-Component code recently in Lua, and I definitely like it, but I also don't like the large overhead of code. So, all things considered, these two functions are probably the minimum of what anyone would need:

Code: Select all

function mixin(to, from)
  for k, v in pairs(from) do
    if to[k] == nil then to[k] = v end
  end
end

function new(class, ...)
  local instance = setmetatable(class, {})
  if class.__index == nil then class.__index = class end
  if class.init then class.init(instance, ...) end
  return instance
end
But even then, people would disagree with me, and I'd disagree with myself if I go back in a months time to look at that. In that regard, I recommend using either secs or middleclass.
szensk
Party member
Posts: 155
Joined: Sat Jan 19, 2013 3:57 am

Re: Object systems or LÖVE should have one

Post by szensk »

That's the wonder of Lua. Anyone can use their own class systems, table prototypes, function closures or none of the above. That's part of the appeal. While I understand your argument most class systems are not overly complicated and the interface can be inferred just by seeing its usage (or a quick look at the code).

I don't know if class commons is still active but that was it's essential effort, to make class systems inter-operable.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Object systems or LÖVE should have one

Post by bartbes »

People have mentioned the lua philosophy already, which is amazingly similar to love's (I wonder how that works), nobody's going to like it, here's tools to do it your own way, have fun!
szensk wrote:I don't know if class commons is still active but that was it's essential effort, to make class systems inter-operable.
It still exists, there's about 5 class libraries supporting it, I think. For those that don't know, it's an API you can use for writing your libraries with, which means that anyone who then uses your library can use the classes as if they were defined in his/her library of choice.
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Object systems or LÖVE should have one

Post by Inny »

As an alternative, and I can see this being fun, is a mixin class system that's the "just add functions" type. Like this:

Code: Select all

function Doohickey(class)
  function class:twist() end
  function class:turn() end
  function class:bump() end
  function class:hop() end
  return class
end

function Amazing(class)
  function class:lookAtThat() end
  function class:stareInAwe() end
  return class
end

Widget = Amazing(Doohickey({}))
instance = new(Widget)
This does create a closure for each function, but only for each class, not for each instance.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: Object systems or LÖVE should have one

Post by Hexenhammer »

bartbes wrote:People have mentioned the lua philosophy already, which is amazingly similar to love's (I wonder how that works), nobody's going to like it, here's tools to do it your own way, have fun!
I see your point but that "philosophy" is practically counter-productive. I also doubt that this is "Lua's philosophy", do you have any statements from the creators to back that up? Lua is minimalist because it was designed as an embedded scripting language and not as a stand-alone programming language like Python. LÖVE is not minimalist, it has a physics engine damn it, countless graphics functions, .. and the devs keep adding more stuff. Except a few thousands lines of pure Lua code which would make LÖVE much better for actually making games.

Again not including a default object system only fractures the community and makes LÖVE less attractive in general because most people these days want to write OO code and to do that with LÖVE you first have to integrate some OO lib. Or write your classes "naked" (i.e. doing the metatable magic by hand) - I have seen that too - ugly, code-duplication galore.
The practical result of your philosophy is people doing that.

And as I said I also see people using Lua tables for everything because there is nothing else included by default. And writing your own container classes like I did is a serious waste of time. Considering all the stuff LÖVE already includes I find it quite baffling that it does not include basic container classes. I mean seriously, a physics engine but no priority queue?
Ok, you might argue the physics engine has to be written in C/C++ because otherwise it would be too slow. But LÖVE is still far from "do everything yourself". If I wanted to do everything myself I would start with writing my own SDL+C core..

I dare to guess that most people are interested in LÖVE because they want an easy to use engine for making games (with Lua), not because they want to write everything from scratch.

But okay, it was just a suggestion. It won't meaningfully affect me personally one way or the other because I am not going to switch from my own code anyway now that I have written it . However IF LÖVE had shipped with a default class system and container library I would have probably used those and my game would be much closer to completion because of the saved time.
User avatar
slime
Solid Snayke
Posts: 2932
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Object systems or LÖVE should have one

Post by slime »

Hexenhammer wrote:I see your point but that "philosophy" is practically counter-productive. I also doubt that this is "Lua's philosophy", do you have any statements from the creators to back that up? Lua is minimalist because it was designed as an embedded scripting language and not as a stand-alone programming language like Python. LÖVE is not minimalist, it has a physics engine damn it, countless graphics functions, .. and the devs keep adding more stuff. Except a few thousands lines of pure Lua code which would make LÖVE much better for actually making games.
Lua's fundamental principles are based on "mechanisms instead of policies." http://www.stanford.edu/class/ee380/Abs ... slides.pdf

LÖVE follows that as well for the most part, although it can manifest itself slightly differently. LÖVE has box2d built in, but it does not have a function to make a box2d-based platformer for you, nor does it force you to use box2d if you want physically-based collision response.

It's fine if you don't like Lua's philosophy, but don't pretend it's going to cost you more than a few seconds of your time to put someone else's class library in your code instead of having one built into the language or the framework.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Object systems or LÖVE should have one

Post by vrld »

Hexenhammer wrote:I also doubt that this is "Lua's philosophy", do you have any statements from the creators to back that up?
Ierusalimschy, Figueiredo and Celes. The Evolution of Lua, in Proceedings of ACM HOPL III (2007) 2-1–2-26:
Section 6.8 wrote:Although objects, classes, and inheritance were not core concepts in Lua, they could be implemented directly in Lua, in many flavors, according to the needs of the application. In other words, Lua provided mechanisms, not policy — a tenet that we have tried to follow closely ever since.
Even more verbose on lua.org/about.html:
A fundamental concept in the design of Lua is to provide meta-mechanisms for implementing features, instead of providing a host of features directly in the language.
Hexenhammer wrote:LÖVE is not minimalist, it has a physics engine damn it, countless graphics functions, .. and the devs keep adding more stuff.
The key difference is that most of these things are mechanisms. Of course there are exceptions like the particle system, but most (if not all) of them offer significantly better performance when implemented in C++ and not Lua.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: Object systems or LÖVE should have one

Post by Hexenhammer »

slime wrote: Lua's fundamental principles are based on "mechanisms instead of policies." http://www.stanford.edu/class/ee380/Abs ... slides.pdf
A container class is a much more basic mechanism than a scaling algorithm. According to that logic you should only give people a getPixel and a putPixel function - the most basic mechanisms - and then let everyone e.g. write his own scaler, line drawing code etc. or drop-in an additional library.

So the LÖVE philosophy here is actually "only the most basic mechanisms EXCEPT where we think we need to write it in C++ for speed" which is slightly different but I agree still pretty close. I concede that LÖVE's philosophy is close to Lua's philosophy.
It's fine if you don't like Lua's philosophy, but don't pretend it's going to cost you more than a few seconds of your time to put someone else's class library
I said the problem with the lack of a standard class library is fragmentation and the fact that people start coding without any class library.. yet do OO.. which leads to horrible code. Again this is not theory, it's my experience based on looking at the code people upload here.

My suggestions were made based on the obviously wrong assumption that this was a toolkit to allow people to easily make games. The whole public face of your project suggests that while I never noticed your "philosophy" being mentioned anywhere.

And sorry "It's super-easy" and "Write everything from scratch yourself!" / "Go hunt for libraries on the web and hope you choose a good one!" are contradictory goals.

Maybe you want to change your sales pitch to "Minimalist! Only the basic mechanisms you need! Write everything else from scratch or stitch together whatever libraries you like! We don't even have a default class or container library! Isn't that great? LÖVE has anything a l33t haxxor needs and nothing more!"

If you advertised that philosophy, it would be horrible for your popularity though. Remember that recently someone even suggested adding an SQL database to LÖVE. I think most of your users have no idea what your "philosophy" is. I am serious, at least put "Minimalist" somewhere on the front page, that would stop people like me and the SQL fellow from wasting their time making suggestions which contradict said goal.
User avatar
Hexenhammer
Party member
Posts: 175
Joined: Sun Feb 17, 2013 8:19 am

Re: Object systems or LÖVE should have one

Post by Hexenhammer »

My suggestions were made based on the obviously wrong assumption that this was a toolkit to allow people to easily make games.
I should clarify this point. I mean my assumption was that "easily make games" was the (primary) goal of the project, not minimalism. Again the entire public face of the LÖVE project suggests that.

Right now the typical LÖVE user is trying to solve all problems in his games with basic Lua tables (again I see it all the time in the code uploaded here). That is not "easy" but certainly "minimalist".
Post Reply

Who is online

Users browsing this forum: No registered users and 19 guests