Проблема управления потоком Java - PullRequest
0 голосов
/ 17 июня 2010

Я программирую простой движок 2d игры.Я решил, как бы я хотел, чтобы механизм работал: он будет состоять из объектов, содержащих «события», которые будут запускаться моим основным игровым циклом, когда это уместно.

Еще немного о структуре: Каждый GameObject имеет updateEvent метод.objectList - это список всех объектов, которые будут получать события обновления.Только объекты в этом списке имеют свой метод updateEvent, вызываемый игровым циклом.

Я пытаюсь реализовать этот метод в классе GameObject (Эта спецификация - это то, что я хотел бы методдля достижения):

/**
* This method removes a GameObject from objectList.  The GameObject 
* should immediately stop executing code, that is, absolutely no more
* code inside update events will be executed for the removed game object.
* If necessary, control should transfer to the game loop.
* @param go The GameObject to be removed
*/
public void remove(GameObject go)

Таким образом, если объект пытается удалить себя внутри события обновления, управление должно перейти обратно к игровому движку:

public void updateEvent() {
    //object's update event
    remove(this);
    System.out.println("Should never reach here!");
}

Вот что у меня такдалеко.Это работает, но чем больше я читаю об использовании исключений для управления потоком, тем меньше мне это нравится, поэтому я хочу посмотреть, есть ли альтернативы.

Метод удаления

<code>public void remove(GameObject go) {
    //add to removedList
    //flag as removed
    //throw an exception if removing self from inside an updateEvent
}

Игровой цикл

<code>for(GameObject go : objectList) {
    try {
        if (!go.removed) {
            go.updateEvent();
        } else {
            //object is scheduled to be removed, do nothing
        }
    } catch(ObjectRemovedException e) {
        //control has been transferred back to the game loop
        //no need to do anything here
    }
}
// now remove the objects that are in removedList from objectList

2 вопроса:

  1. Я прав?в предположении, что единственный способ реализовать часть метода remove-right-сразу, как описано выше, состоит в том, чтобы вызвать пользовательское исключение и перехватить его в игровом цикле?(Я знаю, использование исключений для управления потоком похоже на goto, что плохо. Я просто не могу придумать другой способ сделать то, что я хочу!)

  2. Для удаления изСам список, можно , можно , чтобы один объект мог удалить объект, находящийся ниже в списке.В настоящее время я проверяю флаг удаления перед выполнением любого кода, и в конце каждого прохода удаляю объекты, чтобы избежать одновременной модификации.Есть ли лучший, желательно мгновенный / не опросный способ сделать это?

[Редактировать] После прочтения ваших ответов, я думаю, что я изменю методспецификации.Поведение мгновенного удаления - это то, к чему я привык работать в другом движке, но вы правы, оно не совсем соответствует тому, как работает Java.Пришло время попытаться обернуть мою голову немного другим способом мышления!

Ответы [ 4 ]

2 голосов
/ 17 июня 2010

Я согласен, что исключительный подход - лучший способ реализовать метод удаления в соответствии с вашей спецификацией.

Однако, возможно, вам следует пересмотреть спецификацию. Я бы оставил решение, когда updateEvent завершается для разработчика. Завершение с помощью вызова remove () сбивает с толку и требует использования исключений для управления потоком. Я считаю, что вызов remove () должен только изменить состояние флага. И я не вижу реальной проблемы с зацикливанием всех объектов, проверкой снятого флага для каждого из них.

1 голос
/ 17 июня 2010

Почему бы вам просто:

  • Сохранить объектный список в объекте, который запускает цикл
  • Не позволяйте объектам GameObject иметь доступ к списку (зачем?)
  • Функция updateEvent возвращает логическое значение.Если возвращаемое значение равно false, родительский объект удаляет этот объект из списка событий.Оператор return также служит для прекращения выполнения функции события.
1 голос
/ 17 июня 2010

@ jball ответит отлично - +1.

Другой метод, который я использовал, который работает хорошо и может быть немного чище, - это чтобы ваш метод updateEvent () возвращал логическое значение. Всякий раз, когда True возвращается из updateEvent, вы удаляете () объект.

Это позволяет вашему циклу событий иметь больше контроля над тем, как выполняется сам цикл, и удаляет немного ненужной привязки между вашими классами.

1 голос
/ 17 июня 2010

Почему бы просто не вернуться, т. Е.

public void updateEvent() { 
    //object's update event 
    remove(this); 
    return;   
    //obviously unreachable 
    System.out.println("Should never reach here!");     }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...