3D Art Pipeline, for Games

As I move more into the area of web development, I run into a lot of people who are interested in making games, but have little idea on how they are made, especially the art. Hopefully this post will give a general idea of how art goes down. Specifically of an animated character, from concept to engine.

As a side note, every studio, project, and artist are different. This is meant to be an overview of the general flow, but most projects will have more steps, omit some, combine others, use different software. I

The idea: All things start in with an idea. Maybe it’s several well designed pages, with description and purpose. Other times it’s a napkin that someone scrawled on during lunch, complete with mustard stains .3D Art Pipeline_1

Concept: This is then kicked off to the concept artist. Their job is to turn the words into pictures. This usually starts as many thumbnails which then gets refined into color comps and eventually finalized.

3D Art Pipeline_2

Besides the design document, they usually have a style guide, they follow to help ensure that the character will fit into the rest of the world, and speak the same visual language. An amazing example of this is DOTA 2’s style guide

3D Art Pipeline_3

Their finished product is often a character turn around, with maybe a couple extra action / emotive poses.  This gets passed off to the modeler

3D Art Pipeline_4

The Model: There are many methods for making 3D models, my preferred method is the ‘Box Modeling Method’ in which you start with a box, subdivide it, move the vertices to best fit the shape you want, then rinse and repeat until you have the level of detail you are looking for.

3D Art Pipeline_5

Lets take  a second to describe the anatomy of a model, and polygons. All models are made up of 2D shapes, laid end to end. As you see in the left image, there are a bunch of rectangles (Which all consist of 2 triangles.) While they give the illusion of volume, they are all completely flat. With points that define the area. Then these polygons have color placed on them, through shaders. In fact, in order to see them they have to have 2 different types shaders on them, but lets not worry about that yet.

3D Art Pipeline_6

In order to get the color onto these models, you must lay them out flat, so that you can overlay an image onto them. This is called ‘unwrapping’. You can think of taking an orange rind, and chopping it up into little pieces so it will lay flat.

3D Art Pipeline_7

Once it’s unwrapped, the character artist has to actually make the images (maps) that will be laid onto the model. There are also a handful of maps that go into defining the material of a model.

These are usually done in either a traditional raster image program, like Photoshop, or in a sculpting program like ZBrush or Mudbox. Often mix and matched.

3D Art Pipeline_9

Inside the sculpting programs, the artist doesn’t have to worry about things like polygon limits. They get to just get in there and make all the detail they want, molding millions of polygons. Then at the end, they tell the program to make an image that will tell the low poly starting model, look like the high res beautiful one. That is an over simplification, but the basic idea.

3D Art Pipeline_10

The character artist now has the textures they made from either sculpts or hand painting / photo chopping. The next step is to compile these textures together into a material. A material is an instance of a shader. A shader tells the computer how to display the polygons. Light affecting a model? The shader told it to. Does the character have any color, outline, or transparency? Shader.  Did it move? That could be the shader, depends on how it’s implemented.

It’s good to note there are 2 types of shaders, vertex and fragment/pixel. Where artists are concerned, they are messing with pixel shaders. I’ll get into the difference in a bit.

So, the shader tells the computer how things should look, or rather, the rules to follow when determining what a thing should look like. Such as ‘look at a textureA, multiply it by lighting for the color, look at textureB and modify it by valueC for how shiny this spot is.” The material is then the specific instance, the place where the artist gets to plug in specific textures and values into those slots for textureA, textureB and valueC.

3D Art Pipeline_11

From left to right:
The same rhino with 3 different materials (probably different shaders too.)
A material view, showing primitive objects with different materials applied
A material editor view in 3DS Max

This is a pretty solid high level overview of the how a mesh gets turned into pixels

3D Art Pipeline_12

So, the artist has a finished model, it’s all textured and made pretty. The next step is to make it move, right? Whoa, slow down there buddy. We have to create the system which will allow it to move. This is called rigging. Just like the character artist had to layout the mesh flat, and assign the 3D vertices to a 2D Space, we must again bind each vertex to an object so we can easily move them over time.

This is the job of the rigger. The rigger creates a system of joints (or bones) and other voodoo to define how the character can move. Then they bind these joints to control objects. Further abstracting and distilling down the control, and exposed API (options) that the animator has access to. Once the controls are set up, the rigger then binds the mesh to the joints, in a process called skinning.

3D Art Pipeline_13

Then it can handed over to the animator, to begin, well, animating.

Animation is the process of creating a set of images that will be seen sequentially, over time, to give the illusion of motion. Usually the animator tries to convey things through this motion. “This is a big and heavy robot, moving forward in time.”, “This person just got hit, really hard.”, “This person is sad, and really just wants someone to acknowledge their existence.” The last one doesn’t happen as much in games.

In 3D, the animator does this by setting keys, on frames. Coming from the traditional animation term of ‘keyframe’. Keys define when an object should be at a specific place. It looks something like this

3D Art Pipeline_14

After that it gets exported and is ready for use in the game engine.

A few notes:
If the process is done well, most of these steps can be done in parallel, which is really neat. Not so much the first part (drawing.) But you can totally have a proxy model of roughly the right proportions get rigged with basic controls and passed onto the animator so they can all work in unison. Then update just get passed downstream.

Characters often have effects associated with them. Dust when they walk, fire when fly with their jetpack, lazer eyes, whatever it may be. This is done by a ‘technical artist’ and is a whole ‘nother beast we’ll get into at a later date. Maybe.

Anyways, I hope you found some good info in this high level overview, and will be kind to your artist in the future. They work very hard.

R6: Post Mortem

I recently completed working on a game with 3 other people titled R6. Check it out.

Tech: Socket.io and Babylon.js were the heavy lifters in this project.

it is a 3D multiplayer in browser robot racing game. I wanted to take a moment to go over what worked, what didn’t, any odds and ends of observations.

The Good:

  • Scope: It was surprisingly well scoped. Even though none of us had done a multiplayer game before, and I was the only one who had worked with 3D before (definitely not in browser, or with javascript before.)
  • Research: We broke off into 2 teams at the start. One for front end (Babylon research) and the other for back end (Socket) at the end of the second day we had game logic tied to 3D representations that could be integrated with an event driven back end.
  • Iteration: We hit numerous bugs and hiccups (camera jitter, frame rate issues, rotation / scale.) But because we always worked to have something playable at all times, they never built up. Frame rate was also something that we all ended up improving over time as we spotted things could be improved, because we all worked the whole code.
  • Naive first: While we definitely spent time architecting, especially the core game logic, often times we’d hit areas we just didn’t have enough experience in to make educated guesses. We’d talk briefly, decide on a plan of action, make a note of the probable down falls, and take action. More often than not these solutions worked well enough.
  • Sound: One of our programmers was a musician as wel

The Bad

  • Art Pipeline: art is a large and sometimes unwieldy beast. in order to be efficient we used a bitmap as collision detection server side, which meant there was no actual relation between what the client saw, and what the server was doing other than, I lined them up in 3DS Max. Due to time constraints this was a very manual process, and prone to error. But worse than mild collision inconsistencies, was it was time consuming. While it worked for this project, the next order of business would be building art tools.
  • Art Seclusion: I’ve been an artist on a project where I can’t get my own art in the game, because it has to go through an engineer. This is a terrible experience, I don’t get immediate feedback, as well, in order to tweak and polish requires me to eat up engineer time. This project had a reverse, nobody else could really touch the art / design in any way because of how tied up into my 3D applications it became. Which meant that I was very alone with problems, and if they wanted to input on it, they could not directly do so.
  • More Design Time: This always happens with shorter projects, but by the time it really starts coming to shape and you can polish the levels (or re-make them) your project over. This game could be quite good with another week or so.

I actually really enjoyed doing double duty as a programmer (about 70% of time) and an artist (remaining 30%.) It felt really good to flex a full range of ‘muscles.’

Vector Math: For Fun and Profit

Part 1: Hamsters, Scales, and Addition

Lets talk about vectors for a bit. I was taught briefly about them (along with sin and cos) waaaaay back when, in trig and geometry back in high school. They were just this thing I had to learn and they didn’t tie into reality. After those classes they just gathered dust in the corner. I’d occasionally see it out of the corner of my eye in the form for ‘vector art’ or ‘vertices’  for 3D models, but still, not really relevant. This all changed when I started programming games. Maybe I changed, or maybe they did (it was me, vectors haven’t changed much.) But now we get along great. Vectors are amazing, powerful tools and the best part is that they are dead simple.

I’m going to keep this light and full of pictures, so if you want to dive in deeper, Kahn Academy has you covered.

First, what is a vector? It’s a few numbers that are related, usually describing something to do with space (position, speed, force, etc).  A vector 2 looks like this [2,3] – because there are 2 numbers. Vector 3 [3,2,5]. There is one number for each plane you are talking about. In fact I’m pretty sure you could have a vector 1 if you felt like it and these observations would still apply.

Lets look at a vector in 3D space, talk about a few properties, then we’ll get into actual use, games!

vectors_1

This is vector 3 would be written down as [3,5,2].

Right off the bat we can see that it’s describing a point in space. It’s over a few units to the right (x : 3), it’s up in the air some (y : 5) and it comes at us a bit (z : 2).

Another thing it describes, is a direction. All spaces (a place where vectors live) have something called an origin. When I say that vector is 3 units over to the right, what is it over to the right from? Well, the origin. An origin is (0,0,0) in whatever space you are talking about. What is really cool about physics, or spaces in general is you can always pick your own origin, and align the axis in whatever way makes your life easiest. Though more discussion on that is out of the scope of this post.

vectors_2

Lets pretend that point represents a ball in the air, if you were to stand on the origin and look at the ball, you are looking in it’s direction. So if you know a point in space, you know a direction (always relative to the origin.)

The last thing it describes is a distance, or simply, the length of the line segment that connects the origin to our point. In this case it is a length (sometimes referred to as magnitude) of 6.1644. We got this by using the good ‘ol Pythagorean Theorem. A^2 + B^2 = C^2, or in our case X^2 + Y^2 + Z^2 = L^2 (L, being length.) It doesn’t matter that we have 3 planes instead of 2, the math transfers. In fact it works in 1 dimension as well. 3^2 = 3^2 after all.

vectors_3

I’m getting antsy, lets jump into talking about games. We can pick up operations as we go.

First thing, lets have a character, how about a hamster? That’s what you were thinking as well? Excellent.

vectors_4

Alright, we have our hamster, lets name her Stella. Since this is a game we have to have some mechanics. The first one that comes to mind, is movement. Lets say if the player presses W, Stella will move forward one unit in the X axis. As a vector that looks like [1,0,0]

vectors_5

There are a couple things going on here, I drew just the [1,0,0] vector coming off of the origin. I also drew it coming off of Stella, as that is how vector addition works. You just line them up, and do simple arithmetic.
[1,0,0] +
[2,0,5] =
[3,0,5]

Just like in normal addition, order doesn’t matter. In fact you could break Stella’s new position up into 3 separate vectors and add them together to get her new position
[3,0,0]
[0,0,0]
[0,0,5]

vectors_6

Excellent, Stella can now move forward. If we extend this logic a bit, we can have her move back with D. Instead of adding [1,0,0] we will add [-1,0,0]. We can also subtract [1,0,0] from her position, either way. Just like with arithmetic, it doesn’t matter which way you prefer. We can also giver her side to side by adding and subtracting on the Z axis when the player presses D and A, respectively.

One observation I wanted to point out about the above drawing, you can see that when we break up the vectors, it looks like we are drawing a box. To some extent we are, with 2 points you can define the minimum and maximum points of a box, and if we use the origin as the other point, we totally have 2 points.

vectors_7

You can see I went ahead and decided to draw a triangle that the vector can describe as well. If you think about it a bit more, that box actually describes 3 different triangles. Plus it describes 3 sets of 2 rectangles (each of the faces.) Those faces can all be made up of triangles. I’m getting ahead of myself, but the more relationships you start to see, the more you can have vectors do work for you. Though the opportunities really build up when we start to add sin and cos.

The final thing we will do is make it so that you don’t have to keep tapping the key to move down, lets let you hold the key.

For the sake of argument lets say we are running the game at 30 frames per second. Lets also say that we want Stella to move 5 units per second in the direction we are holding.

After some unit conversion

vectors_8

We come up with 0.16666 as the distance we want Stella to travel, every frame, in whatever direction the player is pressing.

How do we use this number? Well, when are dealing with vectors, numbers that just live by themselves are often referred to as scalars, or scalar value. If you recall, we encountered one of these earlier when were talking about the magnitude of a vector.

Multiplying a vector, by a scalar value (which is what we want to do) is simple. It’s noting more than distribution. In our case, it’s the even simpler because our starting vector looks like [0,0,-1]. So, [0,0,-1] * 0.166 looks like [0 * 0.166, 0 * 0.166, 1*0.166] which becomes [0,0,1.66]

Starting at [0,0,0], if the player holds S for 3 seconds, Stella would then be at [0,0,-15] :   30 (frames per second ) * 3 (number of seconds) * 0.166 (units per second) * [0,0,-1] (our vector)

If the player then taps W for 3 frames, and they’d end up at [0.5,0,-15].

Next time we will look into acceleration, unit vectors / normals. We will do this by putting Stella in spaaaaace.

Backbone Overview

What is Backbone.js? According to their site: “Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.”

To me, it’s few really well laid out objects that you can extend (make copies of) to fit your needs. There are 3 types.

Models: These are at the heart of the whole thing. Each model represents a singular entry or event, such as a song, a user, or a message.

Views: These are used to represent your models to the user of your app. Which is why they usualy contain a render() function. They are also in charge of collecting input from the user.

Collections: As the name implies, they are a collection of things. What things? Models or views.

Lets go over a fairly simple example of rendering an displaying the contents of an album. For spacial reasons, this album will only have 2 songs on it. Don’t worry, they are quality songs.

backbone_1

A few things to note:
Views either have a collection, or a model, that they reference.
Collections have a model that they reference.
So all views, at some point, will reference a model, either directly, or through a collection

Our album data would look something like [{title: “rockin intro”, length: “0:20″, url:”mysite.com/rockinintro”},{title: “outro”, length: “1:11″,url:”mysite.com/rockinoutro”}]

We passed our album data into the app (which is a model), as we instantiated (loaded) the app. The app then went and made the app view (which is a view). After that we created a new album collection from our album data with something like this: this.set(‘currentAlbum’, new Album(albumJSON)); which got called inside the initialize function.

We would have already told our album collection, that it is a set of songs. So the collection knows that when it gets created and passed a set of data, that the data should represent songs.

The collection then automatically goes and makes a model for each song.

–Will be updated with more, later.

nQueens 2

nQueens – Part 2 – Implementation

Last time we discussed the problem of nQueens and the general logic used to create our algorithm. We are now going to take that solution and implement it in code.

Before we were talking, human to human. We do this a lot, so it’s much easier to get ideas across. Now we will be talking human to computer, which is a bit more difficult, they lack the ability to deal with ambiguity. Which means we need to be more precise, and explicit; both in speech and thought.

Lets take a look at our current logic, though for the sack of less drawing, we are moving from a board of 5×5, to a board of 4×4.  Lets review our logic so far.

  • Pick an available number from the column array, and pick one from the row array.
  • Check the major and minor arrays. C + R = Major index , C – R + 3 = Minor index.  (C for column number, R for row number. We are adding 3, to make the minor index 0 based.)
  • If you get a (o) when you check the major and minor arrays, you are good to go. Place a queen at that chosen spot. Then remove the chosen numbers from their respective column and row arrays. Then mark major and minor arrays as taken (x) at the spots you checked. Section 1 has a more detailed walk-through of this.

Let’s see how this looks on a 4×4 board.
chess_2_1

Step 1: Our empty board, all choices are available.
Step 2: We chose 0,0 as it was the first available spot, no conflicts. We took 0 out of both the Row and Column arrays. We also marked the spots taken in the Major and Minor arrays.
Step 3: You’ll see that the first thing we tried, was to place a queen at [1,1]. This was because the numbers were available to us, so we tried it. We then did a lookup in the Major and Minor array, and found there was a conflict with the Minor array, so we moved onto the [1,2] where we placed our second queen.

You’ll note that we no longer have a valid board. There is only 1 available slot and we need to place 2 more queens to have a valid solution. What do we do now?

As a person I’m sure you would say,”Ummm, I guess we try some different spots?” You, person, are totally right. We try some different spots. But how would we tell a computer this? Also since computers are fast at this kind of problem, how do we tell it to try EVERY possible spot, then tell us which ones work.

Lets try some plain language logic for this. We have a good starting point, Step 1, an empty board. With a bit of trial and error, it turns out that for a 4×4 board, there is no solution that involves starting a piece at [0,0]. That means we should step back to the empty board, and try the next possible spot, [0,1] and go through again. chess_2_2

Above, you can see our logic laid out in a branching fashion. For this first iteration I’ve laid each choice to match it’s row:column value. Diagrams laid out like, because of the branching, are often called trees. Get it? Branches, trees. Yeah, you get it. If  we were to fill the above diagram out fully, the [0,0] circle would have one more child node, [1,3].  [1,3] would have no valid children.

chess_2_3

 

 

 

 

 

 

I’ve changed the positioning a bit, to reflect a more typical tree data structure. The [1,3] choice is also shown. Clearly [0,0] is a dud, we must move onto [0,1]. chess_2_4

 

 

 

 

After choosing [0,1], our first 2 child options end up having diagonal conflicts. The third one, however, was just right. Each successive choice in our algorithm also proves to be valid, and we now have one functioning board that satisfies the nQueens requirements. Awesome!

chess_2_5

A successful board

 

 

 

 

 

 

 

Any time you see data branching, as we did in the above node diagram, that problem is a good candidate for recursion. If are comfortable with recursion, then hopefully this post was useful to you by visualizing the flow of data. If you do not know what recursion is, you should google around for resources on it. But before you do, be confident knowing that what we walked through in this post and the previous one, was recursive. If you understood what we’ve said, you can grasp recursion just fine.

That’s all well and good, but what about some code?

Here is my decently commented solution. I solve it using ‘recursion with side-effects.’ Which just means that there are a few variables that each recursive call can all see, and they can all modify.

nQueens

nQueens – Another Approach: Part 1.

I was recently given then problem, “Given an N-sized chess board, give us an example of one solution where you can place N queens on the board so that they wont attack each other, or tell us how many possible solutions there are to a board of N size.”

When I look up documentation on CS problems, higher level math, or even music, they exhibit a few tendencies that make reading the document a slog-fest. They are dry, dense, and steeped in jargon. I feel like I already need to know the answers I’m looking for, in order to parse what they are saying. This catch-22 is terrible. So this post, and hopefully all future ones, will be more casual and full of pictures.

Let’s rephrase the above question in a more approachable fashion, I am also going to condense them into one question. “If I give you a 5×5 grid, show me all the different ways you can place 5 queens on that board so that they can’t attack each other.” Queens are prone to unprovoked attacks it would seem.

Lets take a second here to analyze the question, take out any hints we can from the question, and break the problem down into some simpler chunks.

The first bit to notice, is that the problem asks you to place 5 queens on a 5×5 grid. (I know the original problem is n, but we are sticking with the 5. I drew up pictures, they say 5, not N.) Why only 5? Why not more? As you may have deduced, every time you place a queen on the first row, because the queen can move any number of squares horizontally, there are no more safe places on the first row. With this logic alone, we can safely say that on a 5×5 grid you can never have more than 5 queens without some aggression.

Queens can move vertically as well as diagonally any number of squares.   Our logic so far looks like, “If you place a queen on row ‘a’, then  no other queens can on row ‘a’. ” Is really easy to port over to columns, “If you place a queen on column ‘1’, then no other queens can be placed on column ‘1’.”  However it doesn’t port nearly as well to diagonals. So let’s put diagonals on hold for a second and concentrate on rook movement (horizontal and vertical.)

A rook placed at ‘a,1’ and all the squares no longer possible

Let’s now break up all possible solutions into 2 arrays that look like:
Rows – [a,b,c,d,e]
Columns –  [1,2,3,4,5]
Before we placed our first rook at ‘a,1’, our possibility space looked like the above 2 arrays. You can pick any letter from the first array, and any number from the second array and the result is a valid spot.

Let’s now update the array to reflect our choice of ‘a,1’, we should also save our choice somewhere for later reference.
Rows – [b,c,d,e]
Columns – [2,3,4,5]
Occupied – [‘a,1’]

If we were running this in a computer, the next logical choice would be ‘b,2’, but I am feeling more like ‘c,3’. For no particular reason. Let’s see what that looks like

'c,3' is now taken, we can see all the available slots.

‘c,3’ is now taken, we can see all the available slots.

Rows – [b,d,e]
Columns – [2,4,5]
Occupied – [‘a,1’ : ‘c,3’]

At this point, I’m confident that our logic is sound for horizontal. Whenever we pick a spot, we remove that spot’s letter from the Rows array, and that spot’s number from the Column’s array.  We then move that spot into our occupied array. Following this method there can never be any conflicts. When we convert this to code, as we loop over our column’s array, at every step, every combination we can make is valid. So there is no wasted computation, and very little to store. That’s pretty cool.

A finished board of rooks

A finished board of rooks

Rows – []
Columns – []
Occupied – [‘a,1’ : ‘c,3’ : ‘e,2’ : ‘b,4’ : ‘d,5’]

Now it’s time to dive into diagonals. The whole crux of this method is that any point I want to not want to have to store data about every spot, and loop over that data to see if a spot is valid. That just sounds like a lot of wasted time. In keeping with the spirit my above approach to rooks, I tried to figure out if there was a simple way to store diagonals as a whole.  I found that if we switch from using letters for rows to numbers, and start at 0, we can do some very simple arithmetic to figure out what diagonal we are at.

I mapped out the diagonals on 2 different images. One that goes from upper-left to lower-right, and one that goes from lower-left to upper-right. We will refer to the first one as the major diagonal, and the second as minor. There isn’t any significance to these names, it’s just convention. It also reminds me of music, so I like it.

Major Diagonals

Major Diagonals

Minor Diagonal

Take a moment to look over the images and see if you can put the formula together, and know where we are going next.

If you look at the major diagonal, and you add the row number (r) to the column number (c), your result is the diagonal.  Makes a simple sort of sense right? 3+2 = 5 and 1 + 4 = 5, so both of these are on the same major diagonal.  You’ll also notice that this is conveniently set up with a 0.  So when we store / look up these results we can pass in our result as index, and get our value in constant time. No looping for us!

Minor is the same as major, but instead of adding, we will subtract. Though -4 to 4 isn’t the best range, so we will add 4 (n -1) to that formula. Just to reiterate where we are at:
c + r = major array index
c – r + 4 = minor array index
(I realize now that I have column first instead of array, and for all the earlier examples in the post, I had row first. But the picture is already drawn, so what is done is done. It’s doesn’t change anything, just note we are swapping which comes first now.)

Let’s put it all together, and start from the top. In our open board our values will look something like:
Columns – [0,1,2,3,4]
Rows – [0,1,2,3,4]
Major – [o,o,o,o,o,o,o,o,o]
Minor – [o,o,o,o,o,o,o,o,o]
Occupied – []

To start, I’ll pick ‘0,0’
That means we do a look up of  (0+0) in major and (0-0+4) in minor. Both are (o)pen. That means we can place it, and mark those diagonals as crossed (x).

chess_6

Placed a queen at 0,0

Columns – [1,2,3,4]
Rows – [1,2,3,4]
Major – [x,o,o,o,o,o,o,o,o]
Minor – [o,o,o,o,x,o,o,o,o]
Occupied – [0,0]

If we continue with our computer picking method, the next option is ‘1,1’. Looking at the picture, you and I know that it’s not valid, but let’s see if our algorithm will figure it out.  ‘1,1’ is an option, so it’s a valid rook solution. But now that we are doing queens we need to go look up our major/minor arrays. (1 + 1) in major gives us the (o).k. (1-1+4) in the minor, however, (x)’s out and tells us it’s not valid.

Dreams dashed, we pick ourselves up and move on, to ‘2,1’. (2+1) in the major returns us ‘o’. (2-1+4) in minor returns us o as well! it’s a valid spot. Let’s put our next queen there, and forget about ‘1,1’.

'1,2' I always loved you

‘2,1’ I always loved you

Columns – [1,3,4]
Rows – [2,3,4]
Major – [x,o,x,o,o,o,o,o,o]
Minor – [o,o,o,o,x,x,o,o,o]
Occupied – [0,0 : 2,1]

Looking at this, I’m sure you can tell where the remaining 3 have to go, given the choices we’ve made so far. The algorithm will figure it as well.

Is there a better solution out there? Almost definitely. But with this method: we only have to keep track of a small amount of date, we iterate a minimal amount of times, our look ups are in constant time, and at each successive step, we get to sift through less options.

Part 2 to come later, implementation!

More games, more code

I made 2 games in the past 2 weeks. One as a last hooray with my friends before Hack Reactor devours my time and I don’t get to see them much, let alone game jam, for the next 3 months.

The game we made was Slingship. A quick post-mortem on that

  • Planets and space look cool with little art investment
  • Orbital mechanics are a fun mechanic, but only if you’ve played Kerbal and understand them already, otherwise they are frustrating.
  • If one of your coders gets stumped on a problem, try and diagnose it / change what’s going on early instead of letting them chew on it for a long time. (At least during a game jam.)
  • Everyone loves explosions
  • Even though it’s a game jam. It is very important to find time for polish / level design. Make sure you create something that is playable, not just mechanics in a box.

After that I started Hack Reactor. Which runs Monday – Saturday from 9 a.m. to 8 p.m. Another one of my friends was doing Ludum Dare 33 that weekend. His excitement about it, gave me excitement about it. So I decided that I’d make a game for LD33 as well. It as my first compo (solo) LD entry. I think I only managed to find 10 hours to put into it, but I still was able to produce the game Monster. Quick notes on that.

  • 10 hours isn’t really enough to come up with a game idea and execute it well.
  • As a product, I’m not too fond of it (fairly janky.) But as a sketch, something to point at and say, “This is where I’m going.” It works well
  • It does not take more than one or 2 measures to make a decent looping song.

Vector Trigger

My November 1 Game a Month is wrapped up. I feel this one is my best yet.

Things that worked well:

  • The code for the mechanics were up and running within a few days
  • I knew why it would be fun and could play it really quickly
  • The aesthetic was graphic and simple
  • A lot was learned in how to teach and message the player

Less well:

  • I left too much to the physics engine, causing issues later in development
  • The game required a lot of effort be put into things like the camera, and the feel of running, for it to not be hideous
  • Not as much time was left for animation

The main takeaway for future games is to design a tighter experience with snappier controls. Don’t let the time between physics steps ruin your ideas. And lastly, the more fleshed out your world looks, the more the players expect of it.

 

Play Vector Trigger

Cluster Puffs

I began the one game a month excursion last month (October.) I made 2 games that month, one was for a game jam, the game was titled Arc. We are hoping to polish this game up some more. That game went really well and is fun.

The other game is Cluster Puffs. This game took the bulk of the month and is a systems driven game. The idea behind it is that you have to kill a bunch of cute and cuddly creatures for their own good (or they will eat all their food and they will all die.) There were a myriad of issues with this, the most pervasive being ‘why is this fun.’

After getting the initial system working with spheres, I found that it was indeed a neat simulation and if you let it go their population will boom and bust.  But the ease at which the player could cull the population lacked challenge or thought.

The game went through many more iterations, some for performance reasons, other for design reasons.What I finished with s the best permutation of the thing as a whole, but lacked some of the charm of the earlier systems. In the future I will be answering these design questions up front, and not hoping the answer comes to me as I work (even though the answer will of course, be wrong.)