The Corona Labs Blog
Posted on . Written by

Organizing Corona SDK projectsSomething that isn’t clear by studying Corona’s included SampleCode or any of the other examples and tutorials on this website is the concept of organizing projects. We’ve sort of just let you know that everything goes into your project folder and sent you off on your way—and oh, sub-folders are supported. That’s about all we’ve said on the subject up until now.

However, as your projects get bigger, that may not be quite enough. With more and more resources are being added to your project, such as audio files, images, videos, Lua modules, etc. it can add a whole new layer of complexity to the development process—complexity that isn’t at all necessary.

This tutorial is by no means the end-all to Corona SDK project organization techniques, but it will introduce you to an effective one that you can tweak at your heart’s content to suit your needs perfectly.

Project Structure

Keeping things simple is the best way to ensure your project remains organized, and therefore maintainable. The organization technique I’m going to be coving should suffice for most projects as it is easy to set up, easy to understand, and easy to scale (for when your projects become much larger).

The basic premise you should follow when organizing your project folder is to keep like-files separate from other types, and with their “own kind” so to speak. Here’s an example project hierarchy for demonstration:

  • Project_Folder/ (top-level)
    • images/ (folder)
    • audio/ (folder)
    • videos/ (folder)
    • data/ (folder)
    • scripts/ (folder)
    • main.lua
    • config.lua
    • build.settings
    • Default.png
    • Default@2x.png
    • Icon.png
    • Icon@2x.png

In the above sample folder structure, the only thing that’s in the top-level directory (folder) is main.lua and other files that are required to be at the top-level (such as config.lua, build.settings, etc.).

The folders listed at the top are mostly self-explanatory, but for the sake of being thorough, I’ll go over them anyway:

  • images – image files with the extension of (most-likely) .png or .jpg.
  • audio – audio files (.caf, .mp3, .ogg, etc.)
  • videos – video files (.avi, .mp4, etc.)
  • data – read-only data files used by your app. They can really be any format, but common ones include .json and .xml.
  • scripts – other Lua files (apart from main.lua). More on this in a moment.

And that’s all there is to it! There’s really not much more that needs to explain with this technique, except for maybe one thing: the “scripts” folder.

Let’s say you want to use util.lua in your project. Normally, you’d drop it into the top-level of your project folder (same location as main.lua) and you’d require it like so:


local util = require( "util" )

However, if you were to place util.lua into the ‘scripts’ folder, the above line would not work. You would instead need to specify the sub-directory using the directory name followed by a period (dot) and then the module name, like so:


local util = require( "scripts.util" )

You’ll also have to be mindful of the directory structure when it comes to loading images as well—only you’ll use a slash “/” (as you’d expect) instead of a period (dot). Here’s an example of how to load an image from the ‘images’ sub-directory:


local obj = display.newImage( "images/corona.png" )

Scaling Projects

As your projects adds more images, scripts, and other files, even your sub-directories can begin to get pretty bloated as well! If that happens, you can add more sub-directories, and follow the same conventions already mentioned. Here’s what a game with a few levels might look like:

  • Project_Folder/ (top-level)
    • images/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • audio/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • videos/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • data/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • scripts/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • main.lua
    • config.lua
    • build.settings
    • Default.png
    • Default@2x.png
    • Icon.png
    • Icon@2x.png

The only thing that’s different in the above structure is that the images, audio, videos, and scripts directories now have sub-directories of their own that correspond to those types of assets for specific levels. I’m sure you can see how this might come in handy for a game with 10-20+ levels, and make things a lot more organized and more maintainable in the long run.

Imagine having a game with 50 levels (which is not uncommon), and keeping all resources in the top-level project directory—what a nightmare that would be to maintain!

So whether you use the technique described in this tutorial or one you’ve come up with on your own, it will greatly benefit you—if you’re serious about your Corona SDK projects—to start thinking of your project’s file structure and organization from the beginning.

25 Responses to “Best Practices for Organizing Projects”

  1. David

    Nice. File organization is all well and good… What about Storyboard organization?

    I’d like to see a tutorial or some examples with multiple scenes using Corona’s Storyboard service. I’m organizing a project right now, and I’m finding a lack of examples of multi-scene setups.

    Reply
  2. Tayari

    But what about sprite/imagesheets? Are they available in a sub dir?
    I can only get them to work in the base dir.

    Reply
    • nest

      They work fine in sub directory. You call the image file by folder/filename.extension and the data file with folder.filename

      Reply
  3. Joao

    Great article.

    I’m a starter at Corona and it makes me a big confusion not knowing how to organize files. Almost every sample that comes on corona sdk does not have images separated of regular lua files and this makes a lot of confusion.

    One other thing is when to become modular and that’s a thing that’s not easily found to read about. From a guy like me that comes from rhomobile and rails, this file “desorganization” seams a bit odd :)

    Great article once again… I would love to see more like these with or without storyboard!

    J

    Reply
  4. BeyondtheTech

    I do something similar to that, but I make a parent folder for all of that which shares a folder called “Payload” where I throw my builds in there. When Corona creates the binary, I simply zip up the Payload folder and rename it to .IPA. That way, I can send it off to Testflight or email it to a friend who can import it via iTunes.

    Reply
  5. Mike

    I’m with David, an example using multiple scenes would be helpful. Thanks for covering this issue though, I remember being a bit tripped up by it in the beginning.

    Reply
  6. detour

    An important note if you’re going to be opening files from a directory. For example maybe you’ve got some configuration data in data/config.json. You must use system.pathForFile() when opening the file with io.open(), you cannot just use a relative path like you can with display.newImage(). This is tricky because a relative path passed in will work in the simulator but will *not* work on device.

    Reply
  7. Lerg

    Here is my directory structure. Storyboard enabled.
    /
    - library
    - media
    – audio
    – music
    – images
    — some_scene
    — ui
    — sprites
    - objects
    - view

    In library I store all global lua files like 3rd party modules and game model files – user.lua for managing user accounts and game.lua for managing gameplay states and providing unified APIs for the whole game like game:newImage(filename) or game:newSprite(‘characterName’). Also there is my ui.lua holding all my widgets.

    media is for images and sounds. audio folder for short wav files and music for heh music. In images I store actual graphic files according to either the storyboard they are used in or if they are global (like back button). In sprites are all my characters.

    objects holds xml files of all game objects I use: colors, characters, levels, audio and misc. So I can simply create objects providing only the name in code and rest (sprite sheet dimension, character description and properties) is in xml files. Or I can game.setTextColor(textObject, ‘myMainColor’) and later can change myMainColor to what ever I want.

    And view is where I hold all my storyboard or director scenes lua files.

    Clean and simple.

    Reply
  8. nest

    c’mon this is only file organization. Pretty easy to achieve! What about a tutorial on how organizing projects internally. Building the skeleton of the app. That’s the real challenge when projects get bigger!

    Sorry but looking at the title I expected more

    Reply
    • Jen Looper

      +1 on this one! I use storyboard and have had lots of difficulty finding some MVC type organization model that might work. How about an OOP/MVC architecture post please?

      thanks,
      Jen

      Reply
  9. Bob Dickinson

    That’s great. I guess I hadn’t seen any big announcement about it being safe to use subfolders in all cases (as of earlier this year there were still limitations on sound and video files under Android). I poked around on the forums, and it seem like this is now supported on all platforms/devices. So that’s great. I’m going to go start organizing my projects now.

    I’m still a little annoyed that I have to have 12 icons in the root directory. It would sure be nice if we could get the build tools to look in, oh, I don’t know, an “icons” subfolder ;)

    Reply
    • David

      Yeah, I agree. I didn’t know about the subfolders issue until a few weeks ago when someone else mentioned it to me. And I second that /icons folder thought.

      Reply
  10. Krystian

    Well I’ve created a simple ant script, which goes through all my resources and code directories, does all the changes I want [like creating different image versions for autoscaling, preparing all imagesheets etc etc] and puts everything into single directory read by corona.
    This way I don’t have to worry about anything – I’ve got the project the way I like it, Corona has everything in single directory, and Git is not flooded with unnecessary stuff [like imagesheets].

    Reply
  11. Personalnadir

    Hey,

    One thing which has been mentioned, but which I use a lot, are the use symbolic/hard links to import common code into the project.

    You have to be careful, because the compiler doesn’t play nice with softlinked directories in a few cases, but it means that common images and code can be stored in one place rather than duplicated across multiple projects.

    Has anyone checked how Corona interacts with git submodules? I’ll probably experiment with those for my next project.

    Reply
  12. Jerry Palmroos

    Interesting – I finally got around to organizing all my files exactly as described here, and BOOM! – I get an error that I can’t figure out.

    Here’s the code:

    local backImage = display.newImage( "images\saturn_auroras.png" )

    The file DOES exist in the images directory, yet when the simulator runs, it fails when it reaches this line, with the following message:

    WARNING: Failed to find image(imagessaturn_auroras.png)

    Why is it doing this weird concatenation of the directory and file name?

    Regards,
    Jerry Palmroos
    Charlotte

    Reply
    • Rob

      Feeling like a total n00b, just getting around to learning luna, in my main.lua:

      local background = display.newImage( “images/bg.png” )

      Returns “Warning: Failed to find image(images/bg.png)
      although it exists in the images folder.
      Thoughts?

      Reply
      • Nick

        local background = display.newImage( “images/bg.png”, 100,100 )

        –You need to specify the x,y location at the end.

        –You can control the width by doing this
        background.width = 400
        background.height = 400
        :)

        –Or you can take an image using the newImageRect, and specify width and height
        –on the end…then call the x and y locations below it.
        local grasshopper = display.newImageRect( “images/grasshopper.png”, 250, 40)
        grasshopper.x = 100
        grasshopper.y = 100

        Fun stuff.

        Reply
  13. Seng Keat

    Hi Nathan,

    thanks for your tut – i am trying to do it and it shows some errors of the file
    I have created a folder to contain all my levels but when i start the corona it’s error

    Reply
  14. Lars Jensen

    I agree that putting everything into a single folder becomes hard to deal with. But why is it better to organize first by file type, then by level — as opposed to a more function-oriented organization, such as by level first, or by class first?

    Reply
  15. Hendrix

    I use build 2012.971
    This was a real cold shower to be honest!
    storyboard.gotoScene( ‘resources/scripts/hendrixScript’ )
    like it works in require ( ‘resources.scripts.hendrixScript’ )
    only difference is that just the latter one works

    this is NOT a little issue in my opinion

    Is there a workaround I can use in configfile?

    Reply

Leave a Reply

  • (Will Not Be Published)