1 // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
6 SHADER_DEFINE( shader_tile_colour,
9 "layout (location=0) in vec2 a_co;"
11 "uniform vec2 uOffset;"
15 "gl_Position = vec4( uPv * vec3( a_co + uOffset, 1.0 ), 1.0 );"
20 "uniform vec4 uColour;"
24 "FragColor = uColour;"
27 UNIFORMS({ "uPv", "uOffset", "uColour" })
34 #define FLAG_INPUT 0x1
35 #define FLAG_OUTPUT 0x2
36 #define FLAG_CANAL 0x4
62 static void map_free(void)
64 for( int i = 0; i < arrlen( world.io ); i ++ )
65 arrfree( world.io[ i ].conditions );
67 arrfree( world.data );
76 static int map_load( const char *str )
85 if( str[world.w] == ';' )
87 else if( !str[world.w] )
89 vg_error( "Unexpected EOF when parsing level\n" );
94 struct cell *row = arraddnptr( world.data, world.w );
96 int reg_start = 0, reg_end = 0;
112 if( reg_start < reg_end )
114 if( *c >= 'a' && *c <= 'z' )
116 arrpush( world.io[ reg_start ].conditions, *c );
120 if( *c == ',' || *c == '\n' )
129 vg_error( "Unkown attribute '%c' (row: %u)\n", *c, world.h );
136 vg_error( "Too many values to assign (row: %u)\n", world.h );
144 if( reg_start != reg_end )
146 vg_error( "Not enough values assigned (row: %u, %u of %u)\n", world.h, reg_start, reg_end );
152 vg_error( "Not enough cells to match previous row definition (row: %u, %u<%u)\n", world.h, cx, world.w );
156 row = arraddnptr( world.data, world.w );
159 reg_end = reg_start = arrlen( world.io );
165 vg_error( "Too many cells to match previous row definition (row: %u, %u>%u)\n", world.h, cx, world.w );
169 // Tile initialization
172 if( *c == '+' || *c == '-' )
174 struct cell_terminal term = { .id = cx + world.h*world.w };
175 arrpush( world.io, term );
176 row[ cx ++ ].state = *c == '+'? FLAG_INPUT: FLAG_OUTPUT;
181 row[ cx ++ ].state = FLAG_WALL;
185 row[ cx ++ ].state = 0x00;
192 vg_success( "Map loaded! (%u:%u)\n", world.w, world.h );
196 int main( int argc, char *argv[] )
198 vg_init( argc, argv, "FishLadder" );
201 void vg_register(void)
203 SHADER_INIT( shader_tile_colour );
208 glGenVertexArrays( 1, &world.tile_vao );
209 glGenBuffers( 1, &world.tile_vbo );
213 0.05f, 0.05f, 0.05f, 0.95f, 0.95f, 0.95f,
214 0.05f, 0.05f, 0.95f, 0.95f, 0.95f, 0.05f
217 glBindVertexArray( world.tile_vao );
218 glBindBuffer( GL_ARRAY_BUFFER, world.tile_vbo );
227 glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0 );
228 glEnableVertexAttribArray( 0 );
235 "###-#####-###;aaa,aa\n"
242 "###+#####+###;aa,aaa\n"
249 glDeleteVertexArrays( 1, &world.tile_vao );
250 glDeleteBuffers( 1, &world.tile_vbo );
257 float ratio = (float)vg_window_y / (float)vg_window_x;
258 float const size = 9.5f;
261 origin[0] = -0.5f * world.w;
262 origin[1] = -0.5f * world.h;
265 m3x3_projection( m_projection, -size, size, size*ratio, -size*ratio );
266 m3x3_identity( m_view );
267 m3x3_translate( m_view, origin );
268 m3x3_mul( m_projection, m_view, vg_pv );
269 vg_projection_update();
272 v2_copy( vg_mouse_ws, tile_pos );
274 int tile_x = floorf( tile_pos[0] );
275 int tile_y = floorf( tile_pos[1] );
277 if( tile_x >= 0 && tile_x < world.w && tile_y >= 0 && tile_y <= world.h )
278 world.selected = tile_y * world.h + tile_x;
285 glViewport( 0,0, vg_window_x, vg_window_y );
287 glDisable( GL_DEPTH_TEST );
288 glClearColor( 0.01f, 0.01f, 0.01f, 1.0f );
289 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
291 glBindVertexArray( world.tile_vao );
292 SHADER_USE( shader_tile_colour );
293 glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_colour, "uPv" ), 1, GL_FALSE, (float *)vg_pv );
295 for( int y = 0; y < world.h; y ++ )
297 for( int x = 0; x < world.w; x ++ )
299 glUniform2f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)x, (float)y );
303 struct cell *cell = &world.data[y*world.h+x];
305 if( cell->state & FLAG_WALL ) { v4_copy( (v4f){ 0.4f, 0.4f, 0.4f, 1.0f }, colour ); }
306 else if( cell->state & FLAG_CANAL ) { v4_copy( (v4f){ 0.6f, 0.6f, 0.6f, 1.0f }, colour ); }
307 else if( cell->state & FLAG_INPUT ) { v4_copy( (v4f){ 0.2f, 0.3f, 0.7f, 1.0f }, colour ); }
308 else if( cell->state & FLAG_OUTPUT ) { v4_copy( (v4f){ 0.2f, 0.7f, 0.3f, 1.0f }, colour ); }
309 else v4_copy( (v4f){ 1.0f, 0.0f, 0.0f, 1.0f }, colour );
311 if( world.selected == y*world.h + x )
312 v3_muls( colour, sinf( vg_time )*0.25f + 0.5f, colour );
314 glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, colour );
316 glDrawArrays( GL_TRIANGLES, 0, 6 );