I moved to a new URL! Check it out!

posts tagged with: programming

Dev Log: Anti-clumping Made Easy

Image


Starting to get back into a bit of a groove on this game thing. One little fun thing to work on was the enemy anti-clumping code. I don't want any enemies to stack on top of each other (although it would be smart of them to do so in order to conceal their numbers.) With a short bit of code I can have enemies push each other away, similar to how babies and rocks push away from each other in Offspring Fling.
public virtual void PushAway() {
if (Hitbox != null) {
if (Overlap(X, Y, (int)Tags.Enemy)) {
var e = Overlapped as Enemy;
if (e.Mass >= Mass) {
var push = new Vector2(X - Overlapped.X, Y - Overlapped.Y);

if (push.X == 0 && push.Y == 0) {
push = new Vector2(Rand.Float(-1, 1), Rand.Float(-1, 1));
}

push.Normalize(pushAwayForce);
pushAwaySpeed += push;
}
}
}

var length = Util.Approach((float)pushAwaySpeed.Length, 0, pushAwayForce * 0.5f);

pushAwaySpeed.Normalize(length);


X += (float)pushAwaySpeed.X * 0.01f;
Y += (float)pushAwaySpeed.Y * 0.01f;
}
Pretty neat! This is actually pretty similar to the original code in the prototype many many years ago, except now it's in fancy C# instead of GML. Enemies will call PushAway() every update.

Dev Log: Coroutine Example

Image


Thanks to knowledge passed down from Chevy Ray I was able to get Coroutines working in Otter recently! Coroutines are magical chunks of code that are able to yield their execution and remember their state. It's bonkers what you can do with them using this power.

I added an example to Otter to hopefully help out any folks that are looking into using them:
using Otter;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoroutineExample {
class CoroutineScene : Scene {

public Image ImageBox = Image.CreateRectangle(50);

public Color NextColor = Color.White;
public Color CurrentColor = Color.White;

public CoroutineScene() : base() {
// Center that box.
ImageBox.CenterOrigin();

// Gotta draw the box.
AddGraphic(ImageBox);

// Set the box position.
ImageBox.X = 100;
ImageBox.Y = 100;
}

public override void Begin() {
base.Begin();

// Start the coroutine, yo.
Game.Coroutine.Start(MainRoutine());
}

/// <summary>
/// The main coroutine to execute. This will move the box around and change its color.
/// </summary>
/// <returns>Whatever a coroutine thing returns. Sometimes 0 I guess.</returns>
IEnumerator MainRoutine() {
// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Red;
// Move the box to the top right.
yield return MoveBoxTo(540, 100);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Yellow;
// Move the box to the bottom right.
yield return MoveBoxTo(540, 380);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Green;
// Move the box to the bottom left.
yield return MoveBoxTo(100, 380);

// Wait for 30 frames.
yield return Coroutine.Instance.WaitForFrames(30);
// Set the next color.
NextColor = Color.Cyan;
// Move the box to the top left.
yield return MoveBoxTo(100, 100);

// Start a new coroutine.
Game.Coroutine.Start(MainRoutine());
}

IEnumerator MoveBoxTo(float x, float y) {
// Used to determine the completion.
var initialDistance = Util.Distance(ImageBox.X, ImageBox.Y, x, y);

float currentDistance = float.MaxValue;
while (currentDistance > 1) {
currentDistance = Util.Distance(ImageBox.X, ImageBox.Y, x, y);

// Determine the completion of the movement from 0 to 1.
var completion = Util.ScaleClamp(currentDistance, 0, initialDistance, 1, 0);

// Lerp the color of the box.
ImageBox.Color = Util.LerpColor(CurrentColor, NextColor, completion);

// Spin the box along with its movement.
ImageBox.Angle = Util.ScaleClamp(completion, 0, 1, 0, 360);

// Actually move the box.
ImageBox.X = Util.Approach(ImageBox.X, x, 5);
ImageBox.Y = Util.Approach(ImageBox.Y, y, 5);

// Wait until next frame.
yield return 0;
}

// Done moving. Update the color.
CurrentColor = NextColor;
}
}
}
I'm actually totally not sure if I'm doing it correctly in the example, but it seems to be working out well so far. Going to try using them for various things now in my current projects!

Otter Updates

Otter Updates
Over the past week I've finally pushed some updates to Otter after managing to rip out the Spine animation stuff. It turns out that in order to use the Spine runtime you need a purchased copy of Spine, meaning that if I include the Spine code in Otter everyone that uses Otter would need a copy of Spine... not ideal. (I wish Spine wouldn't license their code like this.)

So now the Spine runtime for Otter lives in a separate repository. It can be used along with Otter if you import it into your solution also using Otter. After you import it you need to give it a reference to Otter (also in your solution) and then give your game project a reference to OtterSpine. Then you should be ready to roll with SpineAnimation.cs.

Other updates to otter include:

* Renamed GetClass to GetEntities on Scene
* Add Vertices graphics type
* Added Color.Mix()
* Corrected issue between game angle and graphics angles
* Fixed issue with BoxCollider constructor
* Fixed some collision bugs
* Added shortcut of Left-Alt in Debugger to hide debugger (useful for screenshots)
* Minor updates to Particle
* Added LerpColor to Util
* Slight changes to Vector2

If there's any bugs or horrific things broken then let me know in the Otter forums!

Dev Log: Some Shaders

Dev Log: Some Shaders
One of the things I miss about working in FlashPunk and working with a bunch of bitmaps and blitting to the screen is the super easy color overlay blending. FlashPunk had an Image blending mode called Tint and it could be used in place of Multiply and it is amazing for doing effects like fading an entire sprite to a specific color. The world of rendering quads and triangles I don't have such a luxury, but I do have shaders.

I've been working on the building islands animation, and here's a really fast version of it:

Image


At the end of it when the island pops out it's silhouetted with solid white. The white fades to cyan, and also fades back to the normal art at the same time. To get this effect I used a simple shader to handle a color overlay.
uniform sampler2D texture;
uniform vec4 overlayColor;

void main() {
vec4 pixcol = texture2D(texture, gl_TexCoord[0].xy);
vec4 outcol = mix(pixcol, overlayColor, overlayColor.a);
outcol.a = pixcol.a;
gl_FragColor = outcol;
}
I also use this code for enemies as well. When they get hit they turn red for a brief moment. I use code in the C# end to determine the color and intensity of the overlay and pass it along to the shader.
var overlay = Util.ScaleClamp(Combatant.Stun, 0, Combatant.StunMax, 0, 1);
var color = new Color(1, 0.2f, 0.1f, overlay);

ImageSpineAnim.Shader.SetParameter("overlayColor", color);
Soon I'll probably make some sort of system that allows me to easily add a bunch of color overlays to the shader and automatically figure out the final color for the shader to use. I'll probably also use the shader for a bunch of different effects down the road.

Dev Log: Slow and Steady

Dev Log: Slow and Steady
I've been tinkering with a lot of systems over the past couple of days. Mostly stuff involving enemies, and some other things involving building islands and structures on the islands.

At some point last week I sat down and tried to figure out path finding with moderate success. I have something working, but it's pretty dang laggy when it has to figure out a path. As far as I know I'm just doing straight up A* path finding and I copied the psuedocode from Wikipedia right into the game. I started looking into using different data structures for storing things to hopefully speed it up, but honestly I still have no idea what I'm doing and I don't know how to use some of these fancy things that people suggest (priority heaps, or something?)

I took a break from that to tinker with placing structures on islands, and trying to figure out how I want to animate the building process for building a structure on an island. This is also a tough one to solve, and I'm not sure if frame by frame stuff in Flash would be good, or if structures should be animated with skeletons similar to the enemies using Spine.

Image


Back in the world of enemies I've started experimenting with behavior trees for how they should interact with the world. It seems like a good way to do things, but part of me feels like it's over-engineering. Setting up a whole series of classes for the system to run the behaviors, and then every simple little task then has to be a behavior command... I kind of like systems like this, but I wonder if it will be worth it in the end working on a system that takes a lot of up-front work to get running.

It's definitely a very different way of doing things outside of the game jam environment. I've made a lot of cool stuff in game jams, but it's all been on top of really odd code that doesn't leave a lot of room for expansion. I'm trying not to design or code myself into a corner when it comes to working on this new game, so things are going a little slower than they did for Offspring Fling, but it's also probably due to the fact that I'm in pretty unfamiliar territory. Working on something that's not a platformer can be pretty tough!

Dev Log: More Explosions

Image


Been having a lot of fun with my workflow of animating in Flash, exporting to a SWF, and then using ShoeBox to convert to a sprite sheet. There are some hiccups in the pipeline still, but hopefully I can get them ironed out before I get any deeper in the art department.

I should really be working on the actual game part of this game, and probably all the systems that are going to be needed to be intertwined, but at this point I'm having way too much fun with particles. I've been bound by the word of Flash and ActionScript 3 for so long. Having 30 particles on the screen in Offspring Fling was a nightmare for performance, but now in the land of SFML, C#, and Otter, I can spawn hundreds of particles and the game doesn't hitch at all -- not even in debug mode!