Small podragivanija in the game

I decided in my free time to try to write your project is a small game in flash.
As a method of displaying images I decided to use a BitmapData, which acts as a camera. At every update using the method draw draw all the game objects that fall within the camera field of view. However, in the process of implementation, there is one problem that I'm fighting for 3rd day.
When movement of the camera, there is a "lag" gaming background. The problem is that this is only a visual effect. In fact, one update takes time <1 MS so it's not about performance.
Actually the question. What is the reason for these "podragivanija"?

Architecture of the program:
1) Creates a timer which is responsible for updating elements of the game.
_timer = new Timer(1000 / FPS);//FPS == 60;
_timer.addEventListener(TimerEvent.TIMER, gameLoop);
_timer.start();
2)Main game loop
private function gameLoop(e:Event):void 
{
 //Counting the time that has passed since the last update
 _date = new Date();
 var deltaTime:Number = (isNaN(_lastUpdate))?0:(_date.getTime() - _lastUpdate) / 1000;

 //START THE PROCESSING LOOP
 //Updating command received from the player.
_playerController.update();

 //Updating the model.
_gameController.update(deltaTime);

 //Updating the camera position.
updateCameraPosition();

 //Updated the display of the game.
_gameView.update();
 //END PROCESSING LOOP
 //Note the time at which he was update.
 _lastUpdate = _date.getTime();
}

3) player controller.update() — updates the movement vector of the player and normalizes it.
4) _gameController.update(deltaTime);
There is a check for collisions.
In case of successful passage of all tests in the class of the player the method is called
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) Updating the view.
public function update():void
{
camera.lock();
 camera.fillRect(new Rectangle(0, 0, _camWidth, _camHeight), 0);
drawLevelAndStuff();
drawUnits();

camera.unlock();

}

7) Method 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++)
{
 //Draw the cell coverage
 matrix.translate(getLocalX(j * LevelView.CELL_WIDTH), getLocalY(i * LevelView.CELL_HEIGHT));
 camera.draw(_level.getCell(i, j), matrix);

 //Draw static objects
 var stuff:IBitmapDrawable = _level.getStuff(i, j);
 if (stuff)
{
camera.draw(stuff,matrix);
}
matrix.identity();
}
}
}


An example of the stick.
belk.su/

Management:
W — forward
S — back
The mouse turn. To start you need to click on the black circle :)

UPD
P. S. www.realmofthemadgod.com/ observed the same effect. If you focus on some element of coverage, the move shows that it does not move smoothly. I began to think that the problem in my eyes, but friends, including from their computers, see the same thing.
October 8th 19 at 01:07
5 answers
October 8th 19 at 01:09
Solution
This so-called Screen tearing effect occurs, as wrote above, due to the fact that the monitor refresh rate is not a multiple of the frequency of those renders. When scrolling redraw regions is big, so artifacts are noticeable stronger. For clarity, can be washed down the test, just where each frame alternately to do the shading bitmaps in white, in black color. Because of the features of those software render target render, it cannot be eliminated with CPU-rendering in General. Solve this problem only the 11th player + stage3d.
Thank you very much. Exactly what I needed. Habr — cake! - Baby.Waters commented on October 8th 19 at 01:12
October 8th 19 at 01:11
maybe I shouldn't update so often the screen... select a acceptable fps and work with it.
by the way, checked out your game, I have no brakes (ff11, c2d, intel gma) - Baby.Waters commented on October 8th 19 at 01:14
also checked, no lag, chrome latest stable - Hoyt_Torphy24 commented on October 8th 19 at 01:17
The fact that it is not in fps. I tried to put it in the range from 30 to 200, the difference is almost not visible.
About lags. Under them I understand a small jump 2-3 pixel which happen 2-3 times in 2 seknudy, and then not always. Try to focus on the stone, for example, and drive diagonally. Noticeable is that the character moves not uniformly. Or I pick and such effects — the norm? - Laurianne9 commented on October 8th 19 at 01:20
October 8th 19 at 01:13
Maybe the reason is that you have a debug version of the flash player. I have the usual, no lag there.
I really should have debug version, however, such lags are observed in chrome. And there, as far as I know, the player your. - Baby.Waters commented on October 8th 19 at 01:16
October 8th 19 at 01:15
Are you sure that the timer doesn't round the interval, in multiples of some number of MS? Also, does the flash that the timer will be called only 60 times and intervals?

Also, if the redrawing is synchronized pictures with the flash scan monitor?

Try at the beginning of each frame to the clock and check whether evenly Wyswietla your code. I suspect that uneven. Also, why do you use a timer, not event enter frame? Maybe flash redraws the objects immediately, but when it starts the next frame?

And anyway, it's mandatory each frame to move and redraw all the objects? Especially those that are invisible? Maybe you can make them classical objects snap to the rectangle and only move that rectangle? You are like a flasher?
I will try to answer in order. As I understand it, it is about values which is initialized to a timer?
_timer = new Timer(1000 / FPS); Yes, in this place he rounds, but doing it once during initialization. So it is in no way should affect the display of images on the screen.

About synchronization I can not say anything. Actually, it was one of the causes of this issue.

Variable deltaTime in the second paragraph once again and determines the time of the call timer. Here is a sample trace of its values:
0.034
0.016
0.016
0.028
0.016
0.016
0.018
0.016
0.017
0.015

In fact, before I always used a login event in the frame, but some of vlasovych forums, or even on habré article about game loops, I read that it is much better to use a timer and coordinates to calculate new value using the difference between the two calls as a.

About redrawing. Most likely it is, but if gameLoop not cause the timer and the input event to the frame, the effect persists.

Every update of the game view defines the objects and texture elements that fall within the camera field of view(rectangle 800 by 600) and draws them on a bitmap. Each update is updated the WHOLE game model.
Sorry, but I don't quite understand what in my code renders the objects that are not in the view?

About the rectangle. Before, I did just that. However, with such a method is hard enough, without dancing with a tambourine, to keep large levels of the game. The selected same time, the method allows to manipulate the levels of any size, for this is just need to implement dynamic loading on parts of the massif, responsible for the location of objects in the level. However, even without this, the game quietly keeps levels 250 000 250 000 pixels(of course this depends on available RAM)
About the rectangle. As I understand it, you propose to keep one large rectangle with attached to it all game objects? In this case, large levels can not be considered. In this case, once again the same will be redrawn with all the objects that are added.

In fact, before I always used the default display list, but under the influence of online articles, and tests comparing the performance of the default method in comparison with the bitmaps, I decided to try the bitmaps.

First and foremost I am a student, and secondly Yes, the flasher. At least I'm writing it a year and a half. Mostly for myself, but implemented and commercial projects.
This game I tried to open for myself new horizons of flash, use non-standard methods. And here came across this problem.

P. S. www.realmofthemadgod.com/ observed the same effect. If you focus on some element of coverage, the move shows that it does not move smoothly. I began to think that the problem in my eyes, but friends the same. - Baby.Waters commented on October 8th 19 at 01:18
Although I think to call me a flasher is not entirely correct. Because I only do programming for this platform. More suitable definition 3 AS a programmer. - Hoyt_Torphy24 commented on October 8th 19 at 01:21
Yes, the movement should be tied to deltaTime, since there is no guarantee that for example the processor does not need another program. As for the redraw, if the flash player updates the image with a frame rate just does not make sense to call your timer more often. It's extra work.

As for the use of mappers, I made a mistake, I thought you all objects in the cycle go around. In your case, really, your approach is correct. I apologize for the inaccuracy.

Then by process of elimination the reason is either 1) a mismatch between the refresh rate of your monitor and the refresh rate of the picture flash player (maybe you can experiment with the frame rate of the video? variable FPS?) or 2) the fact that sometimes the OS takes the CPU time flash on time and it does not redraw the frame, and the eye manages to detect. In this case, you can try to make the background less uniform, so it was hard to notice distortion. Or make a movement with acceleration and deceleration, and is not uniform. Also, you can try to run the video on a normal non-debug player on more powerful dual-core machine, with high prairieton process and to see anything change. - Laurianne9 commented on October 8th 19 at 01:24
Actually 60 FPS, this is a test value. 30 takes place about the same. As and 100.
Checked the flash drive on a computer with 4 core processor, a regular player and a high priority. The effect is the same.
On the second point. It looks like www.realmofthemadgod.com/ once again, and used a method with a less uniform background. As an option, I want to try not to tightly tie the camera to the player. - Baby.Waters commented on October 8th 19 at 01:27
Still play with the acceleration/deceleration of the camera, can also help. And what is written below ogra, too, by the way, may be true: I'm somewhere on Habre saw an article that the objects coordinates ochroleuca (and by some cunning system), and if you take the coordinates from the object, increment them and write back, there will be mistakes. Try them dump to test this version. - Baby.Waters commented on October 8th 19 at 01:30
October 8th 19 at 01:17
And this may not be the accumulation of rounding errors?
For example, if the character is at the 1.1 pixel per frame, in one of the 10 shots he will be 2 pixel and 9 out of 10 only 1. That "twitching".
Perhaps, but in a flash the coordinates of the sprites are of type number — number of floating point. How he handles these numbers, when rendering an object I do not know. That's how I have it implemented:
matrix.translate(getLocalX(j * LevelView.CELL_WIDTH), getLocalY(i * LevelView.CELL_HEIGHT));
camera.draw(_level.getCell(i, j), matrix);

About the character. I tried to updateCameraPosition() simply slip each update the camera to 2 pixels down, that is completely without reference to the character and floating point numbers. The effect persists. - Baby.Waters commented on October 8th 19 at 01:20
Oh yeah.
public function getLocalY(y:Number):Number
{
return _camHeight / 2 + y — camY;
}

public function getLocalX(x:Number):Number
{
return _camWidth / 2 + x — camX;
} - Hoyt_Torphy24 commented on October 8th 19 at 01:23

Find more questions by tags Adobe FlashDevelopment of games