I moved to a new URL! Check it out!

posts tagged with: programming

Dev Log: More Skeletons!

Dev Log: More Skeletons!
This past week has been spent working on some Otter technology for implementing my own skeleton and bone systems.

Image


But Kyle why aren't you using Flash or Spine or Spriter or some other way to implement bone animation!?

Well in regards to flash, I've seen what is necessary for writing a flash file interpreter and I am totally not interested in going down that path at all. Flash is already a giant pain to use for just frame by frame animation, and I've used to create animations way back in my flash cartoon days of college, and that is something I don't want to relive. I wish Flash got an overhaul in regards to its UX, but that'll never happen, so I don't want to rely on it.

In regards to Spine and Spriter, I already use Spine for pure art based skeletons. The thing about Spine is that I actually cannot include the Spine runtime for Otter by default -- it has to live in a separate repository. This is because it is a violation of the Spine license to distribute the runtime to users who may not have purchased the full version of Spine. That is the main issue there, and also I have no idea how to use the Spine skeletons for what I want to do, nor do I know how to create Spine skeletons on the fly at runtime. I would use Spriter, but so far I have not seen any C# runtimes or APIs that don't have major issues.

Image


I ended up just creating my own since I felt that takes less time than learning how to use another tool, and since I have a very simple use case for this I can just jam out my own solution in a relatively quick time. I don't have any need for complicated animation files or animation blending or anything like that. This system is mostly designed to manipulate Entities in Otter, so that I can create big bad enemies built out of multiple pieces.

Also it may end up being the case that these enemies will be created at run time procedurally. If that is the case, I would have no idea how to implement that using Spine, Spriter, or Flash's systems.

Dev Log: Skeletons

Dev Log: Skeletons
This past week I've been chipping away at some general changes to Otter as well as doing some quick experiments with some things that I eventually want to include in my bigger game project.

The most recent of these experiments is setting up a general purposed skeleton system. The main idea is that I want to be able to make up enemies and other objects with a bunch of individual pieces that move around and animate. Normally I could say just using something like Spine or Spriter is good enough for this, but for this I wanted something of my own creation.

Image


The idea is that there is a Skeleton Entity in Otter that contains bones that all move, rotate, and scale based on their parent. Typical skeleton bone behavior. The difference is that each bone can hold an Entity on it. Each individual Entity on the bone can then have its own logic, so for example the first thing I want to have is the ability to destroy individual pieces of the skeleton. I can do that by having the Entities on each bone have logic for taking damage and being destroyed.

Image


So far I have one early iteration of this working but I'm realizing that the math that programs like Spine and Spriter do might be slightly different, and I'm trying to figure out exactly how they approach their transformations. It's a little difficult to find any articles or tutorials on how to code this stuff up yourself, as most people assume that using Spine or Spriter is what you want to do. I could potentially go back to using Spine and try to figure out how to wrangle its data format into loading a Skeleton into my custom format, but sometimes just making something yourself from scratch ends up being more straight forward!

Dev Log: Color Grading Shader

Dev Log: Color Grading Shader
I love post processing shaders! I think they're one of my favorite things to mess with now that I have a cool C# game making framework to play around with. One of my latest experiments was implementing color grading into Stratoforce, and by extension all of my future games built with Otter.

What's color grading? Basically you have a texture that contains every single color possible on it. This texture is usually referred to as a Look Up Table, or LUT. When your texture, or your game, or whatever goes to render itself, the shader can remap all of its colors to the colors on the LUT texture.

Check out these links for more details:
* Unreal Engine Color Grading
* Simple Color Grading for Games
* Color Grading: Another cool rendering trick

So here's what Stratoforce looks like with a normal color table:

Image


And here's a quick test on color grading:

Image


Whoa look at how different all the colors are! The effect is really powerful as it allows you to apply any sort of color corrections to the whole game in real time.

Here is my work flow for creating a color table and using it to alter the colors of the game:

* I downloaded a standard LUT texture from Epic: RGBTable16x1.png

* I took a screenshot of my game with the RGBTable superimposed on the top left corner of the screen.

* I brought the screenshot into Photoshop and played around with some adjustment layers: Hue/Saturation, Color Balance, Curves, etc.

* I then copy merged the RGBTable image from that document and exported it as a new png file.

* I used that png file as the LUT table for the color correction in the shader.

So the standard RGB table looks like this:

Image


And the modified version from the Photoshop file comes out looking like this:

Image


Now the LUT texture gets loaded into a shader as a 3d texture. Whoa a 3d texture! I didn't even know that a 3d texture could exist until yesterday. Basically imagine a cube that is composed of every color possible. The x y z of the cube is actually r g b! That's why the look up table texture looks like a series of squares. Notice how its 16 x 16 x 16 pixels. Crazy, right?

So here's what I had to do for my GLSL shader in Otter:
// Apply the color grading
//pixel is input color, colorGrade is sampler2D of LUT.
vec4 gradedPixel = sampleAs3DTexture(colorGrade, pixel.rgb, 16);
gradedPixel.a = pixel.a;
pixel = gradedPixel;

Since SFML by default only binds textures as 2D textures in OpenGL, I had to find a work around for loading a 2d texture as a 3d one. I found a work around here and used it in my shader.
vec4 sampleAs3DTexture(sampler2D texture, vec3 uv, float width) {
float sliceSize = 1.0 / width; // space of 1 slice
float slicePixelSize = sliceSize / width; // space of 1 pixel
float sliceInnerSize = slicePixelSize * (width - 1.0); // space of width pixels
float zSlice0 = min(floor(uv.z * width), width - 1.0);
float zSlice1 = min(zSlice0 + 1.0, width - 1.0);
float xOffset = slicePixelSize * 0.5 + uv.x * sliceInnerSize;
float s0 = xOffset + (zSlice0 * sliceSize);
float s1 = xOffset + (zSlice1 * sliceSize);
vec4 slice0Color = texture2D(texture, vec2(s0, uv.y));
vec4 slice1Color = texture2D(texture, vec2(s1, uv.y));
float zOffset = mod(uv.z * width, 1.0);
vec4 result = mix(slice0Color, slice1Color, zOffset);
return result;
}

It seems like the real magic is using this dynamically in a game. Interpolating between various LUT textures for different effects seems like it could be really interesting! I'm excited to play around with this kind of stuff more while procrastinating on solving the hard problems of working on this game.

Otter Updates

Otter Updates
Some quick updates to Otter in the dev branch!

* Added the Polygon class: For the Polygon collision stuff I created a quick helper class to keep track of the points in a polygon. This class also has some neat functions that are used in the Collider class to figure out polygon collision stuff.

* Added PolygonCollider: Now there is an actual PolygonCollider in Otter! You can use it to check for collisions with any other type of collider too. I expect there to be some bugs so be on the look out when using it.

* Various Collider Updates: Some of the colliders had some minor bugs so I squashed all of the ones I could find.

Dev Log: Polygon Collisions

Dev Log: Polygon Collisions
I never thought I'd be able to get polygon collisions working in Otter but this past week I managed to jam out a quick prototype of an overlapping polygon test that seems to be working.

Image


Probably not the most exciting image in the world, but it's pretty dang cool to me. I found this tutorial on the Separating Axis Theorem. This tutorial specifically has some great images, and amazing pseudocode with explanations that allowed me to finally understand what the hell to do. I still don't understand some things, like what exactly projecting a vector onto an axis means, but right now I think I have the core of it working.

I'll be working on getting the PolygonCollider integrated into Otter properly over the next few days. That means I'll have to get it working with each other Collider type which shouldn't be too crazy, but we'll see if I end up getting stumped by something!

Platforming Nudging Assistance

Platforming Nudging Assistance
Making a solid feeling platformer isn't as simple as setting up horizontal movement, jumping, and gravity. There are a lot of tricks and behind the scenes magic involved in making something feel good to the player. In the past I've talked about ledge forgiveness, and input buffering, and now I'm going to add nudging assistance to the list!

Ledge forgiveness, input buffering are two tricks that let the player execute their intended action even if they screw it up slightly. Nudging assistance also falls into that category.

The Problem


My latest small game Starforger II is all about roaming around procedural levels. A lot of times the levels have one tile openings in walls that the player wants to navigate into. Take a look at what happens with just a typical platforming physics system when a player tries to navigate into a small tunnel like this.

Image


Even though the player really wants to slide into that hole as they fly by they simply cant because there is no frame in which the player is able to actually navigate into that tile. If their vertical speed is too great they will miss the hole every time even though they are holding down input that would make it seem like they should be able to squeeze into there.

Image


Image