Walking With A Ghost

Sometime recently a new trailer went up for the Space Hulk: Deathwing video game. It’s pretty good:

Some of the guys have been discussing whether or not the unexpected musical selection, Kadebostany’s Walking With A Ghost, works. Juxtaposing action games with slower or offbeat music has definitely been a thing since at least the very successful, memorable, and beautiful “Mad World” trailer for Gears of War:

Given that Space Hulk: Deathwing is a Games Workshop licensee, it’s tempting to quickly dismiss the latest trailer as simple mimicry given GW’s general ineptness and the low quality of many of the offerings from both it and its licensees. However, I think the game studio developers quite possibly put a lot of thought into that selection, and that it comes close to inspired.

Synchronization

First, note how the whole video is well keyed to the music. That’s not coincidental, and took more than just slapping the song over the video. As a counter-example, note how easy it would have been to just throw Mad World over the Gears trailer. Although I don’t actually believe little effort went into tailoring that video to that music, it could have. That song doesn’t have a ton of really distinctive audio shifts, peaks, or valleys, and the action on the video is pretty subdued. They would basically work together no matter what, with no effort to sync them up. It takes a fair bit of close watching to actually pick up a few subtle touch points:

  • When the lyrics go “Worn out places, worn out faces” as the clip pans from the rubble to the face of first the demolished angel statue and then has its first closeup of the face of the soldier (starting at ~9s);
  • The lyrics go “No tomorrow, no tomorrow” as the soldier runs into the dying light, the video fades out, and then comes back in on yet more endless rubble and running (starting at ~22s).
  • Of course the closing, with the “Mad world” chorus as the hero leaps from a minor potential confrontation with a vaguely humanoid enemy into a hopeless situation in a demonically lit setting against truly otherworldly aliens (~40s).

In contrast, Walking With A Ghost has a couple pace changes and definite valleys, all of which the Space Hulk trailer video is keyed to. Several are pretty overt:

  • ~40 seconds in when the music picks up and the video goes from a setting pan and ultra slow motion to live combat;
  • ~70 seconds in, the music slows down again as the video slows to show the Tyranids bringing in reinforcements;
  • ~75 seconds in, the music picks back up into a more flowing style with horns giving a feeling of a Spanish bullfight or Mexican swashbuckling scene while the action picks back up, having switched to swirling swords and close combat until seguing to end with a last stand on steps vaguely reminiscent of a cathedral.

All in all, the video seems to have been certainly choreographed to the music and at a minimum the latter not just cynically slapped on in a cheap ploy to stand out or evoke some gravitas and intellectual veneer.

Lyrics

A few connections though are more subtle and tied to the lyrics, e.g.:

  • ~55 seconds in, “Round and round and round” as flames and the camera swirl around a Terminator;
  • ~64 seconds in, “I’m not creatin’ my flow with my ego” as the camera pans over a pretty solid symbol of ego, a powersword inscribed with “I am wrath. I am steel. I am the mercy of angels.”

With that, it’s worth looking at the full lyrics of the song:

I’m just walking with a ghost
And he’s walking by my side
My soul is dancing on my cheek
I don’t know where the exit is

Every day is still the same
And I don’t know what to do
I’m carrying my tears in a plastic bag
And it’s the only thing I got from you

I have short hair
And I’m faced with a few complications
So, so if you care
Try to analyse the situation
You know, man
As the leaves fall on the ground
My soul is goin’
Round and round and round

So please, do it well
Just break the spell
Why don’t you do it right?
I don’t want another fight
I’m not creatin’
My flow with my ego
I’m taking off my hood
And I’m entering deeply in the wood
You know, man

Bugs are my only food
And it puts me in a strange mood
I ain’t giving you my heart
On a silver plate
Why couldn’t we be just mates?
Oh no, never come back to me
Oh no, never come back to me

I wish i could be a child, write me another dance, another chance, another romance
we could just be friends

I wish i could be a child, write me another dance, another chance, another romance
it could be the end

Accepting a fair dose of lyricism, that actually captures and references an awful lot about a Space Marine’s life, especially those fighting in a space hulk.

It starts with the opening lines:

I’m just walking with a ghost
And he’s walking by my side

What does a Space Marine do but trudge along with the Emperor’s will aiding his every move and his spirit foremost in the Marine’s mind?

Bouncing around a bit, there’s a middle stanza about the Marines’ monastic lifestyle and how their dedication to the Emperor and setting aside of themselves is what gives them their strength as they wade into combat against tremendous odds in dark, unknown enemy territory:

I’m not creatin’
My flow with my ego
I’m taking off my hood
And I’m entering deeply in the wood

Toward the end, it turns out we’re specifically hearing from a Space Marine fighting, probably until he dies, with Tyranids—the bugs of this particular franchise:

Bugs are my only food
And it puts me in a strange mood
I ain’t giving you my heart
On a silver plate
Why couldn’t we be just mates?
Oh no, never come back to me
Oh no, never come back to me

Most dramatically though, most of the song captures what I take as an overarching theme of the Space Marines:

I don’t know where the exit is

Every day is still the same
And I don’t know what to do

My soul is goin’
Round and round and round

So please, do it well
Just break the spell
Why don’t you do it right?
I don’t want another fight

I wish i could be a child, write me another dance, another chance, another romance
we could just be friends

These lines are all about one of the central pathos of the Space Marines. They’re in many ways the pinnacle of humanity. It’s not generally readily apparent from the actual games, but these guys are all ostensibly artists and scholars without par. They’re brilliant, talented, dedicated, create great works while traveling between battles, and have built and maintain the greatest, most human, most advanced worlds and societies remaining in the Imperium of Man. But by and large, they spend all their time locked in a deathgrip with the universe, dying easily and frequently in endless combat in order to defend humanity, often times from itself.

That’s a key part of the appeal of the faction to me: Those Marines that haven’t become completely inured and numbed to that role must realize the deep tragedy of their lives. The brightest and most foresighted must futilely long for a way out of all the fighting, an impossible cessation of endless, all-consuming war. Though their personal specifics are lost to them through their conditioning (presumably—the fluff’s a bit contradictory), some of them must yearn to go back before they were inducted, when they were still children leading simple lives, unconcerned about the fate of humanity and not facing constant pain and death.

So, I would argue that even besides the choreography, the lyrics of the song actually make it an appropriate choice as well.

Conclusion

I figure there’s half a chance the producers of the trailer really did just throw on a cool song they heard that would maybe help their trailer stand out. That said, there’s little denying the whole video has been crafted around that selection. The choreography is too tightly synced, to music that decidedly requires it. At a minimum they weren’t just crassly thrown together with no effort.

At a maximum, the piece was actually chosen with some thought as to the lyrics and what’s going on in this fictional universe. Obviously all of the textual reading above is bullshit and nonsense. But it’s at least as valid as any literary interpretation out there, and I could believe it occurred to a developer if they happened to be actual fans and devotees of the 40k universe.

Asteroids: Drawing Objects

Recently I’ve started mentoring a local high school student a bit on implementing a video game, and this is a technical note toward that.

Drawing basic shapes out of polygons to represent game objects is straightforward and requires just a bit of trigonometry, outlined here.

Shapes

The core idea is that the polygon is located around the object’s current position. So, a standard looking Asteroids ship might be defined as four points about the origin as in this diagram:

Four coordinates defining a fairly standard Asteroids player ship.

Four coordinates defining a fairly standard Asteroids player ship.

The polygon is captured by a list (array) of points in order around the shape. Caveat other restrictions in the game’s code, it doesn’t really matter if they’re clockwise or counter-clockwise. In this case the ship is defined as follows, proceeding counter-clockwise:

  1. (0, 24)
  2. (-18, -24)
  3. (0, -18)
  4. (18, -24)

One cute trick that’s often done in Asteroids is to randomly generate the polygons for the asteroids themselves. The points list needs to be in order though or else the lines will overlap and the shape look funny. There are several ways to do this, but one is to go around in a circle, picking a random angle within that arc of the circle, picking a random distance from the origin for that tip of the rock, and computing the x & y value for that polygon point using that angle and distance.

Drawing

In most polygon graphics APIs, drawing starts by starting a new shape if necessary (i.e., newpath) and moving the cursor to the first point in the list (i.e., moveto). It then loops over each of the other points and draws a line from the previous position to the current point (i.e., lineto). The path is then either closed by drawing a line to the first point in the list from the last, or using a specific function to close the path if the API has one (i.e., closepath).

Rotation and Placement

Of course, in the game the object typically has to rotate and move. Rotation is simple because we’re taking the object’s current position as the origin of the polygon representing it. Each point to draw just needs to be calculated through the basic rotation formula:

x' = (x * cos(angle)) - (y * sin(angle))
y' = (x * sine(angle)) + (y * sin(angle))

In these formulas, x and y are the current point in the polygon list while x' and y' are the actual points to draw. The direction the object is currently rotated to, i.e.,which way the player is facing, is in angle.

This will draw the polygon around the origin, but of course the object is actually somewhere else on screen. This is a simple translation, effectively moving the polygon’s origin to the object’s actual position. In other words, just adding the object’s x and y coordinates to the point to draw:

x' = x' + objectx
y' = y' + objecty

Minor Complications

Although the ship above has somewhat naturally been modeled facing up, angle 0 in trigonometry is actually facing to the right. So, the polygon should instead be modeled with its natural direction facing that way.

Adding just a small detail, essentially all modern computer displays and most software use a slightly different coordinate system from what’s typically used in mathematics: The origin is at the top left of the screen, and the y axis increases going down the screen, not up. Note that this means the 90 degree angle is actually facing down and 270 degrees points straight up.

A wide variety of ways to work with these facts can be applied, but the easiest is just to model the polygon facing to the right and to keep that coordinate scheme in mind. So, the example polygon above would actually be modeled as follows:

The ship actually facing angle 0.

The ship actually facing angle 0.

The counter-clockwise ordering of points would then be:

  1. (24, 0)
  2. (-24, -18)
  3. (-18, 0)
  4. (-24, 18)

Another small detail to keep in mind is that nearly all trigonometry functions in software libraries are based on radians rather than degrees, though most people work more easily in the latter. Converting between the two just requires a simple formula based on the identity relationship between them:

radians = pi * degrees / 180

Code

A simple demonstration of this is in the box below. Pressing the left and right arrow keys make the ship rotate, and it’s being drawn in the center of the screen rather than the origin (you may have to click on the box first to focus the keyboard on it):

The code snippets for this below are in Javascript, but should be easily applicable to most platforms.

The polygon for the ship has been defined as follows:

var playershape = [
  { x: 24,  y: 0},
  { x: -24, y: -18},
  { x: -18, y: 0},
  { x: -24, y: 18},
]

It’s just an array of points, each a Javascript object with an x and y value. There is also a player object that has its own x, y, and angle, representing the player’s position and orientation on screen.

A couple trigonometry helper functions are defined, to convert degrees to radians, and to rotate x and y values:

function degtorad(angle) {
  return 3.1415926 * angle / 180;
}

function rotx(x,y,angle) {
  return (x*Math.cos(angle)) - (y*Math.sin(angle));
}

function roty(x,y,angle) {
  return (x*Math.sin(angle)) + (y*Math.cos(angle));
}

Note that each of the x and y rotations take as input x, y, and angle, because the rotation formula requires each of those values.

As discussed above, the ship is drawn by starting a path at the first point of the polygon, looping through each other point, and then closing it off. At each step the point to draw is rotated about the ship’s position as the origin, and then translated to the ship’s actual position on screen. This function captures that, and is called by the main drawing routine each time the ship needs to be displayed:

function drawplayer() {
  var x, y;  // These will be the point to draw.
  var i = 0;  // i is the current polygon point we're using

  ctx.beginPath(); // ctx is the graphics drawing context in this Javascript program.

  // Calculate the actual draw point by rotating and then translating.
  x = rotx(playershape[i].x, playershape[i].y, player.angle) + player.x;
  y = roty(playershape[i].x, playershape[i].y, player.angle) + player.y;
  ctx.moveTo(x, y); // Start the polygon at this point.

  // Loop through the other points---note that this therefore begins at point 1, not 0!
  for (i = 1; i < playershape.length; i++) {
    x = rotx(playershape[i].x, playershape[i].y, player.angle) + player.x;
    y = roty(playershape[i].x, playershape[i].y, player.angle) + player.y;
    ctx.lineTo(x, y); // Extend the path from the previous point to this new one.
  }
  ctx.closePath(); // Close the path by adding a line back to the start.
  ctx.stroke(); // Draw the path.
}

To initialize the player, its position is set to the middle of the screen and its orientation set as facing straight up:

  player.x = canvas.width / 2;
  player.y = canvas.height / 2;
  player.angle = degtorad(270);

Each time the left or right key is pressed, the ship’s angle is updated like this.

    player.angle -= degtorad(10); // Decrease the angle by 10 degrees, making the
                                  // conversion to radians first before subtracting
                                  // from the current angle.
    while (player.angle < 0) {        // This actually isn't necessary, but just makes sure
      player.angle += 3.1415926 * 2;  // the player's angle is always between 0 and 2*pi.
    }                                 // The drawing routines and other logic will all
                                      // handle that fine, but it can make things easier for
                                      // the programmer in writing other parts of the code.

Conclusion

Those are the basic elements in drawing a simple game like Asteroids. The next complication is having an array or arrays of game objects. That’s necessary to capture all of them that might appear on screen, namely the rocks and bullets. A drawing function like that above then needs to be applied to each game object in the array(s), rather than being just hardcoded to a single game object instance like this example is to the player’s ship.

Chelicerae WIP

WIP of the main body for the Chelicerae Automated Sentry Platform:

platform

Ponoko estimates $8–12 to 3D print this, depending on the granularity of the material used. Nearly all of that is the setup and design review flat fee. The material costs are less than $1.50 in both cases. Hopefully then adding a turret and guns won’t increase the cost substantially. As a point of comparison, the Forge World Space Marine Tarantula weapons platforms are $26 USD. I’m trying to see how bespoke 3D printing will stack up in comparison, looking good so far.