I moved to a new URL! Check it out!

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.
new comment!

Post your comment!

Name
Email
Comment