- Home /
Change sprites colours individualy ( flashing like mario with the star )
I'm making a retro 8 bit plataformer, and I want to know how can I change the pallete of my sprites, similar to the flashing mario, without using other sprite sheets.
This gif from shovel knight is exactly what i want: http://yachtclubgames.com/wp-content/uploads/2014/06/cycle.gif
these too: http://img10.imageshack.us/img10/8199/flashingcolors.png
I dont want to just mess with the color of the material, that tints every color, I'm looking for a way to replace colors individually. ( for making other effects too, like a boss coming out of the dark with the colors gradualy appearing )
you could make animation . Where you can choose Add Curve and Sprite and then color. You can play with many options there.
the color of the material changes every color, and also, I can't change black color by just changing the color of the material. I want to replace colors individually ( including black )
there's a way to change the colors of a sprite to the negative ones? that would help.
@ThiagoTejo, then you should try changing materials texture! Get it by Texture2D.GetPixels(), process as you want and then return them back with Texture2D.SetPixels().
Answer by RabidCabbage · Nov 15, 2014 at 07:02 PM
I had a go at this, not able to test currently, could fail spectacularly!
Sorry if a bit hard to read, I added some comments. :)
Just feed it a Texture2D image & associated Rect somehow (there is probably a better way of handling this, that I fail to find right now)
using UnityEngine;
using System.Collections.Generic;
public class ColorChanger : MonoBehaviour
{
public Texture2D SourceTex;
public Rect SourceRect;
private int x;
private int y;
private int width;
private int height;
private Color[] pixels;
private List<Color> colorList;
private List<Color> backupColorList;
void Start()
{
// Get Rect dimensions
x = Mathf.FloorToInt( SourceRect.x );
y = Mathf.FloorToInt( SourceRect.x );
width = Mathf.FloorToInt( SourceRect.width );
height = Mathf.FloorToInt( SourceRect.height );
// Read image into pixel array
pixels = SourceTex.GetPixels( x, y, width, height );
}
// Make a list of all used colors in the image.
List<Color> GetColorList()
{
var cList = new List<Color>();
foreach( var pixel in pixels )
{
if( cList.Count == 0 )
{
cList.Add( pixel );
Debug.Log( "Added first color: " + pixel );
}
else
{
var found = false;
foreach( Color c in cList )
{
if( c == pixel )
{
found = true;
break;
}
}
if( !found )
{
cList.Add( pixel );
Debug.Log( "Added color " + cList.Count + ": " + pixel );
}
}
}
return cList;
}
// Change one color into another.
void ChangeColor( Color oldC, Color newC )
{
for( var i = 0; i < pixels.Length; i++ )
{
if( pixels[i] == oldC )
{
pixels[i] = newC;
}
}
SourceTex.SetPixels( x, y, width, height, pixels, 0 );
SourceTex.Apply();
}
// or with float's
void ChangeColorF( float oldR, float oldG, float oldB, float oldA, float newR, float newG, float newB, float newA )
{
for( var i = 0; i < pixels.Length; i++ )
{
if( pixels[i] == new Color( oldR, oldG, oldB, oldA ) )
{
pixels[i] = new Color( newR, newG, newB, newA );
}
}
SourceTex.SetPixels( x, y, width, height, pixels, 0 );
SourceTex.Apply();
}
}
Then you could do stuff like:
// Generate a list of unique colors in the image.
colorList = GetColorList();
// Backup original colors and randomize.
backupColorList = colorList;
for( var i = 0; i < colorList.Count; i++ )
{
colorList[i] = new Color( Random.Range( 0f, 1f ), Random.Range( 0f, 1f ), Random.Range( 0f, 1f ), 1f );
ChangeColor( backupColorList[i], colorList[i] );
}
// Change all Black pixels to White using float's
ChangeColorF( 0f, 0f, 0f, 1f, 1f, 1f, 1f, 1f );
Answer by SmilingCatEntertainment · Nov 15, 2014 at 07:21 PM
Ironically, this technique is not as easy on modern, truecolor platforms as it was on the older palettized platforms. In the days of limited colors, this was accomplished by remapping a 2-8 bit color palette of the sprite to different colors, because using 32 bits for one pixel was an unaffordable luxury. Now, we don't have these palettes to play with, and we just use the full 32-bit color spectrum directly.
Some ways to emulate this technique in a truecolor world:
Write a custom shader that can do color replacement and maybe even fully emulate the old color palette functionality (pretty advanced).
Dynamically change the texture as RabidCabbage suggests (may be too slow if too much is being changed each frame).
Have separate textures/sprites for each color combination (which you didn't want but it IS the easiest).
Off the top of my head, if I were to do the shader, I'd try having it take 2 texture inputs - the sprite texture, and a palette texture. I would use the color values from sampling the sprite texture to compute a texture coordinate within the palette texture, and then sample that palette texture for the output color.
I came across some spare time this evening, and came up with the attached implementation of what I was thinking with the shader-based solution. It just requires keeping in $$anonymous$$d the following: Source textures must be supplied with the palette index encoded in the red and green components of the texture. Blue is ignored. Ideally, you want to pick your colors so that it samples the center of the color swatch in your palette, as follows:
4-color palettes (palette texture divided into 2x2 squares): Color 0: (64, 64, 0) Color 1: (192, 64, 0) Color 2: (64, 192, 0) Color 3: (192, 192, 0)
16-color palettes (palette texture divided into 4x4 squares): Colors 0-3: (32, 32, 0);(96, 32, 0);(160, 32, 0);(224, 32, 0) Colors 4-7: (32, 96, 0);(96, 96, 0);(160, 96, 0);(224, 96, 0) Colors 8-11: (32, 160, 0);(96, 160, 0);(160, 160, 0);(224, 160, 0) Colors 12-15: (32, 224, 0);(96, 224, 0);(160, 224, 0);(224, 224, 0)
For the source textures, be sure to use point filtering, and clamp if necessary. For the palette textures, be sure to use point filtering and turn off $$anonymous$$IP mapping.
I cranked it out in about an hour, so I'm sure it can be improved.
Answer by Eric5h5 · Nov 15, 2014 at 08:59 PM
You can just change the sprite color. This will only affect the particular sprite, not all of them. (Because sprites use vertex colors.)
GetComponent(Sprite).color = ....
This works if all you want to do to the sprite is tint it. If you want to replace colors individually like the OP does (for example, blue becomes white, black becomes red, yellow becomes geeen), a different technique is needed.
Answer by blueLED · Nov 15, 2014 at 09:08 PM
This thread talks about shifting hues on a textures, which, I believe, is all that is happening in those examples you posted.
No amount of hue shifting will turn black into red, like the first example shows
They talk about GetPixels and SetPixels. Hue shifting is just a simpler operation, than picking individual colors and changing them.
Your answer
Follow this Question
Related Questions
how can i change the color of a pixel in my sprite 0 Answers
Change color sprite 1 Answer
Change dynamicaly a PNG used in a motion 1 Answer
Get pixel from Rotated Texture2D 1 Answer