I moved to a new URL! Check it out!

posts tagged with: programming

Dev Log: Otter Spine Animations

Dev Log: Otter Spine Animations
Today is a very awesome day, for I finally got Spine animations running in Otter! I only have the super basic stuff right now, but I'm hoping to expand the support as I tinker around with Otter and my next game.

Image


This is a quick test of the test animation that comes with Spine. Right now a skeleton can be loaded up, and play its animations in the most simple way. The next steps will be getting all of the cool spine functionality in and running, like being able to manipulate bones and mix animations and all that kinda stuff.

This hasn't been pushed to Otter yet, and probably won't be for at least a few more days as I test it out and hopefully work out any show stopping bugs that might appear.

While making the Otter implementation of Spine I made great use of the Spine csharp runtime which I just dragged and dropped into Otter, and I also referenced the XNA runtime, along with C#Punk's implementation of a SpineAnimation graphic type.

Flippy Flop Source

Flippy Flop Source
Yesterday I made a quick game called Flippy Flop using Otter. The whole thing only took me two hours or so, and the end result ended up being a relatively clean coded game.

I decided to add the Flippy Flop source code to the Otter source repository on BitBucket in the Examples folder. So now when you grab Otter you'll also get the source for the Otter Pong Game, and the amazing Flippy Flop.

Flippy Flop makes use of the EventRouter included in Otter. The EventRouter was originally authored by some smart Phoenix locals, and is used a lot in their Unity projects. Since it was just a C# implementation I grabbed and it stuck it in Otter. The EventRouter is all about following the Observer pattern. It can be a little weird to use at first, but I'm beginning to see the appeal of it.

(Disclaimer: There may be some bugs in the source for FlippyFlop. I didn't really check it over for memory leaks, which can easily pop up when using an Event system. If you don't make sure you're unsubscribing from events when objects are removed, or clearing the event router, you might find yourself in memory leak city.)

If you have any questions about Otter, or the source code of the game, check out the Otter forums or leave a comment below.

Dev Log: Cooldown Drawing

Dev Log: Cooldown Drawing
Been a little bit sickly feeling these last couple days so I haven't been too active on the dev side of things. It's been super tough because I've been laying down the ground work for these systems that I want to be part of the game, and since I have no idea what I'm doing progress is a little bit slower than I'd like it to be. Maybe I should start working on a platformer on the side so I can at least dip my toes into familiar space every once in awhile.

One of the tasks on my to do list was to figure out how to draw those cool spell cool down graphics you always see in action RPG, and a lot of RTS games. When you have a spell or ability represented as an icon on the screen, one of the most common ways to show it's cool down before you can use it again is an overlay that slowly erodes with a radial wipe.

Image


There are a lot of different ways to do this, but eventually I went with this simple method using a triangle fan. I had written down an idea of using geometry before, but this implementation is waaay simpler than the madness I wrote in my notebook with using four quads or a triangle fan with way too many points. Here's the entire implementation, also available right now to use in Otter as SquareClock.
public class SquareClock : Image {

VertexArray vertices;

/// <summary>
/// Determines the fill of the clock.
/// </summary>
public float Fill {
set {
fill = Util.Clamp(value, 0, 1);
NeedsUpdate = true;
}
get {
return fill;
}
}
float fill = 1;

public SquareClock(int size, Color color) {
Width = size;
Height = size;

Color = color;

NeedsUpdate = true;
UpdateClock();
}

void UpdateClock() {
if (!NeedsUpdate) return;


if (fill == 1) {
//draw box
vertices = new VertexArray(PrimitiveType.Quads);
Append(vertices, 0, 0);
Append(vertices, Width, 0);
Append(vertices, Width, Height);
Append(vertices, 0, Height);
}
else {

vertices = new VertexArray(PrimitiveType.TrianglesFan);

if (fill > 0) {
//draw center
Append(vertices, HalfWidth, HalfHeight);
//draw middle top
Append(vertices, HalfWidth, 0);
if (fill >= 0.125f) {
//draw left top
Append(vertices, 0, 0);
}
if (fill >= 0.375f) {
//draw left bottom
Append(vertices, 0, Height);
}
if (fill >= 0.625f) {
//draw right bottom
Append(vertices, Width, Height);
}
if (fill >= 0.875f) {
//draw right top
Append(vertices, Width, 0);
}

// get vector of angle
var v = new Vector2(Util.PolarX(FillAngle, HalfWidth), Util.PolarY(FillAngle, HalfHeight));
// adjust length of vector to meet square
var l = (float)Math.Max(Math.Abs(v.X), Math.Abs(v.Y));
if (l <= HalfWidth) {
v.X /= l;
v.Y /= l;
}
// append the vector
Append(vertices, HalfWidth + (float)v.X * HalfWidth, HalfHeight + (float)v.Y * HalfHeight);

}
}

DrawableSource = vertices;

NeedsUpdate = false;
}

public float FillAngle {
get { return (fill * 360) + 90; }
}

void Append(VertexArray v, float x, float y) {
v.Append(x, y, Color);

}
public override void Update() {
base.Update();
UpdateClock();
}

}
The downside with this implementation is that I'm pretty limited as to where I can draw the original angle from. Since I've made this into a Graphic type in Otter I can actually flip it, scale it, and rotate it in any way I want, but I won't be able to change where the start and ending angle end up. That's okay for now since I won't be needing that functionality myself, but maybe if I have some time I can implement a more advanced version of it soon.

Otter Updates

Otter Updates
As I work away at my next project I'm also pushing some changes to Otter, which is my 2d game making framework that runs on SFML 2 and C#.

I didn't get to make many updates during the holidays, but now I'm back in the swing of things. Here's some of the latest stuff that's been updated:

Better mouse locking.
You can now lock the mouse to the center of the screen and use the delta mouse positions to track the cursor position. If you use this option you can still just use Input.MouseX and Input.MouseY normally.

Debugger fixes
The mouse unlocks when the debugger is opened, and I think I fixed some bugs with hiding and showing the debugger. The log will now look nicer when using Log to print multiple lines. Added quit to do the same thing as exit.

Session construtor public
Just in case you want to extend session, but I'm not sure if I want to keep it this way.

Updated SFML dlls
I found that someone made new builds of SFML so I was able to update the dll files to fix some bugs (like only being able to click on the title bar to gain focus)

Image shake property (still weird now though)
Images can now shake but this doesn't make too much sense because the shake is updated at every render call (instead of update)

Rich text documentation
Added some more comments to rich text

More Rand functions
Rand.Float() can use a Range now, and there's a method for generating a point inside a circle.

Util additions
Added some stuff to Util that may or may not be useful.

AutoTimer added
A utility component class that might be useful for some stuff.

Linux, OS X stuff
Merged in the .csproj file from Ventero for hopefully Linux and OS X support with Mono? I'm not totally sure how this stuff works but Linux and OS X should be easier to build with this new .csproj file and Mono.

Dev Log: More Data Driving

Dev Log: More Data Driving
How far is too far when it comes to making data driven code? Right now I'm wrestling with this question. I have a bunch of stuff defined in my xml which is all well and good for some parts of this game, but then I came to think of spells and abilities and how to make them data driven... but I think to truly do that would require some sort of scripting!

I was looking into Lua or using some form of Python for scripting in my game, but ultimately I've decided to hold off on that sort of thing. It sounds really fun, especially when I start to consider the modding possibilities of a game that uses a lot of scripting and data driven stuff... but it feels like a large burden to take on very early on in a project (even though getting Lua set up in C# is incredibly easy!)

As I slowly pick away at these systems everything is becoming a little bit more clear with each day of work. I'm still learning the ins and outs of C# and the power of reflection. One thing I started looking into today is custom attributes. It seems like a powerful way to combine data driven and engine driven stuff into one. I think by using custom attributes I could define a lot of data right in a class itself, and I would be mostly doing this in instances where I wouldn't want this kind of data exposed to the end user.

For example right now I have my stat class set up with a Dictionary where the enum StatType is the key, and a float is the value. This is all fine, but it means that in the constructor of my stat manager class I have to define all of those stats by doing Add(StatType, value) a bunch of times. An alternative way to do this might be to define the stats as just floats in the class itself, and apply custom attributes to each one like [Stat] or [CoreStat] or [DerivedStat]. I'm going to spend a little time experimenting with this stuff and we'll see how it turns out!

Dev Log: Fun with Stats

Dev Log: Fun with Stats
I haven't made much progress on my system to set up triggers and actions for Enchantments, but I did make some progress on my player stats system. I coded up a pretty generic Stat class that allows StatMods to be applied. Check it out!
class Stat {

public float BaseValue;
public string Name;

public bool Capped;
public float Cap;

public List<StatMod> StatMods { get; private set; }

bool needsUpdate = false;
float cachedValue;

public Stat(string name, float basevalue = 0) {
Name = name;
BaseValue = basevalue;
Cap = BaseValue * 2;
StatMods = new List<StatMod>();
cachedValue = basevalue;
}

public Stat(float basevalue) : this("", basevalue) { }

public StatMod AddMod(StatMod mod) {
StatMods.Add(mod);
needsUpdate = true;
return mod;
}

public StatMod RemoveMod(StatMod mod) {
StatMods.Remove(mod);
needsUpdate = true;
return mod;
}

public void ClearMods() {
StatMods.Clear();
cachedValue = BaseValue;
}

public float FinalValue {
get {
if (needsUpdate) {
float v = BaseValue;
var m = 1;
foreach (var s in StatMods) {
v += s.Add;
}
foreach (var s in StatMods) {
v += BaseValue * s.Multiply;
}
cachedValue = v;
needsUpdate = false;
}
if (Capped && cachedValue > Cap) return Cap;
return cachedValue;
}
}

public static implicit operator float(Stat stat) {
return stat.FinalValue;
}


}

class StatMod {
public float Multiply = 1;
public float Add;

public StatMod(float add = 0, float multiply = 0) {
Multiply = multiply;
Add = add;
}
}
I'll probably add this into the Utility folder of Otter at some point. Basically you can make a stat, like new Stat(10), then apply modifiers and get the final modified value back. You can also treat it as a float and it will spit out the modified value as well.

Multiply might not work the way you think at first though. Setting Multiply to 1 in a StatMod actually means to Add 100% of the stat to itself. For example, a stat of 100 with a multiplier mod of 1 will calculate as 200. It's as if the mod is saying "BaseStat +100%" when you set it to 1. So 0.5f would be interpreted as +50%, -0.5f would be -50%, and so on.

Modifiers will always be applied with addition, then multiplication. For example if a stat had a base value of 100, and then you apply a modifier with Add set to 50, and then another modifier with Multiply set to 1, then the final result will be 300. It applies the +50, and then the +100%. It doesn't matter which order they're applied in.

Now I'll get back to work on my dumb trigger and action system that I have no idea how to implement right now, yahoo!