Trouble Smoothing out Screen Movement

Blitz3D Forums/Blitz3D Programming/Trouble Smoothing out Screen Movement

-Rick-(Posted 2014) [#1]
I'm pretty sure what the problem is, but I'm not sure how to fix it. Basically its a Zoom view of a star system to show the orbiting planets. There are various levels of zoom, but the one I'm most concerned about is the highest - 64x. Once increasing beyond 1x zoom things get progressively blockier in their movement. I know its because I'm magnifying their size and x/y coordinates with a global ZoomFactor variable. Basically each pixel is getting magnified so when each drawn object moves it doesn't move in single pixel amounts but by the magnified pixel amount (at least, that's what I'm guessing).

I'd really like to smooth that out. This is the zoom level in which I plan to display various game elements like combat, exploration animations, and planet scanning animations.

The other thing I should point out is that I have 3 basic objects that can be the focal point of the draw - The Star, one of its planets or a ship. Everything in view is drawn around whatever the focal point is. The player can also scroll around the focal point with the mouse. If I run the game at full speed it doesn't appear as much as an issue, but I've also incorporated controlled time so if the player slows down time then the effect becomes even more pronounced.

I think these chunks present the relevant code :

This is how ZoomX and ZoomY are set when the star or a planet is the focal point.
;Modify our focus position by Mouse Dragging
	If TimerSecs - Mb1Timer > 100 And Mb1Timer <> 0 Then
		DragX = Float(DragX - MouseXSpeed())
		DragY = Float(DragY - MouseYSpeed())
	Else
		MouseXSpeed()
		MouseYSpeed()
	EndIf
	ZoomX = Float(ZoomX + DragX/ZoomFactor)
	ZoomY = Float(ZoomY + DragY/ZoomFactor)


TimerSecs : Global Integer. It is basically Millisecs(). I set this at the beginning of each program pass-through and I use it to keep track of time.

Mb1Timer : Global Integer. Keeps track of how long mouse button 1 has been held down. I use it to determine if the player wants to drag the screen around.

DragX,DragY,ZoomX and ZoomY are all global floats. DragX/Y keep track of MouseXspeed and MouseYspeed. ZoomX/Y is the center where the focal object (star, planet or ship) is.

This is how ZoomX and ZoomY are set if a ship is the focal point
ZoomX = Float(ship\x - (ship\x - ship\thenx) * TimerSync)
ZoomY = Float(ship\y - (ship\y - ship\theny) * TimerSync)


The following is a portion of the drawing code. sx an sy are local integer variables that hold the position of the center of the drawing area.

ZoomFactor is a Global Integer that keeps track of how much the screen gets magnified.

s\x and s\y are the star x and y coordinates and s\name is just the name of the star
;Draw the Star
			StarX = Float(sx - (ZoomX-s\x)*ZoomFactor*10)
			StarY = Float(sy - (ZoomY-s\y)*ZoomFactor*10)
			Oval StarX - 3 * ZoomFactor,StarY - 3 * ZoomFactor, 6 * ZoomFactor,6 * ZoomFactor
			Text StarX + 3 * ZoomFactor,StarY + 3 * ZoomFactor,s\name


I'm guessing that the "*ZoomFactor*10" portion is what is causing the blocky movement. I track the mouse x/y location so can see that I can move the mouse a few pixels before the screen updates with a chunky jump - or if a ship is the focal point the rest of the stuff draws out as if jumping by several pixels at a time.

I tried creating a new global variable called ZoomXLast and ZoomYLast and then set those values equal to their corresponding ZoomX/ZoomY values at set points of time. Then between between those updates try and draw the screen from where stuff last was to where it is now in % chunks as time passes. The formula looked something like this :

StarX = Float((sx - (ZoomX - ((ZoomX - ZoomXLast) * Interval)) -s\x)*ZoomFactor*10)


Where Interval is a % of time passed between the last ZoomXLast update and the next one to occur.

However, that failed dramatically and just created a double vision image of stuff on the screen. I do use a timersync for ship movement and that did stop the ship jittering around. It now stays firmly planted in the middle of the screen as stuff moves around it (unless you modify its focal point by dragging the screen with the mouse)

Sorry this got long, and I hope I explained things sufficiently enough that someone might have a suggestion for what I can do to solve this. I can show more of the code in its entirety if that is required. I just tried to show snippets of what I thought was relevant.


AngelOnFira(Posted 2014) [#2]
Ok right off the bat, this was my first thought. As you zoom in on something, everything gets pixelated, obviously. That said, imagine a movie. While you watch it, everything flows well. However if you go frame by frame, you can see how each character moves, from picture to picture. Now if you were to zoom in on a 100x100 grid you would be able to see a lot better that each picture is changing.

What I am trying to say is when you zoom in on a sphere with a texture, that texture is going to become more and more pixelated. Also, you are going to be able to see the movement be a lot more jumpy.

So what I would suggest for this would be first off making a timer that puts text on the screen each frame to see how long each frame is. Then see if it changes when you zoom in; if so its the computers processing power that is the issue. If not, you may need to change the movement onto a smaller scale; I you are zoomed in and telling it to move at an amount that is too big for the viewport, that will affect it.

I hope this helps... or I may have a completely wrong idea about your predicament.


-Rick-(Posted 2014) [#3]
You have the right idea, its what I had thought the problem was. I was just wondering what other solutions to this might be out there that I hadn't considered. The solution I came up with works, but still has room from improvement. Although the ship now moves smoothly from one pixel to the next in the blown up view, there is still a fraction of a pause between pixel points that is noticeable when time is running in normal mode (setting time to pass faster speeds things up and the hitch isn't noticeable)

The solve I used was by creating a lastx and lasty field in the ship type. The ship's x/y position is updated each game 'day' so I stored x and y in lastx and lasty. Between each 'day' update I calculated what % of time has passed between the current day and the next day. Then used that % to move the ship between its last location and its present location by that % while displaying in the zoomed mode.

Picture that once I zoom the view pixels I now have 10 pixels between each original pixels. I started out with this where 'o' is when the ship is drawn and '.' is the space jumped.

o.........o.........o.........o.........o.........o.........

After adding in my attempt at smoothing I now have this (but that '.' isn't so much as a jump in space as a very tiny pause only noticeable when the timeflow of the game is slowed.

ooooooooo.ooooooooo.ooooooooo.ooooooooo.ooooooooo.ooooooooo.

I can settle with those results. Perhaps later on when I'm optimizing everything I can revist that and see if I can't reach smooth movement at any speed :

oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

Here is the function I use to monitor Game Time


This is how I apply it to my zoomed in ship
ShipX = Float(sx - (ZoomX-(ship\x-(ship\x-ship\thenx)*TimerSync))*ZoomFactor*10)
ShipY = Float(sy - (ZoomY-(ship\y-(ship\y-ship\theny)*TimerSync))*ZoomFactor*10)


ZoomX and ZoomY have to do with moving around with MouseXSpeed and MouseYSpeed and ZoomFactor is the magnification value (1x,2x,4x,8x,16x and 32x). I'll most likely reduce the number of zoom values there are at a later time. The important one is 32x and the others are just to allow ease in finding nearby planets/ships.

So for the most part this is solved, but if there are other solution methods they would interest me.