X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=fishladder.c;h=4817bdf9a2a20004f7795879f8f96c918fe4b910;hb=a6d22d2e369a955e85d03b1159d4ac02b103ea43;hp=e024fca71987265a050db88d2a0be6b4f99317de;hpb=f8e80fde4a84a6b990ec17c067b2a95847ae744c;p=fishladder.git diff --git a/fishladder.c b/fishladder.c index e024fca..4817bdf 100644 --- a/fishladder.c +++ b/fishladder.c @@ -59,7 +59,22 @@ const char *level_pack[] = "## ##;\n" "## ##;\n" "###+#####+###;aa,aaa\n" - "#############;\n" + "#############;\n", + + // Level 5 + "###############;\n" + "####-##########;abcb\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "## ##;\n" + "##########+####;bcba\n" + "###############;\n" }; m3x3f m_projection; @@ -94,14 +109,16 @@ m3x3f m_mdl; enum cell_type { + k_cell_type_ramp_right = 3, + k_cell_type_ramp_left = 6, k_cell_type_split = 7, k_cell_type_merge = 13 }; v3f colour_sets[] = -{ { 0.9f, 0.2f, 0.01f }, +{ { 0.9f, 0.6f, 0.20f }, { 0.2f, 0.9f, 0.14f }, - { 0.1f, 0.3f, 0.85f } }; + { 0.4f, 0.8f, 1.00f } }; static void colour_code_v3( char cc, v3f target ) { @@ -172,6 +189,8 @@ struct world float sim_start; int simulating; + float frame_lerp; + struct cell_terminal { // TODO: Split into input/output structures @@ -186,6 +205,9 @@ struct world struct mesh tile, circle; + GLuint background_data; + GLuint random_samples; + int selected, tile_x, tile_y; v2f tile_pos; @@ -195,6 +217,9 @@ struct world v2i dir; int alive; char payload; + float death_time; + v2f physics_v; + v2f physics_co; } fishes[16]; @@ -215,7 +240,7 @@ static void map_free(void) world.io = NULL; } -static void map_reclassify( v2i start, v2i end ); +static void map_reclassify( v2i start, v2i end, int update_texbuffer ); static int map_load( const char *str ) { map_free(); @@ -332,7 +357,23 @@ static int map_load( const char *str ) c ++; } - map_reclassify( NULL, NULL ); + // Update data texture to fill out the background + { + u8 info_buffer[64*64*4]; + for( int i = 0; i < 64*64; i ++ ) + { + u8 *px = &info_buffer[i*4]; + px[0] = 255; + px[1] = 0; + px[2] = 0; + px[3] = 0; + } + + glBindTexture( GL_TEXTURE_2D, world.background_data ); + glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 64, 64, GL_RGBA, GL_UNSIGNED_BYTE, info_buffer ); + } + + map_reclassify( NULL, NULL, 1 ); vg_success( "Map loaded! (%u:%u)\n", world.w, world.h ); return 1; } @@ -342,13 +383,72 @@ static struct cell *pcell( v2i pos ) return &world.data[ pos[1]*world.w + pos[0] ]; } +static void map_serialize( FILE *stream ) +{ + for( int y = 0; y < world.h; y ++ ) + { + for( int x = 0; x < world.w; x ++ ) + { + struct cell *cell = pcell( (v2i){ x, y } ); + + if( cell->state & FLAG_WALL ) fputc( '#', stream ); + else if( cell->state & FLAG_INPUT ) fputc( '+', stream ); + else if( cell->state & FLAG_OUTPUT ) fputc( '-', stream ); + else if( cell->state & FLAG_CANAL ) fputc( '*', stream ); + else fputc( ' ', stream ); + } + + fputc( ';', stream ); + + int terminal_write_count = 0; + + for( int x = 0; x < world.w; x ++ ) + { + for( int i = 0; i < arrlen( world.io ); i ++ ) + { + struct cell_terminal *term = &world.io[i]; + if( term->id == y*world.w+x ) + { + if( terminal_write_count ) + fputc( ',', stream ); + terminal_write_count ++; + + for( int j = 0; j < arrlen( term->conditions ); j ++ ) + fputc( term->conditions[j], stream ); + } + } + } + + fputc( '\n', stream ); + } +} + int main( int argc, char *argv[] ) { vg_init( argc, argv, "Fish (Marbles Computer) Ladder Simulator 2022 | N,M: change level | SPACE: Test | LeftClick: Toggle tile" ); } +static void console_save_map( int argc, char *argv[] ) +{ + if( argc >= 1 ) + { + FILE *test_writer = fopen( argv[0], "w" ); + if( test_writer ) + { + map_serialize( test_writer ); + + fclose( test_writer ); + } + } +} + void vg_start(void) { + vg_function_push( (struct vg_cmd){ + .name = "save_map", + .function = console_save_map + }); + // Quad mesh { float quad_mesh[] = @@ -396,6 +496,29 @@ void vg_start(void) init_mesh( &world.circle, circle_mesh, vg_list_size( circle_mesh ) ); } + // Create info data texture + { + glGenTextures( 1, &world.background_data ); + glBindTexture( GL_TEXTURE_2D, world.background_data ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); + vg_tex2d_nearest(); + } + + // Create random smaples texture + { + u8 *data = malloc(512*512*2); + for( int i = 0; i < 512*512*2; i ++ ) + data[ i ] = rand()/(RAND_MAX/255); + + glGenTextures( 1, &world.random_samples ); + glBindTexture( GL_TEXTURE_2D, world.random_samples ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RG, 512, 512, 0, GL_RG, GL_UNSIGNED_BYTE, data ); + vg_tex2d_linear(); + vg_tex2d_repeat(); + + free( data ); + } + resource_load_main(); map_load( level_pack[ 0 ] ); @@ -405,6 +528,9 @@ void vg_free(void) { resource_free_main(); + glDeleteTextures( 1, &world.background_data ); + glDeleteTextures( 1, &world.random_samples ); + free_mesh( &world.tile ); free_mesh( &world.circle ); @@ -496,26 +622,38 @@ static int cell_interactive( v2i co ) return 1; } -static void map_reclassify( v2i start, v2i end ) +static void map_reclassify( v2i start, v2i end, int update_texbuffer ) { - v2i full_start = { 2,2 }; - v2i full_end = { world.w-2, world.h-2 }; + v2i full_start = { 1,1 }; + v2i full_end = { world.w-1, world.h-1 }; if( !start || !end ) { start = full_start; end = full_end; } + + // Texture data + u8 info_buffer[64*64*4]; + u32 pixel_id = 0; + + int px0 = vg_max( start[0], full_start[0] ), + px1 = vg_min( end[0], full_end[0] ), + py0 = vg_max( start[1], full_start[1] ), + py1 = vg_min( end[1], full_end[1] ); - for( int y = vg_max( start[1], full_start[1] ); y < vg_min( end[1], full_end[1] ); y ++ ) + for( int y = py0; y < py1; y ++ ) { - for( int x = vg_max( start[0], full_start[0] ); x < vg_min( end[0], full_end[0] ); x ++ ) + for( int x = px0; x < px1; x ++ ) { + struct cell *cell = pcell((v2i){x,y}); + v2i dirs[] = {{1,0},{0,1},{-1,0},{0,-1}}; + u8 height = 0; u8 config = 0x00; - if( pcell((v2i){x,y})->state & FLAG_CANAL ) + if( cell->state & (FLAG_CANAL|FLAG_INPUT|FLAG_OUTPUT) ) { for( int i = 0; i < vg_list_size( dirs ); i ++ ) { @@ -523,14 +661,47 @@ static void map_reclassify( v2i start, v2i end ) if( neighbour->state & (FLAG_CANAL|FLAG_INPUT|FLAG_OUTPUT) ) config |= 0x1 << i; } + + height = 128; } - else config = 0xF; + else + { + if( cell->state & FLAG_WALL ) + height = 255; + + config = 0xF; + } pcell((v2i){x,y})->config = config; + + u8 *info_px = &info_buffer[ (pixel_id ++)*4 ]; + info_px[0] = height; + info_px[1] = cell->state & FLAG_WALL? 0: 255; + info_px[2] = 0; + info_px[3] = 0; } } + + if( update_texbuffer ) + { + glBindTexture( GL_TEXTURE_2D, world.background_data ); + glTexSubImage2D( GL_TEXTURE_2D, 0, px0 + 16, py0 + 16, px1-px0, py1-py0, GL_RGBA, GL_UNSIGNED_BYTE, info_buffer ); + } } +v2f const curve_3[] = {{0.5f,1.0f},{0.5f,0.625f},{0.625f,0.5f},{1.0f,0.5f}}; +v2f const curve_6[] = {{0.5f,1.0f},{0.5f,0.625f},{0.375f,0.5f},{0.0f,0.5f}}; +v2f const curve_9[] = {{1.0f,0.5f},{0.625f,0.5f},{0.5f,0.375f},{0.5f,0.0f}}; +v2f const curve_12[]= {{0.0f,0.5f},{0.375f,0.5f},{0.5f,0.375f},{0.5f,0.0f}}; + +v2f const curve_2[] = {{0.5f,1.0f},{0.5f,0.8f},{0.5f,0.3f},{0.5f,0.2f}}; +v2f const curve_8[] = {{0.5f,0.8f},{0.5f,0.5f},{0.5f,0.3f},{0.5f,0.0f}}; + +v2f const curve_7[] = {{0.5f,0.8438f},{0.875f,0.8438f},{0.625f,0.5f},{1.0f,0.5f}}; +v2f const curve_7_1[] = {{0.5f,0.8438f},{1.0f-0.875f,0.8438f},{1.0-0.625f,0.5f},{0.0f,0.5f}}; + +float const curve_7_linear_section = 0.1562f; + void vg_update(void) { static int curlevel = 0; @@ -554,15 +725,20 @@ void vg_update(void) vg_info( "Stopping simulation!\n" ); } - float ratio = (float)vg_window_y / (float)vg_window_x; - float const size = 9.5f; + // Fit within screen + + float r1 = (float)vg_window_y / (float)vg_window_x, + r2 = (float)world.h / (float)world.w, + size; + + size = ( r2 < r1? (float)world.w * 0.5f: ((float)world.h * 0.5f) / r1 ) + 2.5f; + m3x3_projection( m_projection, -size, size, -size*r1, size*r1 ); v3f origin; - origin[0] = -0.5f * world.w; - origin[1] = -0.5f * world.h; + origin[0] = floorf( -0.5f * world.w ); + origin[1] = floorf( -0.5f * world.h ); origin[2] = 0.0f; - m3x3_projection( m_projection, -size, size, -size*ratio, size*ratio ); m3x3_identity( m_view ); m3x3_translate( m_view, origin ); m3x3_mul( m_projection, m_view, vg_pv ); @@ -591,7 +767,7 @@ void vg_update(void) sfx_set_playrnd( &audio_tile_mod, &audio_system_sfx, 0, 3 ); map_reclassify( (v2i){ world.tile_x -2, world.tile_y -2 }, - (v2i){ world.tile_x +2, world.tile_y +2 } ); + (v2i){ world.tile_x +2, world.tile_y +2 }, 1 ); } } else @@ -638,47 +814,12 @@ void vg_update(void) // Fish ticks if( world.simulating ) - { + { while( world.sim_frame < (int)((vg_time-world.sim_start)*2.0f) ) { //vg_info( "frame: %u\n", world.sim_frame ); sfx_set_playrnd( &audio_random, &audio_system_balls_switching, 0, 9 ); - - for( int i = 0; i < arrlen( world.io ); i ++ ) - { - struct cell_terminal *term = &world.io[ i ]; - int posx = term->id % world.w; - int posy = (term->id - posx)/world.w; - int is_input = world.data[ term->id ].state & FLAG_INPUT; - - if( is_input ) - { - if( world.sim_frame < arrlen( term->conditions ) ) - { - struct fish *fish = &world.fishes[world.num_fishes++]; - fish->pos[0] = posx; - fish->pos[1] = posy; - fish->alive = 1; - fish->payload = term->conditions[world.sim_frame]; - - int can_spawn = 0; - - v2i dirs[] = {{1,0},{-1,0},{0,-1}}; - for( int j = 0; j < vg_list_size(dirs); j ++ ) - if( pcell( (v2i){ posx+dirs[j][0], posy+dirs[j][1] } )->state & FLAG_CANAL ) - { - fish->dir[0] = dirs[j][0]; - fish->dir[1] = dirs[j][1]; - can_spawn = 1; - break; - } - - if( !can_spawn ) - world.num_fishes--; - } - } - } - + // Update splitter deltas for( int i = 0; i < world.h*world.w; i ++ ) { @@ -688,13 +829,17 @@ void vg_update(void) cell->state &= ~FLAG_FLIP_ROTATING; } } - + + // Update fish positions for( int i = 0; i < world.num_fishes; i ++ ) { struct fish *fish = &world.fishes[i]; struct cell *cell_current = pcell( fish->pos ); - if( !fish->alive ) + if( fish->alive == -1 ) + fish->alive = 0; + + if( fish->alive != 1 ) continue; // Apply to output @@ -760,15 +905,171 @@ void vg_update(void) if( !(cell_entry->state & (FLAG_INPUT|FLAG_CANAL|FLAG_OUTPUT) )) fish->alive = 0; else + { + if( fish->dir[0] ) + { + if( cell_entry->config == k_cell_type_split || + cell_entry->config == k_cell_type_ramp_right || + cell_entry->config == k_cell_type_ramp_left ) + { + // Special death (FALL) + v2_sub( fish->physics_co, fish->physics_v, fish->physics_v ); + v2_divs( fish->physics_v, vg_time_delta, fish->physics_v ); + + fish->alive = -2; + vg_warn( "Special death (fall)\n" ); + continue; + } + } + if( cell_entry->config == k_cell_type_split ) { sfx_set_playrnd( &audio_splitter, &audio_system_balls_important, 0, 1 ); cell_entry->state |= FLAG_FLIP_ROTATING; } + } + } + + // Check for collisions + for( int i = 0; i < world.num_fishes; i ++ ) + { + if( world.fishes[i].alive == 1 ) + { + for( int j = i+1; j < world.num_fishes; j ++ ) + { + if( (world.fishes[j].alive == 1) && (world.fishes[i].pos[0] == world.fishes[j].pos[0]) && + (world.fishes[i].pos[1] == world.fishes[j].pos[1]) ) + { + // Shatter death (+0.5s) + world.fishes[i].alive = -1; + world.fishes[j].alive = -1; + world.fishes[i].death_time = 0.5f; + world.fishes[j].death_time = 0.5f; + } + } + } + } + + // Spawn fishes + for( int i = 0; i < arrlen( world.io ); i ++ ) + { + struct cell_terminal *term = &world.io[ i ]; + int posx = term->id % world.w; + int posy = (term->id - posx)/world.w; + int is_input = world.data[ term->id ].state & FLAG_INPUT; + + if( is_input ) + { + if( world.sim_frame < arrlen( term->conditions ) ) + { + struct fish *fish = &world.fishes[world.num_fishes++]; + fish->pos[0] = posx; + fish->pos[1] = posy; + fish->alive = 1; + fish->payload = term->conditions[world.sim_frame]; + + int can_spawn = 0; + + v2i dirs[] = {{1,0},{-1,0},{0,-1}}; + for( int j = 0; j < vg_list_size(dirs); j ++ ) + if( pcell( (v2i){ posx+dirs[j][0], posy+dirs[j][1] } )->state & FLAG_CANAL ) + { + fish->dir[0] = dirs[j][0]; + fish->dir[1] = dirs[j][1]; + can_spawn = 1; + break; + } + + if( !can_spawn ) + world.num_fishes--; + } + } } world.sim_frame ++; } + + float scaled_time = 0.0f; + scaled_time = (vg_time-world.sim_start)*2.0f; + world.frame_lerp = scaled_time - (float)world.sim_frame; + + // Update positions + for( int i = 0; i < world.num_fishes; i ++ ) + { + struct fish *fish = &world.fishes[i]; + + if( fish->alive == 0 ) + continue; + + if( fish->alive == -1 && (world.frame_lerp > fish->death_time) ) + continue; // Todo: particle thing? + + if( fish->alive == -2 ) + { + v2_muladds( fish->physics_v, (v2f){ 0.0, -9.8f }, vg_time_delta, fish->physics_v ); + v2_muladds( fish->physics_co, fish->physics_v, vg_time_delta, fish->physics_co ); + } + else + { + struct cell *cell = pcell(fish->pos); + v2f const *curve; + + float t = world.frame_lerp; + + v2_copy( fish->physics_co, fish->physics_v ); + + switch( cell->config ) + { + case 13: + if( fish->dir[0] == 1 ) + curve = curve_12; + else + curve = curve_9; + break; + case 2: curve = curve_2; break; + case 8: curve = curve_8; break; + case 3: curve = curve_3; break; + case 6: curve = curve_6; break; + case 9: curve = curve_9; break; + case 12: curve = curve_12; break; + case 7: + if( t > curve_7_linear_section ) + { + t -= curve_7_linear_section; + t *= (1.0f/(1.0f-curve_7_linear_section)); + + curve = cell->state & FLAG_FLIP_FLOP? curve_7: curve_7_1; + } + else curve = NULL; + break; + default: curve = NULL; break; + } + + if( curve ) + { + float t2 = t * t; + float t3 = t * t * t; + + float cA = 3.0f*t2 - 3.0f*t3; + float cB = 3.0f*t3 - 6.0f*t2 + 3.0f*t; + float cC = 3.0f*t2 - t3 - 3.0f*t + 1.0f; + + fish->physics_co[0] = t3*curve[3][0] + cA*curve[2][0] + cB*curve[1][0] + cC*curve[0][0]; + fish->physics_co[1] = t3*curve[3][1] + cA*curve[2][1] + cB*curve[1][1] + cC*curve[0][1]; + fish->physics_co[0] += (float)fish->pos[0]; + fish->physics_co[1] += (float)fish->pos[1]; + } + else + { + v2f origin; + origin[0] = (float)fish->pos[0] + (float)fish->dir[0]*-0.5f + 0.5f; + origin[1] = (float)fish->pos[1] + (float)fish->dir[1]*-0.5f + 0.5f; + + fish->physics_co[0] = origin[0] + (float)fish->dir[0]*t; + fish->physics_co[1] = origin[1] + (float)fish->dir[1]*t; + } + } + } } } @@ -802,11 +1103,11 @@ static void render_tiles( v2i start, v2i end, v4f const regular_colour, v4f cons int uv[2] = { 3, 0 }; - if( cell->state & FLAG_CANAL ) + if( cell->state & (FLAG_CANAL|FLAG_INPUT|FLAG_OUTPUT) ) { uv[0] = tile_offsets[ cell->config ][0]; uv[1] = tile_offsets[ cell->config ][1]; - } + } else continue; glUniform4f( SHADER_UNIFORM( shader_tile_main, "uOffset" ), (float)x, (float)y, uv[0], uv[1] ); if( selected ) @@ -826,30 +1127,12 @@ void vg_render(void) glViewport( 0,0, vg_window_x, vg_window_y ); glDisable( GL_DEPTH_TEST ); - glClearColor( 0.8f, 0.8f, 0.8f, 1.0f ); + glClearColor( 0.369768f, 0.3654f, 0.42f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - float scaled_time = 0.0f, frame_lerp = 0.0f; - - if( world.simulating ) - { - scaled_time = (vg_time-world.sim_start)*2.0f; - frame_lerp = scaled_time - (float)world.sim_frame; - } - v4f const colour_default = {1.0f, 1.0f, 1.0f, 1.0f}; v4f const colour_selected = {0.90f, 0.92f, 1.0f, 1.0f}; - - v2f const curve_3[] = {{0.5f,1.0f},{0.5f,0.625f},{0.625f,0.5f},{1.0f,0.5f}}; - v2f const curve_6[] = {{0.5f,1.0f},{0.5f,0.625f},{0.375f,0.5f},{0.0f,0.5f}}; - v2f const curve_9[] = {{1.0f,0.5f},{0.625f,0.5f},{0.5f,0.375f},{0.5f,0.0f}}; - v2f const curve_12[]= {{0.0f,0.5f},{0.375f,0.5f},{0.5f,0.375f},{0.5f,0.0f}}; - - v2f const curve_7[] = {{0.5f,0.8438f},{0.875f,0.8438f},{0.625f,0.5f},{1.0f,0.5f}}; - v2f const curve_7_1[] = {{0.5f,0.8438f},{1.0f-0.875f,0.8438f},{1.0-0.625f,0.5f},{0.0f,0.5f}}; - - float const curve_7_linear_section = 0.1562f; - + // TILE SET RENDERING // todo: just slam everything into a mesh... // when user modifies a tile the neighbours can be easily uploaded to gpu mem @@ -860,6 +1143,29 @@ void vg_render(void) use_mesh( &world.tile ); + // Draw background + + if(1){ + + SHADER_USE( shader_background ); + glUniformMatrix3fv( SHADER_UNIFORM( shader_background, "uPv" ), 1, GL_FALSE, (float *)vg_pv ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, world.background_data ); + glUniform1i( SHADER_UNIFORM( shader_background, "uTexMain" ), 0 ); + + glUniform3f( SHADER_UNIFORM( shader_background, "uOffset" ), -16, -16, 64 ); + glUniform1f( SHADER_UNIFORM( shader_background, "uVariance" ), 0.02f ); + + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, world.random_samples ); + glUniform1i( SHADER_UNIFORM( shader_background, "uSamplerNoise" ), 1 ); + + draw_mesh( 0, 2 ); + + } + + SHADER_USE( shader_tile_main ); m2x2f subtransform; @@ -867,6 +1173,11 @@ void vg_render(void) glUniformMatrix2fv( SHADER_UNIFORM( shader_tile_main, "uSubTransform" ), 1, GL_FALSE, (float *)subtransform ); glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_main, "uPv" ), 1, GL_FALSE, (float *)vg_pv ); glUniform1f( SHADER_UNIFORM( shader_tile_main, "uGhost" ), 0.0f ); + glUniform1f( SHADER_UNIFORM( shader_tile_main, "uForeground" ), 0.0f ); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); // Bind textures vg_tex2d_bind( &tex_tile_data, 0 ); @@ -877,9 +1188,7 @@ void vg_render(void) render_tiles( NULL, NULL, colour_default, colour_default ); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBlendEquation(GL_FUNC_ADD); + SHADER_USE( shader_ball ); glUniformMatrix3fv( SHADER_UNIFORM( shader_ball, "uPv" ), 1, GL_FALSE, (float *)vg_pv ); @@ -894,76 +1203,21 @@ void vg_render(void) { struct fish *fish = &world.fishes[i]; - if( !fish->alive ) + if( fish->alive == 0 ) continue; - - // Evaluate position - struct cell *cell = pcell(fish->pos); - v2f fish_pos; - v2f const *curve; - - float t = frame_lerp; - - switch( cell->config ) - { - case 13: - if( fish->dir[0] == 1 ) - curve = curve_12; - else - curve = curve_9; - break; - case 3: curve = curve_3; break; - case 6: curve = curve_6; break; - case 9: curve = curve_9; break; - case 12: curve = curve_12; break; - case 7: - if( t > curve_7_linear_section ) - { - t -= curve_7_linear_section; - t *= (1.0f/(1.0f-curve_7_linear_section)); - - curve = cell->state & FLAG_FLIP_FLOP? curve_7: curve_7_1; - } - else curve = NULL; - break; - default: curve = NULL; break; - } - - if( curve ) - { - float t2 = t * t; - float t3 = t * t * t; - - float cA = 3.0f*t2 - 3.0f*t3; - float cB = 3.0f*t3 - 6.0f*t2 + 3.0f*t; - float cC = 3.0f*t2 - t3 - 3.0f*t + 1.0f; - - fish_pos[0] = t3*curve[3][0] + cA*curve[2][0] + cB*curve[1][0] + cC*curve[0][0]; - fish_pos[1] = t3*curve[3][1] + cA*curve[2][1] + cB*curve[1][1] + cC*curve[0][1]; - fish_pos[0] += (float)fish->pos[0]; - fish_pos[1] += (float)fish->pos[1]; - } - else - { - v2f origin; - origin[0] = (float)fish->pos[0] + (float)fish->dir[0]*-0.5f + 0.5f; - origin[1] = (float)fish->pos[1] + (float)fish->dir[1]*-0.5f + 0.5f; - - fish_pos[0] = origin[0] + (float)fish->dir[0]*t; - fish_pos[1] = origin[1] + (float)fish->dir[1]*t; - } + if( fish->alive == -1 && (world.frame_lerp > fish->death_time) ) + continue; v4f dot_colour = { 0.0f, 0.0f, 0.0f, 1.0f }; colour_code_v3( fish->payload, dot_colour ); glUniform3fv( SHADER_UNIFORM( shader_ball, "uColour" ), 1, dot_colour ); - glUniform2f( SHADER_UNIFORM( shader_ball, "uOffset" ), fish_pos[0], fish_pos[1] ); + glUniform2fv( SHADER_UNIFORM( shader_ball, "uOffset" ), 1, fish->physics_co ); draw_mesh( 0, 32 ); } } - SHADER_USE( shader_tile_main ); // Bind textures @@ -973,6 +1227,7 @@ void vg_render(void) vg_tex2d_bind( &tex_wood, 1 ); glUniform1i( SHADER_UNIFORM( shader_tile_main, "uTexWood" ), 1 ); + glUniform1f( SHADER_UNIFORM( shader_tile_main, "uForeground" ), 1.0f ); render_tiles( NULL, NULL, colour_default, colour_selected ); // Draw splitters @@ -989,12 +1244,12 @@ void vg_render(void) if( cell->state & FLAG_FLIP_ROTATING ) { - if( (frame_lerp > curve_7_linear_section) ) + if( (world.frame_lerp > curve_7_linear_section) ) { float const rotation_speed = 0.4f; - if( (frame_lerp < 1.0f-rotation_speed) ) + if( (world.frame_lerp < 1.0f-rotation_speed) ) { - float t = frame_lerp - curve_7_linear_section; + float t = world.frame_lerp - curve_7_linear_section; t *= -2.0f * (1.0f/(1.0f-(curve_7_linear_section+rotation_speed))); t += 1.0f; @@ -1021,7 +1276,7 @@ void vg_render(void) v2i new_end = { world.tile_x + 2, world.tile_y + 2 }; world.data[ world.selected ].state ^= FLAG_CANAL; - map_reclassify( new_begin, new_end ); + map_reclassify( new_begin, new_end, 0 ); m2x2_identity( subtransform ); glUniform1f( SHADER_UNIFORM( shader_tile_main, "uGhost" ), 1.0f ); @@ -1031,7 +1286,7 @@ void vg_render(void) render_tiles( new_begin, new_end, colour_default, colour_default ); world.data[ world.selected ].state ^= FLAG_CANAL; - map_reclassify( new_begin, new_end ); + map_reclassify( new_begin, new_end, 0 ); } //glDisable(GL_BLEND); @@ -1059,7 +1314,8 @@ void vg_render(void) for( int j = 0; j < arrlen( term->conditions ); j ++ ) { - glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + 0.2f, 0.1f ); + float y_offset = is_input? 1.2f: -0.2f; + glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + y_offset, 0.1f ); if( is_input ) { @@ -1102,5 +1358,4 @@ void vg_render(void) void vg_ui(void) { //ui_test(); - sfx_internal_debug_overlay(); }