C
C
Cyril2012-03-28 14:39:15
Game development
Cyril, 2012-03-28 14:39:15

What is the reason for small lags in the game?

I decided in my spare time to try to write my own project - a small game on flash.
As a method for displaying images, I decided to use BitmapData, which acts as a camera. On it, every update using the draw method, all game objects that fall into the camera's field of view are drawn. However, in the process of implementation, one problem arose, with which I have been fighting for the 3rd day.
When moving the camera, there is a "jumping" of the game background. The problem is that this is only a visual effect. In fact, one update takes <1 ms, so it's not a matter of performance at all.
Actually a question. What is the reason for these "jumps"?
Program architecture:
1) A timer is created that is responsible for updating game elements.
_timer = new Timer(1000 / FPS);//FPS == 60;
_timer.addEventListener(TimerEvent.TIMER, gameLoop);
_timer.start();
2) Main game loop

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() - updates the player's motion vector and normalizes it.
4) _gameController.update(deltaTime);
Collision check in progress.
In case of successful passing of all checks in the player class, the method
move(deltaTime):void
{
this.x += movingDirection.x * speed * deltaTime;
this.y += movingDirection.y * speed * deltaTime;
}
5) Update the camera position
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) Update view.
public function update():void
    {
      camera.lock();
      camera.fillRect(new Rectangle(0, 0, _camWidth, _camHeight), 0);
      drawLevelAndStuff();
      drawUnits();
      
      camera.unlock();
      
    }

7) drawLevelAndStuff() method
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();
        }
      }
    }

Flash drive example.
belk.su/
Management:
W - forward
S - back
Turn with the mouse. To start, you need to click on the black circle :)
UPD
PS The same effect is observed in www.realmofthemadgod.com/ . If you focus your eyes on some element of the coating, then when moving, you can see that it does not move smoothly. I have already begun to think that the problem is in my eyes, but friends, including from their computers, see the same thing.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
A
ashcraft, 2012-04-03
@Sk1talec

This is the so-called Screen tearing, the effect occurs, as mentioned above, due to the fact that the monitor refresh rate is not a multiple of the flash render rate. When scrolling, the redraw area is large, so artifacts are more noticeable. For clarity, you can file a test, where you just fill each frame in turn by filling the bitmap, then in white, then in black. Due to the nature of single-buffer software flash rendering, this cannot be fixed with CPU rendering in general. Only the 11th player + stage3d solve this problem.

I
Iliapan, 2012-03-28
@Iliapan

maybe you shouldn't update the screen so often ... choose an acceptable fps for yourself and work with it.

S
skyboy, 2012-03-29
@skyboy

Maybe the reason is that you have a debug version of the flash player. I have a regular one, there are no lags.

E
egorinsk, 2012-03-29
@egorinsk

Are you sure that the timer does not round the interval up to a multiple of some number of ms? Also, does flush guarantee that the timer will be called exactly 60 times and at regular intervals?
Also, is the flash image redrawing synchronized with the monitor scan?
Try getting the clock at the beginning of each frame and see if your code is called evenly. I suspect it's uneven. Also, why are you using a timer and not a frame entry event? Maybe the flash does not redraw objects immediately, but when the next frame starts?
And in general, is it necessary to move and redraw all objects every frame? Especially the ones that are invisible? Maybe you can make them classic objects, bind to a rectangle and move only it, this rectangle? Are you sure you're a flasher?

O
Ogra, 2012-03-30
@Ogra

And this can not be the accumulation of rounding errors?
For example, if a character moves 1.1 pixels per frame, then in one out of 10 frames it will move through 2 pixels, and in 9 out of 10 frames it will pass through only 1. That's "twitches".

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question