Led Shooter

#1

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.

13 Likes

#2

Cute dino! Attack of dead pixels!

1 Like

#3

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

0 Likes

#4

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

#5

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.

3 Likes

#6

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?

0 Likes

#7

Have to do it with native extensions to be fast.

1 Like

#8

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?

0 Likes

#9

Did you try to use render target?

1 Like

#10

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

0 Likes

#11

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.

4 Likes

#12

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;
	//WTF NEED FIX IT NORMAL
	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

#13

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

#14

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)
    end
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

#15

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

#16

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.

3 Likes

#17

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

#18

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.

PC

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

Android

native: 0.059728999999999
lua:0.077413999999999
native: 0.059455
lua:0.082948999999999
native: 0.058417
lua:0.078471
native: 0.059436
lua:0.080285
native: 0.059778999999999
lua:0.077199
native: 0.060198999999999
lua:0.081021
native: 0.059331
lua:0.082233
native: 0.0600940000000011
lua:0.079887999999999
native: 0.058405
lua:0.079704000000001
native: 0.058944
lua:0.07696
native: 0.058088
lua:0.079167999999997
native: 0.056916999999999
lua:0.079489000000002
native: 0.060658
lua:0.082440000000002
native: 0.059473000000001
lua:0.081376000000002
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_pushstring(L,"stream");
	lua_gettable(L, -2 );
	lua_pushstring(L,"leds");
	lua_gettable(L, -3 );
	for(int i=1; i<= size;i++){
		lua_rawgeti(L,-1,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);
		//lua_pop(L,1);
	}
	lua_pop(L,1);
	
	return 1;
}
0 Likes

Need help with Native Extensions(SOLVED)
#19

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?

0 Likes

#20

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