2D Scrolling

Hi,
I’m a beginner in Corona and in programming in general. I’m currently working on a 2D platformer project using Box 2D physics.
I came up with a simple function for scrolling where I use the hero’s origins to define the center of the world :

[code]
heros.xReference = heros.width / 2
heros.yReference = heros.height / 2

function scrolling( event )
world.xReference = heros.xOrigin
world.yReference = heros.yOrigin
world.x = display.contentWidth / 2
world.y = display.contentHeight / 2
end

Runtime:addEventListener( “enterFrame”, scrolling )[/code]

This allow to have a very smooth scrolling so far.
However, how can I stop redrawing the world when the player doesn’t move?

Thanx [import]uid: 25327 topic_id: 5597 reply_id: 305597[/import]

Hi Michael,

Welcome to Corona! I think you’ll find alot of help from the community and from many of the 3rd-party “tools” that make game design easier within Corona.

I just might suggest that you start very simple and learn much more about Corona before attempting a 2D scrolling platformer. As you noticed already, unlike most game development SDKs, Corona does not feature a “camera” but rather “display groups”. This makes alot of things in Corona easier… but it makes scrolling around a potentially vast world (i.e. a 2D platformer) much more challenging, especially in terms of memory management, clearing off-screen elements, pre-loading only those elements the user sees, etc. etc.

And just to quickly answer your question, it’s easy to stop re-drawing the world when your character stops. Perhaps the best way is to simply remove the event listener when your character isn’t moving:

Runtime:removeEventListener( "enterFrame", scrolling )

Then, when movement resumes, you start it up again. You could also just put a boolean flag in there like “isWorldMoving = true/false”, but you’ll get slightly better performance by not calling that loop function at all when you’re not using it.

You might want to just start with a static-screen game to begin, until you learn more. In the meantime, you should check out the amazing “Lime” module which allows designers to implement tile-based worlds from the free tile map editor “Tiled”. It does a crazy amount of other cool things too. :slight_smile:

LIME: http://www.justaddli.me/

Best of luck, and again, welcome to the quickly-expanding Corona community!

Brent Sorrentino
Ignis Design
[import]uid: 9747 topic_id: 5597 reply_id: 19079[/import]

Hi Ignis,
Thanks for your warm welcome and your advices.

I’m really excited to work with Corona! In only 7 days, i’ve achieved things i tought it would takes months with Xcode.

Actually, i’ve started by doing a static 2D platformer and it came out pretty easily. So, I wanted to try a bigger world using display groups and sub-groups (wich i’m used to as I worked with flash for years).

I have a prototype working but i know I have a lot to optimize and learn.

I have a step-by-step learning curves, implementing functionalities only if i fully understand it. Memory management is on my list :slight_smile:

Concerning lime, I heard that it would have performance issue when on the device so I’m not sure if I would go that way. Can you tell me more about that? I was using Tiled when working with Cocos2D and it’s very useful but Xcode is definitively not for me :slight_smile:

Bye

Mikah [import]uid: 25327 topic_id: 5597 reply_id: 19109[/import]

Cool, your past experience with Flash and Cocos2D will probably help your conversion to Corona immensely. Probably the one thing in common with all Corona users is that XCode/Obj-C is not a viable option for them… whether it’s the huge learning curve (if not having learned it in the past) to the complexity of accomplishing basic tasks, most of us admitted at some point that Obj-C is either not cost-effective, not time-effective, or whatever else. And so, we now use Corona!

Memory efficiency is one of the more tricky things with Corona (well, with all languages, to be honest). These handheld phones and tablets are not remotely on par with a desktop/laptop so the issue becomes that much more crucial. For my current game, I have spent extensive time (worth every minute!) building a system to construct levels from text file data, output them in “chunks” when they are nearing visible screen bounds, and then clean up and remove all child objects when the chunk is sufficiently out of view. It’s not yet flexible enough for multi-directional scrolling games, but it’s memory efficient and I think my effort was well-spent… at this point, no less than 26 FPS even on an older iPod Touch. :stuck_out_tongue:

I haven’t been following Lime’s development closely, but all the answers regarding its performance should be found somewhere in its dedicated forum. Graham Ranson is working intensely on this and I’m sure he’ll have the performance issue solved in time. I salute his efforts on this; it’s no small undertaking!

http://developer.anscamobile.com/forums/lime

[import]uid: 9747 topic_id: 5597 reply_id: 19123[/import]

Your “chunk” system looks interesting and tricky!
Do you have games on the app-store already? I’m curious!
Does Lime have this kind of functionalities?

Actually, the levels of my game consists of small square rooms (less than twice the width of the screen) connected to each other by doors. So I was thinking about 2 ideas for memory management :

  1. To draw only the room where the player is. The new room appears when he enters in, just like if you were turning on the light and the previous room fade out in black and is cleaned up. Easy but not very immersive.

  2. The adjacent rooms are drawn (only visible part) but with half size textures scaled to 200% and the collision boxes appear only when you enter the room. More immersive but I’m not sure it would be efficient.

If i understand, to clean-up the memory, you must destroy all objects one by one with its variables? That’s a lot of work :slight_smile:
How the Corona’s garbage works?

Mikah [import]uid: 25327 topic_id: 5597 reply_id: 19135[/import]

Unfortunately my current game (using the chunk scrolling) is some time off from the App Store. Like alot of developers here, I have a “day job” that takes precedence over app development, so I can only work on my game in the evenings or weekends.

I don’t know exactly how Lime cleans up after itself, but there must be some method, otherwise the system would grind to a halt with a certain world size (imagine an immense over-world like that in “Zelda: Link to the Past” scrolling around on an iPhone, it would be lucky to get 1 FPS!). Graham or somebody else, do you wish to answer this for me, in regards to how Lime manages garbage collection?

For your game, if all the rooms are square, I think you could show the current room plus all 4 rooms around it (assuming there are doors on all 4 sides)… but limit it to that amount, not the entire world. 5 rooms would not be too heavy for the system to handle, unless you had something like 50 objects in every room, each with physics bodies and animation and much more. When the player exits a door, a nice easing “slide” move to the next room would look nice, in my opinion. :slight_smile:

Cleaning up objects can be tricky, but not necessarily so. In my chunk system, each chunk has a table (array) called “childTable”. This table is empty, initially. When the chunk is first displayed (slightly off screen, when approaching visible view) this table is populated with the Lua internal IDs of each object within that chunk. When the chunk eventually scrolls off the screen, and gets prompted for removal, I just loop backwards through this table… backwards is very important and there is/was a document on the Corona site describing why, but I can’t locate it anymore. :frowning:

Most important of all, just remember that every reference to an object must be removed before it can be garbage-collected. That includes the object itself, any “listener” on that object (such as a tap or touch sensor), and any references in other tables (i.e. the “childTable” example above).

The following 3 steps are essential for proper garbage collection:

  1. object:removeEventListener(...) (if one was applied)
  2. object:removeSelf() (this also removes physics bodies in the same step)
  3. object = nil

Anyway, there are other methods to keep memory clean and each person finds their own preferred way. My “chunk” system is just one concept. Keep reading the documents and forums and soon it won’t seem so difficult, but avoiding those memory leaks can become an almost obsessive task, unfortunately. I think I finally understand why most games are the work of teams, not individuals. :stuck_out_tongue:
[import]uid: 9747 topic_id: 5597 reply_id: 19150[/import]

If you can’t locate the document describing why it’s essential to loop backwards through an array when UN-populating it, I can describe it in another post… I can explain why, but Ansca did a very nice job of explaining it already, and I was hoping to just link to that article.

Brent [import]uid: 9747 topic_id: 5597 reply_id: 19151[/import]

it’s here:
http://developer.anscamobile.com/content/application-programming-guide-graphics-and-drawing#Common_Pitfalls [import]uid: 6645 topic_id: 5597 reply_id: 19154[/import]

For your game, if all the rooms are square, I think you could show the current room plus all 4 rooms around it (assuming there are doors on all 4 sides)…

Great! Maybe I could put sensors next to doors to detect wich way the player is going. So, when he enters a new room, previously not visible rooms will be drawn accordingly and now not visible rooms wil be cleaned up.

Speaking of sensors, can i use filters on it like this?

herosFilter = { categoryBits = 2, maskBits = 3 }  
  
local sensor = display.newRect( 609, 337, 30, 14 )  
sensor:setFillColor( 31, 102, 246 )  
sensor.isVisible = false  
physics.addBody( sensor, { isSensor = true, filter = herosFilter } )  

Thanks for clarifying those cleaning concept for me. It’s much more understandable now :slight_smile:
Ho! And your post on how filters work is a blessing :wink:
It’s good to see that the Corona’s community has people like you. [import]uid: 25327 topic_id: 5597 reply_id: 19203[/import]

@jmp909
Thanks :slight_smile: [import]uid: 25327 topic_id: 5597 reply_id: 19218[/import]

Happy to help!

If you want the new rooms to scroll into view as the player approaches the door, sensors are absolutely the correct solution. Remember that you can place your 4 sensors and use them repeatedly… just keep them on the screen, but don’t scroll them along with the world/player/enemies or whatever else. They would remain as static, invisible objects in their own display group. If, for some reason, you needed to deactivate a sensor (assume there wasn’t another room to enter in a particular direction) you can easily remove their collision detection with “sensor:isBodyActive = false” (and vice-versa when you want to turn it back on).

Your code for collision filters looks good; if you follow the chart method I outlined, everything should work properly.

Speaking of this line…

sensor.isVisible = false

I think that will automatically make the sensor inactive, and thus it won’t function. This might have changed in the latest Corona release. If it’s not sensing collisions, a solution is this: sensor.isHitTestable = true. This will register the object for collisions even though it’s invisible. If for some reason that doesn’t work, you can also set the sensor’s “alpha” to 0, which obviously makes it invisible to the user, but not to the collision engine.
[import]uid: 9747 topic_id: 5597 reply_id: 19253[/import]

Ok, now I understand why my sensors wouldn’t work…
I will try the alpha method, saves me 2 lines of code :slight_smile:
But why should I leave them out of scrolling elements? The problem is that as the heroe is always in the center of the screen, he will never touch the sensors.

Thanks! [import]uid: 25327 topic_id: 5597 reply_id: 19281[/import]

that’s a different matter then. i guess you’d either want to make your doors sensors, or use a larger invisible object so that the sensor is triggered as he approaches the door [import]uid: 6645 topic_id: 5597 reply_id: 19293[/import]