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.

Points of Pride

There’s this big black dog hanging around in the village of my mind. He’s probably always been there. I don’t always notice him. I notice him something fierce though, when he’s hungry. Now Hubris, he’ll stake your flank, tear it off and eat it raw. Leave you a gapping hole in your ego.I’m pretty sure he doesn’t make himself to obvious, gives me some rope, so to speak. Gives me enough space to get fat, get juicy. Then, well, he sinks his teeth in. It’d be arrogant to think he’s only feeding on the flesh of my ego. I do though. I do think that. Oh, Hubris. Maybe you’ve met.

We are at a point where we have no direction.  We’re isolated. Unsure. Regretful. Barely able to look at the long list of failures. So we started keeping score of our pride points. (A pretty useful method when looking at painful truth. No sugar coating or counter points are needed, cuz, well, WE SCORED POINTS! Here’s what we found:

Let’s start a company without doing any research on the space or startups in general! (Avoiding feeling small, insignificant, and likely to fail; firmly placing my flag at the summit of a delusional mountain) Pride 2, 3pxh 0

Let’s think that we are the BEST and not shatter that conception by walking on eggshells around each other!  Pride 4, 3pxh 0

We’re too good for income. Hint: steady income is a bit of stability. A bit of stability is wonderful to holdback the creeping void. Pride 6, 3pxh 0
I don’t need a job, I’VE GOT A STARTUP! Hint: you do need a job, and it might be a hobby. Pride 8, 3pxh 0
I can be awesome without trying! Taking care of myself? That’s what people that are not great have to do. Hint: this is not facts.  Pride 10, 3pxh 0
Advice? Pffffffffuck that. I’ma do something UNIQUE! Pride 12, 3pxh 0
Investors? Why do we need investors?!??!! Hint: it’s not mostly about the money. Pride 14, 3pxh 0
I think I’ll wait for someone to notice me and roll out a nice carpet for me. Hint: what?!?! GET HUSTLING. Pride 16, 3pxh 0
If we’re not the best, we are nothing. Not the best? Better cry about it a little. Pride 18, 3pxh 0
Sure, people have been playing games for THE WHOLE TIME, and the industry is decades or centuries old. But fuck that. We’re great and don’t need to pay attention to all that noise. Hint: at least acknowledge it. Really though.  Pride 20, 3pxh 0
“Selling Out” Pride 22, 3pxh 0

Now alpha pride; that’s your best bestie. Your bestie’s got your back. Your bestie let’s you know. Let’s you know that you can do it, motherfucker. You can keep running. You can survive sharing something incomplete. That you can overcome anything. That you gotta do your work. Your bestie will let you know: you did that great. Now keep going. 

That’s the pride we want to celebrate going forward.

I published this post. Is it perfect? Ahahha no. But it’s done. And for someone who often hoards data locally, waiting for it to be perfect, waiting to emerge full fledged and brilliant, I say, I’ve got a long way to go in expressing myself. And: I did this great.

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

Harder than expected. Completed

IMG_1237

At least 4 times I wasn’t going to finish my work tonight. “Make 4 sets, document them, and blog about it with next steps.”
“It looks shitty.”
“the process is fucked, I need to start over with a better process”.
“I’m tired.”
“What about tomorrow. I’ll wake up early tomorrow, jog over here, and knock ’em down!”
“UNPLAYABLE. USELESS KNAVE!!”
Ok, so at least 5 times. It happened less when the music was on, and good.
I even put all the things away once. Then I was like: hell no. You need to train yourself to finish. Even when you don’t want to.

Especially when you don’t want to.

This framing made the tomorrow option infeasable.
It clarified the job: complete the production at some quality. It was not: solve the production process from seed to game table

IMG_1234

I’m quite curious to see how playing classic with these blocks is. There is a lot more noise and the pix have a lot more personality. I wish that the symbols were on straighter and closer to the edge.

Challenges:  Switching color paint with each symbol. No running water. Searching for pix (reduced by placing stamps on the pix map). The paint got tackier and tackier as the night wore on. This was a major contributor to the added time and the in-my-opinion lower quality stamping.

Next steps: Make instructions. Sell them at the farmers market. Make a stamp + pad and make more.

The end

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);

Just a first post. Nothing special.

Photoshop teaches us the way fecundity, of mass production of seeds with expected flowers in the few range. But it’s not waste. All the seeds that don’t make it to flower-hood. Some of the seeds feed the birds. Some distract the monkey, get him off our back for a night. Some of the seed sprout, die, and fertilize something yet undreamed. I might have broken my metaphor. So be it.

This is a study for Iris [working title]

 

b

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