static void sitting_duck_update(struct foe_sitting_duck *f) { foe_common_update(&f->common); hit_ship(&f->common.pos, foe_data[f->common.type].radius); vec2_clamp_length(&f->common.dir, foe_data[f->common.type].max_speed); }
/* Task c: Ask coordinates (two integers) from user, and shoot the location. * Returns -1 if user gave invalid input or coordinates, 0 if there was no ship * at the given location; and 1 if there was a ship hit at the location. */ int shoot(void) { int x, y; scanf("%d %d", &x, &y); if (x < 0 || x >= xsize || y < 0 || y >= ysize) return -1; checked(x, y); if (is_ship(x, y) == '+') { hit_ship(x, y); return 1; } return 0; }
static void jarhead_update(struct foe_jarhead *f) { switch (f->state) { case JARHEAD_ALIVE: { vector2 *dir = &f->common.dir; vector2 s = ship.pos; vec2_sub_from(&s, &f->common.pos); vec2_mul_scalar(&s, .0003f); vec2_add_to(dir, &s); foe_common_update(&f->common); hit_ship(&f->common.pos, foe_data[f->common.type].radius); vec2_clamp_length(dir, foe_data[f->common.type].max_speed); } break; case JARHEAD_EXPLODING: if (--f->ttl <= 0) { foe_common_gen_explosion(&f->common, 1.f); kill_foe(&f->common); } else { vector2 *dir = &f->common.dir; foe_common_update(&f->common); /* spiral */ vec2_rotate(dir, f->spin_angle); vec2_add_to(dir, &f->hit_dir); vec2_clamp_length(dir, JARHEAD_MAX_EXPLODING_SPEED); /* trail */ foe_add_trail(&f->common.pos, &f->common.dir, PAL_YELLOW); } break; default: assert(0); } }
static void brute_update(struct foe_brute *f) { vector2 *dir = &f->common.dir; vector2 s = ship.pos; vec2_sub_from(&s, &f->common.pos); vec2_mul_scalar(&s, .004f); vec2_add_to(dir, &s); foe_common_update(&f->common); hit_ship(&f->common.pos, foe_data[FOE_BRUTE].radius); if (vec2_length(dir) > foe_data[FOE_BRUTE].max_speed); vec2_mul_scalar(dir, .7); if (f->common.angle_speed > BRUTE_MAX_ANGLE_SPEED) f->common.angle_speed *= .7; if (brute_is_recovering(f)) foe_add_trail(&f->common.pos, &f->common.dir, PAL_YELLOW); }
/* Task c: Ask coordinates (two integers) from user, and shoot the location. * Returns -1 if user gave invalid input or coordinates, 0 if there was no ship * at the given location; and 1 if there was a ship hit at the location. */ int shoot(void) { unsigned int xpos, ypos; char space; int ret_x = scanf("%u", &xpos); int ret_space = scanf("%c", &space); int ret_y = scanf("%u", &ypos); if (ret_x == 0 || ret_y == 0 || ret_space == 0) { return -1; } if (xpos >= xsize || ypos >= ysize) { return -1; } checked(xpos, ypos); if (is_ship(xpos, ypos) == '+') { hit_ship(xpos, ypos); return 1; } return 0; }
static void evolved_duck_update(struct foe_evolved_duck *f) { vector2 d, od, t; float r; int ship_is_behind; foe_common_update(&f->common); if (foe_bounced) { f->num_trail_segs = 0; } else { if (f->num_trail_segs < MAX_TRAIL_SEGS) f->num_trail_segs++; if (++f->trail_seg_head >= MAX_TRAIL_SEGS) f->trail_seg_head = 0; f->trail_seg[f->trail_seg_head] = f->common.pos; } hit_ship(&f->common.pos, foe_data[f->common.type].radius); od.x = ship.pos.x - f->common.pos.x; od.y = ship.pos.y - f->common.pos.y; vec2_normalize(&od); t.x = -f->common.dir.y; t.y = f->common.dir.x; ship_is_behind = vec2_dot_product(&od, &t) > 0; /* accelerate if behind ship, brake otherwise */ if (ship_is_behind) vec2_mul_scalar(&f->common.dir, .99f); else vec2_mul_scalar(&f->common.dir, 1.2f); /* turn towards ship */ d.x = -(ship.pos.y - f->common.pos.y); d.y = ship.pos.x - f->common.pos.x; vec2_normalize(&d); r = 1.6f*vec2_dot_product(&d, &f->common.dir); if (r < 0) { if (ship_is_behind) r = -f->max_turn_angle; else { if (r < -f->max_turn_angle) r = -f->max_turn_angle; } } else { if (ship_is_behind) { r = f->max_turn_angle; } else { if (r > f->max_turn_angle) r = f->max_turn_angle; } } vec2_rotate(&f->common.dir, r); vec2_clamp_length(&f->common.dir, foe_data[f->common.type].max_speed); }
static void update_inner_state(void) { static int prev_level_tics; inner_state.tics++; switch (inner_state.state) { case IS_WAVE_TITLE: if (inner_state.tics >= WAVE_TITLE_TICS) { set_inner_state(IS_IN_GAME); /* set_inner_state(IS_PRE_WAVE_CLEARED); */ } else { if (inner_state.tics == WAVE_TITLE_TICS/2) { if (!ship.is_alive) spawn_new_ship(); else reset_ship(); } } break; case IS_IN_GAME: level_stat_counters.tics++; game_stat_counters.tics++; if (gc.tics_remaining <= 0) { /* boom. */ hit_ship(&ship.pos, 1.f); trigger_game_over(); } else { gc.tics_remaining--; if (!ship.is_alive) { prev_level_tics = inner_state.tics; set_inner_state(IS_RESPAWNING_SHIP); } else if (!gc.foes_left) { level_stat_counters.waves++; game_stat_counters.waves++; if (gc.tics_remaining > TIME_BONUS_MIN_TICS) gc.score += gc.tics_remaining*TIME_BONUS_PER_TIC; set_inner_state(IS_PRE_WAVE_CLEARED); } else { spawn_new_foes(); } } break; case IS_PRE_WAVE_CLEARED: if (inner_state.tics >= PRE_WAVE_CLEARED_TICS) { gen_ship_implosion(); reset_powerups(); reset_missiles(); reset_bombs(); reset_lasers(); vec2_set(&ship.pos, 0.f, 0.f); /* HACK */ play_fx(FX_WAVE_TRANSITION); set_inner_state(IS_WAVE_CLEARED); } break; case IS_RESPAWNING_SHIP: if (inner_state.tics >= TICS_UNTIL_RESPAWN) { if (gc.ships_left) { spawn_new_ship(); set_inner_state(IS_IN_GAME); inner_state.tics = prev_level_tics; } else { trigger_game_over(); } } break; case IS_GAME_OVER: break; case IS_RANK: if (inner_state.tics >= RANK_TOTAL_TICS) { stop_music(); if (is_highscore(gc.score)) { set_inner_state(IS_HIGHSCORE_INPUT); SDL_ShowCursor(SDL_ENABLE); start_highscore_input(); } else { /* loser. */ SDL_ShowCursor(SDL_ENABLE); start_main_menu(); } } break; case IS_WAVE_CLEARED: if (gc.cur_wave == levels[gc.cur_level]->num_waves - 1 && inner_state.tics >= WAVE_CLEARED_TICS/2) { initialize_stats_table(&level_stat_counters); set_inner_state(IS_LEVEL_CLEARED); } else if (inner_state.tics >= WAVE_CLEARED_TICS) { gc.cur_wave++; assert(gc.cur_wave < levels[gc.cur_level]->num_waves); reset_wave(); set_inner_state(IS_WAVE_TITLE); } break; case IS_HIGHSCORE_INPUT: break; case IS_LEVEL_CLEARED: break; case IS_LEVEL_TRANSITION: if (inner_state.tics >= LEVEL_TRANSITION_TOTAL_TICS) { gc.cur_level = (gc.cur_level + 1)%NUM_LEVELS; set_inner_state(IS_WAVE_TITLE); reset_level(); } break; default: assert(0); } }