У меня есть только несколько комментариев. Во-первых, у вас недостаточно комментариев. Есть места, где неясно, что вы пытаетесь сделать, поэтому трудно сказать, есть ли лучший способ сделать это, но я укажу на них, когда дойду до них. Однако сначала:
#define MSECS_PER_STEP 20
int stepCount, stepSize; // these are not globals in the real source
void loop() {
int i,j;
int iterations =0;
static int accumulator; // the accumulator holds extra msecs
static int lastMsec;
Они ничем не инициализированы. Вероятно, они будут равны 0, но вы должны были их инициализировать. Кроме того, вместо того, чтобы объявлять их статическими, вы можете захотеть поместить их в структуру, которую вы передаете в loop
по ссылке.
int deltatime = msec() - lastMsec;
Поскольку lastMsec
не было (инициализировано и, вероятно, равно 0), это, вероятно, начинается с большой дельты.
lastMsec = msec();
Эта строка, как и последняя, вызывает msec
. Это, вероятно, подразумевается как «текущее время», и эти вызовы достаточно близки, чтобы возвращаемое значение, вероятно, было одинаковым для обоих вызовов, что, вероятно, также является тем, что вы ожидали, но тем не менее вы вызываете функцию дважды. Вы должны изменить эти строки на int now = msec();
int deltatime = now - lastMsec;
lastMsec = now;
, чтобы избежать двойного вызова этой функции. Текущие функции получения времени часто имеют гораздо более высокие накладные расходы, чем вы думаете.
if (deltatime != 0) {
iterations = deltatime/MSECS_PER_STEP;
accumulator += deltatime%MSECS_PER_STEP;
}
У вас должен быть комментарий здесь, который говорит, что это делает, а также комментарий выше, который говорит, что означают переменные.
while (accumulator >= MSECS_PER_STEP) {
iterations++;
accumulator -= MSECS_PER_STEP;
}
Этот цикл нуждается в комментарии. Его тоже не должно быть. Похоже, его можно было заменить на iterations += accumulator/MSECS_PER_STEP;
accumulator %= MSECS_PER_STEP;
. Деление и модуль должны выполняться за более короткое и последовательное время, чем цикл на любой машине с аппаратным разделением (что многие делают).
handleInput(); // gathers user input from an event queue
for (j=0; j<iterations; j++) {
for (i=0; i<stepCount; i++) {
doStep(stepSize/(float) stepCount); // forwards the sim
}
}
Выполнение шагов в цикле независимо от ввода приведет к тому, что игра перестанет отвечать на запросы, если она будет выполняться медленно и отставать. По крайней мере, кажется, что если игра отстанет, все входные данные начнут складываться и выполняться вместе, и все игровое время пройдет как один кусок. Это менее чем изящный способ потерпеть неудачу.
Кроме того, я могу догадаться, что означает цикл j
(внешний цикл), но внутренний цикл мне не ясен. также значение, переданное функции doStep
— что это значит.
}
Это последняя фигурная скобка. Я думаю, что это выглядит одиноким.
Я не знаю, что происходит с тем, что вызывает вашу функцию loop
, что может быть вне вашего контроля, и это может диктовать, что делает эта функция и как она выглядит, но если нет, я надеюсь, что вы пересмотрите структуру. Я считаю, что лучшим способом сделать это было бы иметь функцию, которая вызывается многократно, но только с одним событием в то время (выдается регулярно в относительно короткий период). Эти события могут быть либо событиями пользовательского ввода, либо событиями таймера. События пользовательского ввода просто настраивают реакцию на следующее событие таймера. (когда у вас нет событий для обработки, вы спите)
Вы всегда должны предполагать, что каждое событие таймера обрабатывается в один и тот же период, даже если здесь может быть некоторый дрейф, если обработка отстает. Основная странность, которую вы можете заметить здесь, заключается в том, что если игра отстает в обработке событий таймера, а затем снова догоняет, время в игре может показаться замедленным (ниже реального времени), затем ускоренным (до реального времени) и затем замедлите обратно (к реальному времени).
Способы справиться с этим включают в себя разрешение только одному событию таймера находиться в очереди событий одновременно, что приведет к замедлению времени (ниже реального времени), а затем к ускорению обратно (до реального времени) без интервала суперскорости. .
Другой способ сделать это, который функционально подобен тому, что у вас есть, состоит в том, чтобы последним шагом обработки каждого события таймера была постановка в очередь следующего события таймера (обратите внимание, что никто другой не должен отправлять события таймера {кроме первого). one}, если вы выбрали именно этот способ реализации игры). Это означало бы отказ от регулярных временных интервалов между событиями таймера, а также ограничение способности программы засыпать, поскольку, по крайней мере, каждый раз, когда проверяется очередь событий, будет обрабатываться событие таймера.
person
nategoose
schedule
18.10.2010