4coder-non-source/test_data/lots_of_files/cd.cpp

771 lines
24 KiB
C++

/*
Main game code.
*/
// TOP
#include "cd_random.h"
#include "cd_world.h"
#include "cd_colors.h"
#define FTECH_STRING_IMPLEMENTATION
#include "4tech_string.h"
#ifdef DEVELOPER
# include "cd_hierarchy_editor.h"
#endif
#include "cd_world.cpp"
inline i32
relative_lane(i32 total_lanes, i32 half_visible_lanes,
i32 lane, i32 center){
i32 result = lane - center;
if (result >= total_lanes - half_visible_lanes){
result -= total_lanes;
}
else if (result <= -total_lanes + half_visible_lanes){
result += total_lanes;
}
return(result);
}
inline i32
absolute_lane(i32 total_lanes, i32 relative_lane, i32 center){
i32 result = relative_lane + center;
if (result >= total_lanes){
result -= total_lanes;
}
if (result < 0){
result += total_lanes;
}
return(result);
}
enum Dev_Mode{
DevMode_None,
DevMode_Dbg,
DevMode_Ed
};
struct App_Vars{
Partition part;
b32 initialized;
Partition trans_part;
Asset_Manifest *manifest_memory;
World world;
f32 view_y, view_y_vel;
Random_Series random;
};
struct Dev_Vars{
Partition part;
b32 initialized;
i32 dev_mode;
Hierarchy_Vars hierarchy_vars;
Partition manifest_part;
Partition edit_state_part;
};
void
establish_target(Render_Target *target, Partition *part){
target->push_part = sub_partition(part, Kbytes(256));
cd_memset(target->push_part.base, 0, Kbytes(256));
target->memory_size = Kbytes(256);
target->memory = push_block(part, target->memory_size);
cd_memset(target->memory, 0, target->memory_size);
}
void
establish_bank(Asset_Bank *bank, Partition *part, i32 max_fonts, i32 max_images){
bank->font_max_id = max_fonts;
if (max_fonts > 0){
bank->fonts = push_array(part, Font, bank->font_max_id);
}
else{
bank->fonts = 0;
}
bank->image_max_id = max_images;
if (max_images > 0){
bank->images = push_array(part, Image, bank->image_max_id);
}
else{
bank->images = 0;
}
}
inline b32
btn_pressed(Key_State key){
b32 result = (key.down && !key.prev_down);
return(result);
}
inline b32
btn_down(Key_State key){
b32 result = (key.down);
return(result);
}
inline b32
btn_released(Key_State key){
b32 result = (!key.down && key.prev_down);
return(result);
}
inline b32
btn_up(Key_State key){
b32 result = (!key.down);
return(result);
}
#ifdef DEVELOPER
// TODO(allen): Rewrite these as an asset archive system
// for compression and mod/extension packing.
static void
asset_file_backup(System_API *system){
int len = 0;
char space[1024];
String script = make_fixed_width_string(space);
append(&script, "backup.bat \"");
len = system->DBG_working_path(script.str + script.size,
script.memory_size - script.size);
script.size += len;
append(&script, "\" ");
append_int_to_str(&script, MAX_BACKUP_COUNT);
terminate_with_null(&script);
system->DBG_call_script(script.str);
}
static void
asset_file_delete(System_API *system, char *name){
system->DBG_dump_out(name, 0, 0);
}
static b32
asset_file_write(System_API *system, char *source, char *name){
b32 result = false;
if (system->DBG_copy(source, name)){
result = true;
}
return(result);
}
static b32
asset_file_exists(System_API *system, char *name){
b32 result = false;
File_Dump dump = system->DBG_dump_begin(name);
if (dump.size > 0){
result = true;
system->DBG_dump_end(dump, 0);
}
return(result);
}
# include "cd_hierarchy_editor.cpp"
#endif
extern "C"
App_Step_Sig(app_step){
App_Vars *vars = (App_Vars*)memory.logical;
if (!vars->initialized){
vars->initialized = 1;
vars->part = make_partition(memory.logical, memory.logical_size);
push_type(&vars->part, App_Vars);
vars->trans_part = make_partition(memory.transient, memory.transient_size);
establish_target(main_target, &vars->trans_part);
establish_bank(bank, &vars->trans_part, DBG_FONT_COUNT, IMAGE_COUNT);
main_target->me_to_pixel_transform = unit_to_pixel_transform;
#ifdef DEVELOPER
{
Dev_Vars *dev_vars = (Dev_Vars*)memory.developer;
vars->manifest_memory = (Asset_Manifest*)
manifest_load(system, &dev_vars->manifest_part);
}
#else
vars->manifest_memory = (Asset_Manifest*)
manifest_load(system, &vars->trans_part);
#endif
if (vars->manifest_memory){
Assert(ASSET_MANIFEST_VERSION == vars->manifest_memory->version);
Asset_Walker walker = {0};
Temp_Memory temp = begin_temp(&vars->trans_part);
Asset_Bank_Setup setup =
bank->begin_setup(bank, &vars->trans_part, system);
bank->bind_font(&setup, "LiberationSans-Regular.ttf", DBG_FONT);
bank->bind_font(&setup, "liberation-mono.ttf", DBG_MONO_FONT);
for (Asset_Node *node = walk_first_asset_node(vars->manifest_memory, &walker);
node != 0;
node = walk_next_asset_node(vars->manifest_memory, &walker)){
switch (node->type){
case AssetType_Image:
bank->bind_bmp(&setup, node->name, node->image_id);
break;
}
}
bank->end_setup(&setup);
end_temp(temp);
}
else{
i32 manifest_size = Kbytes(8);
#ifdef DEVELOPER
{
Dev_Vars *dev_vars = (Dev_Vars*)memory.developer;
DBG_expand_partition(system, &dev_vars->manifest_part, manifest_size);
vars->manifest_memory = (Asset_Manifest*)
push_block(&dev_vars->manifest_part, manifest_size);
}
#else
vars->manifest_memory = (Asset_Manifest*)
push_block(&vars->trans_part, manifest_size);
#endif
initialize_empty_manifest(vars->manifest_memory, manifest_size);
{
void *manifest = vars->manifest_memory;
Temp_Memory temp = begin_temp(&vars->trans_part);
Asset_Bank_Setup setup =
bank->begin_setup(bank, &vars->trans_part, system);
bank->bind_font(&setup, "LiberationSans-Regular.ttf", DBG_FONT);
bank->bind_font(&setup, "liberation-mono.ttf", DBG_MONO_FONT);
Manifest_Setup man_setup = {0};
begin_folder(manifest, &man_setup, "game", ROOT);
{
bank->bind_bmp(&setup, "covaris.bmp", BACKGROUND);
bind_image(manifest, &man_setup, "covaris.bmp", BACKGROUND);
bank->bind_bmp(&setup, "Sheila.bmp", SHEILA);
bind_image(manifest, &man_setup, "Sheila.bmp", SHEILA);
bank->bind_bmp(&setup, "HUD_Deck-Box.bmp", HUD_DECK);
bank->bind_bmp(&setup, "HUD_Distance_meter_ly.bmp", HUD_DISTANCE_METER_LY);
bank->bind_bmp(&setup, "HUD_Distance_meter_pc.bmp", HUD_DISTANCE_METER_PC);
bank->bind_bmp(&setup, "HUD_Fuel_Velocity_gauge.bmp", HUD_FUEL_VELOCITY);
bank->bind_bmp(&setup, "HUD_Indicator_off.bmp", HUD_INDICATOR_OFF);
bank->bind_bmp(&setup, "HUD_Indicator_on.bmp", HUD_INDICATOR_ON);
bank->bind_bmp(&setup, "HUD_Numbers.bmp", HUD_NUMBERS);
bank->bind_bmp(&setup, "HUD_Slider.bmp", HUD_SLIDER);
begin_folder(manifest, &man_setup, "HUD", HUD_FOLDER);
bind_image(manifest, &man_setup, "HUD_Deck-Box.bmp", HUD_DECK);
bind_image(manifest, &man_setup, "HUD_Distance_meter_ly.bmp", HUD_DISTANCE_METER_LY);
bind_image(manifest, &man_setup, "HUD_Distance_meter_pc.bmp", HUD_DISTANCE_METER_PC);
bind_image(manifest, &man_setup, "HUD_Fuel_Velocity_gauge.bmp", HUD_FUEL_VELOCITY);
bind_image(manifest, &man_setup, "HUD_Indicator_off.bmp", HUD_INDICATOR_OFF);
bind_image(manifest, &man_setup, "HUD_Indicator_on.bmp", HUD_INDICATOR_ON);
bind_image(manifest, &man_setup, "HUD_Numbers.bmp", HUD_NUMBERS);
bind_image(manifest, &man_setup, "HUD_Slider.bmp", HUD_SLIDER);
end_folder(manifest, &man_setup);
bank->bind_bmp(&setup, "Asteriod_1.bmp", ASTEROID1);
bank->bind_bmp(&setup, "Asteriod_2.bmp", ASTEROID2);
bank->bind_bmp(&setup, "Asteriod_3.bmp", ASTEROID3);
bank->bind_bmp(&setup, "Asteriod_16.bmp", ASTEROID4);
bank->bind_bmp(&setup, "Asteriod_17.bmp", ASTEROID5);
bank->bind_bmp(&setup, "Asteriod_18.bmp", ASTEROID6);
begin_folder(manifest, &man_setup, "ass tree odds", ASS_TREE_ODD);
bind_image(manifest, &man_setup, "Asteriod_1.bmp", ASTEROID1);
bind_image(manifest, &man_setup, "Asteriod_2.bmp", ASTEROID2);
bind_image(manifest, &man_setup, "Asteriod_3.bmp", ASTEROID3);
bind_image(manifest, &man_setup, "Asteriod_16.bmp", ASTEROID4);
bind_image(manifest, &man_setup, "Asteriod_17.bmp", ASTEROID5);
bind_image(manifest, &man_setup, "Asteriod_18.bmp", ASTEROID6);
end_folder(manifest, &man_setup);
}
end_folder(manifest, &man_setup);
bank->end_setup(&setup);
end_temp(temp);
}
}
add_player(&vars->world);
add_asteroid_spawner(&vars->world, 0.5f);
}
clear_target(main_target);
clear_target(dev_target);
Render_Target *dbg_target = 0;
Render_Target *ed_target = 0;
//
// Developer Logic
//
#ifdef DEVELOPER
Dev_Vars *dev_vars = (Dev_Vars*)memory.developer;
if (!dev_vars->initialized){
dev_vars->initialized = 1;
dev_vars->part = make_partition(memory.developer, memory.developer_size);
push_type(&dev_vars->part, Dev_Vars);
// TODO(allen): Don't use game's actual trans_part for dev code!
// Set aside another dev_trans_part instead if you must.
establish_target(dev_target, &vars->trans_part);
dev_target->me_to_pixel_transform = identity_transform;
i32 asset_count = vars->manifest_memory->asset_node_count;
make_hierarchy_vars(system, &dev_vars->edit_state_part, &dev_vars->hierarchy_vars, asset_count);
}
if (btn_pressed(dev_input->fkeys[1])){
if (dev_vars->dev_mode != DevMode_Dbg){
dev_vars->dev_mode = DevMode_Dbg;
}
else{
dev_vars->dev_mode = DevMode_None;
}
}
else if (btn_pressed(dev_input->fkeys[2])){
if (dev_vars->dev_mode != DevMode_Ed){
dev_vars->dev_mode = DevMode_Ed;
}
else{
dev_vars->dev_mode = DevMode_None;
}
}
switch (dev_vars->dev_mode){
case DevMode_None: break;
case DevMode_Dbg: dbg_target = dev_target; break;
case DevMode_Ed: ed_target = dev_target; break;
}
#endif
//
// Execute Game
//
target_transform(main_target, TF_Pixels);
target_transform(dev_target, TF_Pixels);
do_image_general(main_target, bank, 0, BACKGROUND,
Render_Exact,
main_target->dim*.5f,
v2(0,0),
v2(main_target->dim.x*.5f, 0),
v2(0, main_target->dim.y*.5f));
target_transform(main_target, TF_Units);
target_transform(dev_target, TF_Units);
//
// Establish Lanes
//
f32 lane_height = visible_top / total_visible_lanes;
Entity *player_entity = get_player(&vars->world);
i32 player_lane = player_entity->lane;
{
i32 half_rendered_lanes = half_visible_lanes+2;
i32 i = -half_rendered_lanes;
i32 lane_index = player_lane + i;
if (lane_index < 0) lane_index += total_lanes;
f32 lane_y = -lane_height*half_rendered_lanes;
for (; i <= half_rendered_lanes; ++i){
set_lane(main_target, dbg_target, lane_index, lane_y - vars->view_y);
lane_index = (lane_index + 1) % total_lanes;
lane_y += lane_height;
}
}
//
// Move Camera
//
f32 dt = input->dt;
{
f32 lane_shift = lerp(0.f, player_entity->lane_lerp, lane_height);
f32 view_accel = 10.f;
f32 damping = 2.f;
if (vars->view_y != lane_shift){
f32 a = view_accel;
f32 v = vars->view_y_vel;
f32 y = vars->view_y;
a = view_accel*(lane_shift - vars->view_y) + damping*(0 - v);
y = 0.5f*dt*dt*a + dt*v + y;
v = dt*a + v;
vars->view_y_vel = v;
vars->view_y = y;
}
}
//
// Run Simulation
//
world_begin_simulation(&vars->world);
f32 player_speed = 10.f;
f32 lane_change_per_second = 3.f;
Entity *entity = vars->world.entities;
u32 entity_count = vars->world.count;
for (u32 entity_index = 0;
entity_index < entity_count;
++entity_index, ++entity){
if (entity->lane_lerp_dir == 0 &&
entity->lane_lerp != 0){
if (entity->lane_lerp > 0){
entity->lane_lerp_dir = 1;
}
else{
entity->lane_lerp_dir = -1;
}
}
switch (entity->type){
case ET_Player:
{
if (btn_pressed(input->down)){
entity->lane_lerp_dir = -1;
}
if (btn_pressed(input->up)){
entity->lane_lerp_dir = 1;
}
if (entity->lane_lerp_dir > 0){
if (entity->lane_lerp >= 0){
entity->lane_lerp += entity->lane_lerp_dir * lane_change_per_second * dt;
if (entity->lane_lerp >= 1.f){
entity->lane += 1;
entity->lane_lerp = 0;
entity->lane_lerp_dir = 0;
vars->view_y -= lane_height;
}
}
else{
entity->lane_lerp += entity->lane_lerp_dir * lane_change_per_second * dt;
if (entity->lane_lerp >= 0.f){
entity->lane_lerp = 0;
entity->lane_lerp_dir = 0;
}
}
}
else if (entity->lane_lerp_dir < 0){
if (entity->lane_lerp <= 0){
entity->lane_lerp += entity->lane_lerp_dir * lane_change_per_second * dt;
if (entity->lane_lerp <= -1.f){
entity->lane -= 1;
entity->lane_lerp = 0;
entity->lane_lerp_dir = 0;
vars->view_y += lane_height;
}
}
else{
entity->lane_lerp += entity->lane_lerp_dir * lane_change_per_second * dt;
if (entity->lane_lerp <= 0.f){
entity->lane_lerp = 0;
entity->lane_lerp_dir = 0;
}
}
}
if (entity->lane < 0) entity->lane += total_lanes;
if (entity->lane >= total_lanes) entity->lane -= total_lanes;
vec2 pos;
pos.x = 0.f;
if (entity->lane_lerp >= 0){
pos.y = slerp(0.f, entity->lane_lerp, lane_height) - vars->view_y;
}
else{
pos.y = slerp(0.f, -entity->lane_lerp, -lane_height) - vars->view_y;
}
do_image(main_target, bank, dbg_target, SHEILA, pos, 0.2f);
}break;
case ET_Obstacle:
{
f32 speed = entity->speed + player_speed;
entity->x -= speed * dt;
if (entity->x < -25.f){
add_to_kill_list(&vars->world, entity);
}
do_obstacle(main_target, dbg_target,
ET_Obstacle, entity->seed,
entity->x, entity->lane);
}break;
case ET_Obstacle_Spawner:
{
f32 second_per_spawn = entity->second_per_spawn;
entity->spawn_clock += dt;
while (entity->spawn_clock > second_per_spawn){
i32 lane = absolute_lane(total_lanes,
random_between(&vars->random,
-half_visible_lanes*2,
half_visible_lanes*2),
player_lane);
add_asteroid(&vars->world, lane);
entity->spawn_clock -= second_per_spawn;
}
}break;
case ET_Null:
case ET_Count:
default:
InvalidCodePath;
}
}
world_end_simulation(&vars->world);
//
// Render HUD
//
target_transform(main_target, TF_Pixels);
target_transform(dev_target, TF_Pixels);
f32 pos = main_target->dim.y;
f32 gauge_width = main_target->dim.x/8.f;
f32 gauge_height = gauge_width/3.f;
f32 deck_height = gauge_height;
f32 deck_width = gauge_width;
f32 distance_height = gauge_height;
f32 distance_width = gauge_width;
f32 indicator_width = 25.f;
f32 indicator_height = 25.f;
f32 side_margin = 10.f;
f32 slider_width = 10.f;
f32 slider_height = 12.f;
f32 slider_offset = slider_height + 8.f;
f32 extra_deck_width = 50.f;
deck_width += extra_deck_width;
deck_height = deck_width/3.f;
f32 deck_y_shift = 30.f;
{
f32 fuel_amount = 0.5f;
f32 speed_amount = 0.5f;
do_image_general(main_target, bank, 0,
HUD_FUEL_VELOCITY, Render_Exact,
v2(side_margin, pos),
v2(-1.f, 1.f),
v2(gauge_width, 0.f),
v2(0.f, gauge_height));
do_image_general(main_target, bank, 0,
HUD_SLIDER, Render_Exact,
v2(side_margin + gauge_width*fuel_amount*2.f,
pos - slider_offset),
v2(0.f, 1.f),
v2(slider_width, 0.f),
v2(0.f, -slider_height));
do_image_general(main_target, bank, 0,
HUD_SLIDER, Render_Exact,
v2(side_margin + gauge_width*speed_amount*2.f,
pos - gauge_height*2 + slider_offset + 1),
v2(0.f, 1.f),
v2(slider_width, 0.f),
v2(0.f, slider_height));
}
{
do_image_general(main_target, bank, 0,
HUD_DECK, Render_Exact,
v2(main_target->dim.x*.5f, pos+deck_y_shift),
v2(0.f, 1.f),
v2(deck_width, 0.f),
v2(0.f, deck_height));
}
{
do_image_general(main_target, bank, 0,
HUD_DISTANCE_METER_LY, Render_Exact,
v2(main_target->dim.x - side_margin, pos),
v2(1.f, 1.f),
v2(distance_width, 0.f),
v2(0.f, distance_height));
}
{
do_image_general(main_target, bank, 0,
HUD_INDICATOR_OFF, Render_Exact,
v2(1010.f, 760.f),
v2(1.f, 1.f),
v2(indicator_width, 0.f),
v2(0.f, indicator_height));
do_image_general(main_target, bank, 0,
HUD_INDICATOR_OFF, Render_Exact,
v2(1010.f, 760.f - indicator_height*2.f),
v2(1.f, 1.f),
v2(indicator_width, 0.f),
v2(0.f, indicator_height));
}
null_render(main_target);
main_target->execute(main_target, bank);
#ifdef DEVELOPER
//
// Loop Info
//
target_transform(dev_target, TF_Pixels);
vec2 status_pos = v2(25.f, dev_target->dim.y - 25.f);
f32 descend = 20.f;
f32 mouse_alpha = 0.5f;
f32 gui_alpha = 0.75f;
if (loop_mode < 3){
switch (loop_mode){
case 1:
do_string(dev_target, bank, DBG_FONT, status_pos,
"Recording Loop", sizeof("Recording Loop") - 1,
white);
break;
case 2:
do_dbg_rectangle(dev_target,
v4(dev_input->input.mx - 5.f, dev_input->input.my - 5.f,
dev_input->input.mx + 5.f, dev_input->input.my + 5.f),
v4(1.f, 1.f, 0.f, mouse_alpha));
do_string(dev_target, bank, DBG_FONT, status_pos,
"Playing Loop", sizeof("Playing Loop") - 1,
white);
break;
}
}
else{
do_dbg_rectangle(dev_target,
v4(dev_input->input.mx - 5.f, dev_input->input.my - 5.f,
dev_input->input.mx + 5.f, dev_input->input.my + 5.f),
v4(1.f, 1.f, 0.f, mouse_alpha));
do_string(dev_target, bank, DBG_FONT, status_pos,
"Stopped", sizeof("Stopped") - 1,
white);
}
//
// Execute Debug
//
if (dev_vars->dev_mode == DevMode_Dbg){
do_dbg_rectangle(dbg_target,
v4(input->mx - 5.f, input->my - 5.f,
input->mx + 5.f, input->my + 5.f),
v4(0.f, 1.f, 0.f, mouse_alpha));
vec2 info_pos = status_pos;
info_pos.y -= descend;
char space[64];
String string = make_fixed_width_string(space);
append(&string, "mouse = (");
append_int_to_str(&string, dev_input->input.mx);
append(&string, ",");
append_int_to_str(&string, dev_input->input.my);
append(&string, ")");
do_string(dbg_target, bank, DBG_FONT, info_pos,
string.str, string.size,
white);
}
//
// Execute Editor
//
if (dev_vars->dev_mode == DevMode_Ed){
do_dbg_rectangle(ed_target,
v4(input->mx - 5.f, input->my - 5.f,
input->mx + 5.f, input->my + 5.f),
v4(0.f, 1.f, 0.f, mouse_alpha));
// TODO(allen): Need dev_trans_part
hierarchy_editor_step(system, &vars->trans_part, bank,
ed_target, dev_input,
&dev_vars->hierarchy_vars,
&dev_vars->manifest_part,
&dev_vars->edit_state_part,
status_pos, descend, gui_alpha);
vars->manifest_memory = (Asset_Manifest*)dev_vars->manifest_part.base;
manifest_dump(system, vars->manifest_memory);
}
#endif
null_render(dev_target);
dev_target->execute(dev_target, bank);
}
// BOTTOM