struct SVGPath* svgParseFromFile(const char* filename) { FILE* fp; int size; char* data; struct SVGPath* plist; fp = fopen(filename, "rb"); if (!fp) return 0; fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); data = (char*)malloc(size+1); fread(data, size, 1, fp); data[size] = '\0'; // Must be null terminated. fclose(fp); plist = svgParse(data); free(data); return plist; }
Game::Game(const std::string &level, float near, float far, float fov) : camera(fov, resolution.x/(float)resolution.y, near, far) , music(nullptr) , current_mode(MODE_READY) { composition = new RenderTarget(resolution, GL_RGB8, RenderTarget::DEPTH_BUFFER | RenderTarget::DOUBLE_BUFFER); geometry = new RenderTarget(resolution, GL_RGB8, RenderTarget::DEPTH_BUFFER); printf("Loading level %s\n", level.c_str()); std::string base_dir = PATH_BASE "data/levels/" + level; Config config = Config::parse(base_dir + "/level.cfg"); //Read config: start_position = config["/player/start_position"]->as_float(); sky_color = config["/environment/sky_color"]->as_color(); static const glm::vec2 terrain_scale = config["/environment/terrain/scale"]->as_vec2(); static const float fog_intensity = config["/environment/fog_intensity"]->as_float(); camera_offset = config["/player/camera/offset"]->as_vec3(); look_at_offset = config["/player/camera/look_at_offset"]->as_float(); movement_speed = config["/player/speed/normal"]->as_float(); brake_movement_speed = config["/player/speed/brake"]->as_float(); spawn_area_start = config["/game/spawn_area/start"]->as_float(); spawn_area_end = config["/game/spawn_area/end"]->as_float(); spawn_area_size = spawn_area_end - spawn_area_start; spawn_distance = config["/game/spawn_area/distance"]->as_float(); despawn_distance = config["/game/spawn_area/despawn_distance"]->as_float(); difficulty_increase = config["/game/difficulty_increase"]->as_float(); static const Shader::fog_t fog = { glm::vec4(sky_color.to_vec3(), 1.f), fog_intensity }; Shader::upload_fog(fog); TextureArray * colors = TextureArray::from_filename( (base_dir +"/color0.png").c_str(), (base_dir + "/color1.png").c_str(), nullptr); TextureArray * normals = TextureArray::from_filename( (base_dir +"/normal0.png").c_str(), (base_dir + "/normal1.png").c_str(), nullptr); terrain = new Terrain(base_dir + "/map.png", terrain_scale.x, terrain_scale.y, colors, normals); Data * path_file = Data::open(base_dir + "/path.svg"); SVGPath * svg_path = svgParse((char*) path_file->data()); delete path_file; std::vector<glm::vec3> path_nodes; for(int i=0; i< svg_path->npts; ++i) { path_nodes.push_back(glm::vec3( svg_path->pts[i*2], 0, svg_path->pts[i*2 + 1] ) * terrain_scale.x); } svgDelete(svg_path); Path::optimize_vector(path_nodes); // Gets max elevation for a radius around a point to avoid the rails cliping into the ground. for(glm::vec3 &v : path_nodes) { v.y = glm::max(glm::max(glm::max(terrain->height_at(v.x+1.5f, v.z),terrain->height_at(v.x-1.5f, v.z)),terrain->height_at(v.x, v.z+1.5f)),terrain->height_at(v.x, v.z-1.5f)) + 0.2f; } path = new Path(path_nodes, false); rails = new Rails(path, 1.f); rail_texture = Texture2D::from_filename(PATH_BASE "data/textures/rails.png"); rail_material.texture = rail_texture; //Setup player: player.canon_offset = config["/player/canon_offset"]->as_vec3(); player.canon_length = config["/player/canon_length"]->as_float(); //Configure lights: lights.ambient_intensity() = config["/environment/light/ambient"]->as_vec3(); lights.num_lights() = 1; lights.lights[0]->intensity = config["/environment/light/sunlight"]->as_vec3(); lights.lights[0]->type = MovableLight::DIRECTIONAL_LIGHT; //Load enemies: EnemyTemplate::init(Config::parse(base_dir + "/enemies.cfg"), this); //Set up camera: update_camera(); //Create particle systems: wind_velocity = config["/environment/wind_velocity"]->as_vec3(); gravity = glm::vec4(config["/environment/gravity"]->as_vec3(), 1.f); particle_shader = Shader::create_shader("particles"); passthru = Shader::create_shader("passthru"); static const Config particle_config = Config::parse(base_dir + "/particles.cfg"); static const float canon_inner_radius = particle_config["/particles/spawn_radius"]->as_float(); particle_textures = TextureArray::from_filename( PATH_BASE "data/textures/smoke.png", PATH_BASE "data/textures/fog.png", PATH_BASE "data/textures/particle.png", PATH_BASE "data/textures/fire1.png", PATH_BASE "data/textures/fire2.png", PATH_BASE "data/textures/fire3.png", nullptr); static const int max_attack_particles = particle_config["/particles/max_attack_particles"]->as_int(); static const int max_smoke_particles = particle_config["/particles/max_smoke_particles"]->as_int(); static const int max_dust_particles = particle_config["/particles/max_dust_particles"]->as_int(); static const int max_explosion_particles = particle_config["/particles/max_explosion_particles"]->as_int(); attack_particles = new HittingParticles(max_attack_particles, particle_textures, EnemyTemplate::max_num_enemies, false); attack_particles->config.gravity = gravity; system_configs.push_back(&(attack_particles->config)); attack_particles->config.spawn_area = glm::vec4(0.f, 0.f, 0.f, canon_inner_radius); for(auto &p : particle_types) { p.config = attack_particles->config; //Get reasonable defaults system_configs.push_back(&(p.config)); } read_particle_config(particle_config["/particles/light"], particle_types[LIGHT_PARTICLES].config); particle_types[LIGHT_PARTICLES].count = particle_config["/particles/light/count"]->as_int(); particle_types[LIGHT_PARTICLES].spawn_speed = particle_config["/particles/light/spawn_speed"]->as_float(); particle_types[LIGHT_PARTICLES].damage = particle_config["/particles/light/damage"]->as_float(); read_particle_config(particle_config["/particles/medium"], particle_types[MEDIUM_PARTICLES].config); particle_types[MEDIUM_PARTICLES].count = particle_config["/particles/medium/count"]->as_int(); particle_types[MEDIUM_PARTICLES].spawn_speed = particle_config["/particles/medium/spawn_speed"]->as_float(); particle_types[MEDIUM_PARTICLES].damage = particle_config["/particles/medium/damage"]->as_float(); read_particle_config(particle_config["/particles/heavy"], particle_types[HEAVY_PARTICLES].config); particle_types[HEAVY_PARTICLES].count = particle_config["/particles/heavy/count"]->as_int(); particle_types[HEAVY_PARTICLES].spawn_speed = particle_config["/particles/heavy/spawn_speed"]->as_float(); particle_types[HEAVY_PARTICLES].damage = particle_config["/particles/heavy/damage"]->as_float(); //Smoke: smoke = new ParticleSystem(max_smoke_particles, particle_textures, false); smoke->config.gravity = gravity; system_configs.push_back(&(smoke->config)); smoke->config.spawn_area = glm::vec4(0.f, 0.f, 0.f, canon_inner_radius * 2.0); read_particle_config(particle_config["/particles/smoke"], smoke->config); smoke_count = particle_config["/particles/smoke/count"]->as_int(); smoke_spawn_speed = particle_config["/particles/smoke/spawn_speed"]->as_float(); //Dust: dust = new ParticleSystem(max_dust_particles, particle_textures, true); read_particle_config(particle_config["/particles/dust"], dust->config); dust->config.gravity = gravity; system_configs.push_back(&(dust->config)); dust->config.spawn_area = particle_config["/particles/dust/spawn_area"]->as_vec4(); dust->config.avg_spawn_velocity = glm::vec4(particle_config["/particles/dust/avg_spawn_velocity"]->as_vec3(), 0); dust->avg_spawn_rate = particle_config["/particles/dust/avg_spawn_rate"]->as_float(); dust->spawn_rate_var = particle_config["/particles/dust/spawn_rate_var"]->as_float(); dust_spawn_ahead = particle_config["/particles/dust/spawn_ahead"]->as_float(); half_dust_spawn_area = glm::vec3(dust->config.spawn_area.x, dust->config.spawn_area.y, dust->config.spawn_area.z) / 2.f; dust->config.spawn_position = glm::vec4(player.position() - half_dust_spawn_area, 1.f); dust->update_config(); dust->spawn(dust->avg_spawn_rate * 5.0); dust->config.spawn_position += glm::vec4(path->at(player.path_position() + dust_spawn_ahead / 2.f), 0.f); dust->spawn(dust->avg_spawn_rate * 5.0); //Explosions explosions = new ParticleSystem(max_explosion_particles, particle_textures, false); hit_explosion = explosions->config; system_configs.push_back(&(hit_explosion)); kill_explosion = explosions->config; system_configs.push_back(&(kill_explosion)); read_particle_config(particle_config["/particles/hit_explosion"], hit_explosion); read_particle_config(particle_config["/particles/kill_explosion"], kill_explosion); explosions->config.gravity = gravity; system_configs.push_back(&(explosions->config)); hit_explosion_count = particle_config["/particles/hit_explosion/count"]->as_int(); kill_explosion_count = particle_config["/particles/kill_explosion/count"]->as_int(); kill_explosion.spawn_area = particle_config["/particles/kill_explosion/spawn_area"]->as_vec4(); kill_explosion.avg_spawn_velocity = glm::vec4(particle_config["/particles/kill_explosion/avg_spawn_velocity"]->as_vec3(), 0); hit_explosion.spawn_area = particle_config["/particles/hit_explosion/spawn_area"]->as_vec4(); hit_explosion.avg_spawn_velocity = glm::vec4(particle_config["/particles/hit_explosion/avg_spawn_velocity"]->as_vec3(), 0); update_wind_velocity(); //Setup HUD hud_scale = glm::vec2(resolution.x / 800.f, resolution.y / 600.f); hud_static_elements_tex = Texture2D::from_filename(PATH_BASE "/data/textures/hudStatic.png"); fullscreen_quad = new Quad(); fullscreen_quad->set_scale(glm::vec3(resolution.x,resolution.y,0)); hud_lightpos = glm::vec2(594,490) * hud_scale; hud_mediumpos = glm::vec2(644,490) * hud_scale; hud_heavypos = glm::vec2(700,490) * hud_scale; hud_choice_tex = Texture2D::from_filename(PATH_BASE "/data/textures/weap_select.png"); hud_choice_quad = new Quad(); hud_choice_quad->set_scale(glm::vec3(97,92,0) * glm::vec3(hud_scale , 0)); hud_break_tex = Texture2D::from_filename(PATH_BASE "/data/textures/breaks_ready.png"); hud_break_quad = new Quad(); hud_break_quad->set_scale(glm::vec3(190, 25, 0) * glm::vec3(hud_scale, 0)); hud_break_quad->set_position(glm::vec3(glm::vec2(30, 530) * hud_scale, 0.f)); life_text.set_color(hud_font_color); life_text.set_scale(20.0 * hud_scale.x); life_text.set_position(glm::vec3(glm::vec2(26.f, 44.5f) * hud_scale, 0.f)); //Highscore stuff: highscore = new Highscore(base_dir + "/highscore", NUM_HIGHSCORE_ENTRIES); float hs_scale = 40.f; glm::vec2 higscore_base = glm::vec2(735.f, 85.f); int i=0; for(Text &t : highscore_entries) { t.set_position(glm::vec3( (higscore_base + glm::vec2(0.f, (i++)*hs_scale)) * hud_scale, 0.f)); t.set_scale(hs_scale); t.set_text(""); t.set_alignment(Text::RIGHT_ALIGNED); } //Textures game_over_texture = Texture2D::from_filename(PATH_BASE "/data/textures/gameover.png"); startscreen_texture = Texture2D::from_filename(PATH_BASE "/data/textures/start_screen.png"); }