All posts by george

Indra’s Net and Theming

(Indra’s Net is available on both the app store and google play.)

Okay, if you’ve played Indra’s Net or seen screenshots you’ll know that it hardly “themed”. They’re squares, they change colors. There aren’t any cute animals or sugary confections to grab the semantic part of your brain, but there is theming nevertheless!

After establishing the core mechanic I wanted a little something extra to make the game more meaningful. Since in the first formulation the player had to turn all of the tiles white in order to progress, I thought that emptiness might be a neat theme, so the game was called Sunyata and featured the text of the Heart Sutra parsed into 14 sections (hence the current 14-level structure). Each time through the sutra would repeat, and the game became a meditation on emptiness for me. I enjoyed this quite a bit but there was something lacking since the relationships of the squares was never addressed.

With Ben’s suggestion I began looking into Cause and Effect as a potential theme and shortly came upon dependent origination, which coincidentally enough is considered complementary to sunyata in Buddhist philosophy. Having found the two ends of what I wanted, I searched further to discover Indra’s Net, which “is a metaphor used to illustrate the concepts of emptiness, dependent origination, and interpenetration in Buddhist philosophy.” The shoe fit.

The heart sutra, however, did not fit anymore. The new metaphor of Indra’s Net was more playful than the austere Sunyata, and after having played the game for a while I discovered that it put me in a playful mood of discovery and wonder. With that feeling in mind I decided to write a brief story about Cause and Effect which Sarah and I rewrote shortly after. The basic premise, if you haven’t played yet, is that Cause and Effect become separated and go about their own journeys to be finally reunited in the end, where they arrive in a different place (and the next season), for the story to repeat as the board grows bigger/features more colors.

This was the story of how from a purely abstract logic puzzle, a game embracing confusion and addressing separation was created. The theme and story help lower the stakes, make it playful, and allow people to get lost without worry. When we’re lost and without assumptions we can finally start to learn brand new things.

Pro-social Game Design

Today I published an article I’ve been working on about pro-social game design, making things that are good for people. It takes as inspiration games which I very much respect and distills some of the lessons from them. Here’s an abridged version:

There’s an analogy between fast food/slow food and types of games in that the former are easy, low cost upfront, high cost later and the latter are higher cost up front, more challenging, but ultimately better for you.

Three ways to go about making a game that is good for people:

  • let people sit, give them space
  • encourage growth
  • reward the player

If we make enough pro-social games then people’s standards will raise and they will realize that they didn’t really want the cheap stuff to begin with. That’s the job of the indie game designer.

Developing Secant

Secant, our latest release, is a minimalist geometric puzzle game (see the trailer below). Today I’d like to share a bit about what it was like to develop it, from inspiration to design to implementation, along with some road bumps and their solutions.

Backstory + inspiration: In machine learning and statistics one type of problem is classification, which is basically what it sounds like. This can be tricky, because data can be noisy or arranged in some strange shape. A particular type of classifier called a support vector machine (SVM) tries to classify data by cutting it up with planes (or, in the 2D case, with straight lines), so that each region has only a single class. We might say the SVM uses hyperplanes as its basis functions, and because of this support vector machines are inherently limited. So the question emerges: what if you allow other shapes? Secant is just that, played in two dimensions only, where you get circles and lines as your basis functions and your job is to separate data points into regions based on their class (color). Or at least, that’s how I originally thought about it.

Crux problem: With SVMs, all you ever have to worry about for each point is whether it is ‘above’ or ‘below’ each plane (or line). Since planes carve up the plane very nicely (notably, into convex regions) you can simply look at two points, P and Q and ask are they above or below each plane. If they match up on all counts, then they must be in the same region. Now, this is still true with circles and lines, but what doesn’t hold is that is that if they do not match up then they must be in different regions. Evie (aka Evdog) came up with the following situation during her first play through the game:

photo1

Notice that the green and yellow are in different geometric regions (clearly!) yet they are both inside the big circle, outside the small one, and above the line. Since the game doesn’t see this as a win, it doesn’t allow the player to progress (how sad) until they find a solution that doesn’t use such geometric tricks. Since disallowing geometric tricks would surely make for a worse game, I realised that what Evie had done was most assuredly a valid solution. But the question remained: how to correct it?

Two approaches and a decision: There were two ways to go about it. One was to use a flood fill algorithm (think paint bucket in photoshop) which checks if you paint-bucket from each point you don’t get regions with multiple colors painted on them. This was pretty clear to be a solution, but I thought running it on device was going to be a nightmare (it would involve iterating through all of the pixels onscreen and I didn’t even have access to the pixels and would have to redraw it from scratch). So I kept thinking about it, and came up with an alternate solution based on the original logic of being inside or outside each closed region: compute all intersections as vertices, link them up in a graph (where edges are adjacencies between intersections on a shape), find the cycles, and then check the winding number of each data point with respect to each cycle. This would give all the funky weird regions as loops, and then verify that these loops either did/did not go around each point. The main problem with this: it was going to be even worse than flood fill because, while computationally far simpler (with not too many shapes on the board, mind) it would involve finding all cycles and then computing the winding numbers (which would involve making polygonal proxy shapes for the circles or casting a ray from the data point in question and ‘walking’ the circuit to find a minimal enclosing region). In short: this was not going to be any better than flood fill if I could get flood fill to perform reasonably on device.

Solution -> Aesthetic: I tested out the performance of flood fill which was disheartening at first, read up about coroutines in Lua, and ultimately used a grid that was a quarter of the size in each direction (resulting in a ~16x speedup) which, while a bit crude and not so pure, worked in practice. And a magical thing that popped out of this cruder grid? When you beat a level, it fills it in (at half of that resolution, every 8 pixels, for performance reasons with the display–this ain’t being done with shaders y’all) with circles of the appropriate color to show you the regions that you carved the space into. A nice reward for finishing a level (and something a few people asked about only to discover that it had already been implemented)!

w1

If you like these sorts of things, you might enjoy hearing about new releases by joining the google group.

Block Party Kickstarter Recap

This post is well overdo and I’ve been away from the blog for a while. Better late than never.

The Kickstarter was a wild ride. We raised over $22,000 in 40 days and almost 500 people backed the project, most of whom we didn’t know! While I could go into what we did for publicity (cross-campaign promotion is great), the practices we learned (more frequent updates are apparently expected, though I usually think an email more than once a week is spam), or what we could have been doing more of (it worked really well in a classroom setting), I’m instead going to talk a bit about the emotional aspect of running a Kickstarter, at least for us.

Anyone who has done or is planning to do a Kickstarter has likely heard about the slow middle. In short, expect the middle section of your campaign to be crawling, where you have to actively be shouting about what you’re doing for anyone to hear or care. Well, we got into the beginning of our second week, experienced some cross-promotion (thanks, Primo aka Prime Climb!) and had our second biggest day of funding to that point after the launch day (several thousand in a day). Slow middle? Yeah right! We were rocking it!

And this is how the rollercoaster goes. After that wave of hype fizzled, we  were dead in the water. A couple backers a day, a few days we might have had nothing, and after that insane day it felt awful. My guess? Expectation. Watching the money just pour in the door is one of the most surreal feelings I’ve had. Replying to backers with thank-yous as they came in amidst fits of smiling and wide-eyed surprise/lack of ability to respond emotionally to what was happening, that really big and successful day was pretty draining (read: I was not prepared for it). It was also insanely gratifying and uplifting and validating. But three days later I had come down from the high, was experiencing the tiniest amount of traffic, and wondering if we’d fund at all (of course, as the money rolled in we were jumping up and down talking about how we’d fund next week).

Ours was only a moderate case. We did not get millions of viewers (or even tens of thousands) but I can only imagine what that must be like.

The lesson learned? Take each day as it comes, try not to set expectations except when they’re useful for making decisions, and don’t get too attached to what’s happening today because it most likely won’t last. Keep to the work and make better things because you love doing it.

Pixel Blocks

Back in the early days of Block Party, Ben took a bunch of the small cubes we’d acquired to turn into minis and painted them single colors, calling them pixel blocks. Being me, obsessed with only the thing at hand (Block Party) and unwilling to dedicate cycles to think about things not directly relating to it, I dismissed pixel blocks as something Ben’s artistic side fancied and not much more (bad job at input, past self!).

Yesterday I began thinking of games that could be played with less information than complete block party glyphs, and possibly result in an easier manufacturing process as well. Attached are pictures of the first prototype which features 28 cubes and 3 colors where each cube has a unique distribution of colors (and this is all of the distributions over 3 colors and 6 faces–check the math for yourself!).  Not entirely sure about gameplay yet since 28 cubes is a little small and 3 colors is really minimal on information, but there are no doubt some fun solitaire puzzles with these pieces. The set with 4 colors might be more interesting, though iirc it requires 84 cubes to be complete, and I didn’t feel like painting that many by hand. Perhaps another day.

Moral of this story? Listen to your partner and take time to have thoughts that are outside of the narrow box that might be your primary line of inquiry.

image image image

A First Look: Unity and Shaders

I’ve been hearing about Unity for some time and I figured I’d finally check it out. The big takeaway from today: it is a monstrous piece of software and I have a lot to learn. It’s really powerful though, so that’s neat.

I also decided to take my first dip into shaders given that unity makes it really easy to bind shaders to objects. So I read through a tutorial and looked at the math here to produce the following images (they’re animated as in the link above). These are all being done in a shader which is running on the gpu.

Screen Shot 2014-02-19 at 5.18.29 PM Screen Shot 2014-02-19 at 5.32.54 PM Screen Shot 2014-02-19 at 5.35.03 PM Screen Shot 2014-02-19 at 5.38.48 PMScreen Shot 2014-02-19 at 6.16.38 PM Screen Shot 2014-02-19 at 6.22.21 PM

 

For those interested in the shader, the short version (image 1 above) is below. It could probably be optimized a bit.

float wave0 = sin(i.uv.x*300+_Time.y*.5);
float wave1 = sin((i.uv.x*.90096886+i.uv.y*.4338837)*300+_Time.y*.5);
float wave2 = sin((i.uv.x*.62348980185+i.uv.y*.78183148)*300+_Time.y*.5);
float wave3 = sin((i.uv.x*.22252093395+i.uv.y*.97492791218)*300+_Time.y*.5);
float wave4 = sin((i.uv.y*.97492791218-i.uv.x*.22252093395)*300+_Time.y*.5);
float wave5 = sin((i.uv.y*.78183148246-i.uv.x*.62348980185)*300+_Time.y*.5);
float wave6 = sin((i.uv.y*.43388373911-i.uv.x*.9009688679)*300+_Time.y*.5);
float z = 1.0/(1.0+exp(-1.0*(wave0+wave1+wave2+wave3+wave4+wave5+wave6)*2));
return float4(z,z,z,1.0);

Iris: Revelations and HQN

A video to start!

Today was an  exciting day for Iris. Previously we’d made the ripples (as you can see here) circular rings which faded as they emanated outward. This was okay, and it served well enough as an indication of where the ripples were, but we weren’t moved. They were just sub-par, and I had tried to address it a few times by using masks to reduce the aliasing, but it just wasn’t quite good enough. They didn’t allow blending, they weren’t very expressive, and they didn’t look all that great. So today I went and completely rewrote how the ripples functioned and went in favor of a representation which would allow some more flexibility. Originally I was trying to put them on a grid and go for a cellular automata style, but quickly found the number of operations to be too cumbersome to be executing every frame1. Screen Shot 2014-02-03 at 4.44.14 PM I quickly took the approach to iterate over theta and position objects (squares initially) around the circle periodically, which results in the image to the right. This was all right, except as they move outward the representation of the circle gets sparser, which can make it a bit difficult to tell where it is. The solution here is to start rotating the squares, so that at each successive radius they’re being offset a little bit. This leads to the following: Screen Shot 2014-02-03 at 4.48.52 PM Not too shabby. I hit a couple of performance blockages when trying to go for finer resolutions and long fading animations, but those were fixed readily enough by basically killing the squares off on the next frame and persisting them in the ghost images taken of the entire ripple group snapshot.  Given that it’s technically feasible to use this style of ripple, I began wondering what we could achieve with it. Here are a few results from some experiments

Screen Shot 2014-02-03 at 4.54.14 PM Screen Shot 2014-02-03 at 4.56.39 PM Screen Shot 2014-02-03 at 4.58.25 PM

First you’ll see first a sinusoidal modulation in size, giving the sensation that the ripple is pulsing along with it’s growth or visualizing a wave traveling away from the source.

Next up we have circles instead of squares, and the rotation here isn’t quite as standard. It actually rotates them at each step proportional to the square of the radius (whereas the previous samples have linear relationships between angular offset and radius).

Finally there’s using random noise to determine the offset, except this noise is very well behaved. In fact, for each circle there’s a random sign that gets chosen (at each frame) of whether to rotate it CW or CCW by an amount linearly proportional to the radius. Thus it has something like a random interleaving of both CW and CCW spins of the red square sample above.

This is just the beginning of what can be done with this new ripple generation. Various blend modes are available now (and can be chosen at will), and the space of positioning is wide open for exploration. Hopefully this development will help give each of the colors something of their own personality, as well as adding to the aesthetic ceiling of the game (with infinite variations). I’m also excited to see it help immerse players in what is happening aesthetically rather than them keeping focused on getting to the next level.

1. Iterating over a grid of any fine enough resolution is fairly intensive–you can instead just check within the frame which is the square of side length 2r minus the inner square of side length 2r/sqrt(2) given that they circumsribe/inscribe the circle, but it can only do so much and there’s still a lot of useless computation

Iris: Persistence is Key

What started out as a simple sketch a few weeks ago has become our full-time efforts at Three Pixel Heart, and will ultimately lead to our first paid release on the app stores. Currently we’re calling it Iris, and it’s an ambient audiovisual puzzle game based on rhythm, spatial reasoning, and (attempts to) feature a wabi-sabi aesthetic.  Here are a couple screenshots, busy and sparse

Screen Shot 2014-01-28 at 5.48.59 PM Screen Shot 2014-01-28 at 2.54.57 PM

 

The basic mechanic of the game is the player sends out ripples from the enso by tapping, and attempts to fill all squares and triangles with their own color. Additional objects such as color changing circles (featured in the second picture) and amplifiers, as well as different types of movement, add to the complexity of the puzzles. But here I want to talk less about the game itself and more about the creation of it.

Takeaway lessons so far:

  • PERSISTENCE IS KEY. Making a game has ups and downs. Most notably the ups when initially prototyping and realizing something can be fun, downs when getting blocked on technical details or how to expand content (take a break, go for a walk, let your mind off it), and further ups when after making changes you find out they’re improvements by how players enjoy it much more in playtesting. Keep your mental life varied (have other projects, think about different games, keep playing other people’s games) while also putting in substantial work on the current game, and it should pay off.
  • When something confuses players and isn’t meant to, try to change it visually/through audio before adding help text (in Iris that meant changing the goals, which were originally circles, to squares and triangles–it helped a ton! In retrospect making everything circles was idiotic)
  • People like easy puzzles when they are aesthetically rewarding. I have a habit of cutting to the difficult things too quickly and experienced a backlash in the playtesting by watching players get confused. After expanding the difficulty curve out, and even throwing in some extra levels which I thought were trivial and boring, we saw the players enjoy the game more and not get lost when the harder levels came about because they had some time to adjust their minds to the mechanics.
  • Level design is much easier through a physical medium that you can move around to get different senses of what’s possible. Trying to see it all in your head all the time is an extra constraint that should be avoided when attempting to build better levels.
  • Masking objects in corona sdk is terrible (this is a technical point but it’s caused such duress that I feel like including it for anyone who ever uses corona and considers masks–be warned)
  • Listen to playtesters. Keep listening to them even when they tell you things you don’t like.

Thinking of something I didn’t cover? Let me know what I missed!

Games of the Day

I found these two on the Indie Game Enthusiast iOS spotlight section, and how they deserve to be there! If there were a theme here I’d say… games strongly featuring circles! Or, you know, pure mechanics games with simple geometry for visuals, well designed sounds, and properly implemented touch controls. I played them both and they’re great!

Here’s a trailer for Blek, a delightful puzzle game with a unique mechanic

And here’s one for Duet

Game Twik Tuesday

The category for today is: Limited Perception! That means the information you get from the game are going to be more limited than you’d experience in real life. Imagine being an ant, imagine being blind. We have a couple games ideas for you.

  • Zombie Ant (or Ophiocordyceps unilateralis): you control an ant moving around, visualizing the trails of your comrades and enemies as a wavy colorscape immediately in front of you. Avoiding predators and picking up sugar to fuel your journey, you pilot your ant ever higher into the canopy before releasing your spores to infect the next host.
  • Pedestrian Yield: you open the game to hear cars zooming by on either side. An image comes up on the black screen demonstrating that you hold down to move forward. You wait until it sounds clear. You start walking, footsteps fall. You keep walking. The sound of a car comes faster from one side. Is it in front of you, or in your lane? Screeching tires and a thud ring in your ears before the game pauses and resets. Get to the other side and you will learn about how you got here, why you can’t see, and why, of all things, you must cross this busy road to find out more.
  • The Deep: you are deep underwater. Everything is dark, foggy patches of unfocused shades of gray. Water noises surround you with the occasional calls of creatures you can’t name. After a while you will start gasping for air, which you’ll find along your travels in tiny bright patches, but never enough for you to feel comfortable. Avoiding the more dangerous shadows lurking on your sides you must press onward for more oxygen, wondering always when it will end. It won’t.

That’s all for today!