Object-Oriented Sample Game Framework for Corona

I just 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’d like to submit it to Code Exchange but that seems to be down at the moment):
http://www.box.net/shared/uz5beg19h8

Now this is just one approach to doing OOP in Lua; most people would build classes in Lua using metatables, but that approach isn’t quite as flexible (eg. you can’t do multiple inheritance that way.) I originally got the idea for building the code in this way from this thread:
http://developer.anscamobile.com/forum/2010/12/12/finding-objects-parent

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.

Frankly a newcomer could get nothing else from this example framework because they find it confusing, but this notion of modules inheriting from other modules is very very useful.

Going through the modules one by one…

Starting in main.lua we see a bunch of require() statements for other modules. Note that not every module 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.

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 self = display.newGroup()  
Scene.decorate(self)  

That first line shows how every “scene” in Corona can simply be a diplay 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:

Hopper.decorate(self.entities[i])  

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 self.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 notion of modules inheriting from other modules is very very useful. [import]uid: 12108 topic_id: 4760 reply_id: 304760[/import]

As noted in this other thread, there seems to be a tiny memory leak associated with the physics call addBody()
http://developer.anscamobile.com/forum/2010/12/27/leak-or-me-not-getting-it#comment-15218

Assuming that is even a problem (I’m not sure yet) then that can be fixed later. [import]uid: 12108 topic_id: 4760 reply_id: 15219[/import]

Just found it and its the first game template I can understand how its working…!!
Maybe use it for my own game…

Thanks a lot [import]uid: 12632 topic_id: 4760 reply_id: 16774[/import]

Did you post this to the Code Exchange?? I think its helpful also for other developer… [import]uid: 12632 topic_id: 4760 reply_id: 16779[/import]

Glad you found it useful. I was planning to post this to the Code Exchange but never got around to it. I suppose I still should…

ADDITION: http://developer.anscamobile.com/code/object-oriented-sample-game-framework [import]uid: 12108 topic_id: 4760 reply_id: 16781[/import]

I just uploaded a new version where I changed object names in a bunch of places. The logic of the code hasn’t changed at all, but while working on my own project I’ve come to realize that it was confusing how I used the name “self” in different contexts. I thought it would be less confusing to always use the name “self” for consistency, but it was really rather confusing because the keyword “self” has a different meaning in different contexts.

With this change you might be confused by the different naming inside and outside of functions. 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:

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”:

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.
ADDITION: I just updated it with the latest version of ui.lua [import]uid: 12108 topic_id: 4760 reply_id: 18037[/import]

Cool. I was looking for more samples like these a while ago, your addition should serve a good purpose. I also created a little framework for games now where I end up with sprite objects which I can configure in a variety of ways, like self.emphasizeAppearance or self.listenToCollision or self.speedX = N or self.followsTargetSprite = x etc… and then I have a handle function if needed for each sprite, added to the general handler routines of the sprite class. On top of it there’s a phase handler which lets me push the sprite into a phase like “poisoned” along with a counter. Sprites can additionally be physical. A fading out which emits sparkles, moves to the right and gets removed after a while for instance would be done via

[blockcode]
function self:createFoobarSprite()

local function handle(self)
if misc:getChance(10) then
app.spritesHandler:createSparks(self.x, self.y)
end
end

local self = spriteModule.spriteClass(type, subtype, optionalFilename, x, y etc…)
self.energySpeed = -1
self.alphaChangesWithEnergy = true
self.speedX = 4
appAddSprite(self, group, handle)

end
[/blockcode] [import]uid: 10284 topic_id: 4760 reply_id: 18534[/import]

Absolutely those functions all sound like great ideas for an action game engine, but for this example I didn’t want to do anything too specific. Like, would any of those commands be relevant to, say, a card game? I wanted to show a way to set things up generally, and then as someone dives into developing their specific game they should probably layer onto this base what you describe. [import]uid: 12108 topic_id: 4760 reply_id: 18736[/import]

Oh absolutely your layer of abstraction I’m sure is great! My addition above was not meant as criticism or anything. And the code above was a sample of how you’d use the engine (that layer on top), not of the engine itself, so to speak. My engine is a general approach for games which display things on the screen and have some movement. So in a card game for instance, I would actually still use it just in case I want to move a card around or something*, but there’s probably as many fitting yet different frameworks for games as there’s sand on a beach :slight_smile: The sample above just meant to illustrate that FoobarSprite has all its stuff in a single contained place without having to know much about the outside world, this just makes it convenient for me to maintain. (“FoobarSprite” could be a bee, a bullet, a card, a maze wall with physics, a collectible diamond which explodes, a worm, etc.)

*In my framework, I basically have all the general sprite handling functionality separated from the game-specific needs, so the sprite engine wouldn’t be allowed to “know” anything specific about cards (that would go in the sprites-handler class which creates the sprites, or go into another class as needed), just as the phase handling class doesn’t know anything about the specific phases it is used for (e.g. you can have a phase “wildBee” when the bee got stung which lasts for N circles)… however, I also allow enough flexibility so that I adjust the general sprite class whenever a game requires it, on the fly. (It will basically grow and adjust with every game because I don’t set out to write a game engine that does everything.) [import]uid: 10284 topic_id: 4760 reply_id: 18754[/import]

Hello,
thank you for getting the time to read my request.

I have completed my first game game and really appreciates if would have the time to take a look on it and give you your feedback.

This is my first game ever, i haven’t done any game before, and it was really my first experiance and would like to give me your feedback. i have learned Corona and LUA in 4 weeks and just came with this game. I know you may not be satisfied with the code but really i have done my best and would like to have your expertise and suggestion in this regard.

Actually, i have 2 problems; the first problem relates to the craches of the app as i have noticed that the app consumed a lot of texture memory on each stage and therefore, i’m sure there is a serious problem.

second, the app becomes slow on my device at early stages.

One more this, i really would like to know if my code meets at least the minimum requirements form Development Prospective in Corona. In other words, does the overall code shows that i’m working in the correct path?

Please if you have the time just reply back to me to zip the code and email to to you.

Thanks again [import]uid: 11038 topic_id: 4760 reply_id: 19925[/import]

sorry, I can’t just review code sent to me. What you should do is ask specific questions in the New Developer forum and someone (possibly me) will try to answer the question. For example, start a thread about that first problem and post relevant code. [import]uid: 12108 topic_id: 4760 reply_id: 19939[/import]

I’ve updated the code to use newImageRect() instead of newImage(). I only just realized the latter doesn’t work with dynamic image resolution and the former is needed for that; makes me wonder why Ansca didn’t just make newImage() work with dynamic image resolution but oh well. [import]uid: 12108 topic_id: 4760 reply_id: 20213[/import]

Just updated the code with a small change suggested by mtnbkrpro. It’s not a big change that I think everyone would need, but it is a clever trick he came up with to simplify the main menu for a large number of levels. [import]uid: 12108 topic_id: 4760 reply_id: 28818[/import]