HELP! Squash a Bug, Save a Corgi [Updated]

UPDATED 3-12-16, 2:04PM CST:  I’ve actually been trying to figure out this bug for months, and, of course, as soon as I posted about it I figured it out. :D As it turns out, I made a real rookie mistake and messed up my Storyboard segues. I’m going to write a follow-up post explaining what happened…hopefully it will benefit other beginners like me!

Ok y’all, I’ve finally run into a bug that I can’t figure out, which means: the fate of Corgi Corral is in your hands. I’m posting here first, but if I don’t get a response, I’ll try Stack Overflow.

The Bug

Corgi Corral’s navigation stack is set up in a Storyboard and works like this:
Main Menu –> Scene Selection –> GameViewController –> Score Summary

From the Score Summary, the player can either retry the current scene, pick another scene, or return to the main menu.

The bug, which causes the app to slow to a stutter but not crash, occurs when I play four games in a row and then try to start a fifth. So, like this:

  1. Play Level 1 – all good, game plays at 60fps
  2. Play Level 4 – also good, game plays at 60fps
  3. Play Level 3 – things are still great, 60fps
  4. Play Level 2 – excellent performance here as well, 60fps
  5. Play Level 1 — when I return to Level 1, the segue between the Scene Selection screen and the GameViewController suddenly slows to a snail’s pace, the game’s framerate drops to 1fps, activity on all threads plummets, and the overall CPU usage drops to just about nothing. The Level1.sks file seems to load properly, everything is just slow.

The bug also occurs if I retry one of the scenes (so like: 2, 3, 1, 1, 2) instead of playing four different ones.

Since a crash never actually occurs, I paused execution right after the slowdown and took this screenshot of the debug navigator (click to enlarge):

debug navigator

However, I can’t make any sense of it. All I know is that I don’t seem to have a memory leak.

The Trace

I opened up the Time Profiler and recorded myself playing four games and then starting a fifth. I saved the trace, which you can download from Dropbox. (Note: it’s a 50MB file, since it took me about 6 minutes to reach the bug). The problem occurs right around the 5:15 timestamp.

Theories

I’m not experienced enough to be able to debug a problem like this. But I’m guess it has something to do with threading? Or texture loading? Or both? All of my scenes are loaded from .sks files. All of my sprite images are in the asset catalog (which, from what I understand, is necessary for app thinning and should behave like a texture atlas as of iOS 9). I’m not doing any on-demand resource loading. I don’t have any code related to Grand Central Dispatch. The game is accelerometer-controlled, so CPU-usage is naturally high during playtime. When I try to start that fifth game though, it’s like the accelerometer just gives up. Am I hitting some kind of system limit?

Comments are open, because I’m desperate. I’ll update this post with any additional information requested, and also if a solution is found. Thanks in advance!

Who uses SpriteKit/SceneKit?

Apple introduced SceneKit at WWDC 2012 and SpriteKit in 2013. Both frameworks have received updates over the past 3 years and have had multiple sessions dedicated to their new capabilities. Watching at home, however, I could never tell how many people actually attended those sessions. Is anyone even using SpriteKit? It seems like the majority of iOS games are built using cross-platform game engines like Unity.

If you’re an iOS game developer, I’m hoping you won’t mind answering this quick poll (not sure if it’ll show up in RSS readers):

[poll id=”2″]

Ever since Disco Bees was released, I haven’t heard a peep about any popular games made using SpriteKit or SceneKit. The reason I’m curious about this is because I want Apple to keep working on these frameworks, but I worry that they’ll be left to languish if no one is actually using them!

Comments are open on this one; please behave yourselves.

App Pricing Follow-up

I received some really helpful feedback on my previous post, where I wondered aloud about the best way to monetize Corgi Corral. As a result, I have a new idea of what I’d like to do.

Basically, I’d like to include some sort of tip jar with two or three price tiers. I would offer 3 levels of the game for free, and any tip given would automatically unlock the rest and also give the player the option to play as a tri-colored corgi:

Tri-color Corgi

Here’s the tricky part: Consumable in-app purchases cannot be restored. I was curious as to how (Underscore) David Smith got around this problem with his popular fitness app Pedometer++. Pedometer++ features a 3-tiered tip jar that will disable advertisements at any tier. The tips themselves are consumable, meaning you can tip David multiple times for his work on the app. To test his system, I tipped him $1, which removed the ads. I then deleted and re-downloaded Pedometer++ and, as I thought, the ads returned without an option to restore my purchase.

That’s not a big deal for a small inconvenience like banner advertisements (and honestly, I’ll probably just tip David again because he’s awesome). However, in my case, if players pay to unlock all the levels they should really be able to restore that functionality on a new or different device.

This brings me around to a system that more closely resembles what Humble Bundle does: “Pay what you like.” In other words, you choose a one-time purchase price from 3 options, based on…well, the goodness of your heart I guess? It’s an idea that I’ve never seen implemented before in an iOS game and one that I can afford to try.

Setting up in-app purchases sounds like an enormous headache, but I’m actually more concerned about localization and how to word everything. I’m stuck on two things:

  1. What should I name the 3 price tiers? Something goofy like Corgi Fan/Corgi Lover/Corgi Wizard or more straightforward like Bronze/Silver/Gold Supporter? (or maybe something involving the word “thanks”?)
  2. What should the user-facing explanation be? I was thinking something like, “If you’re enjoying Corgi Corral, your support would be greatly appreciated. Purchasing any tier will unlock the full game.” Does that make sense?

And once I figure those two things out…do I dare try to do the translation myself? ?

Anyway, I suppose I’m getting ahead of myself. I have so much more work to do on just finishing all of the art assets that I won’t need to make these decisions for several months, probably!

App Pricing: An Internal Monologue

In case you’re new to my blog: I’m currently in the process of making my first iOS game. It’s short, casual, and is clearly made by a beginner (is that a polite-enough way to say “amateurish?”). I’m hoping to release it sometime this summer and have been thinking a lot about pricing models for iOS games. What follows are some of my loosely-organized thoughts on that subject.

Customer Expectations

People who like to play short, casual games tend to expect them to be ad-supported, free-to-play, or just plain free. However, the developers that I follow, respect, and want to emulate, tend to express disdain toward those pricing models and prefer to promote games that are paid-up-front. Because of this, I feel torn between a niche group of thoughtful, intelligent iOS gamers whose respect I would love to earn, and the general public who couldn’t care less about the indie games market and just wants free games. And the thing is, I’m just a beginner, which brings me to…

Who am I?

Nobody knows who the heck I am. How could they? I’m not known for anything because I haven’t published anything. I have no fanbase, no credibility, and no experience. If I make my game free with ads and localize it as much as possible, there’s a good chance that it could get quite a few downloads. As someone currently wallowing in obscurity, one of my goals is for as many people to play my game as possible. And if people don’t like it, that’s fine—I can learn from it and move on.

However, if I price it at $0.99, even with the best marketing in the world, there’s a good chance that no one will download it. And if no one downloads it, I’ll never know whether or not they like it. I won’t know how to improve. Most of all—I’ll probably be discouraged from making a second game.

Determining Value

From what I understand, if you undervalue your work, no one is going to take you seriously and if you overvalue your work…well, no one is going to take you seriously then either. Online publications are severely criticized for paying very little (sometimes nothing) to their contributors in exchange for “exposure.” I mostly agree with the criticism; however, I also wonder: is there a point where gaining exposure is worth giving away your work for free? What if that work is your first effort? What’s the best or “proper” way to get noticed? Is there value in just “getting something out there” into the world, even if it’s not the most polished thing ever?

Ads are Icky

Advertisements make me feel gross. However, I’d like to make at least $50 off of this game, so I guess I can’t afford to be principled? Gosh that sounds horrible. I’m trying to keep it as least-scummy as possible: banner-ads only (no interstitials), never during gameplay, with an option to pay to remove ads. Honestly, it still makes my skin crawl. And I’m also concerned that it may push away one of my target markets: young children. Games with ads are bad for young kids because they touch the ads accidentally and get taken out of the game and don’t understand what happened. I guess I would just encourage parents to pay to remove the ads? That feels kind of scummy too. Or maybe it’s just business. ¯_(ツ)_/¯

Changing Models

It seems like it would be difficult to switch my app from being ad-supported to paid-up-front if I changed my mind down the road (after release). Will the people who paid to remove ads be angry that all of those who didn’t now suddenly have an ad-free experience? I guess the only example I have to go by is that of Overcast. I paid for Overcast’s extra features, which are now free for everyone, and I’m not mad about it. I mean, I suppose someone would be unhappy but maybe it wouldn’t be so bad?

Anyway, the article that got me thinking about all of this is “Indie Developers Have Always Needed to Treat Their Businesses Like Businesses” which is a very good, concise read.

tl;dr: I absolutely believe that indie studios should charge good money for their games and apps. I’m less sure of what solo, hobbyist devs like me should do, especially with our first games…the ones that we’ll look back on someday and think “wow, look how far I’ve come!”

Status

Quick progress update: I’ve been treating Corgi Corral as sort of a SpriteKit/GameplayKit sandbox, as I really want to learn about everything these frameworks have to offer. Lately I’ve been exploring particle emitters, which means my winter scene now has falling snow and a small campfire! Next up: creating some more custom menu icons to reduce the amount of text in the game.

Using SpriteKit’s Scene Editor for Simple Animations

When I began working on Corgi Corral, I knew I wanted to keep the game as simple code-wise as humanly possible. I wanted there to be one “LevelScene.swift” file that would handle the game logic for all of the levels in the game, and I didn’t want to clutter up that file with level-specific code for animating background/decorative sprites. In fact, I didn’t really want to write that code anywhere.

Enter the SpriteKit scene editor.

I know many developers prefer positioning things in code over using tools like Storyboards or the level/scene editor, but I personally love the ease of drag-and-drop positioning and the ability to preview what things will look like without building and running the app.

This morning, I decided to create and animate some twinkling lights on the fence that encloses the sheep pen. Here’s the end result (and yes, the sheep are wearing scarves):

Snow scene

I could have written something like this to animate the fence sprites:

let textures = [SKTexture(imageNamed:"twinkle1"), SKTexture(imageNamed:"twinkle2"), SKTexture(imageNamed:"twinkle3")]
let twinkleAction = SKAction.animateWithTextures(textures, timePerFrame: 1.0)
fence.runAction(SKAction.repeatActionForever(twinkleAction))

Instead, I decided to make the fence sprites SKReferenceNodes (in case I want to use them in another level) and animate them using the scene editor. To do that, I created an .sks file that matched the dimensions of the fence and placed the fence inside it. Next, I opened the animation timeline at the bottom of the editor and dragged in an “AnimateWithTextures” action from the object library on the lower right.

SpriteKit animation editor

After that, all I had to do was tweak the parameters in the attributes inspector on the right. I set the duration for 3 seconds and dragged my textures from the media library to the “textures” box in the attributes inspector. Finally, I set the animation to loop forever. When I added added the SKReferenceNodes to my scene, they animated automatically. Piece of cake!

Finding My App’s Memory Leak

My plan was to write a quick post explaining how I figured out the source of my app’s memory leak; however, I’ve run into two problems: 1) I think my app actually has a few other minor leaks, so I didn’t fix it completely and 2) the “Allocations” instrument in the latest Xcode beta is absolutely refusing to work now, so I can’t recreate what I saw the other day and take screenshots. As soon as I’m done writing this, I’m going to file a radar because I was able to reproduce the crash using Apple’s own sample game, DemoBots.

Anyway, there are still a couple things I can show you. First, I ran Corgi Corral on my iPhone 6S and played the same level twice. In between levels, the app transitions to another view controller that gives a summary of your score. As you can see, the second time I played the level the app used more memory than before. Each time I hit “retry,” it increased ever so slightly.

Debug navigator

If I hit the “Profile in Instruments” button during gameplay, my app would immediately crash (which is why I’m filing a radar). However, for awhile I was able to get the “Allocations” tool to collect data on the score summary screen. Now, I can only get it to run on the main menu without crashing.

Transfer to Allocations

For what it’s worth, it doesn’t matter whether I select “transfer” or “restart” — the app still crashes, except on the main menu, where I can at least show you what the memory-analyzing tool looks like when it’s running:

Allocations and leaks

See those little green checkmarks next to “Leak Checks”? When I reached my score summary screen, those were showing up as red icons with an “x” in the middle. When I clicked the red icon, it showed me a list of objects that weren’t being deallocated. The list included many instances of “GKAgent2D,” “GKGoal,” “GKBehavior,” “GKComponentSystem”—enough instances to cover the number of sheep in the level. Evidently, even though the SKSpriteNodes were being removed from the scene (and their agents from the scene’s agent system) when the sheep entered the pen, their GameplayKit agents were refusing to die.

I’m hoping that the next beta of Xcode 7.3 will fix my profiling problem, because I’ve become really interested in learning how to analyze my game’s performance! I’m sure there are many more problems to be found and optimizations to be made. For now, I’m off to file a bug report!

February 15th – Progress Update

Corgi Corral iconYikes, I can’t believe it’s already been nearly two weeks since I’ve done this! I admit that I haven’t spent much time working on the game lately, mostly because I just haven’t felt very good. Besides the ever-increasing pregnancy discomforts, I’ve just been feeling sort of discouraged. However, I’m still determined to push through and release the game—no matter what!

Accomplishments

As you can see, I made an icon for the game along with a main menu screen:

Corgi Corral Menu Screen

The title falls from the top of the screen and does a little “bounce” when the app is first launched. As I was setting up the menu, I realized that if I used less text, it would be easier to localize the app into different languages. I switched “Options” to a little gear icon and “Leaderboards” to a simplified Game Center logo. I also changed the “Tap to Start” text to a tapping finger icon:

Screenshot 2-15-16

After that, I shifted my focus to finding the source of a small memory leak. According to Xcode’s debug panel, every time I restarted a level, the app would use about 1 megabyte more memory than it did the previous time. Eventually, I figured out that the app was holding on to a bunch of GameplayKit-related objects for no apparent reason. Like, all of the GKAgent instances should be owned by the sheep SKSpriteNodes, which should have been wiped out when the scene was set to nil. Instead, the game was holding on to their agents, their agents’ behaviors, and all of the GKGoal objects indefinitely.

Now, whenever the game enters its “Game Over” state, I explicitly remove all the GameplayKit-related objects. I think that fixed the problem…or at least, the Allocations instrument isn’t reporting leaks anymore.

What’s Next

Art, art, and more art! Probably going to work on Level 3 scenery, and maybe figure out how to draw a top-down view of a pig. :-)

That’s all for now…thanks for reading!

February 2nd – Progress Update

Between baby-related activities and the ridiculous snowstorm that swept through the Midwest last night, I haven’t had a chance to work on Corgi Corral for a few days. However, a lot of things came together rather quickly last week, so I do have some progress to report (no screenshots, though).

Accomplishments

  • After the time runs out, the game now displays your score, high score, and the name of the medal you’ve earned (bronze, silver, gold or none). The medal name will eventually be replaced by an image.
  • On the Options screen, there is a toggle to turn the sound effects on and off (and it works!).
  • iAds are set to appear on menus, but not in-game. I don’t plan to use a backup ad service, so countries that don’t display iAd won’t ever see them, which is fine.

What’s Next

I’m to the point where I can’t stand not having menu art or an app icon…so yeah. Looks like it’s time to close Xcode, open Affinity Designer, and try to make some passable artwork! I’m about as much of an artist as I am a programmer (which is to say, I sit squarely in the “amateur” category), so we’ll see how this goes! Just wait til I get to the music… ;)

January 25th – Progress Update

It’s been a week since I last blogged; here’s what I’ve been up to!

Accomplishments

  1. I created some art assets for the second level/scene, which has an autumnal theme. The screenshot below shows a funny bug (now fixed) in which a sheep would spawn in the wheelbarrow and be unable to escape.

    Corgi Corral Level 2

  2. The corgi now blinks when idle and barks occasionally during the game.
  3. I created a struct called “LevelConfiguration” that reads information from a property list. The list contains information like how many animals should spawn, what the time limit should be, what sounds should be used, etc.
  4. For scene management, I decided to abandon the idea of a SpriteKit-only solution and ran back to something I’m more familiar with: UIKit and Storyboards. I set up bare-bones view controllers with simple UIButtons and UILabels that players can use to navigate to and from the main menu, options screen, etc. They’re not pretty, but they work, and now all I have to do is create art assets for them:

    Storyboard Layout

  5. After the timer for a level runs out, the game now waits 3 seconds and displays a score summary screen with options to retry the level, select a different level, or return to the main menu.

Under Consideration

Here are a couple of things I’m mulling over:

  • Whether to have the different levels/scenes progressively unlock, or to make them all available from the beginning.
  • Implementing a “medals” system similar to the one used in Flappy Bird with bronze, silver, and gold levels depending on how many critters you herd into the pen. And then maybe you’d need at least a bronze medal to unlock the next level? I don’t know. Still thinking about it.

What’s Next

Now that I have a very simple menu structure set up, it should be relatively painless for me to set up things like iAd, sharing a score via the share sheet, and adding an option to turn off the sound effects. My goal from now until the baby is born in March is to make it so that the only thing I have left to do is add the art, music, and remaining sound effects.

It looks like I started the Xcode project on November 20th, which means I’ve been working on this for a little over two months now (and sometimes only for a couple hours a week). With that in mind, and knowing that it’ll take me a long time to do graphics and music, I’m hoping it’s reasonable to expect the game to be ready to ship sometime before my birthday in July!

January 18th – Progress Update

Corgi Corral Jan 2016

Time for a game progress update!

Things I’ve gotten done

  1. The game now detects the angle you are holding your device when you start playing and sets that as the starting point for accelerometer updates. Previously I had hard-coded some neutral orientation values.
  2. Game states! Now the game is more gamey and less proof-of-concepty. You can tap to start the game, pause and resume it, and start a new game after a “game over” message is displayed. It’s all pretty bare bones but it works.
  3. Animations. I’ve never animated anything before so they’re kinda rough, but the corgi now “runs” and the sheep blink at random times when idle.
  4. Sound effects. I edited some sheep sounds from freesound.org and put them in the game. Personally, I think they’re hilarious. I also learned how to convert audio files to Apple’s Core Audio Format via the command line.

Things I decided not to do

  • Add “flocking” behavior to the sheep. I tried adding some separation, cohesion, and alignment goals to the sheep and I actually didn’t like how it made them behave. There’s nothing wrong with the goals themselves, but when combined with the “wandering” and “fleeing” goals, they just don’t function well enough. It’s also kind of funnier to have the sheep running every which way without any concern for one another.
  • Animate a “+1” when a sheep enters the pen. I decided to animate the score label instead; it quickly scales up and down when the score increases. The sheep also “baaa” when they enter the pen, which I think is much more satisfying.

Things I plan to work on next

The game is now to a point where I have to start working on its overall structure. In other words, it’s going to have to be more than just one scene file and a “LevelScene.swift” class. I need to set it up to accommodate multiple levels and multiple scenes (such as “Menu” and “Options”).

I think I need to make some sort of “level configurator” that loads the details for each level from a .plist. Then I need to create some kind of “scene manager” that can switch between the menu, options, level selection, and also load the correct level. This is all incredibly new to me so I imagine it will take quite awhile to figure out. In fact, this is the part I’ve been dreading because I hardly know where to start. I think I’ll spend time examining Apple’s “DemoBots” sample code (which just came out, so it’s written in Swift and includes the latest APIs) to see how they set up the level loading and switching.

I’ll let you know what I come up with! :)

Time to Make a Game Plan

Most seasoned game devs would probably say that you should start the development process by writing a game design document (GDD). The GDD describes your game’s hooks, characters, objectives, audience, etc. in enough detail that it can serve as the primary reference for you and your team.

Well, I don’t have a team, or a design document. Instead, I started with a concept and hoped to eventually turn it into a game. Now that I have a better idea of how that concept works in practice, I figure it’s time to start nailing down some of the specifics.

Initial elevator pitch: Corgi Corral is a casual, tilt-based herding game that offers fun for all ages. You play as an adorable Welsh Corgi with one job: to herd as many frenzied animals into their pen as possible before time runs out. Avoid obstacles, chase away predators, and try to beat your best score in 9 colorful levels.

Some more game details: I haven’t figured out the perfect time limit for each level yet, but I’m guessing it will be 1-2 minutes. It’s gotta be quick: something you can play while waiting in line.

I’m planning to implement two power-ups that spawn randomly and infrequently:

  • A little clock that you can tap on to add 5 seconds to the game time
  • A “magnet” power up that temporarily draws all of the animals toward the middle of the screen (and away from the edges…yay!). This will either look like a magnet and make a “buzzing” sound when you tap it, or a sheep/cow bell that rings when you tap it. I’m leaning towards the latter, because I think it better fits the character of the game.

As for the aforementioned predators, I’m thinking they’ll wander onto the screen and move slowly toward the pen. If they reach the pen, you lose a couple points from your score. All you have to do to make them go away is chase them off screen.

Monetization: I’ve been going back-and-forth about this a LOT. Personally, I prefer to play games that are paid-up-front with no in-app purchases. However, this is my first game, and although I’d like to add levels in the future, the initial experience will be relatively limited. Right now it’s more important for me to get something out there than to make something mind-blowing. So, with that in mind, I think Corgi Corral will be tastefully ad-supported. By “tastefully” I mean that ads will only be shown on the main menu and the “game over” screen…never during gameplay. And there will of course be an option to remove ads altogether.

So, there you have it! I’m going to spend the rest of my game dev time today with my notebook and pen, knocking out a few more things that will help me move forward such as: what game states I need to set up, what options I will need to record in NSUserDefaults, what information I need to include in the plist for each level, and what scores or achievements the game should highlight.

Trying Affinity Designer

When I decided to make all my own art for Corgi Corral, I figured I would use Photoshop CS6 because that’s what I’m most familiar with. However, after making both the corgi and the sheep in Photoshop, I’ve started to realize that there’s a reason people use Illustrator for vector graphics: Photoshop’s tools just don’t cut it. I can’t afford Illustrator, so I went hunting for an alternative and stumbled upon Affinity Designer ($49.99), which happened to be on sale right before Christmas.

I just started messing with it the past few days, and I really like it. When you create a new document, there are preset sizes for Apple devices such as iPad Retina (1024×768 points) and iPhone 6 (375×667 points). All I had to do was watch a couple of short (< 4 minute) video tutorials before I felt like I knew enough to get started with the pen and shape tools, which are all really flexible. Another thing I like is that when you bring up the list of color palettes (PANTONE, Greys, Colors, Gradients, etc.), it also lists any custom palettes you’ve created from within Apple’s color picker. I’ve created a few palettes in Xcode, and I could access them easily from within Affinity Designer. Finally, I don’t have a graphics tablet, so the ability to do stuff like this is pretty great:

Anyway, the app gets great reviews and an iPad version is coming eventually, so if you’re looking for some intuitive, robust vector graphics or pixel art software, you might want to give Affinity Designer a try. It also has a nice dark interface, if that matters to you!

Herding Success

I finally found a decent fix for the GameplayKit/physics problem I’ve been fussing over for months (and that I wrote about yesterday). The good news is that it’s simple. The bad news is that it’s really only applicable to my particular game and probably won’t help anyone else that is looking for a way to get GKAgents to avoid the edges of the screen. Sorry! If it helps, I filed a radar about it.

Prior to figuring this out, I had just set my sheep to wander at a slow speed when they spawned. I set a low weight for the wandering goal because I mostly wanted them to flee from the corgi. I set the weight of each sheep’s fleeing goal high when the corgi approached, and back to zero when the corgi was farther away. I never changed the wandering goal.

The solution was to switch between the fleeing goal and the wandering goal, turning each completely on or off depending on the distance between sheep and corgi. I also assigned a higher weight to the wandering goal and increased the speed. Here’s the function that handles that logic:

func checkDistanceBetweenCorgiAndCritters() {
        enumerateChildNodesWithName("critter", usingBlock: { node, _ in
            let critter = node as! Critter
            let playerVector = CGPointMake(CGFloat(self.player.agent.position.x), CGFloat(self.player.agent.position.y))
            let critterVector = CGPointMake(CGFloat(critter.agent.position.x), CGFloat(critter.agent.position.y))
            let distance = self.distanceFromCGPoints(playerVector, b: critterVector)
            let maxDistance:CGFloat = 200.0
            
            if distance < maxDistance {
                critter.agent.behavior?.setWeight(100, forGoal: self.fleeGoal)
                critter.agent.behavior?.setWeight(0, forGoal: self.wanderGoal)
            } else {
                critter.agent.behavior?.setWeight(0, forGoal: self.fleeGoal)
                critter.agent.behavior?.setWeight(100, forGoal: self.wanderGoal)
            }
        })
    }

I call them critters instead of sheep so that I have some species-flexibility. ;) The above function borrows a method from Apple’s “AgentCatalog” demo project that calculates the distance between two positions. Now when the sheep get “stuck” along the edges, it’s only momentary because as soon as the corgi moves away, they’re super focused on wandering around.

https://www.youtube.com/watch?v=Grdr028WZFk

What’s Next
Here’s my short list of things to work on next:

  • Add some “flocking” behavior so the sheep tend to travel in cohesive groups.
  • Add a “run” animation for the corgi so it’s not just a legless blob.
  • Animate a little “+1” whenever a sheep enters the pen.
  • Add a pause menu with “resume” and “retry” options (and later an option to quit and return to the main menu).
  • Work on background art.

Spinning in Circles

I spent a long time messing with Corgi Corral yesterday. Too long, probably, because now I can hardly stand to look at it. I hear this is normal though, so I figured I’d take a break today and blog about it instead!

Awhile ago I wrote about the disconnect between GameplayKit’s agent system and SpriteKit’s physics world. I’m still working my way through these issues and have only managed to come up with partial, half-baked solutions. Specifically, I’m struggling with how to handle collisions between the sheep and the edge of the screen.

What Happens
When the sheep, who are part of the GameplayKit agent system, collide with the edges of the screen (an edge chain physics body), they “stick” to the edge and slide along it. Eventually, they all end up huddled against the edges of the screen.

What I’d Like to Happen
When the sheep collide with the edge of the screen, they should turn around and go the other direction.

My Failed Solution
I came up with something that almost works. When I detect a physics collision between the sheep and the edge chain, I run an SKAction that rotates the sheep in the other direction, like so:

sheep.runAction(SKAction.rotateByAngle(CGFloat(-M_PI), duration: 1))

That actually works really well in most cases. The sheep hit the edge of the screen, turn around, and go the other way. The problem is that when they hit the corners, or get pinned between the wall and other sheep, then they spin pretty much indefinitely, like so (tap/click to play the GIF, note bottom left corner):

spinning sheep

They currently have circular physics bodies, but I’ve tried a variety of other shapes and they still get caught in the Spin Cycle of Doom.

Why This Problem Even Exists
In essence, GameplayKit’s agent system and SpriteKit’s physics system are in constant conflict. In the “agentDidUpdate” method, the position of the sprite is always reset to match that of its agent after the agent carries out its goals for that frame. Therefore, the agent system essentially overrides the physics system. So what’s the point of giving sprites with GKAgents physics bodies at all? Well, mostly to prevent them from passing through other sprites and to be able to be notified of collisions.

What Now?
I have three hazy ideas for solutions, but I could really use some help. Here’s my thought process so far:

  1. Maybe there’s something I could do in the agent delegate methods? There’s got to be a use case for those besides just setting the position of the agent and the sprite.
  2. Another idea was that after rotating the sheep, I could apply an impulse to propel it away from the wall. The problem is, I need to know which direction to propel it, and I don’t know how to figure out which edge of the screen it hit. I’m also wondering if this could cause a similar problem with the sheep bouncing around the corners, unable to break out of the back-and-forth pattern.
  3. I could find some way to use the agent system itself to keep the sheep away from the walls. So far, adding the edge chain as an “obstacle” and ordering the agents to avoid it doesn’t work—I suspect because the edge chain is just a line instead of something with actual volume. I could add some large, clear rectangular sprites along (but mostly outside) the bounds of the screen and add those as obstacles maybe?

So yeah, I don’t know. The documentation on GameplayKit is still lacking and the dev forums are pretty much dead. I’m hoping this year’s WWDC will bring some clarity and new features to this otherwise nifty framework.

Got an idea for me? Tweet at me: @bhansmeyer.