Dev Diary #12 – Can I Have Your Attention?
(Note: Please ignore the orange lines in some of the pictures in this post.
They’re simply debug information showing us where clickable areas are)
First of all, we’re having another Public Playtesting Pizza Party next Thursday, and here’s the relevant information. Before that, the tutorial needs some reworking. It was lacking in some areas, and our “look here!” mechanism wasn’t working out.
Last year, Tyler wrote a shader to create a spotlight effect to draw attention to items. It looks nice for small to medium square-ish items, but as you can see to the left, it’s not as effective for different aspect ratios. Also, when we used it for a large “chapter” menu, it became so large that it was totally washed out.
I tried making a rounded-corner rectangle highlight with a CCScale9Sprite and it looked nice, but when Jenn wrote up the updated tutorial, she suggested an office-themed red circle around the appropriate object.
I thought, “ugh, that won’t work out… I’ll be given some circle graphic and it’ll get horribly stretched for rectangular objects and blah blah blah”, but I thought a little more about it. Why not use a CCDrawNode and draw my own Bezier curve?
I started looking up information on curves, and mostly referred to Pomax’s excellent Primer on Bezier curves and the more succinct Wikipedia page. I then thought about how I draw a circle on paper… I generally start at the top, sweep counter-clockwise, and rarely end up at the same point if I’m doing it quickly. My curve should emulate these features.
My first attempt was to make a sixth-order Bezier curve, with two points at the top-middle (one each for start and end), and then one at each corner of the bounding rectangle. You can see how I messed it up to the right… First, I had an off-by-one error where I mistakenly implemented a seventh-order curve, resulting in the Pac-Man-like effect, and second, I noted that the curve ends up much smaller than the bounding rectangle. I could have done something like curve moulding, but figured that making a poly-Bezier curve would be much easier. So now I have four quadratic curves using a total of nine points. Two endpoints at the top-middle once again, four control points at the corners still, but also (shared) endpoints in the middle of the left, right, and bottom edges. You can see another attempt in this image, where it mostly worked, but I translated some endpoints incorrectly.
So a few examples of the final result are to the right. First, I take the bounding rectangle and make it larger, so the curve will contain more of the desired area. Then I randomly offset the rectangle’s top-middle points by a decent amount. Then I randomly offset the rectangle’s corner points a bit less, and then the rectangle’s other midpoints the least, so I don’t end up with indentations in my circle. The anchor points have some constraints to also help in this regard. (Try playing with the anchor points in Figures 38 and 42 on Pomax’s page) Then after calculating all of the line segments, instead of rendering them all at once, I only render a segment at a time in the object’s update function so it looks like someone is drawing it. Finally, the thickness of the line is determined by the size of the rectangle.
Tower Ranges and Areas of Effect
Another thing that I did this week was to crop the tower range ovals and power AOE ovals to the floor. We had a problem where these ovals were being drawn on top of walls. When the z-ordering code was written, walls were always at the back. Nothing can be behind a wall, right? (If it’s part of the level at-hand, that is) So it wasn’t quite as easy as putting the ovals underneath the walls, given the existing object groupings.
After thinking about it for a bit, I figured I could use a CCClippingNode to clip the ovals to the floor. It’s quite easy to use… I just took the CCSpriteBatchNode that makes up our floor, and set it as the stencil of the CCClippingNode. You can see the first versions to the left. I had turned on the inverted property temporarily since nothing was showing up originally.
I was a little confused by the staircasing effect at the top at first until I noticed the alphaThreshold property. In the top image, the transparent parts of the rectangular diamond textures are counting towards the stencil until I set that property to an appropriate value. Then I just had to make it line up with the existing items. You can see some power AOEs being clipped to the floor in this result.
Steve’s Disappearing Act
Finally I’d like to describe an annoying bug that took a long time to fix. Sometimes, all of our “GLVectorSprites” would just disappear. In one particular instance, I noticed that Steve would disappear near the end of level 4. Steffen Itterheim wrote a great article about The Many Reasons Why A Cocos2D Node Won’t Show, but my problem was a little more esoteric.
Some of the shapes that were prerendered from our SWFs are very small, and don’t contribute much to the end result. For example, the artist made a small “AE” logo on Alto’s guitar, but it ended up so small and muddied, I just deleted the PNG before creating the spritesheet. Then in the render code, I say if the PNG can’t be found, continue and don’t render the shape. So far so good.
The problem was, this shape was a clipped shape. To save memory, I’m no longer using a stencil buffer – I’m using the depth buffer to do clipped shapes. So I would render the clipping area solely to the depth buffer, perform glDepthFunc(GL_EQUAL), render the clipped shape, then perform glDepthFunc(GL_LESS). (See where this is going?)
I was aborting the clipped shape after rendering the clipping area, so I had a continue after glDepthFunc(GL_EQUAL). So on drawing the next sprite, nothing would draw since no depth values were equal to the cleared depth buffer value.
Sigh. At least it works now.
Git commit message of the week: “Adds easy access to the welder. Weld me something, sunshine!”
Chat log of the week: (I was talking about a 4MB alloc I saw in Instruments)
S: that’s scary!
T: heh campfire coder stories
T: let me tell you about the one time *flashlight under chin* the memory was never freeeeeeed!
S: … and when they traced the call… the caller was IN THE HOUSE. the dealloced house
And below, an intermittent problem caused a price to be wayyyy higher than we would ever charge for something in the game – one… billion chachings!