Led Shooter


Start working on new game. The main idea to emulate led display. Why led screen? Because it is looks unusually, and it is easy for me to make such art. :grinning:
Now i have working led screen, prototype game mechanic, and working animations.
I don’t know what game mechanics i will use. Now i am making vertical shmup.



Cute dino! Attack of dead pixels!

1 Like


Nice! How did you end up doing the “LED” display? Are they sprites?



Now i am using gui nodes. It is not best way. For screen 45 x 60 it is taking about 5ms to gameobject.guic in pc profiler. And if i make bigger screen, for example 100x100 i can’t get 60 fps.
I am think about buffer, resource.set_texture, and shader. It shoould be much better for performance.

1 Like


One way could be to just render 100x100 normal pixels with no filtering (but yeah, they will be pretty big on a bigger screen) and then just use a mask or just an image with stanced holes in it above that.



I am trying sheder with runtime texture from buffer,(resource.set_texture for model).
Looks like it is not fast way.

self.stream = buffer.get_stream(self.buffer, hash("rgb"))
--Changing stream is very slow. For example this lines in for loops for x and y
--takes about 6ms
--Looks like changing stream is slow. 

self.stream[index + 0] = color.x * 255
self.stream[index + 1] = color.y * 255
self.stream[index + 2] = color.z * 255

Is there are some others ways to fast manipulation with textures?



Have to do it with native extensions to be fast.

1 Like


How? I can send table with pixels to native extension. But how to manipulate with buffer or texture?
Or you talking about for loops? because many problem is loop?



Did you try to use render target?

1 Like


I need changing texture every frame. I don’t need render target



I would try what Andreas recommended. Basically just render a tiny pixel art game then draw a texture with holes in it over that at full resolution. You don’t need anything fancy at all, and you will have good performance.



Thanks, for your try. I already done shader for that, and don’t have problem with render. You can try shader, it should work fast too. led.x = width, led.y = height, led.z = width/height. I use model and runtime pixel texture. But for your example shader can be used for postprocessing.

varying mediump vec2 var_texcoord0;

uniform mediump sampler2D tex0;
uniform mediump vec4 led;

const float ledRad = 0.4; 

vec3 getColor(vec2 uv){
	float center = 0.5/led.y;
	float rad = center * ledRad * 2.0;
	vec2 newRes = vec2(led.x, led.y);

	//get color for one led
	//vec2 pixelUV = uv;
	vec2 pixelUV = floor(uv * newRes) / newRes;
	vec2 coords = pixelUV  - uv + center;
	//fixed circle aspect
	coords.x *=  led.z;
	coords.x += center * 0.08;
	//coords.x -= center;
	float d = length(coords);
	vec3 color = texture2D(tex0, uv).rgb;
	return mix(color, vec3(0), smoothstep(rad *0.9 , rad, d));

void main(){
	gl_FragColor = vec4(getColor(var_texcoord0.xy).rgb, 1.0);
	//gl_FragColor = vec4(color.rgb, 1.0);

1 Like


My problem, is that i need change texture in lua, which is very slow.
I can’t use pixel sprites. Because i need a ability to change color for every pixel in runtime. For example a brightness of pixel can describe it health. Also i need a ability to destroy every pixel of enemy.

1 Like


For screen 30x40 i spend 4-6 ms for loop in lua in android on galaxy s7. On cheap devices it will be much bigger. I am trying to move for loop in native. It should help.

local update_time = os.clock();
local stream = self.stream
local nodes = LED.NODES
local width = self.width
local index = 1
local arshift = bit.arshift
local band = bit.band
    for id = 1, self.width * self.height do
        local color = nodes[id]
        local index = id * 3 - 2
        stream[index] = arshift(band(color, 0xff0000),16)
        stream[index + 1] = arshift(band(color, 0x00FF00),8)
        stream[index + 2] = band(color, 0x0000ff)
local header = { width=self.width, height=self.height, type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGB, num_mip_maps=0 }
resource.set_texture(self.resource_path, header, self.buffer )
print("update time:" .. (os.clock() - update_time))
1 Like


You can also try to sample from that pixel texture in a fragment shader and render the LEDs. That may be even cheaper depending on the shader code.

1 Like


You can try rendering to an 8-bit luminance texture and do palette conversion in a shader. That way you don’t have to write as much data to the buffer. This works only if you have max 255 colors, of course.



Interesting, I need more colors, but I’ll keep it on mind. Also i am thinking about, setting only changed colors. But sometimes i will need changed all pixel, so i should do it as fast as possible

1 Like


Make native for changing texture.
Looks like native is 20-30% faster.

Anybody have ideas how can i increase speed more?

Test for screen 300x400.


DEBUG:SCRIPT: native: 0.029
DEBUG:SCRIPT: lua:0.04
DEBUG:SCRIPT: native: 0.029
DEBUG:SCRIPT: lua:0.039
DEBUG:SCRIPT: native: 0.029
DEBUG:SCRIPT: lua:0.039
DEBUG:SCRIPT: native: 0.03
DEBUG:SCRIPT: lua:0.04
DEBUG:SCRIPT: native: 0.03
DEBUG:SCRIPT: lua:0.039
DEBUG:SCRIPT: native: 0.031
DEBUG:SCRIPT: lua:0.04
DEBUG:SCRIPT: native: 0.031
DEBUG:SCRIPT: lua:0.039


native: 0.059728999999999
native: 0.059455
native: 0.058417
native: 0.059436
native: 0.059778999999999
native: 0.060198999999999
native: 0.059331
native: 0.0600940000000011
native: 0.058405
native: 0.058944
native: 0.058088
native: 0.056916999999999
native: 0.060658
native: 0.059473000000001
static int drawPixels(lua_State* L)
	lua_getfield(L, 1, "width");
	lua_getfield(L, 1, "height");
	int width = luaL_checknumber(L, -2);
	int height = luaL_checknumber(L, -1);
	lua_pop(L, 1);
	lua_pop(L, 1); 
	int size = width * height;
	printf("width=%d height=%d \n",width,height);
	lua_gettable(L, -2 );
	lua_gettable(L, -3 );
	for(int i=1; i<= size;i++){
		int color = luaL_checknumber(L, -1);
		//printf("i=%d color=%d \n",i,color);
		lua_pop(L, 1);
		int r = color >> 16;
		int g = (color & 0x00FF00) >> 8;
		int b= color & 0x0000ff;
		int id = i * 3;
		lua_pushnumber(L, id - 2);
		lua_pushnumber(L, r);
		lua_settable(L, -4);
		lua_pushnumber(L, id - 1);
		lua_pushnumber(L, g);
		lua_settable(L, -4);
		lua_pushnumber(L, id);
		lua_pushnumber(L, b);
		lua_settable(L, -4);
	return 1;

Need help with Native Extensions(SOLVED)

Looks like setting data to stream is very expensive.
If i comment setting data to stream, i get 1 ms instead of 30. (x30 FASTER).:open_mouth:
Why buffer is so slow?



You moved from Lua to C, but you still use Lua calls extensively. You should try working with native representation of buffers directly. https://www.defold.com/ref/dmBuffer/

1 Like