Я реализую простой алгоритм управления разделением (для выровненных по оси 2D-прямоугольников).Алгоритм:
- Для каждого прямоугольника (ячейки), проверьте все остальные на перекрытие
- , если перекрываются, рассчитайте разницу в векторах положения (вектор указывает на верхний левый угол прямоугольника)
- добавить к общему вектору
в конце, сила (ускорение) применяется в направлении, противоположном общему вектору, и положение прямоугольника обновляется с каждым кадром.
Это логика разделения:
bool Cell::seperateFrom(CellsContainer& cells) {
Vector2D force_sum;
int neighbor_count = 0;
for (auto& other : cells) {
if (!(*this == other) && this->overlaps(other)) {
Vector2D position_diff = this->position - other.position;
//normalize
position_diff /= (float)sqrt(std::pow(position_diff.x,2) + std::pow(position_diff.y,2));
force_sum += position_diff;
neighbor_count++;
}
}
if (neighbor_count > 0) {
// calculate steer away vector;
Vector2D steering = force_sum - this->velocity;
//normalize
steering /= (float) sqrt(std::pow(steering.x,2) + std::pow(steering.y,2));
//move by tile size units
steering *= static_cast<float> (TILE_SIZE);
this->addForce(steering);
return true;
} else {
// not overlapping, stop moving
this->velocity *= 0.0f;
return false;
}
}
Я начинаю со случайно сгенерированных случайно скомпонованных прямоугольников, и похоже, что разделение работает, однако результат очень направленный и не очень однородный по размеру прямоугольника (как видно ниже)), и я не понимаю, почему.
РЕДАКТИРОВАТЬ:
Функция updatePosition:
void Cell::updatePosition() {
this->velocity += this->acceleration;
this->position += this->velocity;
this->rectangle.setPosition(this->position);
this->acceleration *= 0.0f;
}
addForce:
void addForce(const Vector2D& force) {this->acceleration += force;}
Основной цикл:
void main_loop(WindowType& window, CellsContainer& cells) {
while (true) {
window.clear();
for (auto& cell_obj : cells) {
cell_obj.seperateFrom(cells);
cell_obj.updatePosition();
window.draw(cell_obj.getRectangle());
}
window.display();
}
}