// Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
-#define VG_CAPTURE_MODE
-#define VG_STEAM
+//#define VG_CAPTURE_MODE
+//#define VG_STEAM
#define VG_STEAM_APPID 1218140U
#include "vg/vg.h"
#include "fishladder_resources.h"
// Forward declerations
// --------------------
+// Utility functions
+// -----------------
+
+static void colour_code_v3( char const cc, v3f target );
+static int hash21i( v2i p, u32 umod );
+
+// Mesh functions
+// --------------
+static void init_mesh( struct mesh *m, float const *tris, u32 length );
+static void free_mesh( struct mesh *m );
+static void use_mesh( struct mesh *m );
+static void draw_mesh( int const start, int const count );
+
+// World buttons
+// -------------
+static struct cell_button *get_wbutton( enum e_world_button btn );
+static void wbutton_run( enum e_world_button btn_name, v2f btn_tex );
+static void wbutton_draw( v2i pos, v2f tex, v4f colour );
+static void level_selection_buttons(void);
+
+// Map/world interface
+// -------------------
+static void map_free(void);
+static void io_reset(void);
+static struct cell *pcell( v2i pos );
+static void map_reclassify( v2i start, v2i end, int update_texbuffer );
+static u32 gen_text_buffer( const char *str, struct sdf_font *font, v2f origin, float size, u32 start );
+static void gen_level_text( struct cmp_level *pLevel );
+static int map_load( const char *str, const char *name );
+static void map_serialize( FILE *stream );
+
+// Career
+// ------
+static void career_serialize(void);
+static void career_unlock_level( struct cmp_level *lvl );
+static void career_unlock_level( struct cmp_level *lvl );
+static void career_pass_level( struct cmp_level *lvl, int score, int upload );
+static void career_reset_level( struct cmp_level *lvl );
+static void career_load(void);
+static void clear_animation_flags(void);
+
+// Gameplay main
+// -------------
+static void simulation_stop(void);
+static void simulation_start(void);
+static int world_check_pos_ok( v2i co );
+static int cell_interactive( v2i co );
+
+void vg_update(void);
+static void render_tiles( v2i start, v2i end, v4f const regular_colour, v4f const selected_colour );
+
+void vg_render(void);
+void vg_ui(void);
+
+// Leaderboard stuff
+// -----------------
+#ifdef STEAM_LEADERBOARDS
+void leaderboard_set_score( struct cmp_level *cmp_level, u32 score );
+void leaderboard_dispatch_score(void);
+void leaderboard_found( LeaderboardFindResult_t *pCallback );
+void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback );
+void leaderboard_set_score( struct cmp_level *cmp_level, u32 score );
+#endif
+
+// Console commands
+// ----------------
static int console_credits( int argc, char const *argv[] );
static int console_save_map( int argc, char const *argv[] );
static int console_load_map( int argc, char const *argv[] );
static int console_changelevel( int argc, char const *argv[] );
+void vg_start(void);
+void vg_free(void);
+
+int main( int argc, char *argv[] );
+
// GLOBALS
// ===========================================================================================================
// UTILITY
// ===========================================================================================================
+static int colour_set_id = 0;
+
static void colour_code_v3( char const cc, v3f target )
{
- static v3f colour_sets[] =
- { { 1.0f, 0.9f, 0.3f },
- { 0.2f, 0.9f, 0.14f },
- { 0.4f, 0.8f, 1.00f },
- { 0.882f, 0.204f, 0.922f }
+ static v3f colour_sets[][4] =
+ {
+ { { 1.0f, 0.9f, 0.3f }, // Yellow
+ { 0.4f, 0.8f, 1.00f }, // Blue
+ { 0.2f, 0.9f, 0.14f }, // Green
+ { 0.882f, 0.204f, 0.922f } // Pink
+ },
+ { { 1.0f, 0.9f, 0.3f }, // Yellow
+ { 0.4f, 0.8f, 1.00f }, // Blue
+ { 0.85f, 0.85f, 0.85f }, // Weiss
+ { 0.2f, 0.2f, 0.2f } // Black/Gray
+ },
+ { { 1.0f, 0.9f, 0.3f }, // Yellow
+ { 0.827f, 0.373f, 0.718f }, // Pink
+ { 0.0f, 0.353f, 0.71f }, // Blue
+ { 0.863f, 0.196f, 0.125f } // Red
+ },
};
if( cc >= 'a' && cc <= 'z' )
{
int id = cc - 'a';
- if( id < vg_list_size( colour_sets ) )
+ if( id < vg_list_size( colour_sets[0] ) )
{
- v3_copy( colour_sets[ id ], target );
+ v3_copy( colour_sets[colour_set_id][ id ], target );
return;
}
}
// Level selection area
- for( int i = 0; i < vg_list_size( button_grids ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct button_grid *grid = &button_grids[ i ];
+ struct career_level_pack *grid = &career_packs[ i ];
for( int y = 0; y < grid->dims[1]; y ++ )
{
memset( encoded.reserved, 0, sizeof( encoded.reserved ) );
- for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct serializable_set *set = &career_serializable[i];
+ struct career_level_pack *set = &career_packs[i];
for( int j = 0; j < set->count; j ++ )
{
{
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;
}
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_serializable ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct serializable_set *set = &career_serializable[i];
+ struct career_level_pack *set = &career_packs[i];
for( int j = 0; j < set->count; j ++ )
{
}
sw_set_achievement( "MASTER_ENGINEER" );
+ #endif
}
}
vg_info( "No save file... Using blank one\n" );
// Reset memory
- for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct serializable_set *set = &career_serializable[i];
+ struct career_level_pack *set = &career_packs[i];
for( int j = 0; j < set->count; j ++ )
career_reset_level( &set->pack[j] );
// =================================
// Decode everything from dstate
- for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct serializable_set *set = &career_serializable[i];
+ struct career_level_pack *set = &career_packs[i];
for( int j = 0; j < set->count; j ++ )
{
if( cell_entry->config == k_cell_type_con_r || cell_entry->config == k_cell_type_con_u
|| cell_entry->config == k_cell_type_con_l || cell_entry->config == k_cell_type_con_d )
{
+ #ifdef VG_STEAM
sw_set_achievement( "CAN_DO_THAT" );
-
+ #endif
+
fish->state = k_fish_state_soon_alive;
fish->dir[0] = 0;
if( collide_next_frame || collide_this_frame )
{
+ #ifdef VG_STEAM
sw_set_achievement( "BANG" );
-
+ #endif
+
// Shatter death (+0.5s)
float death_time = world.sim_internal_time + ( collide_this_frame? 0.0f: 0.5f );
}
else
{
+ #ifdef VG_STEAM
if( world.sim_run > 0 )
sw_set_achievement( "GOOD_ENOUGH" );
-
+ #endif
+
vg_error( "Level failed :(\n" );
}
}
}
-void leaderboard_found( LeaderboardFindResult_t *pCallback );
-void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback );
-
static void render_tiles( v2i start, v2i end, v4f const regular_colour, v4f const selected_colour )
{
v2i full_start = { 0,0 };
if( vg_get_button_down( "primary" ) )
select_from = NULL;
- for( int i = 0; i < vg_list_size( button_grids ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct button_grid *grid = &button_grids[i];
+ struct career_level_pack *grid = &career_packs[i];
int j = 0;
{
if( j < grid->count )
{
- struct cmp_level *lvl = &grid->levels[ j ];
+ struct cmp_level *lvl = &grid->pack[ j ];
// Determine colour
if( lvl->unlocked )
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 );
+ //glUniform1f( SHADER_UNIFORM( shader_tile_main, "uVisibility" ), sinf( vg_time ) + 1.0f );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
void vg_ui(void) {}
+#if STEAM_LEADERBOARDS
void leaderboard_dispatch_score(void)
{
-#if STEAM_LEADERBOARDS
sw_upload_leaderboard_score(
ui_data.upload_request.level->steam_leaderboard,
k_ELeaderboardUploadScoreMethodKeepBest,
ui_data.upload_request.is_waiting = 0;
vg_success( "Dispatched leaderboard score\n" );
-#endif
}
void leaderboard_found( LeaderboardFindResult_t *pCallback )
{
-#ifdef STEAM_LEADERBOARDS
if( !pCallback->m_bLeaderboardFound )
{
vg_error( "Leaderboard could not be found\n" );
}
}
}
-#endif
}
void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback )
{
-#ifdef STEAM_LEADERBOARDS
// Update UI if this leaderboard matches what we currently have in view
if( ui_data.level_selected->steam_leaderboard == pCallback->m_hSteamLeaderboard )
{
ui_data.leaderboard_show = 0;
}
else vg_warn( "Downloaded leaderboard does not match requested!\n" );
-#endif
}
void leaderboard_set_score( struct cmp_level *cmp_level, u32 score )
{
-#ifdef STEAM_LEADERBOARDS
if( ui_data.upload_request.is_waiting )
vg_warn( "You are uploading leaderboard entries too quickly!\n" );
leaderboard_dispatch_score();
else
sw_find_leaderboard( cmp_level->map_name );
-#endif
}
+#endif
// CONSOLE COMMANDS
// ===========================================================================================================
.function = console_credits
});
+ vg_convar_push( (struct vg_convar){
+ .name = "colours",
+ .data = &colour_set_id,
+ .data_type = k_convar_dtype_i32,
+ .opt_i32 = { .min = 0, .max = 2, .clamp = 1 }
+ });
+
// Combined quad, long quad / empty circle / filled circle mesh
{
float combined_mesh[6*6 + 32*6*3] = {
size_level_texts = 6*9*7
;
- for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
{
- struct serializable_set *set = &career_serializable[i];
+ struct career_level_pack *set = &career_packs[i];
for( int j = 0; j < set->count; j ++ )
{
struct cmp_level *lvl = &set->pack[j];
void vg_free(void)
{
+#ifdef VG_STEAM
sw_free_opengl();
+#endif
+
console_save_map( 0, NULL );
career_serialize();