Weapons of Ironguard – Round 2

This the second in a series of posts about the weapons in Ironguard where we’ll take a quick look at 2-3 weapons from the game & explain their primary and alternate fire modes. At this stage in development we have 7 weapons implemented with another 10 planned for the full release.

Chakram

A powerful long-ranged weapon, but you’ll have to wait for it to return to you before you can throw it again.

Primary Fire: A fast moving projectile which pierces enemies. Bounces off the environment and returns to the player. The chakram is not usable until it returns.

Alternate Fire: The chakram spins in front of the player, reflecting any enemy projectiles. Pressing the fire button a second time will unleash a powerful beam from the chakram. You can even switch weapons while this shield is up.

Flamethrower

A short-range weapon which deals a lot of damage but comes at the cost of heat-management.

Primary Fire: Heavy damage over time a short distance in front of the player. Accumulates heat over time. If the flamethrower overheats, it becomes unusable for a short time.

Alternate Fire: Launches a fireball which explodes on contact and leaves a patch of flame on the ground. Immediately overheats the flamethrower.

Plasma Shield

A melee-range weapon which has the added benefit of reflecting enemy attacks from the front.

Passive: While the shield still has energy, enemy attacks from the front are reflected. Each reflected attack consumes some energy; energy replenishes passively over time.

Primary Fire: A very short range shield slam which consumes some of the shield’s energy.

Alternate Fire: Completely depletes the shield’s energy to unleash a massive shield burst which has a much longer range and deals more damage than the primary shield slam.

Weapons of Ironguard – Round 1

This will be the first in a series of posts about the weapons in Ironguard where we’ll take a quick look at 2-3 weapons from the game & explain their primary and alternate fire modes. At this stage in development we have 5 weapons implemented with another 12 planned for the full release.

 

Scatter Blaster

A short-ranged weapon that excels in close-quarters.

Primary Fire: Heavy damage in a cone. Damage is based on proximity to the target.

Alternate Fire: A long range power-shot which explodes and deals damage to enemies in a small radius near the impact point. Deals less damage than the primary fire.

 

Beam Rifle

A powerful energy weapon for taking out tough enemies. Correct use of the heat mechanic is essential for making the most of the beam rifle.

Primary Fire: A powerful beam that pierces through enemies, accumulates heat with each shot. Heat depletes slowly and overheating causes the weapon to become unusable for a short time.

Alternate Fire: A slow moving ball of energy which deals damage over time to nearby enemies and bounces of walls. Shrinks over time until the energy ball dissipates. Size & damage is based on the accumulated heat of the weapon, disperses all heat when used.

 

Grenade Launcher

A powerful risk-reward focused weapon that deals high splash damage – even to yourself.

Primary Fire: A bouncing grenade that explodes shortly after the first bounce (or immediately upon contact with an enemy). Deals a large amount of damage in a small radius and can hurt the player as well.

Alternate Fire: A cluster grenade which splits into 5 grenades on contact with a surface or enemy.

New Title Announced: Ironguard

It’s been a while since we posted an update but we’ve finally got something to share. Over the past few months we’ve been hard at work on our next release: a first-person roguelike shooter named Ironguard.

We’re still in the early stages of development at the moment, but here’s a video of some gameplay in the first stage of the game – the Foundry:

There’s also some screenshots on our IndieDB page.

We’ll be posting regular updates to our twitter channels @AegonGames and @IronguardGame from now on with a weekly spotlight of one of Ironguard’s weapons or items. We’ll see you next time with the first weapon spotlight!

Runtime Colour Variation

One fairly common practice to increase visual variety in video games is to re-colour sprites or textures, but runtime colour variation can also be used as a means of allowing players to further customize their game characters or equipment. For our next project, we need to make use of colour variation for both of these purposes and set out to compare some of the different methods for achieving this goal.

Sword - Full Colour

Original Colour

We want to be able to take this image and apply new colour variations in-game to allow players to dye their character’s equipment to fit their desired colour scheme.

NOTE: The code shown below is HLSL.

 

Tinting

float3 newColour = initialColour * tintColour;

Tinted Result

Tinted

This is the quickest and easiest method of changing a texture’s colour, but it doesn’t produce very good results. The old colours are partially showing through and the whole sword has to be tinted a single colour.

To remove the effect of the old colours showing through, we can desaturate the original image first, but this still leaves us with the issue of only being able to provide a single colour; and in addition, the sword now looks even more monochrome.

float3 Desaturate(float3 colour, float desaturationAmount)
{
	float intensity = 0.3 * colour.r + 0.59 * colour.g + 0.11 * colour.b;
	return lerp(colour, intensity.rrr, desaturationAmount);
}
float3 newColour = Desaturate(initialColour, 1.0) * tintColour;

Sword Result - Desaturated then Tinted

Desaturated then Tinted

 

 

 

 

 

Pros:
– Very easy to do
– Could produce decent results for items that don’t vary greatly in colour

Cons:
– Separate parts of the texture can’t have different colours applied
– Monochrome results aren’t very visually appealing

 

Masking

This requires a little more set up than tinting. Instead of saving colour information in our sprites, we can save what is effectively a “colour ID”.

Sword - Masks

Colour Masks

In this image, each channel represents a separate colour ID which we will swap out with the desired colour in our shader.

 

 

 

float3 newColour = initialColour.r * ColourR + initialColour.g * ColourG + initialColour.b * ColourB;

NOTE: ColourA, ColourB and ColourC are parameters passed to the shader that represent the colours we’d like to use in place of the IDs in the mask.

 

Masked

Masked

The results produced by masking are a marked improvement over tinting, but there are still some issues.

We can’t easily apply more than three different colours to our sprite; and if we wanted a sprite with a different number of colours, we’d need to make a new shader – not an ideal situation.

Pros:
– Not much more complicated than tinting
– Produces good results with a low (and consistent) number of colours

Cons:
– No way to elegantly handle a variable number of colours
– Only allows block colours
– Requires a special workflow for creating sprites

Hue Shifting

This method involves converting your standard RGB sprites into another colour space (in this case, HSV: Hue-Saturation-Value), adjusting the hue, and then converting back to RGB to be displayed on the screen. This is both the most complicated and most expensive method on this list.

float3 newColour = RGBtoHSV(initialColour);
newColour.r = (newColour.r + HueShiftAmount) % 1.0;
newColour = HSVtoRGB(newColour);

NOTE: Colour space conversion functions are fairly long and have been omitted. It’s easy enough to find them through Google.

 

Hue Shifted

Hue Shifted

The results look pretty good – we’ve managed to keep all five of our distinct colours, but shifted the hue to give ourselves a different result from the original sprite.

Pros:
– Good looking results
– No need for special set up or change in workflow

Cons:
– We can’t individually tweak the colours
– Converting between colour spaces is a relatively costly operation

 

Gradient Mapping

Gradient mapping is often used in visual effects, but rarely finds use outside of that narrow topic. Basically, gradient mapping involves creating a grayscale image and mapping each value to a colour in a separate gradient texture.

Gradient Colours

Gradient Colours

Gradient Values

Gradient Values

Black values in the image to the left correspond the leftmost colours in the gradient, whereas white values map to the rightmost colours.

In our shader we use the values taken from our encoded sprite (left) and use them as the U coordinate to sample into our gradient.

float gradientValue = tex2D(GradientIDs, UV).r;
float3 newColour = tex2D(Gradient, float2(gradientValue, 0)).rgb;

Gradient Mapped

Gradient Mapped

This allows us to specify as many colours as we like, which can be swapped out by replacing the gradient texture (which itself is simple enough to generate at runtime).

One other benefit to this method is that we aren’t restricted to a set number of colours. Although I haven’t done this in the example, we could make use of the “inbetween values” to allow for a smooth falloff from one colour to the next.

Pros:
– Allows for a much greater variety of colours. The number is limited only by the width of the gradient texture used
– An arbitrary number of colours can be used (varying by sprite) without needing to make any modifications to the shader
– Not restricted to block colours like many of the other options
– A single channel can be used to store all of your colour information (in addition to a small 256×1 texture – which can be shared between many sprites), freeing up two extra channels for other things and saving memory in the process.

Cons:
– Requires a special workflow. All sprites must now be made as what is effectively a lookup table into a gradient

Conclusion

In the end, we chose to use gradient mapping for our project. The ability for us to have a different number of colours for each sprite is invaluable. We can let players dye their equipment simply by allowing them to change the colours of the “key frames” in the gradient (while optionally allowing more advanced users to play around with the gradient itself, adding/moving/deleting colours).

The one big downside to gradient mapping is that it requires a completely different workflow from what most artists are used to (which becomes even more of an issue when allowing players to create their own sprites – we can’t expect modders to be familiar with uncommon workflows like this). We intend to combat this issue by implementing a comprehensive set of tools inside the editor itself for easily creating these gradient mapped sprites, though that still makes it difficult for players to use image-editing software that they are familiar with.

Ultimately, the choice of how to handle colour variation differs from project-to-project and it’s definitely worth the effort to look into existing solutions to see which is the best fit for your game. Personally, I find gradient mapping to be a really useful but under-used technique and hope to see it used more often in the future.