float terrain_height(terrain* ter, vec2 position) { vec2 amount = vec2_fmod(position, 1.0); vec2 top_left = vec2_new(floor(position.x), floor(position.y)); vec2 top_right = vec2_new(ceil(position.x), floor(position.y)); vec2 bot_left = vec2_new(floor(position.x), ceil(position.y)); vec2 bot_right = vec2_new(ceil(position.x), ceil(position.y)); top_left.x = clamp(top_left.x, 0, ter->width-1); top_left.y = clamp(top_left.y, 0, ter->height-1); top_right.x = clamp(top_right.x, 0, ter->width-1); top_right.y = clamp(top_right.y, 0, ter->height-1); bot_left.x = clamp(bot_left.x, 0, ter->width-1); bot_left.y = clamp(bot_left.y, 0, ter->height-1); bot_right.x = clamp(bot_right.x, 0, ter->width-1); bot_right.y = clamp(bot_right.y, 0, ter->height-1); float s0 = ter->heightmap[(int)top_left.x + (int)top_left.y * ter->width]; float s1 = ter->heightmap[(int)top_right.x + (int)top_right.y * ter->width]; float s2 = ter->heightmap[(int)bot_left.x + (int)bot_left.y * ter->width]; float s3 = ter->heightmap[(int)bot_right.x + (int)bot_right.y * ter->width]; return bilinear_interp(s1, s0, s3, s2, amount.x, amount.y); }
static void toggle_freecam(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, vec2_new(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; freecam = !freecam; camera* cam = entity_get("camera"); landscape* world = entity_get("world"); vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; cam->target = vec3_add(cam->position, cam_dir); } } }
ui_rectangle* ui_rectangle_new() { ui_rectangle* r = malloc(sizeof(ui_rectangle)); r->top_left = vec2_new(10, 10); r->bottom_right = vec2_new(20, 20); r->color = vec4_white(); r->glitch = 0.0; r->time = 0.0; r->texture = asset_hndl_null(); r->texture_width = 1; r->texture_height = 1; r->texture_tile = false; r->border_size = 0.0; r->border_color = vec4_black(); r->blend_src = GL_SRC_ALPHA; r->blend_dst = GL_ONE_MINUS_SRC_ALPHA; r->active = true; return r; }
ui_browser* ui_browser_new() { int width = graphics_viewport_width(); int height = graphics_viewport_height(); ui_browser* b = malloc(sizeof(ui_browser)); b->outer = ui_rectangle_new(); ui_rectangle_move(b->outer, vec2_new(width - 300, 10)); ui_rectangle_resize(b->outer, vec2_new(280, height - 20)); ui_rectangle_set_texture(b->outer, asset_hndl_new_load(ui_style_current->box_back_image), ui_style_current->box_back_width, ui_style_current->box_back_height, ui_style_current->box_back_tile); ui_rectangle_set_border(b->outer, ui_style_current->box_back_border_size, ui_style_current->box_back_border_color); ui_rectangle_set_glitch(b->outer, ui_style_current->box_glitch); ui_rectangle_set_color(b->outer, vec4_grey()); b->inner = ui_listbox_new(); ui_listbox_move(b->inner, vec2_new(width - 290, 20)); ui_listbox_resize(b->inner, vec2_new(260, height - 40)); strcpy(b->directory.ptr, SDL_GetWorkingDir()); ui_browser_chdir(b, b->directory); b->active = true; return b; }
static bool line_aabb_intersection(struct AABB aabb, vec2 line_start, vec2 line_end) { // TODO: optimize? return (line_line_intersection(line_start, line_end, vec2_new(aabb.min.x, aabb.min.y), vec2_new(aabb.max.x, aabb.min.y)) || line_line_intersection(line_start, line_end, vec2_new(aabb.max.x, aabb.min.y), vec2_new(aabb.max.x, aabb.max.y)) || line_line_intersection(line_start, line_end, vec2_new(aabb.max.x, aabb.max.y), vec2_new(aabb.min.x, aabb.max.y)) || line_line_intersection(line_start, line_end, vec2_new(aabb.min.x, aabb.max.y), vec2_new(aabb.min.x, aabb.min.y))); }
static void collision_detection_coins() { /* We simply check if the player intersects with the coins */ character* main_char = entity_get("main_char"); vec2 top_left = vec2_add(main_char->position, vec2_new(-TILE_SIZE, -TILE_SIZE)); vec2 bottom_right = vec2_add(main_char->position, vec2_new(TILE_SIZE, TILE_SIZE)); /* Again we collect pointers to all the coin type entities */ int num_coins = 0; coin* coins[COIN_COUNT]; entities_get(coins, &num_coins, coin); for(int i = 0; i < num_coins; i++) { /* Check if they are within the main char bounding box */ if ((coins[i]->position.x > top_left.x) && (coins[i]->position.x < bottom_right.x) && (coins[i]->position.y > top_left.y) && (coins[i]->position.y < bottom_right.y)) { /* Remove them from the entity manager and delete */ char* coin_name = entity_name(coins[i]); entity_delete(coin_name); /* Play a nice twinkle sound */ audio_sound_play(asset_get_as(P("./sounds/coin.wav"), sound), 0); /* Add some score! */ level_score += 10; /* Update the ui text */ ui_button* score = ui_elem_get("score"); sprintf(score->label->string, "Score %06i", level_score); ui_text_draw(score->label); } } ui_button* victory = ui_elem_get("victory"); /* if all the coins are gone and the victory rectangle isn't disaplayed then show it */ if ((entity_type_count(coin) == 0) && (!victory->active)) { ui_button* victory = ui_elem_get("victory"); ui_button* new_game = ui_elem_get("new_game"); victory->active = true; new_game->active = true; } }
static void reset_game() { /* Set the starting level to demo.level */ current_level = asset_get(P("./levels/demo.level")); level_score = 0; level_time = 0.0; /* New main character entity */ character* main_char = entity_get("main_char"); main_char->position = vec2_mul( vec2_new(20, 20), TILE_SIZE); main_char->velocity = vec2_zero(); /* We can create multiple entities using a name format string like printf */ entities_new("coin_id_%i", COIN_COUNT, coin); /* Get an array of pointers to all coin entities */ coin* coins[COIN_COUNT]; entities_get(coins, NULL, coin); /* Set all the coin initial positions */ for(int i = 0; i < COIN_COUNT; i++) { coins[i]->position = vec2_mul(coin_positions[i], TILE_SIZE); } /* Deactivate victory and new game UI elements */ ui_button* victory = ui_elem_get("victory"); ui_button* new_game = ui_elem_get("new_game"); victory->active = false; new_game->active = false; }
void ui_dialog_set_single_button(ui_dialog* d, bool single) { int width = graphics_viewport_width(); int height = graphics_viewport_height(); d->single_button = single; if (single) { ui_button_move(d->left, vec2_new(width/2 - 75, height/2 + 40)); ui_button_set_active(d->right, false); } else { ui_button_move(d->left, vec2_new(width/2 - 175, height/2 + 40)); ui_button_set_active(d->right, true); } }
void init_game(struct GameMemory *memory) { ASSERT(memory->game_memory_size >= sizeof(struct GameState)); struct GameState *game_state = (struct GameState *)memory->game_memory; struct Camera *camera = &game_state->camera; camera->zoom = 20.0f; game_state->ship_id_map = create_uint_hash_map(); uint32 unit_count = 5; for (uint32 i = 0; i < unit_count; ++i) { struct Ship *ship = create_ship(game_state); ship->size = vec2_new(1, 1); ship->move_velocity = vec2_new(0, 0); float xp = 2.0f * ((float)i - unit_count/2.0f); float yp = -camera->zoom/4.0f; ship->position = vec2_new(xp, yp); ship->health = 5; ship->fire_cooldown = 2.0f; ship->team = TEAM_ALLY; } #if 0 for (uint32 i = 0; i < unit_count; ++i) { struct Ship *ship = create_ship(game_state); ship->size = vec2_new(1, 1); ship->move_velocity = vec2_new(0, 0); float xp = 2.0f * ((float)i - unit_count/2.0f); float yp = camera->zoom/4.0f; ship->position = vec2_new(xp, yp); ship->health = 5; ship->fire_cooldown = 2.0f; ship->team = TEAM_ENEMY; } #endif for (uint32 i = 0; i < 4; ++i) { struct Building *building = create_building(game_state); building->position = vec2_new(random_int(-16, 16), random_int(-16, 16)); building->size = vec2_new(2, 2); } calc_visibility_graph(game_state, &game_state->visibility_graph); }
void scotland_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); static_object* skydome = entity_get("skydome"); landscape* world = entity_get("world"); sun_orbit += frame_time() * 0.01; sun->position.x = 512 + sin(sun_orbit) * 512; sun->position.y = cos(sun_orbit) * 512; sun->position.z = 512; sun->target = vec3_new(512, 0, 512); if (w_held || s_held) { vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float speed = 0.5; if (!freecam) speed = 0.05; if (w_held) { cam->position = vec3_add(cam->position, vec3_mul(cam_dir, speed)); } if (s_held) { cam->position = vec3_sub(cam->position, vec3_mul(cam_dir, speed)); } if (!freecam) { float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; } cam->target = vec3_add(cam->position, cam_dir); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * 0.005; float a2 = (float)mouse_y * 0.005; vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); cam_dir.y += -a2; vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0))); cam_dir = vec3_add(cam_dir, vec3_mul(side_dir, -a1)); cam_dir = vec3_normalize(cam_dir); cam->target = vec3_add(cam->position, cam_dir); } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
static float perlin_noise2D(vec2 v) { vec2 amount = vec2_fmod(v,1.0); vec2 p1 = vec2_floor(v); vec2 p2 = vec2_add(p1, vec2_new(1,0) ); vec2 p3 = vec2_add(p1, vec2_new(0,1) ); vec2 p4 = vec2_add(p1, vec2_new(1,1) ); int h1 = vec2_mix_hash(p1); int h2 = vec2_mix_hash(p2); int h3 = vec2_mix_hash(p3); int h4 = vec2_mix_hash(p4); double result = bismootherstep_interp(h2, h1, h4, h3, amount.x, amount.y); return result / INT_MAX; }
mat3 terrain_axis(terrain* ter, vec2 position) { float offset = terrain_height(ter, position); float offset_x = terrain_height(ter, vec2_add(position, vec2_new(1,0))); float offset_y = terrain_height(ter, vec2_add(position, vec2_new(0,1))); vec3 pos = vec3_new(position.x+0, offset, position.y+0); vec3 pos_xv = vec3_new(position.x+1, offset_x, position.y+0); vec3 pos_yv = vec3_new(position.x+0, offset_y, position.y+1); vec3 tangent = vec3_normalize(vec3_sub(pos_xv, pos)); vec3 binorm = vec3_normalize(vec3_sub(pos_yv, pos)); vec3 normal = vec3_cross(binorm, tangent); return mat3_new( tangent.x, tangent.y, tangent.z, normal.x, normal.y, normal.z, binorm.x, binorm.y, binorm.z); }
_gui_box* _gui_box_init ( double x, double y, double w, double h ) { _gui_box* gb = malloc(sizeof(_gui_box)); gb->dim = _gui_dimension_init(w, h); gb->pos = vec2_new(x, y); return gb; }
ui_dialog* ui_dialog_new() { ui_dialog* d = malloc(sizeof(ui_dialog)); int width = graphics_viewport_width(); int height = graphics_viewport_height(); d->back = ui_button_new(); ui_button_move(d->back, vec2_new(width/2 - 200, height/2 - 100)); ui_button_resize(d->back, vec2_new(400, 200)); ui_button_set_label(d->back, ""); ui_button_disable(d->back); d->title = ui_text_new(); ui_text_move(d->title, vec2_new(width/2, height/2 - 50)); ui_text_align(d->title, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER); ui_text_set_scale(d->title, vec2_new(1.25, 1.25)); ui_text_set_color(d->title, vec4_light_grey()); ui_text_draw_string(d->title, "Title"); d->contents = ui_text_new(); ui_text_move(d->contents, vec2_new(width/2, height/2 - 00)); ui_text_align(d->contents, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER); ui_text_set_color(d->contents, vec4_light_grey()); ui_text_draw_string(d->contents, "Contents"); d->left = ui_button_new(); ui_button_move(d->left, vec2_new(width/2 - 175, height/2 + 40)); ui_button_resize(d->left, vec2_new(150, 40)); ui_button_set_label(d->left, "Left"); d->right = ui_button_new(); ui_button_move(d->right, vec2_new(width/2 + 20, height/2 + 40)); ui_button_resize(d->right, vec2_new(150, 40)); ui_button_set_label(d->right, "Right"); dialog_count++; return d; }
static bool line_line_intersection(vec2 a0, vec2 a1, vec2 b0, vec2 b1) { #if 1 // Implemented based on http://stackoverflow.com/a/17198094/4354008 vec2 v = vec2_sub(a0, a1); vec2 normal = vec2_new(v.y, -v.x); vec2 v0 = vec2_sub(b0, a0); vec2 v1 = vec2_sub(b1, a0); float proj0 = vec2_dot(v0, normal); float proj1 = vec2_dot(v1, normal); if ((proj0 == 0) || (proj1 == 0)) return true; // TODO: float_sign() if ((proj0 > 0) && (proj1 < 0)) return true; if ((proj0 < 0) && (proj1 > 0)) return true; return false; #else vec2 intersection = vec2_zero(); vec2 b = vec2_sub(a1, a0); vec2 d = vec2_sub(b1, b0); float b_dot_p_perp = (b.x * d.y) - (b.y * d.x); if (b_dot_p_perp == 0) return false; vec2 c = vec2_sub(b0, a0); float t = ((c.x * d.y) - (c.y * d.x)) / b_dot_p_perp; if ((t < 0) || (t > 1)) return false; float u = ((c.x * b.y) - (c.y * b.x)) / b_dot_p_perp; if ((u < 0) || (u > 1)) return false; // TODO: make this an output parameter intersection = vec2_add(a0, vec2_mul(b, t)); return true; #endif }
static void toggle_wireframe(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, vec2_new(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; wireframe = !wireframe; } } }
static void fire_projectile(struct GameState *game_state, struct Ship *source, struct Ship *target, int32 damage) { ASSERT(source != target); source->fire_cooldown_timer = source->fire_cooldown; struct Projectile *projectile = create_projectile(game_state); projectile->owner = source->id; projectile->team = source->team; projectile->damage = damage; projectile->position = source->position; projectile->size = vec2_new(0.1f, 0.1f); vec2 direction = vec2_normalize(vec2_sub(target->position, projectile->position)); projectile->velocity = vec2_mul(direction, 5.0f); }
void vegetation_render() { camera* cam = entity_get("camera"); vec2 pos = vec2_div(vec2_new(cam->position.x, cam->position.z), BLOCK_SIZE); pos = vec2_clamp(pos, 1, 1022); char blockname0[512]; char blockname1[512]; char blockname2[512]; char blockname3[512]; char blockname4[512]; char blockname5[512]; char blockname6[512]; char blockname7[512]; char blockname8[512]; sprintf(blockname0, "vegblock_%i_%i", (int)pos.x-1, (int)pos.y-1); sprintf(blockname1, "vegblock_%i_%i", (int)pos.x , (int)pos.y-1); sprintf(blockname2, "vegblock_%i_%i", (int)pos.x+1, (int)pos.y-1); sprintf(blockname3, "vegblock_%i_%i", (int)pos.x-1, (int)pos.y ); sprintf(blockname4, "vegblock_%i_%i", (int)pos.x , (int)pos.y ); sprintf(blockname5, "vegblock_%i_%i", (int)pos.x+1, (int)pos.y ); sprintf(blockname6, "vegblock_%i_%i", (int)pos.x-1, (int)pos.y+1); sprintf(blockname7, "vegblock_%i_%i", (int)pos.x , (int)pos.y+1); sprintf(blockname8, "vegblock_%i_%i", (int)pos.x+1, (int)pos.y+1); static_object* block0 = entity_get(blockname0); static_object* block1 = entity_get(blockname1); static_object* block2 = entity_get(blockname2); static_object* block3 = entity_get(blockname3); static_object* block4 = entity_get(blockname4); static_object* block5 = entity_get(blockname5); static_object* block6 = entity_get(blockname6); static_object* block7 = entity_get(blockname7); static_object* block8 = entity_get(blockname8); /* forward_renderer_render_static(block0); forward_renderer_render_static(block1); forward_renderer_render_static(block2); forward_renderer_render_static(block3); forward_renderer_render_static(block4); forward_renderer_render_static(block5); forward_renderer_render_static(block6); forward_renderer_render_static(block7); forward_renderer_render_static(block8); */ }
void ui_button_event(ui_button* b, SDL_Event e) { if (e.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_point(b, vec2_new(e.motion.x, e.motion.y))) { b->pressed = true; } } else if (e.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; if (b->onclick) { b->onclick(b, b->onclick_data); } } } }
void platformer_update() { character* main_char = entity_get("main_char"); if (left_held) { main_char->velocity.x -= 0.1; main_char->facing_left = true; } else if (right_held) { main_char->velocity.x += 0.1; main_char->facing_left = false; } else { main_char->velocity.x *= 0.95; } /* Give the player some gravity speed */ const float gravity = 0.2; main_char->velocity.y += gravity; /* Update moves position based on velocity */ character_update(main_char); /* Two phases of collision detection */ collision_detection(); collision_detection_coins(); /* Camera follows main character */ camera_position = vec2_new(main_char->position.x, -main_char->position.y); /* Update the framerate text */ ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); /* Update the time text */ ui_button* victory = ui_elem_get("victory"); if (!victory->active) { level_time += frame_time(); ui_button* time = ui_elem_get("time"); sprintf(time->label->string, "Time %06i", (int)level_time); ui_text_draw(time->label); } }
static void terrain_new_chunk(terrain* ter, int i) { const int SUBDIVISIONS = NUM_TERRAIN_SUBDIVISIONS+1; terrain_chunk* tc = malloc(sizeof(terrain_chunk)); tc->id = i; tc->x = i % ter->num_cols; tc->y = i / ter->num_cols; tc->width = ter->chunk_width; tc->height = ter->chunk_height; int x_max = tc->width * SUBDIVISIONS + 1; int y_max = tc->height * SUBDIVISIONS + 1; tc->num_verts = x_max * y_max + x_max * 2 + y_max * 2; vec3* vertex_buffer = malloc(sizeof(vec3) * 4 * tc->num_verts); int index = 0; for(int x = 0; x < x_max; x++) for(int y = 0; y < y_max; y++) { float gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; float gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)); mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } /* Adding fins. Don't look, horrible code */ const float FIN_DEPTH = 5.0; for(int y = 0; y < y_max; y++) { int gx = tc->x * ter->chunk_width + 0; int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int y = 0; y < y_max; y++) { int gx = tc->x * ter->chunk_width + ter->chunk_width; int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int x = 0; x < x_max; x++) { int gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; int gy = tc->y * ter->chunk_height + 0; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int x = 0; x < x_max; x++) { int gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; int gy = tc->y * ter->chunk_height + ter->chunk_height; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } tc->bound.center = vec3_zero(); for (int i = 0; i < index; i+=4) { tc->bound.center = vec3_add(tc->bound.center, vertex_buffer[i]); } tc->bound.center = vec3_div(tc->bound.center, tc->num_verts); tc->bound.radius = 0; for (int i = 0; i < index; i+=4) { tc->bound.radius = max(tc->bound.radius, vec3_dist(tc->bound.center, vertex_buffer[i])); } if (net_is_client()) { glGenBuffers(1, &tc->vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, tc->vertex_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * 4 * tc->num_verts, vertex_buffer, GL_STATIC_DRAW); } free(vertex_buffer); if (net_is_client()) { glGenBuffers(NUM_TERRAIN_BUFFERS, tc->index_buffers); } for(int j = 0; j < NUM_TERRAIN_BUFFERS; j++) { int off = pow(2, j); int x_max = tc->width * SUBDIVISIONS; int y_max = tc->height * SUBDIVISIONS; tc->num_indicies[j] = (x_max / off) * (y_max / off) * 6 + (x_max / off) * 12 + (y_max / off) * 12; uint32_t* index_buffer = malloc(sizeof(uint32_t) * tc->num_indicies[j]); index = 0; for(int x = 0; x < x_max; x+=off) for(int y = 0; y < y_max; y+=off) { index_buffer[index] = x + y * (x_max+1); index++; index_buffer[index] = (x+off) + y * (x_max+1); index++; index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++; index_buffer[index] = x + y * (x_max+1); index++; index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++; index_buffer[index] = x + (y+off) * (x_max+1); index++; } /* Again, adding fins. Don't look horrible code */ int x_base = (x_max + 1) * (y_max + 1); int y_base = (x_max + 1) * (y_max + 1) + (x_max + 1) * 2; for(int x = 0; x < x_max; x+=off) { index_buffer[index] = x + 0 * (x_max+1); index++; index_buffer[index] = x_base + x; index++; index_buffer[index] = (x+off) + 0 * (x_max+1); index++; index_buffer[index] = (x+off) + 0 * (x_max+1); index++; index_buffer[index] = x_base + x; index++; index_buffer[index] = x_base + x+off; index++; } for(int x = 0; x < x_max; x+=off) { index_buffer[index] = x + y_max * (x_max+1); index++; index_buffer[index] = (x+off) + y_max * (x_max+1); index++; index_buffer[index] = x_base + y_max+1 + x; index++; index_buffer[index] = (x+off) + y_max * (x_max+1); index++; index_buffer[index] = x_base + x_max+1 + x+off; index++; index_buffer[index] = x_base + x_max+1 + x; index++; } for(int y = 0; y < y_max; y+=off) { index_buffer[index] = 0 + y * (x_max+1); index++; index_buffer[index] = 0 + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y; index++; index_buffer[index] = 0 + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y+off; index++; index_buffer[index] = y_base + y; index++; } for(int y = 0; y < y_max; y+=off) { index_buffer[index] = x_max + y * (x_max+1); index++; index_buffer[index] = y_base + y_max+1 + y; index++; index_buffer[index] = x_max + (y+off) * (x_max+1); index++; index_buffer[index] = x_max + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y_max+1 + y; index++; index_buffer[index] = y_base + y_max+1 + y+off; index++; } if (net_is_client()) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tc->index_buffers[j]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * tc->num_indicies[j], index_buffer, GL_DYNAMIC_DRAW); } free(index_buffer); } tc->colmesh = malloc(sizeof(cmesh)); tc->colmesh->is_leaf = true; tc->colmesh->triangles_num = (tc->width/4) * (tc->height/4) * 2; tc->colmesh->triangles = malloc(sizeof(ctri) * tc->colmesh->triangles_num); int tri_i = 0; for (int x = 0; x < tc->width; x += 4) for (int y = 0; y < tc->height; y += 4) { float gx = tc->x * ter->chunk_width + (float)x; float gy = tc->y * ter->chunk_height + (float)y; vec3 a = vec3_new(gx , terrain_height(ter, vec2_new(gx , gy )) , gy ); vec3 b = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy )) , gy ); vec3 c = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy+4)) , gy+4); vec3 d = vec3_new(gx , terrain_height(ter, vec2_new(gx , gy+4)) , gy+4); vec3 tang = vec3_normalize(vec3_sub(b, a)); vec3 binorm = vec3_normalize(vec3_sub(d, a)); vec3 norm = vec3_cross( binorm, tang ); tc->colmesh->triangles[tri_i] = ctri_new(a, c, b, norm); tri_i++; tc->colmesh->triangles[tri_i] = ctri_new(a, d, c, norm); tri_i++; } tc->colmesh->bound = cmesh_bound(tc->colmesh); /* For some reason this is not working correctly */ cmesh_subdivide(tc->colmesh, 5); ter->chunks[i] = tc; }
void sea_init() { graphics_viewport_set_dimensions(1280, 720); graphics_viewport_set_title("Sea"); camera* cam = entity_new("camera", camera); cam->position = vec3_new(50.0, 50.0, 50.0); cam->target = vec3_new(0, 5, 0); cam->near_clip = 0.1; light* sun = entity_new("sun", light); light_set_type(sun, light_type_spot); sun->position = vec3_new(20,23,16); sun->ambient_color = vec3_new(0.5, 0.5, 0.5); sun->diffuse_color = vec3_new(1.0, 0.894, 0.811); sun->specular_color = vec3_mul(vec3_new(1.0, 0.894, 0.811), 4); sun->power = 5; light* backlight = entity_new("backlight", light); light_set_type(backlight, light_type_point); backlight->position = vec3_new(-22,10,-13); backlight->ambient_color = vec3_new(0.2, 0.2, 0.2); backlight->diffuse_color = vec3_new(0.729, 0.729, 1.0); backlight->specular_color = vec3_mul(vec3_new(0.729, 0.729, 1.0), 1); backlight->power = 2; shadow_mapper_init(sun); forward_renderer_init(); forward_renderer_set_camera(cam); forward_renderer_set_shadow_light(sun); forward_renderer_set_shadow_texture( shadow_mapper_depth_texture() ); forward_renderer_add_light(sun); forward_renderer_add_light(backlight); folder_load(P("./resources/")); renderable* r_seaplane = asset_get(P("./resources/seaplane.obj")); r_seaplane->material = asset_hndl_new(P("./resources/seaplane.mat")); static_object* s_seaplane = entity_new("seaplane", static_object); s_seaplane->renderable = asset_hndl_new_ptr(r_seaplane); s_seaplane->scale = vec3_new(3,1,3); renderable* r_skydome = asset_get(P("./resources/skydome.obj")); r_skydome->material = asset_hndl_new_load(P("$CORANGE/shaders/skydome.mat")); static_object* skydome = entity_new("skydome", static_object); skydome->renderable = asset_hndl_new_ptr(r_skydome); skydome->position = vec3_new(0, -512, 0); skydome->scale = vec3_new(1024, 1024, 1024); folder_load(P("./resources/corvette/")); renderable* r_corvette = asset_get(P("./resources/corvette/corvette.obj")); r_corvette->material = asset_hndl_new_load(P("./resources/corvette/corvette.mat")); static_object* s_corvette = entity_new("corvette", static_object); s_corvette->renderable = asset_hndl_new_ptr(r_corvette); //s_corvette->collision_body = collision_body_new_mesh(asset_get("./resources/corvette/corvette.col")); s_corvette->scale = vec3_new(1.5, 1.5, 1.5); s_corvette->position = vec3_new(0, 0.5, 0); static_object* center_sphere = entity_new("center_sphere", static_object); center_sphere->position = vec3_new(0, 5, 0); //center_sphere->renderable = asset_get("./resources/ball.obj"); //center_sphere->collision_body = collision_body_new_sphere(sphere_new(v3_zero(), 1.0f)); ui_button* framerate = ui_elem_new("framerate", ui_button); ui_button_move(framerate, vec2_new(10,10)); ui_button_resize(framerate, vec2_new(30,25)); ui_button_set_label(framerate, "FRAMERATE"); ui_button_disable(framerate); }
void scotland_init() { graphics_viewport_set_dimensions(1280, 720); graphics_viewport_set_title("Scotland"); ui_button* loading = ui_elem_new("loading", ui_button); ui_button_move(loading, vec2_new(graphics_viewport_width() / 2 - 40,graphics_viewport_height() / 2 - 13)); ui_button_resize(loading, vec2_new(80,25)); ui_button_set_label(loading, "Loading..."); ui_button_disable(loading); ui_spinner* load_spinner = ui_elem_new("load_spinner", ui_spinner); load_spinner->color = vec4_white(); load_spinner->top_left = vec2_new(graphics_viewport_width() / 2 + 50, graphics_viewport_height() / 2 - 13); load_spinner->bottom_right = vec2_add(load_spinner->top_left, vec2_new(24,24)); ui_button* framerate = ui_elem_new("framerate", ui_button); ui_button_move(framerate, vec2_new(10,10)); ui_button_resize(framerate, vec2_new(30,25)); ui_button_set_label(framerate, "FRAMERATE"); ui_button_disable(framerate); framerate->active = false; ui_button* wireframe = ui_elem_new("wireframe", ui_button); ui_button_move(wireframe, vec2_new(50,10)); ui_button_resize(wireframe, vec2_new(80,25)); ui_button_set_label(wireframe, "wireframe"); wireframe->active = false; ui_elem_add_event("wireframe", toggle_wireframe); ui_button* freecam = ui_elem_new("freecam", ui_button); ui_button_move(freecam, vec2_new(140,10)); ui_button_resize(freecam, vec2_new(65,25)); ui_button_set_label(freecam, "freecam"); freecam->active = false; ui_elem_add_event("freecam", toggle_freecam); loading_resources = true; SDL_Thread* load_thread = SDL_GL_CreateThread(load_resources, NULL); /* New Camera and light */ camera* cam = entity_new("camera", camera); cam->position = vec3_new(512.0, 200.0, 512.0); cam->target = vec3_new(0.0, 0.0, 0.0); light* sun = entity_new("sun", light); light_set_type(sun, light_type_sun); sun->position = vec3_new(0, 512, 0); sun->target = vec3_new(512, 0, 512); /* Renderer Setup */ shadow_mapper_init(sun); forward_renderer_init(); forward_renderer_set_camera(cam); forward_renderer_set_shadow_light(sun); forward_renderer_set_shadow_texture( shadow_mapper_depth_texture() ); forward_renderer_add_light(sun); }
static image* perlin_noise_generate(int x_size, int y_size, int octaves) { unsigned char* data = malloc(sizeof(char) * x_size * y_size); int i, x, y; /* Clear data to average */ for(x = 0; x < x_size; x++) for(y = 0; y < y_size; y++) { data[x + (y * x_size)] = 128; } srand(time(NULL)); debug("Generating perlin noise."); for(i = 0; i < octaves; i++ ) { float wavelength = pow( 2, i); float amplitude = pow( 0.5, octaves-i ); vec2 seed = vec2_new(rand(),rand()); debug("Octave: %i Wavelength: %f Amplitude: %f", i, wavelength, amplitude); for(x = 0; x < x_size; x++) for(y = 0; y < y_size; y++) { /* Four positions are required for tiling behaviour */ vec2 pos, pos_x, pos_y, pos_xy; pos = vec2_div( vec2_new(x, y) , wavelength ); pos_x = vec2_div( vec2_new(x - x_size, y) , wavelength ); pos_y = vec2_div( vec2_new(x, y - y_size) , wavelength ); pos_xy = vec2_div( vec2_new(x - x_size, y - y_size) , wavelength ); pos = vec2_add( pos, seed ); pos_x = vec2_add( pos_x, seed ); pos_y = vec2_add( pos_y, seed ); pos_xy = vec2_add( pos_xy, seed ); float val = perlin_noise2D(pos) * amplitude; float val_x = perlin_noise2D(pos_x) * amplitude; float val_y = perlin_noise2D(pos_y) * amplitude; float val_xy = perlin_noise2D(pos_xy) * amplitude; val = bilinear_interp(val_x, val, val_xy, val_y, (float)x/x_size, (float)y/y_size); data[x + (y * x_size)] += val * 128; } } unsigned char* image_data = malloc(sizeof(char) * 4 * x_size * y_size); for(x = 0; x < x_size; x++) for(y = 0; y < y_size; y++) { int amount = data[x + y * x_size]; image_data[x * 4 + y * x_size * 4 + 0] = amount; image_data[x * 4 + y * x_size * 4 + 1] = amount; image_data[x * 4 + y * x_size * 4 + 2] = amount; image_data[x * 4 + y * x_size * 4 + 3] = 255; } free(data); return image_new(x_size, y_size, image_data); }
int main(int argc, char **argv) { #ifdef _WIN32 FILE* ctt = fopen("CON", "w" ); FILE* fout = freopen( "CON", "w", stdout ); FILE* ferr = freopen( "CON", "w", stderr ); #endif corange_init("../../assets_core"); graphics_viewport_set_size(1280, 720); graphics_viewport_set_title("Noise"); folder_load(P("./")); file_load(P("$CORANGE/textures/random.dds")); glClearColor(1.0, 0.0, 0.0, 1.0); ui_button* info_button = ui_elem_new("info_button", ui_button); ui_button_move(info_button, vec2_new(10, 10)); ui_button_resize(info_button, vec2_new(460,25)); ui_button_set_label(info_button, "Procedural texture from perlin noise and feedback functions"); ui_button* save_button = ui_elem_new("save_button", ui_button); ui_button_move(save_button, vec2_new(480, 10)); ui_button_resize(save_button, vec2_new(380,25)); ui_button_set_label(save_button, "Click Here to save tileable perlin noise to file"); ui_button_set_onclick(save_button, save_noise_to_file); ui_button* spinner_box = ui_elem_new("spinner_box", ui_button); ui_button_resize(spinner_box, vec2_new(32, 32)); ui_button_move(spinner_box, vec2_new(870, 7)); ui_button_set_label(spinner_box, ""); ui_spinner* save_spinner = ui_elem_new("save_spinner", ui_spinner); save_spinner->color = vec4_new(1,1,1,0); save_spinner->top_left = vec2_new(874, 11); save_spinner->bottom_right = vec2_add(save_spinner->top_left, vec2_new(24,24)); srand(time(NULL)); shader_time = (float)rand() / (RAND_MAX / 1000); bool running = true; while(running) { frame_begin(); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: case SDL_KEYUP: if (event.key.keysym.sym == SDLK_ESCAPE) { running = 0; } if (event.key.keysym.sym == SDLK_PRINTSCREEN) { graphics_viewport_screenshot(); } break; case SDL_QUIT: running = 0; break; break; } ui_event(event); } shader_time += frame_time(); ui_update(); noise_render(); ui_render(); graphics_swap(); frame_end(); } SDL_WaitThread(save_thread, NULL); corange_finish(); return 0; }
font* font_load_file(char* filename) { font* f = malloc(sizeof(font)); f->width = 0; f->height = 0; /* Encodes ASCII */ f->locations = malloc( sizeof(vec2) * 256 ); f->sizes = malloc( sizeof(vec2) * 256 ); f->offsets = malloc( sizeof(vec2) * 256 ); SDL_RWops* file = SDL_RWFromFile(filename, "r"); if(file == NULL) { error("Could not load file %s", filename); } char line[1024]; while(SDL_RWreadline(file, line, 1024)) { int tex_id; char tex_file[MAX_PATH]; if (sscanf(line, "page id=%i file=%s", &tex_id, tex_file) > 0) { fpath location; SDL_PathFileLocation(location.ptr, filename); /* +1 to remove beginning quotation */ strcat(location.ptr, tex_file+1); /* remove ending quotation */ location.ptr[strlen(location.ptr)-1] = '\0'; f->texture_map = asset_hndl_new_load(location); } int lineheight, base, scalew, scaleh; int pages, packed, a_chan, r_chan, g_chan, b_chan; if (sscanf(line, "common lineHeight=%i base=%i scaleW=%i scaleH=%i " "pages=%i packed=%i alphaChnl=%i " "redChnl=%i greenChnl=%i blueChnl=%i", &lineheight, &base, &scalew, &scaleh, &pages, &packed, &a_chan, &r_chan, &g_chan, &b_chan) > 0) { f->width = scalew; f->height = scaleh; } int id, x, y, w, h, x_off, y_off, x_adv, page, chnl; if (sscanf(line, "char id=%i x=%i y=%i width=%i height=%i " "xoffset=%i yoffset=%i xadvance=%i page=%i chnl=%i", &id, &x, &y, &w, &h, &x_off, &y_off, &x_adv, &page, &chnl) > 0) { f->locations[id] = vec2_new((float)x / f->width, (float)y / f->height); f->sizes[id] = vec2_new((float)w / f->width, (float)h / f->height); f->offsets[id] = vec2_new((float)x_off / f->width, (float)y_off / f->height); } } SDL_RWclose(file); return f; }
material* mat_load_file(char* filename) { SDL_RWops* file = SDL_RWFromFile(filename, "r"); if(file == NULL) { error("Cannot load file %s", filename); } material* m = material_new(); material_entry* me = material_add_entry(m); char line[1024]; while(SDL_RWreadline(file, line, 1024)) { if (line[0] == '#') { continue; } if (line[0] == '\r') { continue; } if (line[0] == '\n') { continue; } if (strstr(line, "submaterial")) { /* Skip Empty Submaterials */ if (me->num_items == 0) { continue; } else { me = material_add_entry(m); continue; } } char type[512]; char name[512]; char value[512]; int matches = sscanf(line, "%511s %511s = %511s", type, name, value); if (matches != 3) continue; material_item mi; int type_id; char* end; float f0, f1, f2, f3; if (strcmp(type, "shader") == 0) { mi.as_asset = asset_hndl_new_load(P(value)); type_id = mat_item_shader; } else if (strcmp(type, "texture") == 0) { mi.as_asset = asset_hndl_new_load(P(value)); type_id = mat_item_texture; } else if (strcmp(type, "int") == 0) { mi.as_int = atoi(value); type_id = mat_item_int; } else if (strcmp(type, "float") == 0) { mi.as_float = atof(value); type_id = mat_item_float; } else if (strcmp(type, "vec2") == 0) { f0 = strtod(value, &end); f1 = strtod(end, NULL); mi.as_vec2 = vec2_new(f0, f1); type_id = mat_item_vec2; } else if (strcmp(type, "vec3") == 0) { f0 = strtod(value, &end); f1 = strtod(end, &end); f2 = strtod(end, NULL); mi.as_vec3 = vec3_new(f0, f1, f2); type_id = mat_item_vec3; } else if (strcmp(type, "vec4") == 0) { f0 = strtod(value, &end); f1 = strtod(end, &end); f2 = strtod(end, &end); f3 = strtod(end, NULL); mi.as_vec4 = vec4_new(f0, f1, f2, f3); type_id = mat_item_vec4; } else { error("Unknown material item type '%s'", type); return NULL; } material_entry_add_item(me, name, type_id, mi); } SDL_RWclose(file); material_generate_programs(m); SDL_GL_CheckError(); return m; }
u64 load_pixel_frame(u64 texture, int x, int y, int x2, int y2){ texture_info texinfo; if(!try_get_texture_info(texture, &texinfo)){ char namebuf[100]; get_textures(texture, namebuf, sizeof(namebuf)); stbi_info(namebuf, &texinfo.width, &texinfo.height, &texinfo.comp); set_texture_info(texture, texinfo); } vec2 size = vec2_new(texinfo.width, texinfo.height); texture_section sec = {.uv_offset = vec2_div(vec2_new(x, y), size), .uv_size = vec2_div(vec2_new(x2 - x, y2 - y), size), .render_offset = vec2_new(0,0), .pixel_size = vec2_new(x2 - x, y2 - y)}; //sec.uv_offset.y = 1.0 - sec.uv_offset.y; add_texture_sections(texture, sec); return 0; } u64 load_pixel_frame_center_of_mass(u64 texture, int x, int y, int x2, int y2, int cx, int cy){ texture_info texinfo; if(!try_get_texture_info(texture, &texinfo)){ char namebuf[100]; get_textures(texture, namebuf, sizeof(namebuf)); stbi_info(namebuf, &texinfo.width, &texinfo.height, &texinfo.comp); set_texture_info(texture, texinfo); } vec2 size = vec2_new(texinfo.width, texinfo.height); int center_x = (x2 + x) / 2, center_y = (y2 + y) / 2; texture_section sec = {.uv_offset = vec2_div(vec2_new(x, y), size), .uv_size = vec2_div(vec2_new(x2 - x, y2 - y), size), .render_offset = vec2_new(center_x - cx, center_y - cy), .pixel_size = vec2_new(x2 - x, y2 - y)}; add_texture_sections(texture, sec); return 0; } CREATE_TABLE2(animation, u64, animation_state); struct{ u32 count; i32 * texture; u64 * texid; }loaded_textures; i32 get_animation_gltexture(u64 tex){ u64 * id = memmem(loaded_textures.texid, loaded_textures.count * sizeof(u64), &tex, sizeof(u64)); if(id != NULL){ ASSERT(*id == tex); return loaded_textures.texture[id - loaded_textures.texid]; } char buffer[100]; get_textures(tex, buffer, sizeof(buffer)); i32 newtex = load_gl_texture(buffer); list_push(loaded_textures.texture, loaded_textures.count, newtex); list_push2(loaded_textures.texid, loaded_textures.count, tex); return newtex; }
static void collision_detection() { /* Collision is fairly simplistic and looks something like this. @-----@ We check for collision in those points here which @ @ are @ signs. If any are colliding with a solid tile | | then we shift the player so that they are no longer @ @ colliding with it. Also invert the velocity. @-----@ */ character* main_char = entity_get("main_char"); const float buffer = 4; const float bounce = 0.5; vec2 diff; /* Bottom Collision */ diff = vec2_fmod(main_char->position, TILE_SIZE); vec2 bottom1 = vec2_add(main_char->position, vec2_new(buffer, TILE_SIZE)); vec2 bottom2 = vec2_add(main_char->position, vec2_new(TILE_SIZE - buffer, TILE_SIZE)); bool bottom1_col = tile_has_collision(level_tile_at(current_level, bottom1)); bool bottom2_col = tile_has_collision(level_tile_at(current_level, bottom2)); if (bottom1_col || bottom2_col) { main_char->position = vec2_add(main_char->position, vec2_new(0,-diff.y)); main_char->velocity.y *= -bounce; } /* Top Collision */ diff = vec2_fmod(main_char->position, TILE_SIZE); vec2 top1 = vec2_add(main_char->position, vec2_new(buffer, 0)); vec2 top2 = vec2_add(main_char->position, vec2_new(TILE_SIZE - buffer, 0)); bool top1_col = tile_has_collision(level_tile_at(current_level, top1)); bool top2_col = tile_has_collision(level_tile_at(current_level, top2)); if (top1_col || top2_col) { main_char->position = vec2_add(main_char->position, vec2_new(0, TILE_SIZE - diff.y)); main_char->velocity.y *= -bounce; } /* Left Collision */ diff = vec2_fmod(main_char->position, TILE_SIZE); vec2 left1 = vec2_add(main_char->position, vec2_new(0, buffer)); vec2 left2 = vec2_add(main_char->position, vec2_new(0, TILE_SIZE - buffer)); bool left1_col = tile_has_collision(level_tile_at(current_level, left1)); bool left2_col = tile_has_collision(level_tile_at(current_level, left2)); if (left1_col || left2_col) { main_char->position = vec2_add(main_char->position, vec2_new(TILE_SIZE - diff.x,0)); main_char->velocity.x *= -bounce; } /* Right Collision */ diff = vec2_fmod(main_char->position, TILE_SIZE); vec2 right1 = vec2_add(main_char->position, vec2_new(TILE_SIZE, buffer)); vec2 right2 = vec2_add(main_char->position, vec2_new(TILE_SIZE, TILE_SIZE - buffer)); bool right1_col = tile_has_collision(level_tile_at(current_level, right1)); bool right2_col = tile_has_collision(level_tile_at(current_level, right2)); if (right1_col || right2_col) { main_char->position = vec2_add(main_char->position, vec2_new(-diff.x,0)); main_char->velocity.x *= -bounce; } }
void platformer_init() { /* Set the viewport title */ graphics_viewport_set_title("Platformer"); /* Register functions for loading/unloading files with the extension .level */ asset_handler(level, "level", level_load_file, level_delete); /* Load Assets */ folder_load(P("./tiles/")); folder_load(P("./backgrounds/")); folder_load(P("./sounds/")); folder_load(P("./levels/")); /* Register some handlers for creating and destroying entity types */ entity_handler(character, character_new, character_delete); entity_handler(coin, coin_new, coin_delete); /* Create our main character */ character* main_char = entity_new("main_char", character); /* Add some UI elements */ ui_button* framerate = ui_elem_new("framerate", ui_button); ui_button_move(framerate, vec2_new(10,10)); ui_button_resize(framerate, vec2_new(30,25)); ui_button_set_label(framerate, " "); ui_button_disable(framerate); ui_button* score = ui_elem_new("score", ui_button); ui_button_move(score, vec2_new(50, 10)); ui_button_resize(score, vec2_new(120, 25)); ui_button_set_label(score, "Score 000000"); ui_button_disable(score); ui_button* time = ui_elem_new("time", ui_button); ui_button_move(time, vec2_new(180, 10)); ui_button_resize(time, vec2_new(110, 25)); ui_button_set_label(time, "Time 000000"); ui_button_disable(time); ui_button* victory = ui_elem_new("victory", ui_button); ui_button_move(victory, vec2_new(365, 200)); ui_button_resize(victory, vec2_new(70, 25)); ui_button_set_label(victory, "Victory!"); ui_button_disable(victory); ui_button* new_game_but = ui_elem_new("new_game", ui_button); ui_button_move(new_game_but, vec2_new(365, 230)); ui_button_resize(new_game_but, vec2_new(70, 25)); ui_button_set_label(new_game_but, "New Game"); void on_newgame(ui_button* b, void* unused) { reset_game(); } ui_button_set_onclick(new_game_but, on_newgame); /* Reset all the game variables */ reset_game(); }