Как справиться с периодическим обновлением многих объектов? - PullRequest
3 голосов
/ 10 ноября 2011

Я работаю над небольшой Java-игрой, опираясь на классические астероиды.

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

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

В настоящее время я обращаюсь с этим так:

//This method is called by a timer that is run every 30 milliseconds
//It will iterate through all objects that require periodic updates and call their
//update method every 30ms.
public void frameUpdateLoop(){
    for( Updating u : allObjectsThatNeedPeriodicUpdates ){
        u.update();
    }
}

public class EnemySpawner implements Updating{
    private static final int SPAWN_TRESHOLD=500;
    private int timeUntilNewEnemySpawns=SPAWN_TRESHOLD;

    //This method is called by frameUpdateLoop()
    //It is only supposed to do work once every 500ms, but is called every
    //30ms nonetheless.
    public void update(){
        timeUntilNewEnemySpawns -= 30; //Subtract time since last update
        if( timeUntilNewEnemySpawns <= 0){
            SpawnNewEnemy();
            timeUntilNewEnemySpawns = SPAWN_TRESHOLD;
        }
    }
}

Конечно, это только пример того, как я используюпоэтому я удалил ненужные части.

Мой вопрос: Это правильный (= хороший способ) внедрение такой системы обновлений? При чтении я заметил, что большинствовремя, в течение которого таймер используется для такой задачи.

Но это потребовало бы от меня одновременной работы десятков таймеров (по одному для каждого объекта, который требует обновления).Если я правильно понимаю, каждый экземпляр Timer также создает новый поток, поэтому я боюсь, что это может стать проблемой в какой-то момент (потеря производительности обработки потоков перевешивает мою текущую систему - или число потоков становится слишком большим).

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

Большое спасибо за предложения,Советы и исправления на эту тему!

Ответы [ 2 ]

0 голосов
/ 10 ноября 2011

Ваш метод выглядит хорошо, это то, что делает Half-Life.Единственное отличие состоит в том, что Half-Life (и многие другие, в том числе ваши) действительно отправляют Delta Time в функцию обновления, чтобы вам не приходилось жестко кодировать 30 мс в каждой функции обновления.Итак:

public void update(int deltaTime){
    timeUntilNewEnemySpawns -= deltaTime; //Subtract the delta time
    if( timeUntilNewEnemySpawns <= 0){
        SpawnNewEnemy();
        timeUntilNewEnemySpawns = SPAWN_TRESHOLD;
    }
}

Использование такого разностного времени позволит вам изменить интервал обновления, если вы когда-либо хотели / нуждались.И да, у вас может быть и будет множество счетчиков, которые будут отслеживать различные внутриигровые события.

Я мог бы также изменить deltaTime и timeUntilNewEnemySpawns на java-эквивалент TimeSpanтак что вы можете получить доступ к некоторым полезным методам, таким как TotalSeconds и тому подобное.Это не обязательно, хотя.

0 голосов
/ 10 ноября 2011

Мне очень нравится ваш дизайн с Updating интерфейсом, абстрагирующим детали того, что на самом деле должно быть обновлено.Конечно, ваша текущая реализация не очень элегантна.Может быть, вам следует создать несколько методов, таких как updateEveryFrame(), updateEverySecond() и т. Д.?Каждый объект реализует только те методы, которые ему необходимы для работы, оставляя другим нас без операций.

Timer на самом деле хороший выбор здесь также :

Этот класс масштабируется до большого числа одновременно запланированных задач (тысячи не должны представлять проблем)

Однако я бы порекомендовал разбить allObjectsThatNeedPeriodicUpdates на: allObjectsThatNeedUpdateEveryFrame, allObjectsThatNeedUpdateEverySecond и т. Д. Создатьпериодическое задание для первого сбора, другое (с другим интервалом) для другого.

...