Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Retro 8 bit palette sprites! — Gideros Forum

Retro 8 bit palette sprites!

SinisterSoftSinisterSoft Maintainer
edited May 2017 in Code snippets
I wondered if there was an easy way to make paletted sprites - as used in Mario, Sonic, Metroid, etc...

So I made a demo!

1) First I changed a copy of my 8 bit paletted png file and modified it to look like a grey scale image instead using a hex editor. I looked for the IHDR chunk in the file, it should be at the beginning, changed byte 10 from a 3 to a 0, then I looked for the iCCP chunk (if there is one) and changed it to zCCP.

here is the resulting image (it will appear black, but there are actually some pixels set in there!)...
https://www.dropbox.com/s/4x5rvku2zlnumg7/clown8.png?dl=0

2) Then I wrote the shader and demo code. Here it is:
application:setBackgroundColor(0x2288aa)
 
clownTexture=Texture.new("clown8.png")
 
palettes=RenderTarget.new(256,256) -- 256 palettes of 256 colours each, so far I'm only using 1
 
clown=Pixel.new(clownTexture)
 
clown:setPosition(100,100)
clown:setScale(3)
 
shaderV=[[
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
uniform highp mat4 vMatrix;
varying mediump vec2 fTexCoord;
 
void main() {
  vec4 vertex = vec4(vVertex,1.0);
  gl_Position = vMatrix*vertex;
  fTexCoord=vTexCoord;
}	
]]
 
paletteF=[[
uniform lowp sampler2D fTexture;
uniform lowp sampler2D fPalettes;
uniform float palette;
varying mediump vec2 fTexCoord;
 
void main() {
	lowp vec4 colour8 = texture2D(fTexture,fTexCoord);
	lowp vec2 index = vec2(colour8.r,palette);
	lowp vec4 colour32 = texture2D(fPalettes,index);
	gl_FragColor = colour32;
}
]]
 
local result,paletteShader=pcall(Shader.new,shaderV,paletteF,Shader.FLAG_FROM_CODE,{
	{name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true}, 
	{name="fTexture",type=Shader.CTEXTURE,vertex=false},
	{name="fPalettes",type=Shader.CTEXTURE,vertex=false},
	{name="palette",type=Shader.CFLOAT,vertex=false},	}, 
	{{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0}, 
	{name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0}, 
	{name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0}, })
 
if not result then
	print("Shader error:",paletteShader)
end
 
clown:setTexture(palettes,1)
clown:setShader(paletteShader)
 
stage:addChild(clown)
 
function setPalette(p,c)
	palettes:clear(0xffffff,0)
	local pixel=Pixel.new()
	for loop=1,#c do
		pixel:setPosition(loop-1,p-1)
		pixel:setColor(c[loop][1],c[loop][2] or 1)
		palettes:draw(pixel)
	end
end
 
paletteNo=1
myPalette={{0x000000},{0xffffff},{0xffbf5f},{0xff9f3f},{0xff5f1f},{0xbf5f3f},{0x9f1f1f},{0x9f9f9f},{0x5f5f5f},{0xff7676},{0xff00ff,0}}
setPalette(paletteNo,myPalette)
clown:setShaderConstant("palette",Shader.CFLOAT,1,paletteNo-1)
 
count=0
function gameLoop(e)
	count=count+1
	if count%120==0 then
		myPalette[2]={math.random(0xffffff)}
		setPalette(paletteNo,myPalette)
	end
end
 
stage:addEventListener(Event.ENTER_FRAME,gameLoop)
It should display a clowns face and the colour of the face should change every 2 seconds or so.

You can use the idea and routines to make games that share a common set of graphics but show them as different palettes.

Likes: antix

Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
https://deluxepixel.com
+1 -1 (+1 / -0 )Share on Facebook

Comments

Sign In or Register to comment.