void game_step()

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();
    }