Archive for the Category Programming

 
 

An Application for Creating Novel Escher-like Tessellations of the Plane

Over the past several weeks I have been investigating desktop applications for creating novel Escher-like tilings of the plane. Basically I’ve determined that none of what is publicly available is useful to me. The game I have in development will involve an animated Escher-like tessellation of a double logarithmic spiral — see here. The “logarithmic spiral” part of it means the publicly available applications can’t help me: they are too limited in what they will do and I can’t extend them because they are proprietary, so I have created my own tool.

These applications are “too limited” in the sense that none encompass everything possible that one would regard as a 2D tessellation. You have some applications that simplistically shoehorn you into a few kinds of geometries ignoring the richness of the whole domain of tiled patterns. You have other applications that try to take the domain seriously and follow the mathematical literature on the subject. What this means, generally, is that they allow the user to construct a tessellation in terms of its “wallpaper group” which is the mathematical classification of a plane pattern based on the symmetries the pattern admits.

The latter seems like what one would want but in practice it isn’t, at least it is not what I want. It is too heavy of a constraint to work only in terms of wallpaper group because there are all kinds of patterns one might be interested in that fall outside of this formalism: Escher’s tessellations of the Poincare disk model of the hyperbolic plane, for example, or, say, any kind of aperiodic tiling or any tessellations that admit similarity as a symmetry, i.e. scaling, such as Escher’s square limit etchings, or my case: various spiral patterns.

It is instructive that Escher himself did not work in terms of symmetry groups. He created his own classification system which Doris Schattschneider refers to as Escher’s “layman’s theory” of tilings in her book Visions of Symmetry (the authoritative text on Escher’s tessellations). Escher’s classification system comes from a pragmatic perspective rather than a formal mathematical perspective. He starts with basic cells — a square, a rectangle, an isosceles right triangle, etc. — and then enumerates the ways in which one can surround the cell with itself that result in tilings of the plane. There is a good overview of his system here.

What I like about Escher’s approach is that it is geared towards construction. When you try to make one of these things you start with a tile or some a small set of simple tiles that tile the plane. You try to modify them until you get something you like. I decided to implement software that captures that approach. I didn’t want to have to be too concerned with “wallpaper group” or other abstractions which I don’t personally find to be intuitive anyway.

What I came up with is the following application that is written in C#. Below is video in which I use the application to construct something like Escher’s butterfly tessellation — system IX-D in his layman’s theory — but on a double logarithmic spiral (This is going to be the basis for the art of the first level of my game; the butterflies will be animated, flapping their wings, etc.)

The way the application works is that there are two kinds of tiles: normal tiles and tile references. Normal tiles are composed of “sides”. There are two kinds of sides: normal sides and side references. Tile references and side references point to a another tile or side and say basically, “I am just like that tile or side, except apply this transformation to me”. The transformations that tile references can apply to a tile are defined in terms of affine transformation matrices. The transformations that side references can apply are just two kinds of flipping relative to the sides’ end points, either flipping “horizontally” or flipping “vertically” or both. The application then allows the user to add and move vertices on any sides that are on tiles that are marked as editable and then resolves all the references in real-time.

Right now, all of the information about tiles and sides and which is a reference to which has to be hand coded as an XML file, which is a pain (for the above I wrote a separate Python program that generated the XML defining a double logarithmic spiral of tiles that interact with each other according to Escher’s IX-D system), but it is an extremely flexible formulation (it could, for example, handle hyperbolic tessellations in theory … if you added a kind of side that is a circular arc and moebius transformations to the set of transformations the applications knows how to apply to referenced tiles).

Eventually I’d like to release this application  as open source but I am not sure it will be useful to anyone but me in its current form. I need to incorporate the part that one has to hand code in XML into the actual GUI … fix bugs and bezier curves and so forth, but please feel free to contact me if you are interested in the application in its current state or otherwise.

What I am working on…

I’m working on a puzzle game for iPads that takes the mechanics of a somewhat obscure game from the 1990s(*) and puts them on a double logarithmic spiral.

The final app will be styled similar to one of M. C. Escher’s tessellations of the plane with the tessellation changing at level breaks. I don’t have a name yet…

Gameplay will be like the following, which is video of a prototype I wrote in C# (just WinForms to the GDI, nothing fancy). I’m going to write the real thing in Swift using Sprite Kit, unless Swift turns out to be too immature in which case I’ll use C++ and Cocos2d-x again.

*: The identity of which I leave as an exercise for the reader.

Discretely Distributed Random Numbers in C#

Random numbers generated from a discrete distribution are a commonly needed thing in game development.

By “discrete distribution” we just mean the roll you get from something like an unfair die, e.g. you want a random number from 0 to 5 but you want 4 and 5 to be twice as likely as 0, 1, 2, or 3. If we think of each possible random value as having a weight, in this case 0, 1, 2, and 3 would have a weight of 1 and 4 and 5 would have a weight of 2.

A simple way to generate these kinds of random values is the following. Given some n such that we want random values ranging from 0 to n-1 where for each 0 ≤ i < n we have a weight w(i):

  1. Build a data structure mapping cumulative weight to each value i. By cumulative weight we mean for each i the sum of w(0), … , w(i-1).
  2. Generate a random number r from 0 to W-1 inclusive where W is the total weight i.e. the sum of w(i) for all i.
  3. If r is a cumulative weight in our data structure return the value associated with it; otherwise, find the value v that is the first item in the data structure that has a cumulative weight greater than r and return v-1.

Obviously the data structure in the above could just be an unordered array but a better way to do it is to use a binary search tree because 3. will then be O(log n) rather than linear. In Java you can do this with a TreeMap. In C++ you can do this with an std::map (or in C++ you can do the whole thing with boost::random::discrete_distribution).

However, in C# you can’t just use a SortedDictionary, which is a binary search tree under the hood. You can’t use a SortedDictionary because it does not expose the equivalent of C++’s std::lower_bound and std::upper_bound or the equivalient of Java’s TreeMap.floorEntry(…) and TreeMap.ceilingEntry(…). In order to perform the “otherwise” part of 3. above you need to efficiently be able to find the spot in the data structure where a key would go if it was in the data structure when it is in fact not in the data structure. There is no efficient way to do this with a SortedDictionary.

However, C#’s List does support a BinarySearch method that will return the bitwise complement of the index of the next element that is larger than the item you searched for so you can use that. The downside of the above is that there will be no way to efficiently add or remove items to the discrete distribution, but often you don’t need this functionality anyway and the code to do the whole algorithm is very concise:

class DiscreteDistributionRnd
    {
        private List<int> m_accumulatedWeights;
        private int m_totalWeight;
        private Random m_rnd;

        public DiscreteDistributionRnd(IEnumerable<int> weights, Random rnd = null)
        {
            int accumulator = 0;
            m_accumulatedWeights = weights.Select(
                (int prob) => {
                    int output = accumulator;
                    accumulator += prob;
                    return output;
                }
            ).ToList();

            m_totalWeight = accumulator;
            m_rnd = (rnd != null) ? rnd : new Random();
        }

        public DiscreteDistributionRnd(Random rnd, params int[] weights) : 
            this(weights, rnd) { }

        public DiscreteDistributionRnd(params int[] weights) : 
            this(weights, null) { }

        public int Next()
        {
            int index = m_accumulatedWeights.BinarySearch(m_rnd.Next(m_totalWeight));
            return (index >= 0) ? index : ~index - 1;
        }
    }

where usage would be like the following:

            DiscreteDistributionRnd rnd = new DiscreteDistributionRnd(3,1,2,6);
            int[] ary = new int[4] {0,0,0,0};
            for (int i = 0; i < 100000; i++)
                ary[rnd.Next()]++;
            System.Diagnostics.Debug.WriteLine(
                "0 => {0}, 1 => {1}, 2 => {2}, 3 => {3}",
                (float)(ary[0] / 100000.0),
                (float)(ary[1] / 100000.0),
                (float)(ary[2] / 100000.0),
                (float)(ary[3] / 100000.0)
            );

Cocos2d-x + Box2d Breakout Updated

Cocos2d-x releases since version 3 have broken compatibility with old tutorials. This can especially be a problem when you want to do something slightly non-standard from the point-of-view of Cocos2d-x.

If you want to use physics in a Cocos2d-x game the current standard way to do this is to use the integrated physics classes, which are Chipmunk-based by default and can use Box2d too in some hybrid way the details of which are not at all clear. However,  in my case I want to use Box2d, period, Box2d in a non-integrated manner for transparency and in order to leverage the vast amount of code that you get to peruse and possibly use by writing to vanilla Box2d. When doing something like this it can be hard to know where to start given that any sample code you find will be broken.

For setting up a Box2d/Cocos2d-x project there was always this BreakOut implementation to Cocos2d-iphone by Ray Wenderlich, link, which is transliterated into Cocos2d-x here but to relatively ancient versions of both Box2D and Cocos2d-x. I’ve taken that code and updated it to Cocos2d-x version 3.2 and Box2d version 2.3.

Here is my updated version.

To use do the following:

  1. Setup a cocos2d-x v3.2 project via the python script. This will give you Box2d v2.3 set up in your project without you having to do anything else.
  2. Copy the source code in the above zip file into your project’s Classes directory.
  3. Copy the image files the Ball.jpg, Block.jpg, and Paddle.jpg from here into your project’s Resources directory.
  4. Build.

(You can copy over the music/sound files too. I have the relevant calls commented out in the code above)

Zzazzy 1.0.0

My iPad game Zzazzy has made it through the review process and is now on the App Store: see here.

So that took a little longer than I had intended …

I will be updating the page I have for it here this week with more detailed instructions than what the app itself provides (There is a tutorial mode but it really just covers the basics), but basically it is an action puzzle game in which you lay tiles on a board to form interlocking words, but you’re building words against the clock where

  • forming large grids of words puts time back on the clock
  • not using tiles eventually leads to tile death which takes time off the clock.

It’s a continuous play type of game, like Tetris or something, but with a completely new game mechanic.

Snurtle and My Greatest Contribution to Mathematics, Such That It Was

This summer coming up will be 20 years since the summer after I graduated from college. I’m currently in that golden period in between software jobs — starting a new one in March — and, given the free time, have just done something which I have been meaning to do since that summer.

I generated the following image in a non-ad hoc manner, with re-useable software that I developed myself.

That year after college I was kind of shiftless. I chose to just not participate in the whole interview circus that normally accompanies one’s senior year of MIT and let myself graduate without having plans of any kind for the future. I think that I was tired mostly and was kind of sick of the universe of engineering and all of its hurdles and dog and pony shows, and I think I kind of half-understood that this would be the last time in my life in which it would be possible for me to be totally free of that universe — until, I guess, retirement.

Anyway, I lived in the slums of Boston — that is, Roxbury — with a friend of mine from high school and some roommates we found, one of whom ended going to jail (but that is another story), worked temp jobs, and didn’t do much of anything … except for some reason I became obsessed with aperiodic tilings of the plane and substitution tilings generally and put a lot of effort into coming up with one of my own. I wanted to find, for reasons that aren’t clear to me now, an aperiodic analog of the normal regular hexagon tiling.

It’s kind of a blur — I don’t really remember where the above came from as a sequence of steps — but the above is a patch of the best tiling I discovered during this period. It is generated via the following substitutions. The lengths of the sides of triangles and trapezoids are multiples of ϕ, the golden ratio.

As far as I know, the above is original and has not been discussed in the literature but I never was able to come up with local matching rules on the hexagons to enforce aperiodicity.

At that time I did develop software for working on these sorts of structures but what I came up with in retrospect wasn’t The Right Thing. This wasn’t all together my fault. Those were different times: no GitHub, no free code. If I wanted to output into a vector format it would have to be my own vector format. If I wanted to render that format to the screen I would have to write code to render that vector format to the screen, and so on. Also GUI applications were all the rage and were still new and shiny, so I was biased in that direction. I never really liked what I came up with then, and it wasn’t portable anyway; it was a black-and-white Macintosh application in C.

Having the negative example of that project all those years ago made it easy to see what I actually needed: not a GUI application but a programming language. So last week, I wrote one: a little language for specifying recursive structures like the above and rendering them in SVG. I’m calling it Snurtle because it is basically a combination of Python (a snake) and the turtle-based graphics of Logo. I chose Python syntax because I wrote the Snurtle interpreter in Python and thus got tokenization for free using Python’s “tokenize” module.

So, for example, the following simple substitution

is represented by the following Snurtle script:

sub square(n):
    terminal:
        poly("bisque", "orangered", 1 ):
            forward(n)
            turn(PI/2)
            forward(n)
            turn(PI/2)
            forward(n)
    nonterminal:
        rectangle(n)
        branch:
            turn(PI)
            forward(n/2)
            turn(-PI/2)
            forward(n/2)
            square(n/2)
            square(n/2)

sub rectangle(n):
    terminal:
        poly("lightskyblue", "orangered", 1 ):
            forward(n/2)
            turn(PI/2)
            forward(n)
            turn(PI/2)
            forward(n/2)
    nonterminal:
        square(n/2)
        turn(PI)
        square(n/2)

yielding

which, I think, is self-explanatory except for the “branch” block. Branch blocks tell Snurtle to push the state of the turtle on to a stack and then pop it when exiting the branch i.e. branch works like parentheses operators in L-systems. Also the following Snurtle constructs are not illustrated in the above:

  • flip blocks: similar in syntax to branch above. Tell Snurtle to multiply the angle arguments passed to turn statements by -1. (i.e. flipping them)
  • stroke and fill blocks: similar to “poly” above.

Anyway, here is my snurtle source code. Usage to generate the above would be:

snurtle.py -w -s square -k 500 -m 8 -o squares.html -c “10,10” “snurtle_scripts\squares.snu

where

  • -w : wrap the generated SVG in HTML (so it can be viewed in browser)
  • -s : initital substitution used to kick off the recursion
  • -k : scale factor in SVG output
  • -m : max stack depth before substituting in terminal blocks rather than nonterminal and ending the recursion
  • -o : output filename
  • c : starting coordinate of the turtle.
  • -d : Comma delimited string as -c, that provides width and height attributes for the SVG. (not shown)

Snurtle is pretty rough at this point, but I plan to continue working on it, especially if there is interest. Check back here, The Curiously Recurring Gimlet Pattern, for updates — or on this Quora blog which I will try to keep in sync — if you are interested. In particular, I plan on adding the following features / dealing with the following issues:

  • Substitutions can’t currently have more than one argument. I just never got around to adding this functionality as I never had a use-case in all the sample scripts I have tried, but there is no reason to limit “sub” blocks in this way.
  • Color, stroke color, and stroke thickness parameters to poly, stroke and fill blocks should be optional with intelligent defaults but aren’t currently.
  • Maybe add a z-order parameter to poly, stroke, and fill.
  • Add variables.
  • Possibly add “mirror” blocks which would be syntactic sugar for executing the block’s body in a flipped branch and then executing it again normally. This would be handy in definitions of complicated structures like my golden hexagon substitution.
  • Add “reverse” blocks which would cause the statements in a block to be executed in last to first order, recursively running compound statements this way too.
  • Add some kind of loop control structure, “repeat” or something.
  • Built-in system variables for (like “PI” above) for current stack depth and max stack depth.
  • Add exponentiation to the set of operations that can be performed in expressions.

New Zzazzy screenshot

Here is what the game is looking like currently (click for fullscreen):
screenshot

The World’s Simplest 2D Curve Library

For the game I’m working on I need to have sprites that travel along curving paths.

I’m talking about the sprites traveling along somewhat arbitrary curves, meaning curves that look good, not curves that result from gravity or other physical forces. If you need those kinds of curves, e.g. the parabolic trajectories of cannonballs, you need to simulate the forces acting on the sprites and that is not what I’m talking about in this post.

Caveat aside, an arbitrary curving path is a pretty common thing to need but I think is unnecessarily headache-inducing because curves in graphics are just confusing. Maybe you’ve found yourself thinking

  • I don’t know what the difference between a spline, a bezier curve, a bezier curve of various degrees, a B-spline, a t-spline, etc. is.
  • I don’t know which of the things mentioned above I need.
  • Every time I try read the wikipedia article on these things the math gets heavy and my eyes glaze over

etc.?

So assuming it’s not just me, as a public service I’m going to try to clear this up.

Short version, if you need to have a sprite that travels along a curving path from point A to point B in x amount of time, you probably need a cubic bezier curve and generally, in 2d game programming, all you will ever need probably is n cubic bezier curves possibly concatenated together. You can concatenate them yourself if you need to do that, so what you need is a way to define a cubic bezier and a function get the point along the bezier at some time t. Despite what you would think from trying read the literature, this turns out to be trivial — I mean less than a dozen lines of code.

More thoroughly, explaining away my bulleted list above:

  • A spline is a more general term than a “bezier curve”: a bezier curve is a particular polynomial function (that I will implement below) that defines a curve that goes from point A to point B given some control points. A bezier spline is an aggregation of n of these. A general spline can be an aggregation of other kinds curves e.g. a B-spline is composed of a bunch of curves that are generalizations of bezier curves.
  • The only kinds of beziers you need to be concerned with are quadratic and cubic beziers. Quadratic beziers are just parabolas and are not interesting. Cubic beziers are curves that go from point A to point B and are tangent to a given line at A and tangent to given line at B. They are defined by A and B plus two other control points that define the tangent lines and the weight they have on the curve.
  • Cubic bezier curves are easy to implement. See below.

So here is my curve “library”:
Bezier.h

#include &lt;utility&gt;

class Bezier {
	private:
		float x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_;
	public:
		Bezier(float x1, float  y1, float x2, float y2, float x3, float y3, float x4, float y4);
		std::pair&lt;float,float&gt; getPoint(float t) const;
};

Bezier.cpp

#include &quot;Bezier.h&quot;

Bezier::Bezier(float x1, float  y1, float x2, float y2, float x3, float y3, float x4, float y4) :
		x1_(x1), y1_(y1),
		x2_(x2), y2_(y2),
		x3_(x3), y3_(y3),
		x4_(x4), y4_(y4) {
}

std::pair&lt;float,float&gt; Bezier::getPoint(float t) const {
	float x = (x1_+t*(-x1_*3+t*(3*x1_ - x1_*t))) + t*(3*x2_+t*(-6*x2_ + x2_*3*t)) + t*t*(x3_*3-x3_*3*t) + x4_*t*t*t;
	float y = (y1_+t*(-y1_*3+t*(3*y1_ - y1_*t))) + t*(3*y2_+t*(-6*y2_ + y2_*3*t)) + t*t*(y3_*3-y3_*3*t) + y4_*t*t*t;
	return std::pair&lt;float,float&gt;(x,y);
}

You define a cubic bezier by making a Bezier object giving the constructor four points. (x1,y1) and (x4,y4) will be the start and end of the curve. The curve will be tangent to line segment (x1,y1)-(x2,y2) at its start and tangent to (x3,y3)-(x4,y4) at the end. To get a point along the curve call getPoint(t) where t=0.0 gives you (x1,y1), t=1.0 gives you (x4,y4), and 0.0 < t < 1.0 gives you the point along the curve in which 100t percent of the curve has been traversed e.g. 0.5 is halfway.

So that’s it. Code is here. I also included a Win32 GDI project that draws cubic beziers, screenshot below. (The sample program is also a little example of how to write a very basic Win32 program, which these days younger programmers seem to appreciate as a sort of parlor trick…)

Syzygy Update

So, looking at the early entries of this blog, I must have started working on Syzygy around the beginning of the year 2012 because by March 2012 I had the Win32 prototype done. At that time, I didn’t own a Macintosh, didn’t own an iOS device, had never heard of cocos2d-x, and, professionally-wise, was still writing image processing code for Charles River Labs / SPC. Since then SPC was killed, and I moved from Seattle to Los Angeles … but anyway as of today, about a year later, I have the primary functionality of Syzygy running on my iPad, re-using the source code, mostly, from that prototype. I haven’t really been working on it the whole time — there was a lot of moving-to-California in there somewhere, but here’s a screenshot (click for full-size):

There’s a common question in the mobile games forum of gamedev.net, “How can I make a game for iOS only using Windows?”. The answer to this is either (1) you can’t or (2) write your game to Marmalade or cocos2d-x on Windows and then when you are done get a friend with a Mac to let you register as an Apple developer, build under Xcode, and submit to the App store. I always say (1) is the serious answer and if you are unserious, or want to develop a really simple game, then go with (2). Basically I say this because you need to run your game on a device frequently and early, and I’m seeing the truth to this now.

Now that I have Syzygy running on a device I’m seeing issues with input which are artifacts of running on an iPad. The prototype implemented mouse input as a stand-in for touch input. It turns out touch screens and mice aren’t the same thing. The game plays on the device, but when you drag tiles your finger is in the way of the tile visually. You can’t see the tile you are dragging — this seems like it wouldn’t be a big deal, but it kind of is. … This sort of thing is the reason, in my opinion, that if you are not testing on a device during primary development then you are not really serious…

So not sure what I’m going to do about this, I’m thinking of making the tile the user is dragging larger and offset to the upper-left while the user is dragging it. The problem with this is to make it look nice I’d have to have large versions of all the relevant art and some of it I don’t even really remember how I rendered in the first place…

Marble Madness Madness

gamedev.net recently linked to this video about the making of Marble Madness, which got me thinking about the raster-to-vector via contour extraction script I wrote in Python last year and the fact that, it being the future and all, I can probably find all of the art from Marble Madness unrolled into a single image file. So three clicks later and, oh yeah:

(Click the image for full size)

So I ran the above through my raster-to-vector converter. Here are the results (zipped, this is a huge file, over 20,000 SVG paths)  This file kills Adobe Illustrator. It took 15 minutes just to open it.

SVG for a single level is more manageable.  Here’s  the 2nd level as unzipped SVG … (curious to see if various browsers can handle this) Illustrator could handle this one pretty well so I experimented with applying various vector filters. Below is a bit of it with the corners rounded on the paths (click for a larger version):


Not sure what this all amounts to … just some stuff I did today. However I did learn

  • Python is slow. It took a really long time to generate the big file, seemed too long. I think C++ would’ve been like an order of magnitude faster — that’s my intuition anyway.
  • My contour extraction program really works which is kind of surprising — I thought for sure running it on something like this would crash it. (It does still have the problem that it can’t handle paletted raster image formats, but that’s the only bug I encountered)