Last Login:
September 01, 2015


User Profile

Hits: 59,260
Joined April 08, 2010
Examples (2)
Favorite Users

Tile-Based Discrete Wavefront Propagation
Posted on December 03, 2013 at 03:03

Originally posted on my blog. It involves math and code, so a lot of formatting has been lost on the bastardized 64digits version.


I'm currently building a very simplistic first-person shooter in WebGL. An example of this algorithm, with the debug code left in, is available here. The map is represented by a grid - a cell is solid if its 0, and empty if its 1. This is trivial to render by using a standard recursive 4-direction flood fill algorithm. Unfortunately, using WebGL without compiling to asm.js from another language reduces the performance of my computer to a pile of junk from 2003, except that now all the API calls are 10 times as expensive. While my GPU is perfectly capable of bulk-rendering an entire map without breaking a sweat, WebGL starts choking the instant I try to make more than 50 or so draw calls. It's kind of pathetic, really.

Frustum culling is the obvious answer, but I need it to be highly efficient. This means adjusting the frustum to account for corners, so I only render the visible portions of the level. While a lot of the speed concerns I currently have can be alleviated using batch rendering, this will stop working the instant I put in details that can't be batch rendered. Consequently, I want the algorithm to be as close to perfect as possible, only rendering rooms that are visible and no others.

This is where Tile-Based Discrete Wavefront Propagation comes in. The central idea is to represent the viewing frustum as a wave that flows through the level, getting split up when it hits corners. If properly implemented, this will be exact, only rendering rooms that are visible and no others. It turns out that you can implement this in O(n) time, but we can't use the naïve recursive flood-fill anymore, because it's depth first. If we want to simulate a wave, we need to render the grid using a breadth-first search, to simulate it slowly spreading outward. Breadth first search is implemented using a queue by simply pushing all neighboring nodes on to the queue and rendering them until the queue is empty.

As the wave propagates through the level, we adjust the left and right angles of each individual wavefront according to the walls that we hit. This requires that we deal with two possible cases: the case where a wall is in front of the wave as it propagates through the level, and the case where it isn't. The only time the wave can actually be split up is when a wall is in front of it - the rest of the time, it is simply clipped on the sides. "Front" and "side" are defined based on what direction the wave came from.

Starting with the case where there isn't a wall in front, we check to see if there is a wall on the right. If there is, we check the angles of it's corners. If either angle is inside the culling frustum, we change the right-angle to the one that is "farthest inside" (done in code by simply checking each angle one after the other). Then we do the same for the left wall, this time changing the left-angle, if appropriate. Then we send the updated angles to the neighboring tiles - the left one gets (left-angle,new-right-angle), the front gets (new-left-angle,new-right-angle), and the right gets (new-left-angle,right-angle).

If there is a wall in front, everything stays the same (note that the front wall has it's own set of corners you must check), but the angles that get sent through the neighboring tiles change. The left wall gets (left-angle,new-left-angle), the front doesn't exist so we ignore it, and the right wall gets (new-right-angle,right-angle). This effectively splits the wave down the middle, but it makes things complicated. Before, if a new left-angle was outside the culling frustum, we would just set it to the old left-angle. This doesn't work anymore, because we're splitting the wave, which means we require a new left-angle that isn't equal to the old left-angle. To solve this, if the new left-angle fails to exist, we set it to the old right-angle instead of the old left-angle, and vice-versa for the new right-angle.

Conceptually, this isn't too complicated, but the actual implementation gets complicated very fast due to angles being a giant pain in the ass to work with. We have to seed the initial queue with the neighboring tiles, and deal with getting proper frustum culling working, which is far more difficult than it seems. This will require a sizable number of utility functions, so we'll look at those first:

Code: Javascript
function realmod(i,m) { i=(i%m); return i+((i<0)*m); } // Mathematically correct modulo
// Queue implementation using a circular array. Resize is very expensive, but almost never happens, because it remembers its size after each frame.
function Queue(sz) {
  this.array = new Array(!sz?1:sz);
  this.push = function() {
    for (var i = 0; i < arguments.length; i++) {
      if(this.length>=this.array.length) {
      this.array[this.cur] = arguments[i];
      this.length += 1;
  this.pop = function() { return this.get(--this.length); }
  this.peek = function() { return this.get(this.length-1); }
  this.get = function(i) { return this.array[this.modindex(i)]; }
  this.clear = function() { this.cur=-1; this.length=0; }
  this.resize = function(nsize) {
    var sz=this.array.length;
    var c = this.cur+1;
    for(var i=sz-c; (i--)>0;) {
  this.modindex = function(i) { return realmod(this.cur-i,this.array.length); }
function realfmod(x,m) { return x - Math.floor(x/m)*m } // Implements mathematically correct fmod
// Gets absolute distance between two angles
function getAngleDist(u,v) { return Math.PI - Math.abs((Math.abs(u - v)%(Math.PI*2)) - Math.PI); }
// Gets the signed distance between two angles
function getAngleDistSign(u,v) { return ((realfmod(v - u,Math.PI*2) + Math.PI)%(Math.PI*2)) - Math.PI; }
  function getdx(dir) { dir=((dir+4)%4); return (dir==0)-(dir==2); }
  function getdy(dir) { dir=((dir+4)%4); return (dir==1)-(dir==3); }
  function exists(x,y,m,w) { var i = x + (y*w); return x>=0 && x<w && i<m.length && (m[i]&1)!=0; }
  function exists_dir(x,y,m,w,dir) { return exists(x+getdx(dir),y+getdy(dir),m,w); }
  // Gets the angle of a point from the player's origin (which is the camera's origin)
  var getangle = function(x,y) { return Math.atan2(y-player[0].elements[2],x-player[0].elements[0]); }
  // Gets the angle of a corner, offset from the given point by dir and diri.
  var getangle_dir = function(x,y,dir,diri) { return getangle(x+getdx(dir)*5 + getdx(diri)*5,y+getdy(dir)*5 + getdy(diri)*5); }

First, the modulo operators in most programming languages are actually remainder operators. They do not perform mathematically correct modulo, and their behavior when you feed them negative numbers is not what you'd expect. The first thing we do, then, is define a modulo function that actually behaves like the modulo operator. We then use this to build a circular queue that resizes itself when necessary. When resizing, the queue must move all items to the right of the index over, which is a costly operation, so we let it keep it's size across frames. This makes the number of resize operations essentially zero.

The next few functions deal with angles. Angles are inherently circular, and this causes all sorts of problems. If our left-angle is 355°, and our right angle is 5°, the distance between these two angles is 10°, not 350°. There is a standard method to getting the absolute distance between two angles using the floating point modulo operator, which is implemented in getAngleDist(). This is all well and good, but we have defined left and right angles, which means we need to know if something is on the left hand side, or the right hand side. This requires a signed angular distance function, which makes things much more complicated because, once again, the floating point modulo operator is not actually modulo, it's a remainder.

So, we need to implement a proper floating point modulo operator. The standard fmod() function is implemented using the following formula:

fmod(n,d) = n - trunc(n/d)*d

It's trivial to change this formula into one that gives us the correct behavior (remember, truncation is not flooring!):

fmod(n,d) = n- floor(n/d)*d

We can use this to define a function such that, as long as b-a, when forced into the range [0,2π), is less than π (or 180°), we get a positive distance. If it goes past π, it becomes negative and heads back towards 0, just like in the absolute value distance function, but now with the proper sign. We will use this later to determine if a tile crosses over our angular culling frustum. getdx(),getdy(),exists(), and exists_dir() are all used to either bump x/y coordinates according to a direction, or determine if a specific tile exists. Now we get to the real function:

Code: Javascript
var roomq = new Queue(10); // queue holding nodes
var drawmap = function(x,y,m,w,langle,rangle) { // map drawing function
  var i = x + (y*w);
  // draw floor
  for(var j = 0; j < 4; ++j) { // Push initial neighbors on to the queue
    var nx=x+getdx(j);
    var ny=y+getdy(j);
    if(!exists(nx,ny,m,w)) { // If it doesn't exist, we ran off the edge of the map or hit a wall
      // draw wall
    } else {
  var dir=0; // Stores the direction the wave is going. 0: (+) x-axis, 1: (+) y-axis, 2: (-) x-axis, 3: (-) y-axis
  while(roomq.length>0) {
    x = roomq.pop();
    y = roomq.pop();
    langle = roomq.pop();
    rangle = roomq.pop();
    dir = roomq.pop();
    var i = x + (y*w);
    var room=m[i];
    if((room&2)==2) continue; // If true, we already visited this node
    var mid = [langle,getAngleDistSign(langle,rangle)/2];
    if(mid[1]<0) continue; // If this is less than 0, langle has cross over rangle, so there's nothing to render.
    var angles=[getAngleDistSign(getangle(x*10+5,y*10+5),mid[0]),
    if(angles[0]>mid[1] && angles[1]>mid[1] && angles[2]>mid[1] && angles[3]>mid[1]) continue;
    if(angles[0]<-mid[1] && angles[1]<-mid[1] && angles[2]<-mid[1] && angles[3]<-mid[1]) continue;
    if(Math.abs(angles[0])>Math.PI/2 && Math.abs(angles[1])>Math.PI/2 && Math.abs(angles[2])>Math.PI/2 && Math.abs(angles[3])>Math.PI/2) continue;
    m[i]=(m[i]|2); // Only mark as done if we actually render it. This let's us recover from inconsistencies.
    // Draw floor
    var nlangle=langle;
    var nrangle=rangle;
    var front = exists_dir(x,y,m,w,dir); // Is there a wall in front of us?
    var lwall = exists_dir(x,y,m,w,dir-1); // To the left?
    var rwall = exists_dir(x,y,m,w,dir+1); // To the right?
    if(!front || !lwall) { //left wall or front wall check
      if(getAngleDist(mid[0],nlangle)>mid[1]) nlangle=(!front)?rangle:langle;
    if(!lwall) { // This corner is only checked for left walls
      if(getAngleDist(mid[0],nlangle)>mid[1]) nlangle=langle;
    if(!front || !rwall) { //right wall or front wall check
      if(getAngleDist(mid[0],nrangle)>mid[1]) nrangle=(!front)?langle:rangle;
    if(!rwall) { // Only right wall
      if(getAngleDist(mid[0],nrangle)>mid[1]) nrangle=rangle;
    for(var j = dir-1; j <= dir+1; ++j) {
      var k = (j+4)%4; // get proper direction
      var nx=x+getdx(k);
      var ny=y+getdy(k);
      if(!exists(nx,ny,m,w)) { // We ran off the edge of the map or hit a nonexistent block
        // Draw wall
      } else {
        if(j==dir-1) { roomq.push(nx,ny,langle,(!front)?nlangle:nrangle,k); }
        else if(j==dir) { roomq.push(nx,ny,nlangle,nrangle,k); }
        else { roomq.push(nx,ny,(!front)?nrangle:nlangle,rangle,k); }
var reversefill = function(x,y,m,w) {
  var i = x + (y*w);
  if(x<0 || x>=w || i>=m.length) return;

First, we push our 4 neighboring tiles, provided they exist, on to the queue, seeding them with appropriate directions that radiate outward from our starting point. Then, we start running through the queue, and do an initial check to see if we already dealt with this tile. If not, we check to make sure that the left-angle is really less than the right-angle, and then go into standard frustum culling. In order to figure out if a tile is within our view, we need to ensure that the entire tile is either to the right or to the left of our angular viewing frustum. This means that all 4 corners must have angles outside of our frustum, and they must all be on the same side. If they are not on the same side, then the cone could have passed through the center.

This is what the first two if statements do. The problem is that a tile directly behind us will also be considered straddling the angular range, because our distance function wraps at 180°. To solve this, we have a third if statement that throws away everything that is more than 90° (or π/2) away from the center of our frustum. This means the maximum horizontal field-of-view is 180°. Note that this culling is independent of the algorithm, you'd be using this same logic if you were only doing simple frustum culling.

If the tile survived the culling function, we mark it as visited. It's important that we only mark a node as visited after we have decided to render it because of a very nasty edge-case that can happen during the breadth-first traversal. It's possible for a tile that is rendered on one side of a split frustum to reach a visible tile on the other side of the split, and erronously mark it as invisible, using it's own frustum. The tile actually is visible, but only to the frustum on the other side of the split.

Then, we check the appropriate corners and assign langle and rangle appropriately. The neighbors are iterated and new values passed as needed. Once this phase of the algorithm is completed, we call reversefill(), starting on the same tile we called drawmap() with. This will use the standard fill algorithm to reset the "visited" marks on the map. By doing this, we avoid having to set all 2500 nodes of a 50x50 map to 0. The algorithm is now complete.

Because this algorithm runs in O(n) time and is exact, it is asymptotically optimal. The problem is that it is only optimal in a single-threaded sense. The breadth-first iteration technique allows us to run each individual level concurrently, but this will only reduce the worst-case complexity from O(mn) to O(max(m,n)). 50 is a lot better than 2500, but this is only for a very, very large room. If we're dealing with a hallway, the concurrent performance would be identical to the single-threaded performance!

Consequently, while this is useful for tight corridors, the algorithm itself isn't really that useful outside of the game's narrow domain. Once the rooms start getting large enough, you're probably better off brute-forcing most of it and using approximations. However, the algorithm is exact, which is very important for calculating Enemy Line-of-Sight. So if you're dealing with a grid-based game and need to figure out if an enemy has a direct line of sight, this technique allows you to make a precise calculation, since it only hits tiles that are visible, and no others. This gives it an advantage over naïve raytracing, which requires many rays and is prone to giving false-negatives when dealing with narrow hallways.

Unfortunately, it still breaks when you try to make it work with FoV's greater than 180°, so unless you split them up into 90° chunks, it's pretty useless for things like lighting. I'm probably not the first to come up with the algorithm, either; someone probably invented this in their garage in 1982. Oh well.

Solar Noise - EP
Posted on December 08, 2012 at 01:12

My Solar Noise EP is now available for $3.99 on bandcamp, itunes, Google Play, Amazon MP3, and a bunch of other online stores I've never even heard of! It has 5 tracks - Solar Noise, Tidal Forces, and 3 alternate mixes, including a remix by my friend Apelsin, who is way better than me (and also mastered the album). Here is the track list:

1. Solar Noise (Original Mix)
2. Solar Noise (Club Mix)
3. Solar Noise (Apelsin Remix)
4. Tidal Forces (Original Mix)
5. Tidal Forces (Club Mix)

A full-length preview can be found on youtube, and you may preview each individual track on bandcamp before making a purchase. Note that bandcamp is the only website that I know for sure offers lossless versions of the tracks. If you are a DJ in charge of a radio station, send me a message either on twitter or by e-mail and I will give you a promo code to download the club mixes for free. If you are interested in a physical CD, tell me! If enough people are interested in CDs I can make a print run of them.

What Is A Right Answer?
Posted on August 23, 2012 at 02:14

I find that modern culture is often obsessed with a concept of wrongness. It is a tendency to paint things in a black and white fashion, as if there are simply wrong answers and right answers and nothing in-between. While I have seen this in every single imaginable discipline (including art and music, which is particularly disturbing), it is most obvious to me in the realm of programming.

When people aren't making astonishingly over-generalized statements like trying to say one programming language is better than another without context, we often try to find the "best" way to do something. The problem is that we don't often bother to think about exactly what makes the best answer the best answer. Does it have to be fast? If speed was the only thing that was important, we'd write everything in assembly. Does it have to be simple? I could list a thousand instances were simplicity fails to account for edge-cases that render the code useless. Does it have to be easy to understand? If you want something to be easy to understand, then the entire C standard library is one giant wrong answer that's being relied upon by virtually every single program in the entire world.

For a concept taken for granted by most programmers, defining what exactly makes an implementation "optimal" is incredibly difficult. A frightening number of programmers are also incapable of realizing this, and continue to hang on to basic assumptions that one would think should hold everywhere, when very few of them actually do. Things like "the program should not crash" seem reasonable, but what if you want to ensure that a safety feature crashed the program instead of corrupting the system?

The knee-jerk reaction to this is "Oh yeah, except for that." This phrase seems to underlie many of the schisms in the programming community. Virtually every single assumption that could be held by a programmer will be wrong somewhere. I regularly encounter programmers who think you should do something a specific way no matter what, until you ask them about making a kernel. "Oh yeah, except for that." Or a sound processing library. "Oh yeah, except for that." Or a rover on mars. Or a video decoder. Or a raytracer. Or a driver. Or a compiler. Or a robot. Or scientific computing.

All these except-for-that's betray the fundamental failure of modern programming culture: There is no right answer. The entire concept of Right and Wrong does not belong in programming, because you are trying to find your way to a solution and there are billions of ways to get there, and the one that works best for your particular situation depends on hundreds of thousands of independent variables. Yet, there is a "right answer" on Stack Overflow. There are books on writing "proper code". There are "best practices". People talk about programming solutions that are "more right" than others. There are black and white, right and wrong, yes or no questions pervading the consciousness of the majority of programmers, who foolishly think that you can actually reduce an engineering problem into a mathematical one, despite overwhelming evidence that you simply cannot escape the clutches of reality and how long it takes an electron to reach the other side of a silicon wafer.

If you ask someone how to do something the right way, you are asking the wrong question. You should be asking them how to solve your problem. You didn't do something the wrong way, you simply solved the wrong problem.


Original Post

An Artist Trapped Inside A Software Engineer
Posted on August 19, 2012 at 11:47

Originally posted on my blog.


Almost a decade ago, I thought I wanted to make games. I began building a graphics engine for that purpose, since back then, there were almost no open-source 2D graphics engines using 3D acceleration. It wasn't until later that I discovered I liked building the graphics engine more than I liked building games.

Times have changed, but I continued to tinker away on my graphics engine while going to college and learning just how stupid the rest of the world is. In the most recent bout of astonishing stupidity, my country has decided it doesn't recognize political asylum for people it doesn't like. It wasn't until reality had begun a full-scale assault on my creativity and imagination that I truly understood why artists feel compelled to lose themselves in their imaginations.

My imagination. It is something I could not possibly describe in any meaningful way. Art exists because some things can't be described, they must be shown. And yet, few things in my imagination are my own. I hunt down talented artists and visionaries, lose myself in the worlds they constructed, then take everything out of context and reconstruct my own worlds, perhaps based on another artist's vision, using the same concepts. I construct multiple visualizations, art styles, and game elements. My mental stage is fueled by awesome music, music that launches my imagination into incredible creative sprees. Sometimes I craft incredible melodies of my own, but rarely are they ever truly expressed in any satisfactory way in my music.

My life is one of creative frustration. I became obsessed with computer graphics as a way to realize my vision, but I wasn't interested in simply learning how to 3D model (which I happen to be terrible at, like everything else). I don't see the world as CGI, I see the world through the lens of a GPU. I look at things and ask, how might I render that? My imagination is not a static picture or movie, its a world that meant to be explored. Sometimes I play games for the storyline, or the gameplay, but the one thing that has always grabbed me is the ability to explore. I played Freelancer for 5 years, installed hundreds of mods, and was constantly enthralled simply by the exploration, the enormous universe, finding new systems, and discovering new places.

I can't draw a leaf. But I can create a mathematical model of it. I can calculate the textures and patterns, the branching veins and how each has their own specular, diffuse and transfer lighting functions. I can build abstractions and simulations, genetic recombinations and simplex noise algorithms. After I build tools to procedurally generate all the elements of a world, maybe then I can bring my imagination to life. But then, it's not really my imagination, it's what other artists inspire in me. I want to get as close to an artistic vision as possible, and beyond. I want to expand their artistic ideas and make them into something that is truly beautiful and inspiring, a clear extension of their vision, where it's soul shines like a beacon instead of being buried under bureaucratic bullshit.

I am an artist who cannot draw. I'm a musician incapable of painting the sonic landscape of my imagination. I am a dreamer who has no dreams of his own. If I am a programmer, it is because programming is the only way for me to express my creativity. But programming itself is not simply a means to an end. Programming is my paintbrush, my canvas, and my palette. I know how to read x86 assembly. I have abused C++11 lambdas to create temporary closures to hold a mutable state. I've crafted architectures and APIs and object-inheritance schemes and functional undo/redo stacks and lockless queues and kd-trees. Programming is my art and my music, and every new language or algorithm is another instrument for me to use when building my symphony.

Yet, many programmers hold little respect for alternative opinions. People who don't conform to strict guidelines are viewed as either terrible programmers or "cowboy" programmers destined to bring ruin to every project they touch. Everything must follow protocol, everyone must do things this way or that way. Instead of celebrating our diversity in programming languages, we viciously attack each other as using a "terrible language". Perhaps I have simply been inside a strange anomaly where everyone is obsessed with corporate practices and coding standards instead of building things.

Or perhaps I'm an artist trapped inside a software engineer.

What Do You Hate About Game Design?
Posted on July 11, 2012 at 05:24

More specifically, what is the most infuriating or otherwise painful part of game development? Listing multiple things is encouraged, with the most annoying listed first.

Answers To All The Questions I Asked As A Kid
Posted on May 30, 2012 at 06:10

Originally posted on my blog.


When I was growing up and trying to figure out what was going on in this crazy planet I was born on, there were several important questions I asked that took many, many years to find answers to. What was frustrating is that almost every single answer was usually extremely obvious once I could just find someone who actually knew what they were talking about. So here are the answers to several simple life questions that always bugged me as a kid, based on my own life experiences.

1. What is the purpose of Math?
Math is simply repeated abstraction and generalization. All of it. Every single formula and rule in mathematics is derived by generalizing a simpler concept, all the way down to the axioms of set theory. It was invented to make our lives easier by abstracting away annoying things. Why count from 2 to 6 when you can simply add 4? Adding is simply repeated counting, after all. But then, if you can add 4 to 2 and get 6, you should be able to generalize it so you can add 4 to 2.5 and get 6.5, and what about adding 2 to 4 over and over and over? Well that's just multiplication. What about multiplying 2 over and over and over? Well that's just exponentiation. What's that funky Gamma Function I see every now and then? That's simply the factorial (5! = 5 · 4 · 3 · 2 ·1) generalized to real and complex numbers, so it can evaluate 5.5!, its just written G(5.5 - 1) = G(4.5). Math is generalization.

Usually smart people figured all the generalizations out for you, so in some cases you can simply memorize a formula or look it up, but its much easier to simply remember the rules that the smart people figured out for you so you can rederive everything you need without having to memorize it. When you understand the rules (which are all carefully constructed to be consistent with each other), you can then use Mathematics as a language to express problems in. By abstracting the problem into mathematics, the answer becomes much easier to obtain. The only thing math does is make thing easier to do by abstracting them. That's all.

2. Why does college think high grades in math correspond to programming ability?
This is because programming is math. Programming is all about abstracting a problem to automate it. Think of it as a lingual descendant of Math. The problem is that in high school they teach you calculus and programming at the same time and try to tell you that they are related. They aren't. Calculus doesn't have anything to do with programming. Set Theory does. The mathematical constructs of logic are what programming derives from, not calculus. Naturally, they don't teach you any of that. Even though you can consider programming a sub-discipline of mathematics, ones programming ability is not connected to your test-taking abilities.

3. How do you compose music?
First, you come up with a melody. The best way to do this is to find a song you like, and figure out its melody. Knowing basic music theory will help, because then you know what a chord progression is, so you can find that too. Simply rip off all the common chord progressions you like - you'll come up with your own later. Rhythm is important too, so take note of that - be careful to focus on notes that seem to carry the beat.

Great, that was the easy part. But how do you make techno music? How do you record things? How does it get on a computer? All I have is this stupid electric piano I can record things off of, there has to be a better way! The answer is DAWs and VSTi, or Digital Audio Workstations and their virtual instrument plugins. A great DAW to start with is FL Studio, and there are a lot of free VSTi plugins floating around. VSTi plugins are simply synths or effects or other tools that you drop into your DAW and use to play notes or modify the sound. If you want natural sounding instruments, use samples. Soundfonts are widely supported, have an extension .sf2 and there are gigabytes upon gigabytes of free samples everywhere. You should try to hunt down an independent artist whose music you like, they'll often be willing to give on advice on how they create they're style.

But now I've made a song, where do I post it? Soundcloud, newgrounds,, and bandcamp lets you sell it for moneys. Don't worry if you're terrible, just keep doing it over and over and over and paying attention to advice and constructive criticism.

4. How do you draw clean art?
Clean digital art is commonly done using vectorization and gradients. There are multiple photoshop techniques that can be combined with tablets to create very nice looking lines by doing fake-tapering and line adjustments, but more commonly the tablet is simply pressure sensitive. There are many different techniques for doing various styles, so its more appropriate to ask the artist themselves.

5. Why do adults kiss?
I say instinct but no one really knows yet (only 90% of humans kiss). Provided you are in a culture that does kiss, you'll grow up to be around 16-17 and suddenly you'll feel this inexplicable urge to kiss whomever you've fallen in love with for no apparent reason. It's theorized to have arisen due to needing to evaluate certain proteins in a potential partner, which requires physical contact, along with various other things. I say instinct because I always thought it wasn't instinct and I wouldn't fall for it and then why am I fantasizing about kissing girls CRAP.

6. Why do adults fall in love in the first place?
Instinct. By the time you are 20, if you haven't yet found an intimate partner, you will feel crushing loneliness regardless of how many friends you have. Do not underestimate just how badly Nature wants you to have babies. This is why people get desperate - the desire to be in an intimate, loving relationship can be extremely powerful. It also leaves a giant hole that often explains various other bizarre things adults do in apparent attempts to kill themselves in the most amusing way possible.

7. Why don't popular people respond to fan mail very often?
This usually only comes up if you are using a bad medium. Artists often want to talk to their non-retarded fans, but the majority of people are incredibly stupid (see below), and thus in certain cases the signal-to-noise ratio is so high they simply can't justify spending the time to find you in a sea of insane idiocy when they have better things to do, like be awesome. Some artists simply don't want to be bothered, and this is usually the result of being disillusioned with how utterly stupid most people are, so it's hard to blame them, but unfortunate. Usually there will be a way to at least throw a meaningful thank you to the artist, possibly by e-mail or twitter if you look hard enough, and they will always appreciate it if they can just find your message. Never assume an artist is too stuck up and full of themselves to answer you. They just can't find you. Although quite a few of them actually are assholes.

8. Why is everything I do always wrong?
Because people are idiots and have no idea what they're talking about. Only ever listen to someone telling you that you are doing something wrong if you know they have extensive experience in exactly what you are trying to do. Otherwise, take the advice with a mountain-sized lump of salt, because people in specialized professions almost always take advice out of context and inappropriately simplify it to the point of it actually being completely wrong. There is always a catch. This is taken up to eleven in programming - I once had someone who did networking tell me my choice of language for my graphics engine was completely wrong and insisted I was so bad at programming I should just stop, because it would make the world a better place. He is an asshole, and he is completely wrong. Don't listen to those people, ever.

9. Why does everyone call everyone else an idiot?
BECAUSE EVERYONE IS AN IDIOT. The best you can hope to do is dedicate your life to not being an idiot in your choice of profession and don't think it makes you qualified to give advice on vaguely related fields (see networking programmer above).

10. Why do adults argue about everything?
Because they are 10-year-olds that have to pay taxes, and nobody really knows how to pay taxes properly. They don't know what they're doing. Common sense is not common, people are not rational, and people are idiots. They don't care if they're wrong, and they don't care if you're right. They just don't care, because life sucks, and life isn't fair, and they didn't get the memo until after they wasted their youth either being too drunk to remember anything, or studying in a library all day to get a useless scrap of paper.

Do something that matters to you, and know this: Life isn't fair, so you have to make it fair. You have to do things the hard way. You have to fail miserably hundreds of times and keep on trying because you aren't going to let life win. You have to do what matters to you, no matter what anyone else thinks. You have to fight for it, and you have until now until you die to win. Go.

Properly Dreaming About Success
Posted on May 26, 2012 at 13:55

Originally posted on my blog



"We are what and where we are because we have first imagined it." - Donald Curtis

The wisdom of antiquity suggests that we must first imagine what we want to achieve if we are ever to succeed, but science has other ideas. A study demonstrated that visualizing yourself reaching a goal tricks your brain into thinking you actually did it, causing a relaxation response, which in turn robs you of ambition and energy.

This is a troubling counter-argument to age-old wisdom, but perhaps both sides can be right? I have been relentlessly pursuing the same goal for many years, and from my experience, it matters what you visualize just as much as if. In particular, one should imagine what you are actually trying to create, rather than what you would do with all your riches.

By coupling your imagination to your problem solving skills, you can draw a line between where you are now and what you need to do to make your vision come to life. This both solidifies your goals, highlights potential problem areas and outlines a clear plan of action, which helps prevent procrastination caused by not knowing what to do. Simply imagining that we are living the high life after hitting the big time, however, merely drains us of ambition by creating a false sense of accomplishment. You must visualize your finished creation, not the act of finishing it.

There is a marvelous, unspeakably beautiful thing that wanders around in my subconscious. Every now and then I am given another glimpse, or shown another spark of inspiration of this indescribable vision that seems so real and yet could not possibly be written about, because nothing like it has ever existed. It's like looking into a future that could arrive tomorrow if only I could bring it to life. Sometimes I wonder if I'm losing my way, only for something else to trigger another magnificent concept. It shows me why I can never give up, even it if takes me an eternity to craft my thoughts into a new reality.

Your imagination is a tool, and like any other, it can be used or abused. Wield it wisely.

Multithreading Problems in Game Design
Posted on May 24, 2012 at 06:53

Why Windows 8 Does The Right Thing The Wrong Way
Posted on March 15, 2012 at 04:05

Originally posted on my blog


Yesterday, I saw a superb presentation called "When The Consoles Die, What Comes Next?" by Ben Cousins. It demonstrates that mobile gaming is behaving as a disruptive technology, and is causing the same market decline in consoles that consoles themselves did to arcades in the 1990s. He also demonstrates how TV crushed cinema in a similar manner - we just don't think of it like that because we don't remember back when almost 60% of the population was going to the movie theaters on a weekly basis. Today, most people tend to go to the movie theater as a special occasion, so the theaters didn't completely die out, they just lost their market dominance. The role the movie theater played changed as new technology was introduced.

The game industry, and in fact the software industry as a whole, is in a similar situation. Due to the mass adoption of iPads and other tablets, we now have a mobile computing experience that is distinct from that of say, a console, or even a PC. Consequently, the role of consoles and PCs will shift in response to this new technology. However, while many people are eager to jump on the bandwagon (and it's a very lucrative bandwagon), we are already losing sight of what will happen to stabilize the market.

People who want to sound futuristic and smart are talking about the "Post-PC Era", which is a very inaccurate thing to say. PCs are clearly very useful for some tasks, and its unlikely that they will be entirely replaced by mobile computing, especially when screen real-estate is so important to development and productivity, and the difficulty of replicating an ergonomic keyboard. The underlying concept of a PC, in that you sit down at it, have a keyboard and mouse and a large screen to work at, is unlikely to change significantly. The mouse will probably be replaced by adaptive touch solutions and possibly gestures, and the screen might very well turn into a giant glass slab with OLEDs on it, or perhaps simply exist as the wall, but the underlying idea is not going anywhere. It will simply evolve.

Windows 8 is both a surprisingly prescient move on part of Microsoft, and also (not surprisingly) a horrible train wreck of an OS. The key concept that Microsoft correctly anticipated was the unification of operating systems. It is foolish to think that we will continue on with this brick wall separating tablet devices and PCs. The difference between tablets and PCs is simply one of both user interface and user experience. These are both managed by the highest layers of complexity in an operating system, such that it can simply adapt its presentation to suit whatever device it is currently on. It will have to once we introduce monitors the size of walls and OLED cards with embedded microchips. There will be such a ridiculous number of possible presentation mediums, that the idea of a presentation medium must be generalized such that a single operating system can operate on a stupendous range of devices.

This has important consequences for the future of software. Currently we seem to think that there should be "tablet versions" of software. This is silly and inconvenient. If you buy a piece of software, it should just work, no matter what you put it on. If it finds itself on a PC, it will analyze the screen size and behave appropriately. If its on a tablet, it will enable touch controls and reorganize the UI appropriately. More importantly, you shouldn't have to buy a version for each of your devices, because eventually there won't be anything other than a computer we carry around with us that plugs into terminals or interacts with small central servers at a company.

If someone buys a game I make, they own a copy of that game. That means they need to be able to get a copy of that game on all their devices without having to buy it 2 or 3 times. The act of buying the game should make it available to install on any interactive medium they want, and my game should simply adapt itself to whatever medium is being used to play it. The difference between PC and tablet will become blurred as they are reduced to simply being different modes of interaction, with the same underlying functionality.

This is what Microsoft is attempting to anticipate, by building an operating system that can work on both a normal computer and a tablet. They even introduce a Windows App Store, which is a crucial step towards allowing you to buy a program for both your PC and your tablet in a single purchase. Unfortunately, the train-wreck analogy is all too appropriate for describing the state of Windows 8. Rather than presenting an elegant, unified tablet and PC experience, they smash together two completely incompatible interfaces in an incoherent disaster. The transition is about as smooth as your head smashing against a brick wall. It does the right thing, the wrong way.

The game industry has yet to catch on to this, since one designs either a "PC game" or a "mobile game". When a game is released on a tablet, it's a special "mobile version". FL Studio has a special mobile version. There is no unification anywhere, and the two are treated as separate walled gardens. While this is currently an advantage during a time where tablets don't have the kind of power a PC does, it will quickly become a disadvantage. The convenience of having familiar interfaces on all your devices, with all of the same programs, will trump isolated functionality. There will always be games and programs more suited to consoles, or to PCs, or to tablets, but unless we stop thinking of these as separate devices, and instead one of many possible user experiences that we must adapt our creations to, we will find ourselves on the wrong side of history.

Success Is Not What You Think It Is
Posted on March 10, 2012 at 22:08

Originally post on my blog



"Successful people seem to have a long history of building bigger successes on top of smaller successes. In other words, successful people are successful." - Daniel Tenner

The above quote has a lot more truth in it than I really want to admit. I strive to be a successful person, but I simply cannot escape the fact that I have to build all my successes on top of smaller successes, and why, while I continue to strive for what some would consider absurdly ambitious goals, I end up inserting more and more steps between each one. Sometimes I'm productive, and sometimes I'm not. Sometimes I feel like I could take on the world, and sometimes I curl into a fetal position. Some people wonder why I try so hard, and I wonder how those people couldn't try so hard - but there is always a catch.

It seems that "success" has a devilishly slippery definition. It means something different to everyone, but people tend to assume that their view of success is shared by the majority. We argue about how much work you need to do versus how much is healthy, we talk about having fun at your job, we talk about making sacrifices, we talk about a lot of things. What we never seem to talk about is what success actually means for you.

In our endless quest for success, we've forgotten that everyone has a different finish line.

Do you know what success means to me? Some people are surprised when they discover it has nothing to do with money, or fame, or even having kids. These things don't matter to me. There are only 3 things that are precious to me, and they are what my entire life is dedicated to creating. If I weren't working towards making those things happen, I'd go insane. To me, the most important thing I will ever do in my life is to take a dream, an idea, a world that exists only inside my imagination, and to make it come alive for people to explore. If only a few thousand people see it, that's fine. If I end up working at a terrible job just to support myself because I can't make any money off it, fine. If it gets ridiculed and laughed at, fine. My success hinges only on my ability to create what I want to create.

Some people have similar dreams (they tend to be artists, who often understand my goals better than programmers), but some do not. Some people measure success by how much money they make. Some people measure success by how popular they are. Some people measure success by solving a problem or crafting an elegant mathematical proof. We can't simply ignore success that we don't understand. This is why the entire concept of a self-help book has to be taken with a grain of salt - it will only be useful to you if it matches up to what success really means to you, and people are entirely too good at convincing themselves that they want something they don't actually need.

Advice on how to be successful is more useful when it is made more general. I always say that you should stop at nothing to achieve your dreams, no matter what they are. Perhaps I should also suggest for you to make sure that your dreams are truly your own. Are you trying to climb your own mountain, or have you been scaling someone else's cliffs? Maybe trying to figure out how to be successful isn't as important as figuring out what success means to you in the first place.

Prev Page | Next Page

Recent Activity
Active Users (0)