This week my post is going to be necessarily short. Noel and I have been working on preparing the first beta for Casey’s Contraptions, and there is still plenty to do before our intended milestone on Friday. He is deep at work squeashing bugs and working on loose ends, while I have been working on creating levels. Yes, you could say I got all the fun while he was hard working, but somehow solving those bugs always involves the rag doll thrown around, poked, squashed, and generally mistreated during his tests (I have this theory that is all due to his repressed feelings as a game developer that doesn’t want to make violent games; he is probably dying to make a zombie FPS). Anyway, look at the pretty thumbnails of my levels!
I still have plenty to do before Friday, so you will have to tune in some other day for part 3 of the Designing Casey’s Contraptions series (if you have not read the previous posts, they are here, and here). While the more artsy readers wait, the coders will have another (small) ration of… Core Animation (I bet you were not expecting it, given the title of the post and everything).
The Story So Far
As you may remember I started working on the Elephant Run game with the intention of doing it all with Core Animation, and so demonstrate what I called Thesis A:
Thesis A: Core Animation is just fine for most 2D games…
But giving the last few weeks, let me present you with Postulate B:
Postulate B: …but you will suffer if you try.
To explain this postulate, I will present you with the latest in layer scrolling! And some other issues. Yes, that’s the noise of my teeth grinding, shut up.
Scrolling is easy! Cannot you just use…
Let’s start by defining what I was looking for:
- a window into a coordinate system plane populated by objects…
- that smoothly changes how its borders map to that underlying coordinate system…
- and loads the objects to be displayed as they are needed, while keeping memory requirements in check.
If you were just idly browsing the documentation, you have probably seen a few CA classes that look pretty promising: there is a CAScrollLayer that looks exactly right, and even a fancy CATiledLayer that can make you think of something like this the first time you read about it:

Sadly, it is actually more like this:
![]()
CATiledLayer
What does the documentation say about tiled layers?
CATiledLayeris a subclass ofCALayerproviding a way to asynchronously provide tiles of the layer’s content, potentially cached at multiple levels of detail.As more data is required by the renderer, the layer’s
drawLayer:inContext:method is called on one or more background threads to supply the drawing operations to fill in one tile of data.
That sounds pretty promising to take care of point 3, and since it lets you create tiles of the content you would say 1 can be covered too.
When you start messing with it though, the first impression is that is slow. Like really slow. You may even notice that slow fade of tiles and think “hey! Is just my old friends, the damn implicit animations trying to make it look cool when what I need is to make it appear NOW! Let’s just disable those pesky animations!”. But I am going to save you the effort by editing the docs for you so they are a bit more useful.
CATiledLayeris a subclass ofCALayerproviding a way to asynchronously provide tiles of the layer’s content, potentially cached at multiple levels of detail.As more data is required by the renderer, the layer’s
drawLayer:inContext:method is called on one or more background threads to supply the drawing operations to fill in one tile of data.
Don’t ask me why I didn’t see that the first time around. Or the 20th. But anyway, CATiledLayer good for photo galleries and zooming into big images… for games, not so much.
CAScrollLayer
CAScrollLayer has no problems providing both points 1 and 2. To make it work, you create a layer, give it the bounds size of your “window”, then add sublayers to it. The moment you send either scrollToPoint: or scrollToRect: to the scroll layer, its sublayers will scroll by. (Note the layer doesn’t have scroll bars, and will not do a thing when you touch it; you need a UIScrollView for that).
You can also send a scrollPoint: or scrollRectToVisible: to any CALayer, and it will look through its superlayers for a CAScrollLayer to forward these messages to after the proper adjustment of coordinates.
The way CAScrollLayer accomplishes scrolling is pretty straightforward. It just animates changes to its bounds origin (that as we saw in a previous post determines the origin of coordinates for all the sublayers), and by default masks contents to its bounds (maskToBounds property is NO for any other type of layer). To adjust the speed at which the layer scrolls, you can use a transaction to override the duration around your scrolling messages.
All this is great, but point 3 is the tricky one. To be able to add and remove sublayers on the fly, change their contents, or any other dynamic behavior to happen while scrolling, we need notifications. And you see, the bounds property never sends letters while being animated. Instead of a nice “Hey, I am scrolling! I am at (1.0, 1.0)! Now (1.01, 1.0)! Guess what? Now is (1.03, 1.0)!”, it just tells you something like “You want me to go to (20.0, 1.0)? OK, ciao!”. Some properties are just not sociable.
By the way, if you know how to get the bounds to behave, please tell me. But beware, have a running program to show me, because I cannot tell you how many times I was like “this trickery SHOULD do it! It SHOULD work!”, just to find it didn’t.
Anyway, practical solutions to this? Only 2 I can think of. Either scroll in grid sized chunks that allow you to swap pieces at the end of the scrolling, or create your own animatable CGPoint property to take care of the notifications while scrolling (your own properties, as seen previously, can send nice display and drawInContext: messages periodically while animating).
Next Core Animation article I will go about creating a custom scroll layer that does all this, but that will be another day. Until then, don’t be like me and have fun creating games with OpenGL or freaking Cocos2D!

Lazrhog; February 9, 2011, 4:07 PM
Andrew Pouliot; February 9, 2011, 4:25 PM
Miguel A. Friginal; February 9, 2011, 4:41 PM
Brett Park; February 9, 2011, 5:42 PM
Miguel A. Friginal; February 9, 2011, 5:57 PM
Sean Kelleher; February 10, 2011, 3:12 PM
Miguel A. Friginal; February 10, 2011, 7:21 PM
Alex; February 14, 2011, 5:04 PM
Miguel A. Friginal; February 14, 2011, 5:20 PM
Alex; February 14, 2011, 7:05 PM
Miguel A. Friginal; February 14, 2011, 7:33 PM
Alex; February 18, 2011, 1:13 PM
Bill; March 1, 2011, 11:28 PM
Justin; March 27, 2011, 1:43 PM
Miguel A. Friginal; March 27, 2011, 2:01 PM