X-Git-Url: https://harrygodden.com/git/?p=fishladder.git;a=blobdiff_plain;f=fishladder.c;fp=fishladder.c;h=b8f6d5ba1d692a126ef5e75761bb93a2488fc325;hp=22438c9c45f7fa3133a1c3c4d6102c22a336a308;hb=c3c51a48e2c5880cbadb3244c745185b0a7b3971;hpb=681351050c11616480f7aa8467ca8eb3b81e193e diff --git a/fishladder.c b/fishladder.c index 22438c9..b8f6d5b 100644 --- a/fishladder.c +++ b/fishladder.c @@ -1,7 +1,8 @@ // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved +#define MARBLE_COMP_VERSION 4 //#define VG_CAPTURE_MODE -//#define VG_STEAM +#define VG_STEAM #define VG_STEAM_APPID 1218140U #include "vg/vg.h" @@ -68,7 +69,8 @@ enum e_world_button enum e_game_state { k_game_state_main, - k_game_state_settings + k_game_state_settings, + k_game_state_update }; #define FLAG_CANAL 0x1 @@ -121,7 +123,7 @@ static struct cell_description cell_descriptions[] = { // 0-3 - {}, + { .trigger_pos = { 0.5f, 0.25f }, .trigger_sprite = k_sprite_brk_d }, { .start = { 1, 0 }, .end = { -1, 0 }, .trigger_pos = { 0.5f, 0.25f }, .trigger_sprite = k_sprite_brk_d }, { .start = { 0, 1 }, .end = { 0, -1 }, .trigger_pos = { 0.25f, 0.5f }, .trigger_sprite = k_sprite_brk_l }, { .start = { 0, 1 }, .end = { 1, 0 }, .trigger_pos = { 0.25f, 0.5f }, .trigger_sprite = k_sprite_brk_l }, @@ -280,7 +282,8 @@ world = { .mode = k_world_button_mode_toggle }, { .mode = k_world_button_mode_toggle }, { .mode = k_world_button_mode_toggle } } - } + }, + .selected = -1 }; // Forward declerations @@ -310,7 +313,7 @@ static void io_reset(void); static struct cell *pcell( v2i pos ); static void lcell( int id, v2i pos ); static void map_reclassify( v2i start, v2i end, int update_texbuffer ); -static void gen_level_text( struct cmp_level *pLevel ); +static void gen_level_text(void); static int map_load( const char *str, const char *name ); static void map_serialize( FILE *stream ); @@ -401,16 +404,16 @@ static struct world_theme } world_themes[] = { - { - "Wood", - { 0.89f, 0.8f, 0.7f }, - &tex_tiles_wood - }, { "Minimal", { 0.8f, 0.8f, 0.8f }, &tex_tiles_min }, + { + "Wood", + { 0.89f, 0.8f, 0.7f }, + &tex_tiles_wood + }, { "Lab", { 0.7f, 0.7f, 0.7f }, @@ -643,33 +646,66 @@ static void map_reclassify( v2i start, v2i end, int update_texbuffer ) } } -static void gen_level_text( struct cmp_level *pLevel ) +static void gen_level_text(void) { // Old style UI. ui_px const unit_scale_px = 4*UI_GLYPH_SPACING_X; // 4 char per unit ui_begin( &world.st.world_text, world.w*unit_scale_px, world.h*unit_scale_px ); - - for( int i = 0; i < vg_list_size( pLevel->strings ); i ++ ) + + if( world.pCmpLevel ) { - struct world_string *wstr = &pLevel->strings[i]; - - if( wstr->str ) + for( int i = 0; i < vg_list_size( world.pCmpLevel->strings ); i ++ ) { - ui_px pos[2]; + struct world_string *wstr = &world.pCmpLevel->strings[i]; - pos[0] = -UI_GLYPH_SPACING_X/2; + if( wstr->str ) + { + ui_px pos[2]; - if( wstr->placement == k_placement_bottom ) - pos[1] = 2*-unit_scale_px; - else - pos[1] = (world.h-1)*-unit_scale_px -6; + pos[0] = -UI_GLYPH_SPACING_X/2; - ui_text( &world.st.world_text, pos, wstr->str, 1, k_text_align_left ); + if( wstr->placement == k_placement_bottom ) + pos[1] = 2*-unit_scale_px; + else + pos[1] = (world.h-1)*-unit_scale_px -6; + + ui_text( &world.st.world_text, pos, wstr->str, 1, k_text_align_left ); + } } } // re-create level scores - + for( int i = 0; i < vg_list_size( career_packs ); i ++ ) + { + struct career_level_pack *set = &career_packs[i]; + + ui_text( &world.st.world_text, + (ui_px [2]){ + set->origin[0]*unit_scale_px, + -(set->origin[1]+set->dims[1]+1)*unit_scale_px + 18 + }, + set->title, 1, k_text_align_left ); + + for( int j = 0; j < set->count; j ++ ) + { + struct cmp_level *lvl = &set->pack[j]; + + if( lvl->completed_score && !lvl->is_tutorial ) + { + char num[10]; + snprintf( num, 9, "%d", lvl->completed_score ); + + ui_text( &world.st.world_text, + (ui_px [2]){ + lvl->btn.position[0]*unit_scale_px + unit_scale_px/2, + -lvl->btn.position[1]*unit_scale_px - unit_scale_px/2 + }, + num, 1, k_text_align_center ); + } + } + } + + //ui_text( &world.st.world_text, (ui_px [2]){ 0, 0 }, "Preview", 1, k_text_align_left ); ui_resolve( &world.st.world_text ); } @@ -1172,6 +1208,7 @@ struct dcareer_state struct dlevel_state { i32 score; + i32 unlocked; i32 reserved[2]; } @@ -1187,7 +1224,7 @@ static void career_serialize(void) return; struct dcareer_state encoded; - encoded.version = 2; + encoded.version = MARBLE_COMP_VERSION; encoded.in_map = world.pCmpLevel? world.pCmpLevel->serial_id: -1; memset( encoded.reserved, 0, sizeof( encoded.reserved ) ); @@ -1204,7 +1241,7 @@ static void career_serialize(void) dest->score = lvl->completed_score; dest->unlocked = lvl->unlocked; dest->reserved[0] = 0; - dest->reserved[1] = 0; + dest->reserved[1] = 0; } } @@ -1223,24 +1260,16 @@ static void career_unlock_level( struct cmp_level *lvl ) static void career_pass_level( struct cmp_level *lvl, int score, int upload ) { if( score > 0 ) - { - if( score < lvl->completed_score || lvl->completed_score == 0 ) - { - #ifdef VG_STEAM - if( !lvl->is_tutorial && upload ) - leaderboard_set_score( lvl, score ); - #endif - - lvl->completed_score = score; - } + { + lvl->completed_score = score; + gen_level_text(); - if( lvl->unlock ) career_unlock_level( lvl->unlock ); + if( lvl->unlock ) + career_unlock_level( lvl->unlock ); #ifdef VG_STEAM if( lvl->achievement ) - { sw_set_achievement( lvl->achievement ); - } // Check ALL maps to trigger master engineer for( int i = 0; i < vg_list_size( career_packs ); i ++ ) @@ -1320,7 +1349,14 @@ static void career_load(void) struct dlevel_state *src = &encoded.levels[lvl->serial_id]; if( src->unlocked ) career_unlock_level( lvl ); - if( src->score ) lvl->completed_score = src->score; + if( src->score ) + { + lvl->completed_score = src->score; + + // Apply unlocking to next levels in case there was an update + if( lvl->unlock ) + career_unlock_level( lvl->unlock ); + } if( lvl->serial_id == encoded.in_map ) lvl_to_load = lvl; @@ -1330,10 +1366,13 @@ static void career_load(void) if( console_changelevel( 1, &lvl_to_load->map_name ) ) { world.pCmpLevel = lvl_to_load; - gen_level_text( world.pCmpLevel ); + gen_level_text(); } career_load_success = 1; + + if( encoded.version < MARBLE_COMP_VERSION || 1 ) + world.st.state = k_game_state_update; } // MAIN GAMEPLAY @@ -1393,6 +1432,7 @@ static void simulation_start(void) if( world.pCmpLevel ) { world.pCmpLevel->completed_score = 0; + gen_level_text(); } } @@ -1507,7 +1547,7 @@ static void vg_update(void) if( console_changelevel( 1, &world.st.lvl_to_load->map_name ) ) { world.pCmpLevel = world.st.lvl_to_load; - gen_level_text( world.pCmpLevel ); + gen_level_text(); } world.st.lvl_to_load = NULL; @@ -1555,6 +1595,9 @@ static void vg_update(void) m3x3_translate( m_view, origin_current ); m3x3_mul( m_projection, m_view, vg_pv ); vg_projection_update(); + + if( world.st.state == k_game_state_update ) + return; // Mouse input // ======================================================================================================== @@ -1974,21 +2017,26 @@ static void vg_update(void) // Spawn new marble if( (target_peice->state & FLAG_EMITTER) && !(target_peice->state & FLAG_TRIGGERED)) { - struct fish *fish = &world.fishes[ world.num_fishes ]; - lcell( cell_current->links[trigger_id], fish->pos ); - - fish->state = k_fish_state_soon_alive; - fish->colour = target_peice->emit[ trigger_id ]; - - if( target_peice->config != k_cell_type_stub ) - { - struct cell_description *desc = &cell_descriptions[ target_peice->config ]; - v2i_copy( desc->start, fish->dir ); - fish->flow_reversed = 1; - - world.num_fishes ++; - alive_count ++; - } + if( world.num_fishes < vg_list_size( world.fishes ) ) + { + struct fish *fish = &world.fishes[ world.num_fishes ]; + lcell( cell_current->links[trigger_id], fish->pos ); + + fish->state = k_fish_state_soon_alive; + fish->colour = target_peice->emit[ trigger_id ]; + + if( target_peice->config != k_cell_type_stub ) + { + struct cell_description *desc = &cell_descriptions[ target_peice->config ]; + v2i_copy( desc->start, fish->dir ); + fish->flow_reversed = 1; + + world.num_fishes ++; + alive_count ++; + } + } + else + vg_warn( "Max marbles exceeded\n" ); } else { @@ -2084,14 +2132,19 @@ static void vg_update(void) struct cell *cell_ptr = pcell( fish->pos ); if( cell_ptr->config != k_cell_type_stub ) - { - struct cell_description *desc = &cell_descriptions[ cell_ptr->config ]; - - v2i_copy( desc->start, fish->dir ); - fish->flow_reversed = 1; - - world.num_fishes ++; - alive_count ++; + { + if( world.num_fishes < vg_list_size(world.fishes)) + { + struct cell_description *desc = &cell_descriptions[ cell_ptr->config ]; + + v2i_copy( desc->start, fish->dir ); + fish->flow_reversed = 1; + + world.num_fishes ++; + alive_count ++; + } + else + vg_warn( "Max marbles exceeded\n" ); } } } @@ -3191,7 +3244,61 @@ void vg_ui(void) gui_text( (ui_px [2]){ vg_window_x / 2, 28 }, world.pCmpLevel->description, 1, k_text_align_center ); } - if( world.st.state == k_game_state_settings ) + if( world.st.state == k_game_state_update ) + { + gui_group_id( 34 ); + + ui_global_ctx.cursor[2] = 458; + ui_global_ctx.cursor[3] = 316; + ui_global_ctx.cursor[0] = vg_window_x / 2 - 229; + ui_global_ctx.cursor[1] = vg_window_y / 2 - 158; + + gui_new_node(); + { + gui_capture_mouse( 200 ); + gui_fill_rect( ui_global_ctx.cursor, 0xE8303030 ); + + ui_px title_pos[2]; + title_pos[0] = ui_global_ctx.cursor[0] + 229; + title_pos[1] = ui_global_ctx.cursor[1] + 16; + + gui_text( title_pos, "Update 1.5", 2, k_text_align_center ); + + gui_text( (ui_px [2]){ ui_global_ctx.cursor[0] + 16, title_pos[1] + 45 }, + "Welcome to the first update to marble computing!" + "\n" + "New features have been added:\n" + "\n" + " - Settings menu\n" + " - Map skins\n" + " - More levels and a new block type\n" + " - Scores for each level\n" + " - Zooming and panning (mousewheel)\n" + "\n" + "There is much more in the works, such as a\n" + "soundtrack, and the rest of the levels for the\n" + "3 bit computer!\n" + "\n" + "Thank you everyone for enjoying my game :)\n", + 1, k_text_align_left + ); + + ui_global_ctx.cursor[2] = 100; + ui_global_ctx.cursor[3] = 30; + ui_global_ctx.cursor[0] += 229 - 50; + ui_global_ctx.cursor[1] += 316 - 30 - 16; + + if( gui_button( 1 ) ) + { + world.st.state = k_game_state_main; + } + gui_text( (ui_px [2]){ ui_global_ctx.cursor[0] + 50, + ui_global_ctx.cursor[1] + 4 }, "OK", 1, k_text_align_center ); + gui_end(); + } + gui_end(); + } + else if( world.st.state == k_game_state_settings ) { gui_group_id( 35 ); @@ -3249,7 +3356,7 @@ void vg_ui(void) if( colour_set_id > 0 ) colour_set_id --; } - gui_text( ui_global_ctx.cursor, "<", 1, 0 ); + gui_text( ui_global_ctx.cursor, "<", 2, 0 ); gui_end_right(); ui_global_ctx.cursor[2] = 150; @@ -3270,7 +3377,7 @@ void vg_ui(void) if( colour_set_id < vg_list_size( colour_sets )-1 ) colour_set_id ++; } - gui_text( ui_global_ctx.cursor, ">", 1, 0 ); + gui_text( ui_global_ctx.cursor, ">", 2, 0 ); gui_end_down(); } gui_end_down(); @@ -3290,7 +3397,7 @@ void vg_ui(void) if( world_theme_id > 0 ) world_theme_id --; } - gui_text( ui_global_ctx.cursor, "<", 1, 0 ); + gui_text( ui_global_ctx.cursor, "<", 2, 0 ); gui_end_right(); ui_global_ctx.cursor[2] = 150; @@ -3310,7 +3417,7 @@ void vg_ui(void) if( world_theme_id < vg_list_size( world_themes )-1 ) world_theme_id ++; } - gui_text( ui_global_ctx.cursor, ">", 1, 0 ); + gui_text( ui_global_ctx.cursor, ">", 2, 0 ); gui_end_down(); } gui_end_down(); @@ -3434,7 +3541,6 @@ static int console_credits( int argc, char const *argv[] ) vg_info( " miniaudio MIT0 miniaud.io\n" ); vg_info( " QOI MIT phoboslab.org\n" ); vg_info( " STB library MIT nothings.org\n" ); - vg_info( " Ubuntu Regular ubuntu.com\n" ); return 0; }