in procgen/src/games/dodgeball.cpp [378:444]
void game_step() override {
BasicAbstractGame::game_step();
float vx = last_move_action / 3 - 1;
float vy = last_move_action % 3 - 1;
agent->face_direction(vx, vy);
if (special_action == 1 && (cur_time - last_fire_time) >= 7) {
auto new_ball = add_entity(agent->x, agent->y, vx * ball_vscale, vy * ball_vscale, ball_r, PLAYER_BALL);
new_ball->collides_with_entities = true;
new_ball->expire_time = 50;
new_ball->vrot = BALL_V_ROT;
last_fire_time = cur_time;
}
num_enemies = 0;
for (int i = (int)(entities.size()) - 1; i >= 0; i--) {
auto ent = entities[i];
if (ent->type == ENEMY) {
num_enemies++;
if (ent->spawn_time == 0) {
choose_vel(ent);
} else {
ent->spawn_time -= 1;
}
bool can_fire = (cur_time - ent->fire_time) >= enemy_fire_delay;
if (can_fire) {
float dx = ent->x - agent->x;
float dy = ent->y - agent->y;
float bvelx = (ent->x < agent->x ? 1 : -1);
float bvely = (ent->y < agent->y ? 1 : -1);
if (fabs(dx) < 1) {
fire_ball(ent, 0, bvely);
ent->vx = 0;
ent->vy = bvely * ENEMY_VEL;
} else if (fabs(dy) < 1) {
fire_ball(ent, bvelx, 0);
ent->vx = bvelx * ENEMY_VEL;
ent->vy = 0;
}
// Uncomment to enable diagonal firing
// else if (fabs(fabs(dx) - fabs(dy)) < 1) {
// fire_ball(ent, bvelx, bvely);
// }
}
ent->face_direction(ent->vx, ent->vy);
} else if (ent->type == PLAYER_BALL || ent->type == ENEMY_BALL) {
if (ent->x < ent->rx || ent->x > (main_width - ent->rx)) {
ent->will_erase = true;
} else if (ent->y < ent->ry || ent->y > (main_height - ent->ry)) {
ent->will_erase = true;
}
}
}
erase_if_needed();
}