Monday, May 29, 2017

Lunar Lift Support

Hi, thanks for playing Lunar Lift!

If you have questions or feedback, please email me at pk@patkemp.com. Thanks!


Tuesday, August 11, 2015

Procedural Generation for "Hopper"



One of my current projects is a mobile version of a simple Flash game I made years ago called Three Blind Mice. I'm referring to the new game as "Hopper" for now. Here's how it works:
  • You enter a sequence of moves by swiping up, down, left or right.
  • After each swipe you have a couple seconds to add another move to your sequence. Swiping up, up, and left will enter the moves up, up, and left.
  • When you finish swiping, your character hops according to the moves you entered.
  • The goal is to collect stars, the more stars you collect in one sequence, the higher your score.
  • Land on the grey stone tile to finish the level.
  • Avoid hopping off screen or into water.

The strategy of the game involves keeping track of the sequence of moves you entered. It's a simple concept that I wanted to revisit after having grown as a designer and programmer.

One of the things I hoped to improve for the mobile version was the procedural level generation. I had a few goals in mind:
  • The levels should be interesting to play and varied from one another.
  • The levels' complexity should be influenced by a parameter so I can escalate their difficulty.
  • Each level should have at least one perfect solution, meaning a single sequence of moves that collects all the stars and reaches the goal.
Let's take a look at the methods I've tried so far.


Method #1: Two Bridges

1) Create two grass shorelines separated by water.
 2) Pick a random position on each shoreline and connect them by a bridge. Repeat for a second bridge.
3) Place some dirt and grass tiles randomly.
4) Place the player, goal, and stars.

My first attempt was the "two bridges" method. I started by filling the grid with water tiles, which are impassable by the player. Then I placed a line of grass tiles along the top and bottom edges of the grid. I was thinking of these as shorelines and the water in between as a river the player was attempting to cross via a bridge.

To generate the bridge, I first selected a random horizontal position on each shoreline. I also selected a random vertical position between the two shorelines out in the water where the bridge would bend. I then placed dirt tiles in a vertical line out from the random shoreline positions to the bend position in the river. Finally, I connected the ends of those two lines with a horizontal line. Now I had a bridge generation function that let me connect any two shoreline positions using something resembling taxicab geometry.

Single bridge generation.

However, I didn't like how the single bridge felt like such an obvious solution, so I drew a second bridge overtop of it using new random positions (hence "two bridges"). I also placed some dirt and grass tiles at random positions to visually break up the obvious paths and provide possibilities for shortcuts.

I placed the player start position and goal on the opposing shorelines, and the stars were spawned on random dirt tiles. That latter bit compromised the goal of ensuring a perfect solution, because occasionally the stars would be spawned on an unreachable dirt tile "island" surrounded by impassable water.


Method #2: Weighted Drunken Walk


1) Fill with water.
 2) Randomly scatter dirt and grass tiles.
3) Draw the drunken path with dirt and grass.
4) Place the player, goal tile, and stars along the path.

In order to fix the unreachable star problem, I decided I should start by generating a perfect solution path and then building the level to accommodate it. That way I could place all the stars along that path and know they could be reached. To generate the path, I first tried a weighted drunken walk:

  1. Define a start position and end position.
  2. Randomly choose a neighboring tile from the start position to "walk" to.
  3. Check if the new position is the end position. If so, you're done. If not, repeat step 2.
Instead of "pure" random walking, I assigned weighted values to the four possible directions: 0.75 for up, 0.25 for down, and 0.5 for left and right. So each time a random direction is picked for step 2, it's 3 times more likely to pick up than down, which encourages the path to progress upwards towards the goal.

Once I've recorded the move sequence for the perfect solution path, I drew it to the grid with dirt and grass tiles. Dirt tiles turn into water once the character has stepped on them, so I only place these on positions that are only visited once in the perfect solution path. 

Weighted drunken walk path.

I also added the randomly placed dirt and grass like in the first method, but when it came time to place stars I only placed them on positions along the perfect solution path. That way, I knew all the stars could be reached by following the path and levels always had at least one perfect solution.

Unfortunately, the drunken walk algorithm frequently doubles back on itself by random chance. This prevented me from placing as many dirt tiles as I wanted because I couldn't determine that a position was revisited needlessly due to the drunken walking or if the retracing was necessary to get back after collecting a star on a peninsula. The levels also just looked ugly, which was reason enough on its own to try something else.


Method #3: Waypoints

1) Fill with water.
 2) Randomly place a few waypoints.
3) Draw a path that connects the waypoints in sequence with dirt and grass.
 4) Randomly scatter dirt and grass tiles.
5) Place the player, goal tile, and stars along the path.

My third and current method for producing a perfect solution path is to randomly place a few waypoints-- arbitrary positions that the path must pass through-- between the start and end positions. Then I draw connecting bridges between each pair of waypoints in sequence. The connecting bridges work much like ones in my "two bridges" method but they consist of a maximum of two lines instead of three. I also randomly selected if a bridge's horizontal line should be drawn before its vertical line.

Flipping between horizontal-first and vertical-first.

This bridge flipping works well because it produces paths that sometimes retrace themselves and sometimes don't. If I wanted to control the amount of retracing, I could probably weight the random choice between horizontal-first and vertical-first so it was more or less likely to match the choice made for the previous bridge, which is typically when the retracing occurs.

So far, the waypoint method of generating the perfect solution is working well. The resulting solution is much more deliberate in its progress towards the goal and retraces itself less than the drunken walk, which allows me to place many more dirt tiles. I've also added arrow tiles, which slide your character one tile when they are landed on. Like with dirt tiles, I only place these at positions that are only visited once by the perfect solution path since they block movement in any direction other than what the arrow allows. Again, the waypoint method allows for more of these occurrences.

Another plus of the waypoint method is that it provides a good way to control the complexity of a level, which was one of my original goals for the procedural generation. By adjusting the number and placement of the starting waypoints, I can vary how long and convoluted the perfect solution path is. 

I've added a difficulty parameter which controls those waypoint placement properties as well as the odds of dirt and arrow tiles appearing. It still needs tuning, but so far I'm pretty happy with the results:

left: 0% difficulty, center: 50% difficulty, right: 100% difficulty


Placeholder art courtesy of Daniel Cook's Miraculously Flexible Prototyping Tiles.

Wednesday, December 24, 2014

Ludum Dare 31 Post-Mortem: Hop 'N' Chop

A couple weeks ago, I participated in the Ludum Dare 31 72-hour game jam. I made a 1-button shooting/cooking game called Hop & Chop:

 Click to play


I'm pretty happy with how it turned out, and the response has been pretty positive. I thought I'd talk a bit about the development process and what I think of the final product.

Planning the recipe

I went into this Ludum Dare with a few goals in mind. First, I wanted to work solo. Collaborating with other developers is one of my favorite parts of game jamming, but I had some social obligations that prevented me from being available all weekend. I didn't want to flake out on anyone, so I decided to go it alone this time. I did end up reaching out to the multi-talented Teo Acosta, who took time away from his own game jam to compose the awesome music track in the game.

Second, I wanted to keep the scope very small. I've participated in quite a few game jams so far, and this is by far the most important lesson I've learned. I try to come up with a game so simple that I can get it up and playable in a matter of hours. That's the only way I've ever been able to end up with something even remotely polished by the end.

For Hop & Chop, I'd had already brainstormed an unrelated a 1-button shooting game where your gun bounced and rotated out of your control and all you could do was time your shots. When the Ludum Dare theme "Entire game on one screen" was announced, I wasn't feeling particularly inspired by it, so I decided to try out the "bouncing shooter" concept.

My third goal was to draw some sprites of food. For whatever reason, I find drawing food to be satisfying, so I figured I'd pick a food-related theme. Just like that, the shooting/cooking idea came together.

Cooking up a storm

With my simple concept in mind, I managed to get something playable Friday night: a cook avatar that bounced around shooting cleavers and some fish that could be chopped up:



If you look closely, you'll notice that the fish are first chopped into large chunks, which are then chopped into medium chunks, which are then chopped into small chunks, which don't get chopped any smaller. This is the beginnings of the "ingredients system", which would later allow me to build out the various recipes in the game. This system is nothing fancy, but it ended up taking the most time to fully implement.

I'm going to go into some of the details of how the ingredients were set up in Unity. I'll try to keep the technical stuff to a minimum, so bear with me!


This is a screenshot of some ingredients in the Unity editor. On the left are the "prefabs" for ingredients of various stages. On the right is the inspector window for the currently selected ingredient prefab Fish0 with the various Food script fields I exposed from code. Each of the ingredient prefabs on the left have the same Food script on them.

The most interesting fields are the Next Stage Foods and Combines With lists. These are lists of objects that I can drag-and-drop ingredient prefabs into in order to establish relationships between ingredients or the different stages of an ingredient.

For example, the Fish0 prefab has Fish1 and Fish2 listed in the Next Stage Foods list. That means when the Fish0 game object collides with a flying knife, the Food script will destroy it and create new game objects based on the Fish1 and Fish2 prefabs. You can see on the left that those prefabs have sprites that look like the two halves of a fish. As a result, the whole fish appears to be chopped into two halves. If we were to inspect the Fish1 and Fish2 fields, they'd both have Fish3 listed in their Next Stage Foods lists, and Fish3 would have Fish4 in its list as well. The idea is to set up a chain of ingredients for the player to progress through by chopping. 

Similarly, when two ingredient game objects collide, each of their Food scripts check to see if the other is on their Combines With list. If so, both ingredients are destroyed and a new ingredient from the Next Stage Foods list is created. For example, the Dough1 prefab you see on the left might have Pork1 in its Combines With list. If two of those ingredient game objects collide, they are both destroyed and a new Dumpling0 is created. The pork ingredient chain and the dough ingredient chain are then merged into a new dumpling ingredient chain.

All of the recipes in the game were put together by dragging-and-dropping ingredient prefabs into each other's lists to establish these chains of progression and combination. It took a while to build the ingredient system out in code, but once it was in place, I could quickly assemble and tweak recipes in the editor. This proved to be very useful when I decided to squeeze in the fried rice and mochi recipes during the final hours of the game jam!

Taste testing

So how did the game turn out? I had fun working on it, and the finished product still makes me chuckle. The comments I've gotten on the Ludum Dare page and in face-to-face playtests have been mostly positive. That said, player feedback and my own observations have revealed a number of design issues. I'm going to list just a few of the issues and then describe how I might go about addressing them.

One of the most common issues was that players couldn't tell what's going on with all the chaotically bouncing ingredients. It is pretty easy for players to spam their way through the first few recipes without understanding how ingredients are chopped and combined. They typically get stuck on the fried rice or dumpling levels because those require more deliberate tactics. It turns out my precious ingredient chains can be pretty inscrutable when they're represented by dozens of sprites bouncing around the screen.

To make the underlying system more apparent to the player, there are several techniques I could try out. One solution that wouldn't require additional code functionality is to simply add in more recipes that introduce each mechanic more gradually so the player can observe and internalize them in isolation. Another approach is to explain how the game works to the player explicitly through text, illustrations, or a directed tutorial, although that would be work-intensive and risks boring the player. A third option is to just change the system itself to something more comprehensible. What if each level was a discrete step in a recipe instead of making the entire dish? What if the ingredients don't move at all? What if the game was turn-based?

The issue that was most often voiced by the players themselves was how the control scheme worked. People seem to understand quickly that they can't control their avatar, but shooting accurately is still a significant timing challenge. I'd already taken steps during development to make hitting targets easier: I slowed the avatar rotation several times and made the default projectile fire 3 cleavers in a spread pattern, increasing the odds of hitting something.

I could continue to tweak and tune in this manner, or I could change the control scheme entirely. Sure, the "spinning gun" was the original concept, but that doesn't make it immune to change. What if the avatar moved side to side and didn't rotate, like a traditional SHMUP? What if the avatar stayed stationary and shot towards wherever the player tapped, like a "turret style" shooter? What if there was no avatar, and projectiles shot up from the bottom of the screen? These would all be cheap experiments, so they'd probably be worth trying out.

Finally, lots of players get stuck due to the level structure. Recipes typically require the player to perform chopping, combining, and cooking actions in sequence. There is also limited "ammo", which consists of different cooking tools they can shoot to perform each action. There are several awkward situations that occur if the player doesn't perform a given step in a recipe. Players often run out of "knife" ammo before they've finished chopping. This is especially noticeable if the recipe then requires combining and cooking steps, which can't be completed with the un-chopped ingredients. The player has to wait for the level timer to run out and the level to end so they can try again.

In fact, I added the 10- to 15-second time limit as a quick and dirty way to reduce the pain of these "stuck moments" by only making the player wait a few seconds for the level to reset. Kludgey design fixes like that are typical of game jams, but now that there's time to think the problem through, I should do better. What if there was no limited ammo, and the appropriate cooking tool became equipped based on the current recipe step? What if there were no discrete levels, and new ingredients kept spawning for successive recipes? 


Food for thought

All this reflection might be overkill for such a simple game jam project, but hopefully it was interesting to read. It was certainly a good game design exercise for me. This game jam was just what I needed after a recent string of uncompleted projects. It's so refreshing to finish something, even if it's small and low-risk. Now I've got to learn what I can from this experience and carry over the enthusiasm into my next game.

Thanks for reading!


Monday, July 28, 2014

Stuff I've been making (other than video games)

Hey folks, it's been a while since my last post, but I've still been busy working on stuff. No real news with Peak Condition, but I've started a new game prototype which I will be posting about soon. First though, I thought I'd talk about some of the non-game projects I've been working on lately.

Pixel art beads

I ran across an artist named Sarah Haghayegh (aka Pixelosis) at a convention who makes awesome beaded classic video game sprites, and I thought it looked like a lot of fun. I've pretty much copied her idea, only I'm designing my own pixel art patterns instead of using existing sprites. Here are a few I've made for friends:


I've always enjoyed the austerity of pixel art design, and these definitely scratch that itch. When making retro pixel art sprites for games, I typically work with a self-imposed limited palette, so it's amusing to actually be restricted to the bead colors I've purchased. Once I've designed the pattern, the actual beading process is fairly rote. That means I can bead while carrying on a conversation, which is great for occasions like my weekly Make Stuff Night (which I've been meaning to blog about!)



MonkeyHut

Feiya and I are going to Burning Man this year, and we're building a PVC shade structure called a MonkeyHut. The MonkeyHut is designed to shelter our tent from the sun while being flexible enough to stand up to strong desert winds. It's also cheap and easy-to-assemble. Here's a slideshow of our test-build in the park:

(Feiya took all the pictures, which is why you only see me working. Off-camera, Feiya was pounding rebar, bending PVC, and assembling the tent.)

The assembly was a success, and we discovered a few things we need to tweak. For example, we oriented our silver shade tarp incorrectly, which is why it doesn't reach the bottom of the PVC "ribs" in the last picture.

I've been stressing out over getting this thing made, so it was a huge relief to see it come together so well. Now I'm only slightly terrified that a strong wind will rip it up and fling it across the desert. 

Wooden dice

Another Burning Man related project I've been working on is my playa gift that I'll be giving out: handmade loaded dice. I bought some wooden craft cubes and went to work with Feiya's wood-burner to score the pips. The 6-side pips will actually be hollowed out and filled with Tungsten weight putty to weigh that side down and increase the odds of rolling a 1, which is represented by the iconic Man logo. Here's a picture of the dice in progress:



I'm making about 60 dice, so I've got plenty of work left to do. I've still got to putty most of them, sand their edges, touch up any pips that need it, and finish them with mineral oil. I've made a few prototypes to test the "loaded-ness" of the weighted pips, and I've gotten pretty good results. Here's a picture with a loaded die with tallies showing the test roll distributions:



Well, that's all for now. Next time, I'll talk about the new video game prototype I'm working on!

Friday, June 6, 2014

Peak Condition Log 06: It's finished! (for now?)

Download Peak Condition for either PC or Mac.

I finished the game by the end of May as I'd planned, but "finished" is a relative term, apparently. More on that below.

 Here's the new stuff:
  • Settled on the title "Peak Condition". Thanks J. Walton!
  • Added sound effects. Thanks freesound.org!
  • Added a "lunge" maneuver. Hit space bar when both of your climbing picks are attached and you'll lunge upwards and forwards, which is great for getting up onto ledges. Careful though: lunging drains all your pick stamina.
  • Added 4 difficulty levels for mountain generation: Easy, Medium, Hard, and Expert. The difficulty for a mountain is determined by the random seed string length, so longer mountain names are more difficult.
  • Added a ring of trees around the mountain to fence the player in and add some scenery.
  • Added a very rough tutorial which is played when the mountain seed is set to "Mt. Tutor".
  • Added a new death animation.
  • Fixed the victory detection.
  • Miscellaneous bug fixes and tweaks.

Phew, that last weekend in May was pretty busy! I squandered an entire Saturday's worth of gorgeous Summer weather, but I'm really happy with how much I got done. I completed all but one of the tasks in my "MVP" list on Trello. I can finally call this one finished and move onto my next prototype!

That was the plan, anyway. When I showed the game to my design meetup group last Sunday, I got a lot of great feedback and encouragement to continue working on it. When I look at my Trello board, there are still several features I'm just dying to get into the game. I feel like this concept has still got a lot of unfulfilled potential, and I'm not quite ready to call it quits yet.

However, I am ready to take a break for a while. I'll probably play around with some other prototype ideas I've been eager to start on before coming back to Peak Condition. In the meantime, I'd love to hear your thoughts on the current build and where you think the game could go in the future.

Sunday, May 25, 2014

Mountain Climber Dev Log 06: What's in a name?


Download the latest stand-alone build for PC or Mac. Or if you prefer, play in your browser. By the way, I don't have a Mac and I'm not really familiar with how best to distribute downloadable Mac builds, so I just zipped up the .app folder that Unity spat out. Please let me know how that works for you.

Changes in this build:

  • Implemented and styled the main menu.
  • Added a pause menu triggered by the "escape" key.
  • Reverted to the two separate pick stamina bars.
  • Iterated on the crosshair and stamina UI.
  • Experimented with an alternate "auto-hang" climbing style.
  • Added an altimeter.
  • Miscellaneous tweaks and bug fixes.
A week to go until my self-imposed deadline, and the game is coming right along. I styled the UI and added some simple fading transitions between screens, and it's already feeling much more like a "real" game.

Implementing and skinning the Unity GUI components was a lot less painful than I'd expected. I'd heard how limited the standard Unity GUI components were, but for a simple game like mine, they actually seemed pretty easy to use. Keep in mind that I'm coming from years of Flixel development, which required a lot of manual GUI work. I still plan to try out NGUI if I attempt a more GUI-heavy game, but for the time being, I'm glad I got a chance to try out the standard components and form my own opinion.

I switched back to the "per-pick" stamina bars so I could separate out two pieces of feedback that were previously both signaled by the crosshair: whether a pick is ready to use and whether the targeted surface is within range. The crosshair UI is now solely for reporting if a targeted surface is within range. Each pick's stamina bar now darkens when it is attached to a surface and brightens again when it is free and ready for use. I also added a pulse effect on a pick's stamina bar at the moment it impacts a surface. Hopefully this makes the climbing feedback easier to use while playing, but I wouldn't be surprised if I end up iterating on it one or two more times.

In response to some player feedback, I played around with a different climbing mechanic, which I dubbed "auto-hang." With auto-hang enabled, the player doesn't have to click and hold to keep a pick attached to the wall. Instead, they just click to attach the pick and click again to detach and attach to a new location. It makes the game quite a bit easier and consequently diffuses most of the tension. Ultimately, I decided it wasn't right for the game, but I left the functionality in as a debug menu option, so if you'd like to try it out, simply pause the game using the escape key and enable auto-hang.

I'm getting pretty sick of calling this game "the mountain climber game", and with a week to go, it's high time I settled on an actual title for the thing. My current ideas are mostly just cribbed from online thesaurus searches and mountain climbing glossaries:
  • Pinnacle
  • Ascent
  • Summit
  • Peak
  • Acro
As you can tell, I could probably use some help in the name department. If you've got any suggestions, I'd love to hear them in the comments.


Tuesday, May 13, 2014

Mountain Climber Dev Log 05: The Peak is in Sight



Click here to play the latest build. Here's what's new:
  • A single stamina meter instead of two "per-pick" stamina meters. The idea was to simplify the UI. The meter also turns red when you're running out of stamina.
  • A new mountain is generated each game according to a random seed in the form of the mountain's name. So "Mt. Rainier" will produce the same mountain every time. You can even type in your own mountain names and see what kind of mountain you get.
  • Player movement tweaks.
  • Terrain generation tweaks. See below.

I spent a fair amount of my time on the new terrain generation for this build. I tried to find a workable range of values to randomize so that each mountain felt climbable but somewhat unique. You may notice that the mountains have a lot less side-to-side vertex warping than in previous builds. The result is that the surfaces are mostly vertical and perhaps back to feeling more voxel-like. The reason I did this was to work around a problem I'd been having with the player movement.

As I added more and more angled surfaces to the mountains, I noticed that the player frequently "bumped their head" when jumping near a seemingly vertical surface. The problem is that the character controller doesn't have very complicated collision detection, so whenever the capsule-shaped collider hits anything on its top-most portion-- even a very slightly angled vertical surface-- it counts as a ceiling and stops the movement.

I tried making the climbing picks hold the player farther out from the wall, but that doesn't solve the problem when jumping from a standstill. I also looked into overriding or ignoring the default ceiling collision behavior, but it's tricky to tweak Unity's standard character collision code.

Eventually, I looked at the problem and the amount of other work I had to do, and decided to change the terrain to no longer produce the problematic geometry. It's definitely a sacrifice in terms of cool mountain shapes, but I'm hoping it's worth the saved time and effort.

My other news is that I've set an arbitrary deadline for myself: I'll release the finished mountain climber game by the end of this month (May 31st). My hope is that having a finite amount of time to spend will help me prioritize my efforts more efficiently, like with the ceiling-bumping issue. I'm also eager to move onto new projects, so knowing that I'll be freed up to do that in June is something to look forward to.

Thanks a lot for all the great feedback on the last update. I'd love to hear your thoughts on the latest build, especially on the terrain generation. Let me know in the comments if you find any particularly good (or bad!) mountain generation seeds.

Take care!