From: hgn Date: Sun, 14 Nov 2021 05:20:57 +0000 (+0000) Subject: level save/load X-Git-Url: https://harrygodden.com/git/?p=fishladder.git;a=commitdiff_plain;h=7838efe822ca9336a69936004dd6d9bed70910fb level save/load --- diff --git a/build.sh b/build.sh index 9acfd36..328e432 100755 --- a/build.sh +++ b/build.sh @@ -82,11 +82,13 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then mkdir build.linux/cfg -p mkdir build.linux/textures -p mkdir build.linux/sound -p + mkdir build.linux/maps -p cp $target ./build.linux/$target cp ./steam/libsteam_api.so ./build.linux/libsteam_api.so cp -r ./textures/ ./build.linux/ cp -r ./sound/ ./build.linux/ + cp -r ./maps/ ./build.linux/ if [ "$run_after" = true ]; then echo "Playing" @@ -99,10 +101,12 @@ else mkdir build.win32/cfg -p mkdir build.win32/textures -p mkdir build.win32/sound -p + mkdir build.win32/maps -p cp $target ./build.win32/$target cp -r ./textures/ ./build.win32/ cp -r ./sound/ ./build.win32/ + cp -r ./maps/ ./build.win32/ cp ./lib/glfw3.dll ./build.win32/glfw3.dll if [ "$run_after" = true ]; then diff --git a/fishladder.c b/fishladder.c index 09bcf43..4af1302 100644 --- a/fishladder.c +++ b/fishladder.c @@ -4,6 +4,14 @@ #include "vg/vg.h" #include "fishladder_resources.h" +const char *level_pack_1[] = { + "level0", + "level1", + "level2", + "level3", + "level4" +}; + const char *level_pack[] = { // Level 0 @@ -224,6 +232,8 @@ struct world fishes[16]; int num_fishes; + + char map_name[128]; } world = {}; static void map_free(void) @@ -241,7 +251,7 @@ static void map_free(void) } static void map_reclassify( v2i start, v2i end, int update_texbuffer ); -static int map_load( const char *str ) +static int map_load( const char *str, const char *name ) { map_free(); @@ -372,7 +382,9 @@ static int map_load( const char *str ) } map_reclassify( NULL, NULL, 1 ); - vg_success( "Map loaded! (%u:%u)\n", world.w, world.h ); + vg_success( "Map '%s' loaded! (%u:%u)\n", name, world.w, world.h ); + + strncpy( world.map_name, name, vg_list_size( world.map_name )-1 ); return 1; } @@ -426,31 +438,85 @@ 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[] ) +static int console_save_map( int argc, char const *argv[] ) { + char map_path[ 256 ]; + + strcpy( map_path, "sav/" ); + strcat( map_path, world.map_name ); + strcat( map_path, ".map" ); + + FILE *test_writer = fopen( map_path, "wb" ); + if( test_writer ) + { + map_serialize( test_writer ); + + fclose( test_writer ); + return 1; + } + else + { + vg_error( "Unable to open stream for writing\n" ); + return 0; + } +} + +static int console_load_map( int argc, char const *argv[] ) +{ + char map_path[ 256 ]; + if( argc >= 1 ) { - FILE *test_writer = fopen( argv[0], "wb" ); - if( test_writer ) + // try from saves + strcpy( map_path, "sav/" ); + strcat( map_path, argv[0] ); + strcat( map_path, ".map" ); + + char *text_source = vg_textasset_read( map_path ); + + if( !text_source ) { - map_serialize( test_writer ); + strcpy( map_path, "maps/" ); + strcat( map_path, argv[0] ); + strcat( map_path, ".map" ); - fclose( test_writer ); + text_source = vg_textasset_read( map_path ); + } + + if( text_source ) + { + map_load( text_source, argv[0] ); + free( text_source ); + return 1; + } + else + { + vg_error( "Missing maps '%s'\n", argv[0] ); + return 0; } } + else + { + vg_error( "Missing argument \n" ); + return 0; + } } -static void console_load_map( int argc, char *argv[] ) +static int console_changelevel( int argc, char const *argv[] ) { if( argc >= 1 ) { - char *text_source = vg_textasset_read( argv[0] ); - - if( text_source ) - map_load( text_source ); - - free( text_source ); + // Save current level + if( console_save_map( 0, NULL ) ) + if( console_load_map( argc, argv ) ) + return 1; } + else + { + vg_error( "Missing argument \n" ); + } + + return 0; } void vg_start(void) @@ -464,6 +530,11 @@ void vg_start(void) .name = "map_load", .function = console_load_map }); + + vg_function_push( (struct vg_cmd){ + .name = "changelevel", + .function = console_changelevel + }); // Quad mesh { @@ -472,11 +543,8 @@ void vg_start(void) 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, - 0.48f, 0.48f, 0.5f, 0.52f, 0.52f, 0.52f, // Static dot - 0.375f, 0.25f, 0.5f, 0.75f, 0.625f, 0.25f, // Downwards pointing arrow - 0.25f, 0.625f, 0.75f, 0.5f, 0.25f, 0.375f, // Left - 0.625f, 0.75f, 0.5f, 0.25f, 0.375f, 0.75f, // up - 0.75f, 0.375f, 0.25f, 0.5f, 0.75f, 0.625f + 0.0f, 0.0f, 0.0f, 1.0f, 4.0f, 1.0f, + 0.0f, 0.0f, 4.0f, 1.0f, 4.0f, 0.0f }; init_mesh( &world.tile, quad_mesh, vg_list_size(quad_mesh) ); @@ -537,7 +605,7 @@ void vg_start(void) resource_load_main(); - map_load( level_pack[ 0 ] ); + console_load_map( 1, level_pack_1 ); } void vg_free(void) @@ -727,7 +795,7 @@ void vg_update(void) if( changelvl != curlevel ) { - map_load( level_pack[ changelvl ] ); + console_changelevel( 1, level_pack + changelvl ); curlevel = changelvl; // TEMP!!! code dupe @@ -1312,6 +1380,11 @@ void vg_render(void) SHADER_USE( shader_tile_colour ); glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_colour, "uPv" ), 1, GL_FALSE, (float *)vg_pv ); use_mesh( &world.circle ); + + int const filled_start = 0; + int const filled_count = 32; + int const empty_start = 32; + int const empty_count = 32*2; // Draw i/o arrays for( int i = 0; i < arrlen( world.io ); i ++ ) @@ -1320,12 +1393,7 @@ void vg_render(void) int posx = term->id % world.w; int posy = (term->id - posx)/world.w; int is_input = world.data[ term->id ].state & FLAG_INPUT; - - int const filled_start = 0; - int const filled_count = 32; - int const empty_start = 32; - int const empty_count = 32*2; - + v4f dot_colour = { 0.0f, 0.0f, 0.0f, 1.0f }; for( int j = 0; j < arrlen( term->conditions ); j ++ ) @@ -1367,8 +1435,73 @@ void vg_render(void) { glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.0f, 0.0f, 0.0f, 1.0f ); glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), -0.5f + cosf( vg_time * 4.0f ) * 0.2f, sinf( vg_time * 4.0f ) * 0.2f + (float)world.h * 0.5f, 0.05f ); - draw_mesh( 0, 32 ); + draw_mesh( filled_start, filled_count ); + } + + // Level selection UI + float ratio = ((float)vg_window_x/(float)vg_window_y); + + m3x3f ui_view = M3X3_IDENTITY; + m3x3_scale( ui_view, (v3f){ 1.0f, -ratio, 1.0f } ); + glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_colour, "uPv" ), 1, GL_FALSE, (float *)ui_view ); + + // Calculate mouse in UIsp + v3f mouse_ui_space = { ((float)vg_mouse[0] / (float)(vg_window_x)) * 2.0f - 1.0f, + (((float)vg_mouse[1] / (float)(vg_window_y)) * 2.0f - 1.0f)*(1.0f/ratio), 0.0125f }; + + // Get selected level + const float selection_scale = 0.05f; + int const level_count = vg_list_size( level_pack_1 ); + int level_select = -1; + + if( mouse_ui_space[0] <= -0.9f ) + { + float levels_range = (float)level_count*selection_scale*0.6f; + float level_offset = ((mouse_ui_space[1] + levels_range) / levels_range) * 0.5f * (float)level_count; + level_select = floorf( level_offset ); + + // Draw selector + if( level_select >= 0 && level_select < vg_list_size( level_pack_1 ) ) + { + glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.369768f, 0.3654f, 0.42f, 1.0f ); + + use_mesh( &world.tile ); + glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), + -1.0f, + (-(float)level_count + (float)level_select * 2.0f ) * selection_scale * 0.6f, + selection_scale + ); + draw_mesh( 2, 2 ); + + use_mesh( &world.circle ); + } + + if( vg_get_button_down( "primary" ) ) + { + console_changelevel( 1, level_pack_1 + level_select ); + } } + + glUniform4f( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 0.4f, 0.39f, 0.45f, 1.0f ); + + // Draw levels + for( int i = 0; i < level_count; i ++ ) + { + v3f level_ui_space = { + -0.97f, + (-(float)level_count + (float)i * 2.0f ) * selection_scale * 0.6f + selection_scale * 0.5f, + selection_scale * 0.5f + }; + + float scale = vg_clampf( 1.0f - fabsf(level_ui_space[1] - mouse_ui_space[1]) * 2.0f, 0.9f, 1.0f ); + level_ui_space[2] *= scale; + + glUniform3fv( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), 1, level_ui_space ); + draw_mesh( empty_start, empty_count ); + } + + glUniform3fv( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), 1, mouse_ui_space ); + draw_mesh( empty_start, empty_count ); } void vg_ui(void) diff --git a/vg/vg_console.h b/vg/vg_console.h index 23b4480..612e815 100644 --- a/vg/vg_console.h +++ b/vg/vg_console.h @@ -25,7 +25,7 @@ struct vg_console struct vg_cmd { - void (*function)( int argc, char *argv[] ); + int (*function)( int argc, char const *argv[] ); const char *name; } *functions; @@ -139,7 +139,7 @@ static void vg_console_free(void) static void execute_console_input( const char *cmd ) { char temp[512]; - char *args[9]; + char const *args[9]; int arg_count = 0; int in_token = 0; diff --git a/vg/vg_m.h b/vg/vg_m.h index 6906837..9e70c92 100644 --- a/vg/vg_m.h +++ b/vg/vg_m.h @@ -17,6 +17,11 @@ static inline float vg_maxf( float a, float b ) return a > b? a: b; } +static inline float vg_clampf( float a, float min, float max ) +{ + return vg_minf( max, vg_maxf( a, min ) ); +} + #define VG_MIN( A, B ) ((A)<(B)?(A):(B)) #define VG_MAX( A, B ) ((A)>(B)?(A):(B)) @@ -98,6 +103,28 @@ static inline void v2_muladds( v2f a, v2f b, float s, v2f d ) d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s; } +static inline float v2_length2( v2f a ) +{ + return a[0]*a[0] + a[1]*a[1]; +} + +static inline float v2_length( v2f a ) +{ + return sqrtf( v2_length2( a ) ); +} + +static inline float v2_dist2( v2f a, v2f b ) +{ + v2f delta; + v2_sub( a, b, delta ); + return v2_length2( delta ); +} + +static inline float v2_dist( v2f a, v2f b ) +{ + return sqrtf( v2_dist2( a, b ) ); +} + // Vector 3 // ==================================================================================================================