She’s my little buddy.
Devlog
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):
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.
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!
February 15th – Progress Update
Yikes, 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:
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:
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
- 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.
- The corgi now blinks when idle and barks occasionally during the game.
- 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.
- 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:
- 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
Time for a game progress update!
Things I’ve gotten done
- 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.
- 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.
- 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.
- 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):
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:
- 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.
- 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.
- 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.
Is It Fun?
Over the past few days I’ve put in quite a bit of work on my first iOS game. I’ve tweaked physics, learned how to implement a timer, messed with GameplayKit, and continued to refactor my code so that it’s more clear and efficient.
Yesterday I realized that I hadn’t asked myself a very important question about the game: Is it fun? The answer, as the game currently stands, is no.
So then, the next logical question is: how can I make it fun? Before I attempt to answer that, let me tell you a bit about the game.
Introducing Corgi Corral
I’m planning to call it Corgi Corral. You play as a corgi and your goal is to herd a group of animals (starting with sheep) into their pen. The game is written in Swift, using SpriteKit, and at the moment is accelerometer-controlled. Here’s a very early screenshot:
At the moment, the game doesn’t keep score and the sheep aren’t set to flee from the player (instead they just spawn in random positions at the beginning and wander aimlessly). I haven’t set up a lick of collision detection. The timer does nothing except count down. In other words: it’s not even close to being done. But I can already tell that it’s not fun. Funny, maybe, but not fun.
What makes a game fun?
I’m not going to get into Csíkszentmihályi’s theory of flow or the pros and cons of various game mechanics. And obviously, different people find different games fun. But for this game, specifically, I have some ideas.
Challenge. One of the problems with the game as it stands is that there’s not enough skill involved. The accelerometer controls can be a bit unpredictable as can the movements of the sheep, so it’s difficult to make decisions as a player that might improve your score. Therefore, tweaking the responsiveness of both the player and the sheep needs to be a priority. While some randomness in a game is okay, it’s frustrating as a player when you feel like you can’t change your technique to effect a better outcome.
Additionally, I’m torn as to what method of time-based gameplay to use. Should I set a time limit and count down, and see how many sheep the player can get safely into their pen in that amount of time? Or should I start at zero and count up, requiring the player to herd all the sheep into the pen and then awarding them a score based on how long it took? Feedback on that is welcome.
Personality. When I got the idea for Corgi Corral, I pictured it as a somewhat serious game. After all, corgis are actually herding dogs and this is something they used to do for a job. As I began working on the game, however, I changed my mind completely. I want the game to be zany and frantic and silly. I want it to make people laugh.
How can I achieve that? Having a time-based game already introduces an element of franticness, but I can do more. Music and sound effects will help. Some goofy physics and cute animations might also do the trick.
What if the corgi had a little cape? What if there were power ups? What if one level took place in SPACE? I don’t know. All I know is that I need to stay imaginative. After all, corgi-related games remain a mostly unexplored frontier. The possibilities are endless.
Progression. In other words: what makes players want to keep playing? At the moment, I don’t have a good, definitive answer to that. I know that I want Corgi Corral to be a game that people can play while waiting in line. However, I also want to introduce mechanics that make the game a little harder as time goes on. Perhaps there will be a minimum number of sheep that players must herd in order to unlock the next level. The next level might introduce ponds or fire pits or some way to lose sheep while also increasing the minimum number required to progress. Again, feedback and ideas are welcome.
Developing in the open
From this point forward, I plan to post a lot of code snippets and screenshots of the game’s progress. As a beginner, I feel that blogging about this experience (the good and the bad) will not only benefit other beginners but will help me learn as well.
I can’t say for certain how often I’ll post, and this whole idea might get tossed aside for awhile when my son is born (from what I hear, having a newborn can be a bit time-consuming!). I’ll do my best!