1. icon for News
  2. icon for TCHOW

News

Tuesday, September 24, 2013

Making Rktcr Levels: Disruptable Platforms and Gems

In this Rktcr editing tutorial, I'll talk about how to create disruptable platforms and gems. These are platforms and gems that only one of the vehicle's wheels collide with. This tutorial assumes knowledge of the editor basics.

If you own the full version of Rktcr (and, really, you should), you can grab this level pack to follow along.

In this tutorial, we'll make a level where the player needs to navigate out of the a starting box by letting the front wheel fall through one segment and the back fall through another. After this, the player will need to pick up the final gem with the appropriate wheel (lest it be knocked into the abyss).

Disruptable Platforms

First, we'll make the two short segments in the bottom of the starting area disruptable by going into property edit mode (select, shift-tab), selecting collide (up/down, then enter), and changing the value to 1/2 for the left/right segment (delete, 1/2, enter).

The polygons will now be highlighted in white/gray, indicating that the front/back wheel (only) will collide with them.

Of course, it never hurts to actually check by playtesting the level (select start portal, then press enter).

Disruptable Gems

Making the gem collide (instead of be picked up by) the front wheel is a similar procedure. Select the gem, drop into edit mode (tab) and set the property front_collide to 1:

The gem will be surrounded with a white band to indicate that the front wheel collides with it.

As before, you can always confirm that things are working as you expect by playtesting.

Conclusion

In today's rather short tutorial, I showed you how to make disruptable platforms by setting the collide property on level geometry, and how to make disruptable gems by setting that front_collide and back_collide properties on gems. It is worth noting that -- though we did not do so in this tutorial -- you can also change the collide property on dynamics.

Disruptable platforms and gems can lead to situations where players need to carefully consider the vehicle's orientation. They can add challenge to maze-like levels and also allow for tricky momentum-conservation strategies (like letting the wheel that does not collide spin around the one that does).

Next Steps

I've covered nearly all of the features of the Rktcr editor. The only tutorial subjects that remain are bursts; style layers; and claims.

Tuesday, September 17, 2013

Making Rktcr Levels: Dynamics and Constraints

In this Rktcr level creation tutorial, I will describe how to add dynamic (i.e. physically-simulated) geometry to levels, and how to add constraints between these dynamic bodies. This tutorial builds on ideas introduced in the basics and geometry tutorials.

And, as before, you'll need the latest full version of Rktcr (v3.1 as of this writing).

In this tutorial, I'll start with some existing static geometry, and make some of it dynamic. Above, you can see the plan I'll be following.

If you'd like to follow along, you can download a zip file containing this level (along with the finished version) here. Place the files in your ".rktcr/e_levels" folder, start Rktcr in edit mode, and load tut-dynamics with f4.

Making Dynamics

In Rktcr, all dynamic bodies are created from static geometry, much in the same way smoothed polygons are created from regular polygons.

Select the static geometry you'd like to make dynamic with right-click, press space to open the creation prompt, type dynamic (or dtab, if you're feeling lazy), and press enter.

You can make a dynamic body static again by selecting it (right click) and pressing x. (This deletes the "dynamic" modifier.)

Dynamics Parameters

Dynamics have two types of edit mode: geometry (tab), and parameter (shift-tab). Geometry edit mode does what you'd expect -- edits the geometry underlying the dynamic. Parameter edit mode allows you to change some physical (and physics-effecting) parameters:

  • source_tag shouldn't be changed.
  • seed is the seed for the (somewhat randomized) convex decomposition algorithm. If you don't like how the dynamic is being split into red and green regions, change this.
  • gravity is the direction of gravity effecting the block (0-7 are fixed, 8 is "down relative to the current view").
  • density is what it sounds like. If the object seems too heavy, use something lower.
  • moment_factor scales the moment of inertia. Increasing/decreasing will make the object spin less/more easily.
  • rel_pos is a starting offset for the object as (x,y,theta). It don't recommend using it.

Warning

When working when dynamics, save often! Sometimes, the convex decomposition produced by Rktcr's code can contain degenerate polygons, which -- in turn -- will make Box2D (which Rktcr uses for simulation) assert() when you attempt to test a level.

There will be a fix for this in the next version of Rktcr. Until then, save before you test. (The -- admittedly cumbersome -- work-around is to change the seed value used on the problematic dynamic until you find one where the editor doesn't exit upon running the level.)

Testing

This is what the level looks like after creating all the required dynamics:

At this point -- be sure to save! -- you can press enter to go into physics test mode. (If you end up in play test mode, it's because a portal side was selected.) In physics test mode time runs inexorably forward, and you can grab and pull on objects using the mouse.

Physics test mode will be useful as we create our various constraints.

Constraints

Plain dynamics bodies are fine for creating stacks and tippy platforms, but for the sort of stunts we have planned for this level, we need some physics constraints. Physics constraints are created in the Rktcr editor by pressing c. This creates a constraint between the current dynamic selected and either the previous two dynamic selected or (if the previous selection wasn't a different dynamic) the world.

Another way to say that is: to constrain two dynamics to each-other, right click on them in turn and then press c; to constrain a dynamic to the world, right click on it twice and press c:

Once a constraint has been created, its endpoints may be moved by pressing g while the constraint is selected:

Pressing tab while a constraint is selected allows you to edit its type:

For the hanging circles in the level, we want the constraint type rope, which prevents the constraint points from getting further apart (but does allow them to get closer).

Adding Ropes

Let's finish up the rope constraints. Keep in mind that x can be used to delete constraints, and make sure to set the constraint type to rope (using edit mode -- tab). Also, I find that using the size-1 grid (1) and holding shift (snap to grid), helps to keep things aligned when moving constraint endpoints.

Note that the red/blue color of the lines connecting a constraint to its adjacent dynamics depends on the order in which they were selected, and isn't important to the actual simulation (so if yours don't match mine, don't worry).

At this point (and after saving), you can drop into test mode with enter and make sure everything moves how you want it to (e.g. try dragging the circles with your mouse to get a feel for the rope constraint).

Other Constraints

The first stunt in the level uses rod constraints. Create these as before, but make sure there is no previously selected dynamic by right-clicking on the c-shaped piece twice before pressing c. If you do this properly, one end of the constraint (the one connected to the world) will show as an x instead of a box. Also, make sure to set their type to rod in edit mode (tab).

I slightly offset the bottom sides of the rod constraints because if I let them start vertical the c-shape would fall before the vehicle entered it. (This is one reason test mode is super-useful when working with dynamics.)

Finally, connect the ramp to the background with a pin constraint, so it will pivot up as the vehicle drives under it and then fall back into place. (Note that pin constraints are actually placed at the average of the two endpoints.)

The constraint's type should be pin by default, but it doesn't hurt to hit tab and check.

Finishing Up

All the constraints are now in place:

Generally, it's good to playtest levels as you go along, but I elided that for the sake of this tutorial. So, the question becomes: is this a winnable level?

Well, the last part is quite tricky (removing the circles might be a good idea), but, yeah, it is possible.

Next Steps

Dynamics are one way to add excitement (and chaos) to a level, but certainly not the only way. In upcoming tutorials, I'll talk about other methods, including working with disruptable platforms and gems; and adding bursts. I'll also go into making your level prettier using style layers; and giving folks a par time using claims.

Sunday, September 15, 2013

Brighter 'Bows

The HTML5 version of Rainbow features vibrantly colored Rainbows; when porting to C++, I traded off a bit of the brightness of the rainbows for softer intersection behavior. This weekend, I set out to brighten the bows in the C++ port, while retaining nice bow intersections.

html5: bright bows

old C++: dull bows

new C++: bright bows

As you can see, the C++ version has been improved to have bows as bright as the HTML5 version.

The Goal

In Rainbow, the player can split the rainbow they control into multiple "fronts" and drive these fronts separately. Each front leaves a rainbow trail.

I would like several conditions to hold:

  1. Trails freshly produced by a front should draw over older trails.
  2. Fronts should always remain visible.
  3. No hard edges should be introduced.

To justify briefly: (1) arises because I want players to see what they are currently controlling; (2) is important because players should be able to see how much rainbow they have left; and (3) just seems like how magical rainbow substance should behave.

The Old Solutions

HTML5

In the HTML5 version of Rainbow, the entire rainbow is redrawn each frame with each vertex's depth set based on the number of ticks from the beginning of the rainbow. This method actually fails all three of my ideal conditions in some cases, e.g. when drawing with an older front.

C++

In the C++ port, the rainbow is accumulated into a framebuffer. This pretty much guarantees that condition (1) holds. Condition (2) is satisfied by always drawing (but not accumulating) the very front of the bow over the top of everything in a different rendering pass.

This leaves condition (3) -- no hard edges. This is solved by drawing the blow slowly instead of all at once. Specifically, every time a front moves, it draws over its last 10 positions with partially-transparent segments. This has the effect of slowly building up the bow color over 10 steps:

Unfortunately, because it draws over each of the old positions with the same opacity (alpha value) -- set, in an ad-hoc way to 1/8th -- the effective opacity of the bow is only about 73%.

The New Solution

Let me start by considering a simpler version where we only draw over the last 4 locations. Labeling the segments that get drawn as 1-4 and the locations traversed a-g (both from oldest to newest), one can sketch this diagram:


  ...               ...
frame 4:         1 2 3 4
frame 3:       1 2 3 4
frame 2:     1 2 3 4
frame 1:   1 2 3 4
          ---------------
location:  a b c d e f g

I.e. location a will be drawn into by segment 1, and then no others; location b gets drawn by 2 then 1, location c by 3 then 2 then 1, and so on.

So what opacity value should we pick for segment 4 if we want locations d and beyond to have opacity αtarget? Well, it depends what the next passes (1-3) will draw over it. Let's say that segments 1-3, when drawn, will cover fraction αnext of a pixel. Then we can select opacity value x for segment 4 by writing down the blending equation:

αtarget = αnext + (1 - αnext)x

αtarget - αnext = (1 - αnext)x

x = (αtarget - αnext)/(1 - αnext)

This passes some basic sanity checks -- if we want 100% coverage after segments (1-3) are drawn (i.e. αtarget = 1), we need to draw segment 4 with 100% opacity (i.e. x = 1). Also, if αnext is greater than αtarget then we get negative values -- which makes sense, as segment 4 can't prevent the subsequently drawn segments from covering the location, so it needs to attempt to preemptively remove coverage.

Implementation

Since I'd like the rainbow to smoothly fade in from a cleared start, I chose a "fade" opacity value, f to vary smoothly from 0% coverage (at the trailing edge of the oldest segment) to 100% (at the leading edge of the newest).

In the pixel shader, other factors that influence opacity -- band color, edge-of-band "antialiasing" texture -- are looked up. Letting their product be called m, the shader sets:

αtarget = f * m

αnext = min(1.0, f + 1/10) * m

These values are used to compute the final opacity value x as outlined above. This results in a variable-opacity front that produces a more vibrant bow:

Next Steps

I was a bit worried about having a divide in the pixel shader, but profiling on iOS shows negligible effect on frame time.

Since all of this math is actually done on 8-bit color values, some inaccuracy (and banding) does result. I could avoid this (and the above-mentioned divide) by doing the computation of x with a look-up-table that takes these errors into account. However, the artifacts are not so severe that this is a high priority.

Some Methods That Didn't Work

Before settling on the present solution, I tried all sorts of other ideas including multi-pass rendering and different blending modes. While none of them were what I wanted, they did produce some interesting pictures.

Monday, September 9, 2013

Making Rktcr Levels: Geometry Types

In this Rktcr level editing tutorial, I will talk about the different kinds of level geometry available to you in the editor. I will assume familiarity with the basics of Rktcr level editing.

As before, Rktcr full version 3.1 or newer is required. (While version 3.0 technically includes the editor, it fails to include a font used thereby.)

You can grab the level pack for this tutorial here. The 'tut-geom' file is the starting point and the 'tut-geom-finished' is the finished level. To make us of them, place the files in your ".rktcr/e_levels" folder, and load into the editor using f4.

Getting Started

To start this tutorial, create and name a portal side ("start") and gem ("goal"), and save (f1) this as a new file. I placed the portal and gem far apart because I anticipate adding lots of platform geometry, but you can always place them wherever and adjust it later. (You could also use the starting point from the level pack, but it's probably quicker just to create it yourself.)

Types of Geometry

When you open the create prompt -- space, then backspace to delete that pesky space that appears the first time you open it for some reason -- you'll notice quite a few options:

We will be using all of the geometry-related options in this tutorial. A brief overview:

Create Menu Options

  • poly -- create basic straight-line polygons. Workhorse geometry, covered in the basics. Reviewed below.
  • arc/[->arc] -- create/[turn selected polygon into] arc-gon -- a polygon where each corner is replaced by a circular arc. Covered below.
  • smooth -- create a subdiv-smoothed version the currently selected polyon. Covered below.
  • dynamic -- create a dynamic (rigid body) version the currently selected polyon. Will be covered in a later tutorial.
  • side -- create a portal side. See the basics.
  • gem -- create a portal side. See the basics.
  • paint, ppoly, ppoly* -- functions relating to level-set-painting geometry. Covered below.

Polygons

First, let's create some polygons; they are a good fundamental starting point, after all. Additionally, the polygon editing controls remain useful for arcgons and smooths.

The controls for polygon creation are explained in detail in the basics, but to briefly review: tab to toggle edit mode; right-click to select, shift right-click to multi-select; grab, scale, and rotate to move verts; extrude and divide to create more verts; x to remove verts.

Arc-Gons

Now let's add some arc-gons to the level. Create an arc-gon using the prompt and drop into edit mode (Space, arc, enter, tab).

All the polygon editing controls still work, but now apply to the "cage" around the actual arc-gon. Additionally, left-click dragging will edit the radius associated with the selected corners.

When two adjacent corners's radii are longer than their edge, their radii are clamped. You can use this to precisely control the radius of a corner by placing a zero-length vertex some (fixed amount) of grid units away:

For example, in the above picture, the marked verts constrain the bottom left and upper right corners to have radii no greater than one grid unit and two grid units, respectively.

Converting Polygons to Arc-gons

One can also create arc-gons from polygons using the ->arc create command. This will convert the current polygon into an arc-gon with zero-radius corners.

Here, I've used ->arc on a duplicate of the left ceiling polygon, then smoothed the internal vertices by going into edit mode, selecting them, and left-click dragging.

Really, you could just always work with arc-gons, but sometimes you don't want to worry about accidental left-click drags introducing small-radius corners.

Smoothed Polygons

Another way of creating polygons with smooth corners is to use the subdivision modifier. These look "gooier" and a bit more organic to me than arc-gons.

Above -- from left to right -- I've created a poly and modified it a bit; then selected it and applied smooth (space, smooth, enter); and, finally, dropped into edit mode (tab) to adjust the vertices more.

Note that duplicating a smoothed poly will give you a copy of the underlying cage, not the smoothed version, and pressing x on a smoothed poly will delete just the smoothing.

Level-Set Painting

Our level is coming along nicely. Let's finish it off by creating some geometry with level set painting. Painting is a free-form method of specifying geometry; you draw values into a grid, then extract contours of this potential field for use as level geometry.

To start, we'll need a canvas to paint on. Create one by typing paint at the create prompt (i.e. space, paint, enter). This will immediately drop into painting mode.

In painting mode, you add material with left-click and remove it with right-click. Red lines show the level geometry that (may) be created from the current paint. The yellow line shows the outline of the canvas. This will be automatically resized if you paint outside its borders.

The brush has two parameters, a radius (modify with shift-mousewheel) and a falloff distance (modify with ctrl-mousewheel). The above image shows a few options. The falloff doesn't really do much unless you start painting a lot of positive and negative strokes, in which case it changes (a bit) how the generated geometry moves.

If you are painting large areas, the editor can bog down. In this case, you can use up arrow and down arrow keys to adjust the painting grid resolution. This is non-destructive (you can always switch back to an old resolution without a problem).

Note also that some simplification is always run on the output level geometry, so using finer grids may not actually change the number of vertices in your level.

Adding Paint-Polygons

If you have been playtesting your level, you will have noticed that your awesome paint doesn't actually appear in the game yet. This is because you need to create paint polygons to pull information out of the paint.

The ppoly* command (i.e. space, ppoly*, enter) creates paint polygons for all contours in the currently selected canvas, while poly creates a polygon based on a seed point at your current mouse cursor.

Once created, paint polygons can be grabbed to offset them from their canvas positions, or deleted with x (useful for removing shards). Additionally, changes in the original canvas will be reflected in the extracted outlines. This can be useful for minor edits to platform shapes.

Note that sometimes -- due to, e.g., topological changes in the canvas -- one can end up with multiple ppoly's for the same contour. This results in overlapping geometry and is generally bad news for your levels.

Wrapping up

In this tutorial, I showed you how to use Rktcr's four different types of level geometry: basic polygons, the somewhat smoother arc-gons, the organic looking smooth modifier, and the freeform paint-based geometry.

I find that each type of geometry lends itself to a different style of level -- as you'll notice in the game -- but that it can occasionally be useful to mix them up for specific situations.

Next Steps

Now that you are familiar with the various ways to create level geometry, it's time to add details and graphical polish. In upcoming tutorials, I'll talk about adding dynamic objects and constraints; working with disruptable platforms and gems; adding bursts; making your level prettier using style layers; and giving folks a par time using claims.