Share Your Code
I put together a basic game framework to show novice programmers how to organize your code in a modular, object-oriented way. You can download the project from here:
I wouldn't necessarily recommend starting here if you are totally new to programming, but if you have a little previous familiarity with object-oriented programming then this is a good head-start in using Corona. I originally got the idea for building the code in this way from this thread:
Now this is just one approach to doing OOP in Lua; most people would build classes in Lua using metatables, but there are multiple reasons I prefer this other approach. One, you can't set the metatable on display objects:
Two, using metatables isn't quite as flexible (eg. you can't do multiple inheritance that way.) Three, well what's discussed in this thread:
Basically there's a tradeoff between memory and performance; my approach runs faster than metatables but uses a little more memory.
Anyway, here's an explanation touching on many features being demonstrated:
First off, a novice programmer might be wondering what's the advantage to splitting up the code into a dozen different files like this. Well, one advantage is that it enables you to write shared functions in one place and simply tell other parts to use that code. A good example is all the different levels of your game. Rather than copy-pasting the game logic in each level, you simply link them all to the same shared code. Then later when you make adjustments to the code, you can make your adjustments in one place instead of having to repeat the changes in a dozen different places.
It's gets even better because you can build up a chain of modules linking to other modules, what's called "inheritance." I strongly suggest looking up that term, but for a great example observe in my code how both Menus and Levels are types of Scenes. Level1 is in turn a type of Level; because a Level is a type of Scene, level1.lua automatically gets code from both level.lua and scene.lua in a chain.
Next, notice how the name "obj" is used outside of functions and "self" is used inside. Basically, inside a function with a colon (otherwise known as a "method") the keyword "self" refers to the object that owns the function. So when you see the following code, both the names "obj" and "self" refer to the same object:
1 2 3
function obj:dosomething() self.x = 200 end
But the tricky thing is that "self" doesn't always refer to the same object; it all depends on context. For example, in this case "self" refers to "obj.button" and not "obj":
1 2 3
function obj.button:dosomething() self.x = 200 end
I know that can take getting used to, but wrapping your head around the "self" keyword is one of the most important concepts in object-oriented programming.
Frankly a newcomer could get nothing else from this example framework because they find it confusing, but these two notions of modules inheriting from other modules and the "self" keyword are very very useful.
Going through the modules one by one...
Starting in main.lua we see a bunch of require() statements for other modules. Not every module in the project is directly required by main, because all of these required modules also themselves require other modules. main.lua also has functions for switching scenes by calling the new() function in various modules, commented out code for checking memory, and finally at the very bottom everything is set in motion by starting up the main menu.
Note that the level loading function in main.lua is currently setup so that the buttons in menu.lua use a trick with function closures to call different levels. A different approach to accomplishing the same task is suggested by mtnbkrpro in the comments below; you should check out his code too.
In menu.lua we see a bunch of buttons being placed around the screen. The buttons use functions passed to the menu from main, and those functions slide out the current scene and start a new one. The two most interesting lines to look at are lines 7 and 8:
local obj = display.newGroup() Scene.decorate(obj)
That first line shows how every "scene" in Corona can simply be a display group that everything else is inserted into. That second line is how all of the code from the Scene module is linked to the Menu.
In scene.lua not much is going on right now. The few methods in there are simply to transition your scenes onto and off the screen. This is just a placeholder that you could fill in later with more functionality shared by all scenes, like loading screens or background music.
level1.lua shows the inheritance chain described earlier. We have the screen transitions shared by all scenes, plus we also have code shared by all levels but not by all scenes. Specifically, all levels have walls surrounding the screen and that's what setup_walls() does. We also use the following line to attach code from yet another module to a bunch of entities in the level:
level2.lua is pretty much the same thing as level1, except instead of making the entities into Hoppers they are made into Floaters.
level3.lua demonstrates multiple inheritance by making the entities have properties of both Hoppers and Floaters. Again, I can't think of any way to do this with metatables, but it's pretty simple to do this using decorators to add new functions to existing objects.
Both hopper.lua and floater.lua are similar except, well, one has code to hop up when the users taps the screen and the other has code to float around randomly. Notice the line "if obj.bodyType == nil then" that's used to make sure the physics body is only added once when both decorators are used (ie. multiple inheritance.)
So there you have it. Hopefully others find this educational. Again, even if everything else in this example framework confuses you, the two notions of the "self" keyword and modules inheriting from other modules are very very useful.