Page 1 of 1

Having trouble with Metatables

Posted: Sat Sep 23, 2023 9:25 pm
by MaxGamz
Everything is working with my game except when I tried introducing object oriented programming to it. I want to hopefully implement monsters and enemies to my game but I decided to first work on a coin system. I followed a tutorial for metatables however I'm still having trouble getting the coin system to work in my game and I'm not sure why. I have experience with object oriented programming however not with lua obviously.
Gaym.love
(883.66 KiB) Downloaded 60 times

Re: Having trouble with Metatables

Posted: Sun Sep 24, 2023 1:31 pm
by Endaris
The way I see it you have no issue with metatables.
When Coin.updateAll(dt) is called from love.update, lua correctly navigates into the metatable when it can't find an index "update" on the instance of the coin and finds the update method there to call spin:update which is where your actual problem is.
You set instance.spin to nil in your constructor and never set it to anything else so it obviously has to crash when you try to call update or draw on it and there is no spin field on the metatable that your coin can fall back to.
The intuitive fix would be to simply call instance.anim() at the end of the constructor but there are some problems in that function I'm leaving to you to find.
Depending on what you actually want to do with your coins, putting an idle spin on the metatable may make sense or not.

Maybe to elaborate a bit in which manner metatables are used in your code to imitate class functionality:
All the class functions are defined on Coin.
When creating a new instance, a new table is created and Coin is set as its metatable. A metatable serves to specify certain interactions and the one crucial for class-like functionality is __index. Whenever an index is accessed on your table that has no value, Lua will navigate into the metatable to access the index on the table you have defined in __index instead - so Coin.
So basically the class imitation works through this fallback behaviour - the moment you decide to define a function on the table instance, it will take precedence over the one on your "class" table.
So concretely:
Coin.updateAll calls instance:update(dt) on every instance found in your ActiveCoins table and the first step of that is getting whatever is inside instance.update before executing it. instance itself lacks update but it has a metatable. Lua looks up __index, finds the Coin table and gets the value for the index "update" from there. Then it calls the function on the instance table. The fact that the program crashes inside of Coin:update is the best proof your metatables work because it would never even find that function otherwise.