1. icon for News
  2. icon for TCHOW

News

Monday, August 26, 2013

Learn to Play Rktcr

There have been a few let's plays of Rktcr recently -- which you should definitely check out -- It's really fun to see people picking up the game and getting into it.

However, the general conclusion from these folks seems to be "wow, I could definitely solve this if I had more time to put into it." You'll see a lot of failing in these videos. This led me to create my own quick Rktcr video series...

Learn To Play Rktcr

This series is aimed at teaching you (the Rktcr neophyte) basic tools and habits that will make you an effective player and -- ideally -- decrease both my frustration when I'm watching you and your frustration as you are playing.

There are ten videos in the playlist, and I feel like I really hit my stride around video four or five.

Note also that the sound quality on my webcam microphone is somewhat poor. It's listenable, but I will keep this in mind when recording future videos.

Thursday, August 22, 2013

Rktcr Wallpapers and Posters

I've been spending most of my Rktcr-related time over the last few days sending out free copies to reviewers and lets-players. This is actually quite time-consuming, since I'm writing a new blurb for each person. I know it would be simpler to copy-paste, but it seems only fair that if they are going to invest the time to check out the game, I should invest the time to write something for just them.

However, I have put a little time into making cool assemblages of Rktcr sprites. These might work well as posters or desktop wallpapers (though they are perhaps a bit busy for a desktop with icons). Regardless, I like the way they look.

I can make these in pretty much any aspect ratio and resolution, so if you would like a custom size, let me know via e-mail or comment.

Posters

These were designed for 11x17 (top row) or 8.5x11 (bottom row) paper. Feel free to download and print.

Wallpapers

I included some dark variants for the desktop wallpapers because, well, you never know.

Wednesday, August 21, 2013

Rktcr: Now for sale

Rktcr is now for sale on Desura. It's $5 now, and will be $10 if you wait too long.

Your TODO list:

  1. Try the Rktcr demo. If you like it, proceed to (2), else goto (3).
  2. Buy Rktcr.
  3. Tell folks you think might like Rktcr about it.
  4. Help me come up with things I should do if Rktcr sales reach various targets.

In service of (4), let me say that I will change my hair/beard style if Rktcr sells more than 1024 copies.

Please leave more suggestions in the comments below, should you feel so inclined.

Tuesday, August 20, 2013

Rktcr Demo3

Rktcr's third demo is now available, (actually it was out yesterday, which you would know if you followed me on twitter) with improved future visualization, a new example world, snappier dialog, and a host of little tweaks and improvements.

I'll get into just what (some of) those tweaks and improvements were in a moment. Before that, let me strongly encourage you to:

Download Demo3 now. (August 19, 2013)

Contains Windows (Vista or later; 32-bit), OSX (10.7+; 64-bit), and Linux (64-bit) builds. Requires a recent, OpenGL-capable graphics card, a few gig of memory, and a vigorous spirit.

Like previous demos, this demo corresponds to a full version (from which the above screenshots are drawn). Unlike previous demos, you should be able to actually buy this full version... soon. now, over at Desura. The price is $5 for early adopters, and will increase to $10 in about a month.

Changes

  • Future visualization is drawn using full wheels instead of lines; collision and rotation are now much easier to gauge.
  • The example world has been changed to feature levels that showcase each core movement mechanic in the game (and happen to include some of the new levels).
  • Dialog included with the demo is a different plot than previous demos, and has been re-written in a much less verbose [though perhaps not less unique] style.
  • Gems have individual appearances.
  • Font size for challenge levels and team names is larger.
  • Times now typeset with lighter leading zeros (slight readability improvement).
  • Portal glimmers and flame particles fade when travelling.
  • Gems do not change colors when travelling. (Though, for reasons of temporal mechanics, objects may still appear to shift when moving backward in time through a portal. Time's weird like that.)
  • VSYNC enabled.

Sunday, August 18, 2013

Rktcr: Tying Up Loose Ends

It was not so long ago that I was making a list of what needed to done for Rktcr's release. Today, I find myself with a finished list, polishing and adjusting little things.

I realize, however, that I haven't posted about two of the items on that list, despite having finished them a while ago. So this post will (briefly) remedy that.

World Trimming

This took longer than expected to finish, as I managed to run into a few world generation bugs along the way. Specifically, it turned out that my code for selecting gem/non-gem levels was modifying the wrong array, so worlds were being generated without very many (or sometimes any) non-gem zones. Fixing this revealed that that proportion of non-gem zones was too high, and so I adjusted further.

Once I got world generation working the way I wanted, trimming was relatively straightforward. I ended up going with the average score method outlined in this post.

After trimming, every zone appears in 15%-17% of 3-gem worlds; 36%-38% of 7-gem worlds; and 73%-75% of 14-gem worlds. This is about as even as I could have hoped for.

Dialog

As planned, I re-wrote the script from the demo ("oracle") and added a new script ("sheriff") based on some ideas I had kicking around. Both are quite snappy -- I limited the number of lines in each scene to as close to bare minimum as I could.

I also, just today, finished a second editing pass; mainly for positioning. With this, I'm confident enough in the dialog to call it done.

Friday, August 16, 2013

Finishing Rktcr's Worlds

Rktcr's list of things to do before release is getting pretty spare. One of the major unfinished bullets was the creation of a few more world levels, three of which I had done already, and three of which I finished up today.

I also decided to stream the creation process, and you can watch the recordings over here. At one point I had four simultaneous viewers (though that might have just been a counting glitch).

The Levels

From left to right, I added: a zone that uses disruptable platforms in excellent (and tricky) ways; a zone all about platform straddling and momentum; and a zone that is about doing straddle jumps.

For each zone, I played through all possible paths to provide information for the world generator (and establish par times).

The above image shows the 127 paths I managed to finish out of the 144 -- that's (3 starts) x (3 ends) x (8 gravities) x (gem / no gem) -- I attempted. Creating these paths tends to take up the bulk of my level-building time; it can occasionally be frustrating, but mostly is a pretty calming experience.

It also impresses me that I'm still finding new refinements and strategies for getting the vehicle around. I think that there are folks out there who are going to connect with this game and do some amazing things.

Thursday, August 15, 2013

More Music for Rktcr

Today's chunk of work on Rktcr included the creation of four more challenge levels (two in the impossible category!); updates to path drawing; the inevitable bugfixes; and -- what I'm actually going to talk about in this post -- some updates to the soundtrack.

Rktcr's soundtrack is largely drawn from my (quite large) collection of Reason noodlings. (Many of which are entirely unsuitable for game music.)

What I Added

Today, I set out to finding and/or build music for the challenge levels and the passages. I wanted contemplative tracks, uncomplicated, but with a bit of motion. I think I dug up a few good ones.

Here are two of them:

Elevatored Chimes is probably the mellowest piece of music I've ever created. It was sitting around mostly complete but unmixed, and seemed perfect for the beginner challenge levels in Rktcr. After a bit of EQ-ing to integrate the oboe and chimes (and knock some sharp corners off the strums and drums), the resulting track is a calming blur.

Evidence of Motion is a track that I started earlier this week as... well, something different than this. But I found a nice hats loop which pushed it into what it is now: calm, with a bit more motion than Elevatored Chimes. As such, I think it makes sense as the background for the intermediate challenge levels.

Other Tracks

A few other tracks, which aren't uploaded to Soundcloud:

I unearthed and recut an old track called "Rktcr Background Mockup" (which, perhaps startlingly, wasn't in the game yet); I haven't decided if the resulting "Mockup" will get used for impossible challenge levels or for world levels without gems.

The other contender for the background of impossible challenge levels is a track called "Piano Figure" which I spent some quality time reworking and extending today. It has some a-freaking-mazing drums in it (bordering on too big for game music), and a cello top line which is perhaps a bit grating; but the track has a good heart. (It's also 6/4 time with drums on the 1's and 3.5's -- I love that syncopation energy.)

Wednesday, August 14, 2013

More Rktcr World Variety with Flip Connections

One of my (smaller) TODOs for Rktcr's release was to improve the flexibility of world generation by changing the way that connections work.

Connections used to work like this: there were "on left" and "on right" portals. When portals were connected, the combination of their on-left flags and up-vector would uniquely determine which of the two possible portal-matching transformations (mirroring + rotation or just rotation) got used.

With my update, there are only portals with an up direction. Connections are responsible for indicating whether portals are connected with matching up-vectors (and mirroring) or opposite up-vectors (and no mirroring).

Why is this an improvement? Well, portals are stored with their levels, so are fixed for all worlds; connections are stored with worlds (really, connections define worlds). So with this update, world generation has effectively twice the number of possible connections to choose from. This allows for more varied worlds and more replayability.

Monday, August 12, 2013

Rktcr's Mineral Pipeline

In Rktcr, your goal is to come up with a path that collects fourteen gems (at least for teams with large-size worlds; smaller worlds have fewer). Until recently, these gems had clever names (and mineral associations), but all drew the same in game. Since gem styles was an item on my release to do list, I spent some time over the last two days making each gem unique.

In this post, I'll talk about how I made these gems. The content pipeline isn't very long (blender + a python script), but it certainly served its purpose adequately.

It's also worth saying up front that I included in Rktcr several minerals not cut into gemstones. Dialog still refers to these as gems. The pedantic among you may abhor this.

Modeling: Blender

All the gems in Rktcr start in Blender -- a 3D modelling program I've been using for a long time. One of the great things about Blender is the integrated python scripting. The following script scrapes all objects named "Gem:*" out of a .blend file and deposits triangle lists into Rktcr's distribution directory:

#!/usr/bin/env python

import bpy
import struct
import math

for obj in bpy.data.objects:
    if obj.name[0:4] != 'Gem:':
        continue
    gem = obj.name[4:]
    print('Doing ' + gem)
    blob = open('../dist/gems/' + gem + '.blob', 'wb')

    mesh = obj.data
    count = 0
    for poly in mesh.polygons:
        count += (len(poly.vertices) - 2) * 3
 
    for poly in mesh.polygons:
        norm = poly.normal
        a = []
        a_norm = []
        b = []
        b_norm = []
        for vi in poly.vertices:
            vert = mesh.vertices[vi].co * 0.1
            if poly.use_smooth:
                norm = mesh.vertices[vi].normal
            if len(a) == 0:
                a = vert
                a_norm = norm
            else:
                if len(b) != 0:
                    blob.write(struct.pack('fff',*a_norm))
                    blob.write(struct.pack('fff',*a))
                    blob.write(struct.pack('fff',*b_norm))
                    blob.write(struct.pack('fff',*b))
                    blob.write(struct.pack('fff',*norm))
                    blob.write(struct.pack('fff',*vert))
                    b = vert
                    b_norm = norm
        blob.close()
quit()

Loading

Why write out binary blobs instead of (say) using .obj export? One big reason is simplicity. This is the code I use to import the models:

Vector3f vert, norm;
while (
    file->read(reinterpret_cast< char * >(&norm), sizeof(norm)) && 
    file->read(reinterpret_cast< char * >(&vert), sizeof(vert))) {
    verts.push_back(vert);
    norms.push_back(norm);
}

Of course, it would be even simpler to slurp the file directly into (GPU?) memory, but I decided to defer that because it would require monkeying a bit with Rktcr's file handling layer.

Rendering

Minerals rendered as diffuse-only shaded models would be pretty boring. After casting about for a one-size-fits-all rendering approach, and being unsatisfied with everything I could come up with, I ended up crafting seven different display styles.

Diffuse

Even though diffuse rendering is rather boring, it is used in-engine for rendering "ghost" gems -- gems the player has already picked up on this path.

Clear

Clear gems are rendered in two layers -- a back shell and a front shell. Both shells are rendered using a base color and an additional highlight looked up from a lighting texture using a pseudo-reflection vector. Lighting on the back shell is tinted to the gem color, while lighting on the front shell is simply added.

Metallic

Metallic gems use one layer rendered with a Phong material. For being such a simple shading model, it works quite well (especially when coupled with the right geometry).

Dusty Metallic

The dusty metallic model is metallic with a "dust" texture used to modulate the specular power and alter the diffuse color. I found that using Blender's rendering of the gem with only ambient occlusion was a good starting point for dust textures.

Refractive

The refractive style is used for a few different minerals that occur in not-so-pristine crystals. It renders the gem with a dust texture (like "dusty metallic") and highlights from texture-based vertex lighting (like the "clear" style). Additionally, the inside of the gem is rendered by looking up in an "inside" texture using a pseudo-refraction vector.

Unfortunately, for all its sophistication, I'm not very happy with the outputs of this style just yet. It can be very tricky balancing the dust, lighting, and refraction effects to achieve a nice look.

Tourmaline

The "tourmaline" style started out as a single-purpose rendering engine for -- you guessed it -- tourmaline; however, I ended up using it for one other mineral as well.

This style renders in a single pass, generating front and back reflections using two different psuedo-reflection vectors. Like a "clear"-style gem, the front reflection is added and the back reflection is modulated. However, unlike a "clear"-style gem, the tint color is set using a texture.

Opal

The opal gets its own rendering engine to deal with the milky outer shell and the reflective inner fire. The gem is drawn in three passes -- the shell is drawn with low opacity, the fire, then the shell again.

The fire is made to shimmers by using a pseudo-reflection vector to look up vertex colors in a texture.

The shell uses a modified diffuse lighting model to fake subsurface scattering.

The Finished Minerals

Above, you see all fourteen gems (plus the goal gem for challenge levels and a placeholder gem used in the editor) rendered by the game; I'm not entirely happy with all of them yet (e.g. obsidian probably needs a second light to have good contrast with the background). However, this is probably quite close to the set of gems that I'll be shipping August 21st.

Saturday, August 10, 2013

World Curation for Rktcr

As I close in on a full public release of Rktcr, one of my tasks is to settle on a set of worlds to ship with the game. I've already talked about how my code generates worlds, but this is only part of the story.

You see, the pool of worlds I generate is skewed -- only candidate worlds that are solvable are maintained, and this tends to bias toward worlds that use zones with many potential paths. But how bad is this skew? To investigate, I generated 1000 3-gem worlds and made a plot of the number of times each zone appears divided by the total number of zones:

Ideally, this curve should be flat -- each zone should appear about the same number of times. But this is not the case.

The zone on the far left (which actually only appears once out of the 1000 worlds) doesn't have its claims properly set, so -- as far as the world generator knows -- is basically impassible. This should change once I re-work the level somewhat, so it is probably safe to ignore.

However, the second-least-frequent zone is still about than 8 times less likely than the most frequent zone.

Flattening the Distribution

There is no reason for me to ship this set of 1000 worlds, however. Is there a subset with a better distribution of zones? It appears so:

One trimming method I came up with is to repeatedly pick a world whose zones all appear more frequently than average, and remove that world. This flattens the curve somewhat, but soon enough the method runs out of worlds to remove.

The max-min approach removes the world with the most frequent least frequent zone; since this can always find a world to remove, I terminate the search when there are 100 worlds remaining.

Finally, I tried an approach that repeatedly removes the world whose zones have the highest average frequency. This flattens the size-3 worlds the most of any of the methods, with the second-leftmost and rightmost zones only varying about 5% in frequency. (I'm disregarding the leftmost zone, as I mentioned above).

Using the average-frequency metric does seem to come at a slight price, however -- the average number of zones per world decreases to 5.2, from an average (over the starting 1000) of 5.5.

Large Worlds

Three-gem worlds are the smallest that appear in Rktcr. How do these approaches work on the medium (seven-gem) and large (fourteen-gem) worlds? Are they even needed?

Looking at the frequency of each zone in 1000 worlds with seven gems (left), and fourteen gems (right), it appears that some leveling might help. Interestingly, the fourteen-gem worlds already seem more balanced. I conjecture that this is because they are each already using (on average) 25 zones of the 30 possible, which makes it hard to not pick a zone; additionally, the larger world size may provide more flexibility in entering a zone resulting in more potential for completion.

The top-half strategy fails to work for both seven-gem and fourteen-gem worlds as they tend to contain more than half the zones already, so always have one which is less frequent than average.

Max-min again provides some leveling, especially effective at the bottom end (in terms of frequency).

Finally, removing worlds with the highest average frequency works well at the top end, though the fourteen-gem worlds result (right) does have a pronounced jump at the most frequent position, and both suffer from a roll-off toward the left.

Further Investigation

It appears that, for three-gem worlds, the average frequency heuristic works well; while for larger worlds, some combination of average frequency and maximum minimum frequency might be better for leveling the distribution at both the high and low ends.

However, frequency of appearance doesn't tell the whole story. In a follow-up post, I plan to investigate the co-occurrence of zones as well as (possibly) the connections between zones. It will be especially interesting to see if the trimming strategies I've outlined tend to skew these other statistics.