Решил в свободное от учебы время попробовать написать свой проект — небольшую игру на flash.
В качестве метода вывода изображений я решил использовать BitmapData, который выполняет роль камеры. На него каждый update с помощью метода draw отрисовываются все игровые объекты которые попадают в поле зрения камеры. Однако в процессе реализации появилась одна проблема, с которой я воюю уже 3ий день.
При перемещений камеры, происходит «подлагивание» игрового фона. Проблема в том, что это только визуальный эффект. На деле же, один update занимает время <1 мс поэтому дело совсем не в производительности.
Собственно вопрос. В чем причина этих «подлагиваний»?
Архитектура программы:
1) Создается таймер который отвечает за обновление элементов игры.
_timer = new Timer(1000 / FPS);//FPS == 60;
_timer.addEventListener(TimerEvent.TIMER, gameLoop);
_timer.start();
2)Главный игровой цикл
private function gameLoop(e:Event):void
{
//Считаем время, которое прошло с момента последнего апдейта
_date = new Date();
var deltaTime:Number = (isNaN(_lastUpdate))?0:(_date.getTime() - _lastUpdate) / 1000;
//НАЧАЛО ОБРАБОТКИ ИГРОВОГО ЦИКЛА
//Обновляем команды полученные от игрока.
_playerController.update();
//Обновляем игровую модель.
_gameController.update(deltaTime);
//Обновляем позицию камеры.
updateCameraPosition();
//Обновляем отображение игры.
_gameView.update();
//КОНЕЦ ОБРАБОТКИ ИГРОВОГО ЦИКЛА
//Засекаем время, на котором закончился апдейт.
_lastUpdate = _date.getTime();
}
3) PlayerController.update() — обновляет вектор движения игрока и нормализует его.
4) _gameController.update(deltaTime);
Идет проверка на столкновения.
В случае успешного прохождения всех проверок в классе игрока вызывается метод
move(deltaTime):void
{
this.x += movingDirection.x * speed * deltaTime;
this.y += movingDirection.y * speed * deltaTime;
}
5) Обновляем позицию камеры
private function updateCameraPosition():void
{
var levelWidth:int = _gameLevel.maxWidth / 2 - 1;
var leveHeight:int = _gameLevel.maxHeight / 2 - 1;
if ((levelWidth + 1) * LevelView.CELL_WIDTH > _gameController.player.x + GAME_WIDTH / 2
&& ( -levelWidth - 1) * LevelView.CELL_WIDTH < _gameController.player.x - GAME_WIDTH / 2)
{
_gameView.camX = _gameController.player.x;
}
if ((leveHeight + 1) * LevelView.CELL_HEIGHT > _gameController.player.y + GAME_HEIGHT / 2
&& ( -leveHeight - 1) * LevelView.CELL_HEIGHT < _gameController.player.y - GAME_HEIGHT / 2)
{
_gameView.camY = _gameController.player.y;
}
}
6) Обновляем view.
public function update():void
{
camera.lock();
camera.fillRect(new Rectangle(0, 0, _camWidth, _camHeight), 0);
drawLevelAndStuff();
drawUnits();
camera.unlock();
}
7) Метод drawLevelAndStuff()
private function drawLevelAndStuff():void
{
var minColumn:int = (camX - _camWidth / 2) / LevelView.CELL_WIDTH - 1;
var minRow:int = (camY - _camHeight / 2) / LevelView.CELL_HEIGHT - 1;
var maxColumn:int = minColumn + _camWidth / LevelView.CELL_WIDTH + 1;
var maxRow:int = minRow + _camHeight / LevelView.CELL_HEIGHT + 1;
var matrix:Matrix = new Matrix();
for (var i:int = minRow; i <= maxRow; i++)
{
for (var j:int = minColumn; j <= maxColumn; j++)
{
//Отрисовываем покрытие клетки
matrix.translate(getLocalX(j * LevelView.CELL_WIDTH), getLocalY(i * LevelView.CELL_HEIGHT));
camera.draw(_level.getCell(i, j), matrix);
//Отрисовываем статические объекты
var stuff:IBitmapDrawable = _level.getStuff(i, j);
if (stuff)
{
camera.draw(stuff,matrix);
}
matrix.identity();
}
}
}
Пример флешки.
belk.su/
Управление:
W — вперед
S — назад
Мышкой поворот. Для старта нужно нажать на черный круг :)
UPD
P.S. В
www.realmofthemadgod.com/ наблюдается тот же эффект. Если сфокусировать взгляд на каком-то элементе покрытия, то при перемещении видно, что оно движется не плавно. Я уже начал думать, что проблема в моих глазах, однако друзья, в том числе и со своих компьютеров, видят то же самое.