Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Object-Oriented Lua Tutorials
Started by ArdentKid Dec 05 2012 01:19 AM

* * * * * 1 votes
51 replies to this topic
[TOPIC CONTROLS]
Page 1 of 3 1 2 3
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

I wrote a 4-part tutorial on how to structure your game code in an OO fashion. I've gotten highly positive reviews from it as well. Hope it helps!

I. Introduction and Setup

II. Classes (Encapsulation)

III. Custom Events

IV. Inheritance and Polymorphism

V. Working Example

 

Please feel free to leave your feedback here!



[TOPIC: post.html]
#2

srdjan@multimediaworx.com

[GLOBAL: userInfoPane.html]
srdjan@multimediaworx.com
  • Enthusiast

  • 89 posts
  • Corona SDK

These tutorials are great!

Thank you
uid: 101952 topic_id: 33679 reply_id: 133919


[TOPIC: post.html]
#3

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

WOW! Fantastic tutorial! I am going to start my next app the right way this time using your approach. I have 2 questions:

1- what about say something like collisions between object? For instance I want an object to change color when it collide with another object (of different class like cat and mouse using your code example) do I need to keep the collision code seperate from the class cat and dog or integrate them into the cat/mouse classes like you did with show hide functions?

2- I would love to see a small app example combining all the concepts in your tutorial. It is one thing to see each bloc but it would really if we could see for instance a typical main.lua and maybe couple of modules representing the different behaviors. You could even use the cat and mouse modules!

Thanks for sharing a much better way to program in Lua/Corona. Lua is great but as soon the app gets complex, it really a nightmare to keep track of everything! Your way is a great solution.

THANKS.

Mo
@Lairdgames
uid: 100814 topic_id: 33679 reply_id: 134045


[TOPIC: post.html]
#4

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Thanks Guys!

LaridGames-
1- The best practice I know for manual collision detection is to keep it separate from the rest of your game (in a class called Collision.lua). Using the cat and mouse example, I would dispatch an event to add collision when showing an object, and then remove it when hiding. So when the cat/ mouse shows itself, do

scene:dispatchEvent({name='addCollision', target=self})

Do something similar for when they hide off-screen (i.e. 'removeCollision')

Then have the Collision class listen for the add and remove events starting when the class loads:
scene:addEventListener('addCollision', Collision)
function Collision:addCollision(event)
   --add event.target to an array. i.e. self.catArr or self.mouseArr
   --based on a property like event.target.name
end

The Collision class should also always be running a Runtime check on the arrays you want to compare collision. If you're checking everything against everything, then you can probably just have one array.

When something collides, dispatch an 'onCollision' event with both targets as parameters (you can do "target1", "target2" or "target" and "other", whatever)

2- Wish I had the time to provide sample code. I may be able to hack something up in the coming weeks, heard the same request for the dynamic sprites tutorials. The only thing I really have in my main.lua (except for global variables and device checking) is storyboard.gotoScene("SceneTitle").
uid: 36792 topic_id: 33679 reply_id: 134048


[TOPIC: post.html]
#5

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Thank you! That's great stuff. Would love to see a collision class define in your tutorial serie when you get a chance. No problem about a full sample. I was just curious about how to setup the app since I am use to basically put everything into a gameScreen.lua module. Your way seems 1000 ways better!
It seems if I understand correctly, for any app you would simply:

1- create a class for each object (cat or mouse) or for each game element like score, health bar
2- let those objects/elements talk to each other and react in appropriate manner

That's sound easier than controlling everything with spaghetti code all in one module !

THANKS!

Mo
uid: 100814 topic_id: 33679 reply_id: 134089


[TOPIC: post.html]
#6

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Yup, that's the power of Object Oriented :)
uid: 36792 topic_id: 33679 reply_id: 134099


[TOPIC: post.html]
#7

rcuba87

[GLOBAL: userInfoPane.html]
rcuba87
  • Observer

  • 2 posts
  • Corona SDK

Hello ArdentKid,

I find these tutorials helpful in reinforcing what I was already applying on my own application. But I was wondering about one particular aspect that I am not too sure about.

How do you access class properties from an instance function?

For example, say your Enemy class had a class property maxAttacks to define the maximum number of attacks the enemy can do. This should apply to all enemies, hence why it makes sense to make it a class property.

Now, each enemy instance has the attack() function where part of it would check if that maximum has been reached, but within that attack function, 'self' refers to the enemy instance not the Enemy class.

Now, upon creating each enemy instance I could copy the value of that class property to a property in the instance thus making it available through 'self' in the attack function. But since it is going to be the same for every instance, it seems wasteful to do that.

Thanks for your help.
uid: 142439 topic_id: 33679 reply_id: 134739


[TOPIC: post.html]
#8

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Hey rcuba87 - You can reference those "static class variables" by just using the class name! For example:

--Enemy.lua
local Enemy = {
   MaxAttacks = 10
}

function Enemy:New()
   --blah blah
end

function Enemy:attack()
   if (self.totalAttacks == Enemy.MaxAttacks) then
      --do stuff
   end
end

As a matter of fact, anything defined "locally" outside of the class functions, but in the same file (including the Class itself) are available to all the functions in that file. Hope that helps!
uid: 36792 topic_id: 33679 reply_id: 134743


[TOPIC: post.html]
#9

rcuba87

[GLOBAL: userInfoPane.html]
rcuba87
  • Observer

  • 2 posts
  • Corona SDK

Hey ArdentKid,

Thanks for the reply, definitely helped. I don't know why I didn't just try that at first. I'm sorry to bother you again, but I have another question regarding an OO approach in LUA. Sorry if it is a bit long, but I would really appreciate your opinion.

How would you handle Subclassing/Inheritance in your implementation (specially regarding the Instances recycling)?

To keep with the running example (even though I don't have 'enemies' in my app haha), One could keep the single 'Enemy' class and create some logic to differentiate between types of instances and create or re-use the specific instances (i.e. with the specific image/sprites and specific properties/values) when necessary, but it makes more sense to make them into their own subclasses.

My issue is exactly how to handle the inheritance while maintaining the idea of the instance recycling.

Here is how I see it. Please let me know what you think.

First the parent Enemy class. It only defines and prepares an instance and attaches any properties and functions that every Enemy type should have. It does not keep track of instances. This is up to the subclasses

--Enemy.lualocal Enemy = {    -- All class properties Enemy}function Enemy:New(config)    -- Create new Image/Sprite using parameters included in 'config'    -- Attach all instance level properties that all enemy objects should have with values from 'config'    -- Attach all instance level functions that all enemy objects should have    -- Return the instanceend-- All other function definitions (like the instance functions) for this parent classreturn Enemy


Now the subclass. This uses the parent class to create a basic instance, attaches all properties/functions specific to the sublcass instances and also keeps track of its own instances for recycling.
--SubEnemy.lualocal Enemy = EnemyClass    -- EnemyClass = require( "Enemy" ) has already been called on whatever script will include this Enemy sublcasslocal SubEnemy = {    -- All class properties for Subenemy    Instances = {},    defaultConfig = nil  -- This would be the default values of all properties (including Image/Sprite info) for all instances of this class}--This function would be called right after loading the script with a table of all the default values to be used when generating new instancesfunction SubEnemy:Initialize(config)    defaultConfig = configendfunction SubEnemy:New(config)     local seInstance = Enemy:New(config) -- The 'config' used would be either the parameter to this function or, if that is nil, then the 'defaultConfig' of the class       -- Attach all instance level properties of subEnemy objects with values from 'config', if 'config' is nil, use class defaultConfig    -- Attach all instance level functions subEnemy objects    -- Override any property/function necessary by just re-defining and re-assigning    table.insert(self.Instances, seInstance)    return seInstanceendfunction SubEnemy:Get(config)    -- Check for available instance, if so, reset using 'config', if 'config' is nil, use class defaultConfig    -- If no instance is available, create a new one (passing 'config')    -- return the new instanceendfunction SubEnemy:Dispose(obj)	-- As your implementationend-- All other function definitions (like the instance functions) for this parent classreturn SubEnemy
uid: 142439 topic_id: 33679 reply_id: 135010


[TOPIC: post.html]
#10

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Hey rcuba87 - sorry for the late reply!

To answer your question, I only keep track of instances in my Final Classes. Also, I've finished the inheritance tutorial, hope it helps:

http://www.ardentkid.com/blog/2012-12-24/inheritance-oo-lua-44
uid: 36792 topic_id: 33679 reply_id: 136295


[TOPIC: post.html]
#11

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Geek

  • 2,597 posts
  • Corona Staff

Thanks for sharing these tutorials with everyone!
uid: 84637 topic_id: 33679 reply_id: 136298


[TOPIC: post.html]
#12

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Hey all,

I've received fairly concerning feedback from a knowledgable source regarding these tutorials. Please see this post for details: http://www.reddit.com/r/learnprogramming/comments/17300n/ooplua_tutorials_for_corona_mobile_dev/

I really do enjoy helping the community in whatever way I can, so I will begin work on a re-write as soon as I can, and I apologize for sharing any misleading knowledge about writing OO-Lua.
uid: 36792 topic_id: 33679 reply_id: 140115


[TOPIC: post.html]
#13

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Do not worry about it! I know that you did what you thought at the time was right. It takes a lot of guts to come back here and say what you said. My hat to you!

I LOVE your tutorials about OOP. Please write some more when you get a chance! I am trying to get away from my spaghetti type of code (basically having one BIG game.lua and multiple .lua for help, options...) I really need to do a better job with game.lua and your method seems to be the way to go. I hope one day you will have enough time to put together a simple app using OOP so we can the actual flow...

THANKS for sharing with the community.

Mo
uid: 100814 topic_id: 33679 reply_id: 141730


[TOPIC: post.html]
#14

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Hey All,

The re-write of this tutorial is finally complete! I mashed them up into one definitive guide. Enjoy!

http://www.ardentkid.com/blog/from-zero-to-oo-ardentkids-guide-to-object-oriented-lua-with-corona-sdk
uid: 36792 topic_id: 33679 reply_id: 142875


[TOPIC: post.html]
#15

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Nice! I'll suggest it to be included to the resource centers:

http://www.coronalabs.com/resources/tutorials/

http://developer.coronalabs.com/forum/2013/01/07/corona-resource-centre-tutorials-templates-and-more

Naomi
uid: 67217 topic_id: 33679 reply_id: 142884


[TOPIC: post.html]
#16

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Thanks Naomi!
uid: 36792 topic_id: 33679 reply_id: 142886


[TOPIC: post.html]
#17

rcuba87

[GLOBAL: userInfoPane.html]
rcuba87
  • Observer

  • 2 posts
  • Corona SDK

Hello ArdentKid,

Thank you for being so thorough with updating your tutorials to help us too. I did realize some time ago when I was trying to implement inheritance with your framework, that your former approach was not exactly OO but I do think that for simpler, less inheritance-intensive purposes it is still a valid approach.

I do wonder one thing in your revised tutorials.

In your subclasses Animal and Cat, near the beginning of their scripts, you are creating a local variable "Super" into which you load the respective super class script. You then reference this local variable whenever you need to access parent variables/methods.

Is that local "Super"variable not redundant? I thought that the call Class([parentClass]) took care of creating a "super" variable that directed to the parent class.

Is there any particular reason why you are creating this local "Super" variable in each subclass?

Thank you for your continued help!
uid: 142439 topic_id: 33679 reply_id: 143141


[TOPIC: post.html]
#18

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

@Ardenkid: thank you so much for the re-write! Beautiful. One suggestion about the full example. Rather than counting on people donation, I will strongly suggest your make the example paid. Say $10-20 and have people who really want to start using OOP to pay for it.

Of course just a suggestion. Maybe other people would have better suggestions to make writing a full example worth your time.

Mo
uid: 100814 topic_id: 33679 reply_id: 143152


[TOPIC: post.html]
#19

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

@rcuba87 - you can just put the super class's require in the class call: Class(require("someParentClass")), but then make sure you replace all your calls to the super class with for example "self.super.show(self)" instead of just "Super.show(self)". I like the the second one better syntactically, so thats why I localize it.

@LaridGames - thats a good idea but Im not sure how many people would buy it. Its still a good recommendation so im leaning that way now. Thanks!
uid: 36792 topic_id: 33679 reply_id: 143207


[TOPIC: post.html]
#20

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Hey All,

The re-write of this tutorial is finally complete! I mashed them up into one definitive guide. Enjoy!

http://www.ardentkid.com/blog/from-zero-to-oo-ardentkids-guide-to-object-oriented-lua-with-corona-sdk
uid: 36792 topic_id: 33679 reply_id: 142875


[TOPIC: post.html]
#21

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Nice! I'll suggest it to be included to the resource centers:

http://www.coronalabs.com/resources/tutorials/

http://developer.coronalabs.com/forum/2013/01/07/corona-resource-centre-tutorials-templates-and-more

Naomi
uid: 67217 topic_id: 33679 reply_id: 142884


[TOPIC: post.html]
#22

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

Thanks Naomi!
uid: 36792 topic_id: 33679 reply_id: 142886


[TOPIC: post.html]
#23

rcuba87

[GLOBAL: userInfoPane.html]
rcuba87
  • Observer

  • 2 posts
  • Corona SDK

Hello ArdentKid,

Thank you for being so thorough with updating your tutorials to help us too. I did realize some time ago when I was trying to implement inheritance with your framework, that your former approach was not exactly OO but I do think that for simpler, less inheritance-intensive purposes it is still a valid approach.

I do wonder one thing in your revised tutorials.

In your subclasses Animal and Cat, near the beginning of their scripts, you are creating a local variable "Super" into which you load the respective super class script. You then reference this local variable whenever you need to access parent variables/methods.

Is that local "Super"variable not redundant? I thought that the call Class([parentClass]) took care of creating a "super" variable that directed to the parent class.

Is there any particular reason why you are creating this local "Super" variable in each subclass?

Thank you for your continued help!
uid: 142439 topic_id: 33679 reply_id: 143141


[TOPIC: post.html]
#24

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

@Ardenkid: thank you so much for the re-write! Beautiful. One suggestion about the full example. Rather than counting on people donation, I will strongly suggest your make the example paid. Say $10-20 and have people who really want to start using OOP to pay for it.

Of course just a suggestion. Maybe other people would have better suggestions to make writing a full example worth your time.

Mo
uid: 100814 topic_id: 33679 reply_id: 143152


[TOPIC: post.html]
#25

ArdentKid

[GLOBAL: userInfoPane.html]
ArdentKid
  • Enthusiast

  • 51 posts
  • Corona SDK

@rcuba87 - you can just put the super class's require in the class call: Class(require("someParentClass")), but then make sure you replace all your calls to the super class with for example "self.super.show(self)" instead of just "Super.show(self)". I like the the second one better syntactically, so thats why I localize it.

@LaridGames - thats a good idea but Im not sure how many people would buy it. Its still a good recommendation so im leaning that way now. Thanks!
uid: 36792 topic_id: 33679 reply_id: 143207



[topic_controls]
Page 1 of 3 1 2 3
 
[/topic_controls]