Недавно я занимался разработкой игр в качестве хобби и решил, что для того, чтобы изучить начальные и конечные аспекты разработки игр, я должен создать игру и визуализировать все сам (без использования игрового движка). Это оказалось довольно сложным, однако я делаю большие успехи. Однако я столкнулся с проблемой, которая, как мне кажется, может быть связана с тем, как телефоны Android воспроизводят свою графику, и потребует некоторого разъяснения по этой проблеме.
Проблема
Моя игра содержит ряд шаров в пушке; когда пользователь нажимает на экран, пушка запускает шары, и двигатель (который я реализую) обрабатывает обновления информации о местоположении и обнаружение столкновений оттуда. Теперь, до того, как я реализовал обнаружение столкновений, моя игра работала очень плавно и отзывчиво, однако, когда я сказал движку рисовать шарик, только если он находится в пределах границ, и «отскакивать» его от стены, казалось бы, движок цикл теперь занимает значительно больше времени для запуска.
Это было бы хорошо, если бы не задержка, которую он обеспечивает для пользовательского опыта. Например, при прикосновении к экрану сейчас для отображения мяча как движущегося по экрану требуется ~ 2 секунды, а иногда он вообще не появляется . Раньше реакция была мгновенной.
Далее, когда я комментирую часть обнаружения столкновений моего физического движка, он возобновляет свое обычное реагирующее поведение.
То, что я думаю, вызывает такое поведение
Примечание: я отказался от этого предположения (см. «Отладочная информация» ниже)
Я думаю, что, поскольку в моей игре не реализован ограничитель кадров, и что он рендерит так быстро, как это позволяет аппаратное обеспечение, он выводит на экран так много старых кадров (в некотором буфере, может быть?), Что он занят рисованием, пока должен обновлять физику. Хотя моя отладка до сих пор не показала, что это так, я не могу прийти к какому-либо другому выводу.
Какой-то код
Обратите внимание, что этот код будет довольно запутанным, чтобы понять, не зная, что все делает. Я просто включил его на тот случай, если кто-то особенно хочет иметь какой-то код для работы. Переменные поясняются ниже выдержки.
PhysicsEngine.updateBeadPositions (float) :
private void updateBeadPositions(float delta){
//Update all of the beads currently on the board.
beads = control.getBoard().getValues();
temp_x = 0.0f;
temp_y = 0.0f;
//For each row...
for(Bead[] row : beads){
//For each bead...
for(Bead bead : row){
//If this bead exists...
if(bead != null){
temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);
//If the coordinates are within the bounds of the game
if(outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setYCoordinate(temp_y);
}
}
}
}
//If the cannon Bead has been set...
if(control.getCannon().getReleased() != null){
//Update the cannon bead
if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){
control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
}
else{
temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);
//TODO: Commented out collision checkers!
//If the horizontal coordinates are within the bounds of the game
if(!outwithHorizontalBounds(temp_x, control.getBoard())){
//If the vertical coordinates are within the bounds of game
if(!outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setYCoordinate(temp_y);
}
//Otherwise...
else{
//Bounds off the wall in the y direction
control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
}
}
//Otherwise...
else{
//Bounce off the wall in the x direction (flip the x velocity)
control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
}
}
}
}
Здесь переменные определены как:
control
это ссылка на мой игровой контроллер. Он упаковывает большую часть кода игры.beads
является ссылкой на 2D-массив, который содержит бусы на доске в настоящее время (исключая тот, который движется)delta
разница во времени между предыдущими вызовами физического движка и текущим вызовом
Смотрите комментарии в коде для любых других объяснений.
PhysicsEngine.outwithHorizontBounds (float, Board) :
private boolean outwithHorizontalBounds(float x, Board board){
//If the horizontal values are within the bounds...
if(x > (board.getRight() - bead_radius)){
return true;
}
if(x < (board.getLeft() + bead_radius)){
return true;
}
//Otherwise, it is not.
return false;
}
Метод outwithVerticalBounds(float, Board)
имеет эквивалентную функциональность, но в направлении y.
Мой вопрос
А как насчет обнаружения столкновений, что может привести к такому резкому замедлению рендеринга экрана? Я знаю, что это очень интенсивная операция, но моя отладка показала, что обновления физики завершаются одновременно с розыгрышами.
Отладочная информация
Последнее обновление: 29 января 2013 г. 16:27 EST
Вот совокупность отладочной информации, которую я получил до сих пор. Я буду обновлять это с течением времени:
update()
Метод в моем двигателе, занимает, в среднем, только.018 ms
для выполнения. Обычно задержка прыгает до0.020 ms
, когда я нажимаю на экран, чтобы освободить шарик.После сравнения времени проведения розыгрышей и обновлений игры оказалось, что я был прав: они происходят одновременно . Таким образом, это не могло быть проблемой, верно?
Суть
FPS
игры примерно одинакова87
(на нижнем уровне)60 FPS
, но этот всплеск не связан с выпуском шарика. У этого нетFPS
недостатков. Это имеет смысл, так как единственная часть, которая увеличивает его сложность после того, как бусинка отпущена, - этоupdate()
вызов, рисование все равно происходит как можно быстрее.После дальнейшего тестирования стало очевидно, что это не тот случай, когда экран отстает от физики. Я проверил это с помощью простого логического флага, при котором фон экрана становился белым, когда я к нему прикасался, и это происходит немедленно . Таким образом, должна быть какая-то другая причина, по которой шарик не тянет. Я скоро обновлю.
Дополнительная информация
Вот некоторая дополнительная информация, которая должна помочь вам понять мои обстоятельства:
Я тестирую это на Google Nexus 7.
На карте довольно много шариков, которые обновляются одновременно (около 30), но только один из них движется.
Обычно, после того как шарик начинает двигаться (после начальной задержки и, если он действительно вытягивается), он продолжает двигаться очень плавно.
Важно отметить, что у меня есть другие элементы пользовательского интерфейса, которые обновляются в ответ на событие касания. Например, шарик, загруженный в пушку, становится новым шариком при прикосновении к экрану (что означает, что он был отпущен), но мобильный шарик просто не рисуется.