Почему вы хотите избежать этого? Следует избегать циклических зависимостей, если вы хотите создать класс многократного использования. Но Player - это не тот класс, который вообще нужно многократно использовать. Хотели бы вы когда-нибудь использовать плеер без мира? Возможно нет.
Помните, что классы - это не более чем наборы функций. Вопрос в том, как разделить функциональность. Делай все, что тебе нужно. Если вам нужен круговой упадок, так тому и быть. (Кстати, то же самое относится и к любым функциям ООП. Кодируйте вещи так, чтобы они служили цели, а не просто слепо следуйте парадигмам.)
Отредактируйте
Хорошо, чтобы ответить на вопрос: вы можете избежать того, что Игроку нужно знать Мир для проверки столкновений, используя обратные вызовы:
World::checkForCollisions()
{
[...]
foreach(entityA in entityList)
foreach(entityB in entityList)
if([... entityA and entityB have collided ...])
entityA.onCollision(entityB);
}
Player::onCollision(other)
{
[... react on the collision ...]
}
Вид физики, который вы описали в этом вопросе, может быть обработан миром, если вы выставите скорость сущностей:
World::calculatePhysics()
{
foreach(entityA in entityList)
foreach(entityB in entityList)
{
[... move entityA according to its velocity as far as possible ...]
if([... entityA has collided with the world ...])
entityA.onWorldCollision();
[... calculate the movement of entityB in order to know if A has collided with B ...]
if([... entityA and entityB have collided ...])
entityA.onCollision(entityB);
}
}
Однако обратите внимание, что вам, вероятно, рано или поздно понадобится зависимость от мира, то есть когда вам нужна функциональность мира: вы хотите знать, где находится ближайший враг? Вы хотите знать, как далеко находится следующий выступ? Зависимость это есть.