SOLVED Parallax problem

neutro

Member
Hello.
I'm currently working on a ice level, with parallax layers. The problem is that the "Bg_Mountains" adjusts one pixel to the right whenever player and camera stops moving right. And adjusts one pixel left if player moves left and stops. It doesn't look good in my opinion. Anyone got some thoughts on this problem? Do I have to upscale the whole project to "hide" this(it doesn't go away I know) or is there any other way?


Code in oCamera step event:
GML:
var mountains = layer_get_id("Bg_Mountains");

layer_x(mountains, lerp(0, camera_get_view_x(view_camera[0]), 0.90 )  );
The game is in 320x180 resolution.
Thankful for some suggestions!
 
Last edited:
That works aswell, but the One-pixel snap, left/right is still there. So annoying :(
It could be that your parallax code is running prior to the camera being updated, leading to a one pixel snap. Not 100% sure but this is often the cause of unwanted movement as you describe it.

What you could try that often solves this is moving the parallax code to the End Step event. Again not 100% sure this is the problem in your case, but its worth a shot.
 

TheouAegis

Member
Or Predraw.
Or Begin Draw.
Basically, update all positions before stuff is actually drawn. End Step is typically good enough, but in the off chance it's not, use the Predraw event instead.
 

neutro

Member
It could be that your parallax code is running prior to the camera being updated, leading to a one pixel snap. Not 100% sure but this is often the cause of unwanted movement as you describe it.

What you could try that often solves this is moving the parallax code to the End Step event. Again not 100% sure this is the problem in your case, but its worth a shot.
Or Predraw.
Or Begin Draw.
Basically, update all positions before stuff is actually drawn. End Step is typically good enough, but in the off chance it's not, use the Predraw event instead.
I tried with the code in End Step, Pre-Draw and Begin Draw. I tried with mountain-sprite with different widths. Same result.
If I change the * value, like:
GML:
layer_x(mountains, camera_get_view_x(view_camera[0]) * 0.5);
instead of 0.9, the effect isn't that obvious. But instead, the mountains move to fast for a nice parallax effect. :( I'm beginning to think game maker is way to complicated even for those simplest issues. How can this even be a problem? Never had it with construct, or godot. Seriously having thoughts on switching engine.
 

TheouAegis

Member
I tried with the code in End Step, Pre-Draw and Begin Draw. I tried with mountain-sprite with different widths. Same result.
If I change the * value, like:
GML:
layer_x(mountains, camera_get_view_x(view_camera[0]) * 0.5);
instead of 0.9, the effect isn't that obvious. But instead, the mountains move to fast for a nice parallax effect. :( I'm beginning to think game maker is way to complicated even for those simplest issues. How can this even be a problem? Never had it with construct, or godot. Seriously having thoughts on switching engine.

edit: dang, horrible typos in my first edit
That sounds to me like a rounding issue. Try
Code:
layer_x(mountains, floor(camera_get_view_x(view_camera[0]) * 0.90) ) ;
in the Pre-Draw event.
If that doesn't work, change "floor" to "round", then if it still doesn't work, change "round" to "ceil".
 

sp202

Member
@TheouAegis None of those solutions worked, but what did work was drawing the sprite rather than using a background layer.
GML:
draw_sprite_tiled(sBG_Mountains_IceLevel,0,0.6*camera_get_view_x(view_camera[0]),4)
Not sure what that reveals about the core issue.
 

TheouAegis

Member
@TheouAegis None of those solutions worked, but what did work was drawing the sprite rather than using a background layer.
GML:
draw_sprite_tiled(sBG_Mountains_IceLevel,0,0.6*camera_get_view_x(view_camera[0]),4)
Not sure what that reveals about the core issue.
Views are updated during the Pre-Draw event. So stick the layer scrolling in the Begin Draw event. From what I can tell, the background layer doesn't get drawn until after the Begin Draw event.

No sprite tiling needed.

Verified with room_speed of 1 fps.
 

neutro

Member
edit: dang, horrible typos in my first edit
That sounds to me like a rounding issue. Try
Code:
layer_x(mountains, floor(camera_get_view_x(view_camera[0]) * 0.90) ) ;
in the Pre-Draw event.
If that doesn't work, change "floor" to "round", then if it still doesn't work, change "round" to "ceil".
Same result, with floor, round and ceil. Anything to do with the walkspeed?
Walkspeed is set to 1.
Framerate on Mountains sprite? I've tried different values.
Room settings?
Width: 1280, Height: 184,
Viewport 0 enabled,
Camera Properties: X pos: 0, Y pos: 4,
Viewport Properties, X pos: 0, Y pos: 0, Width: 320, Height: 180,
Object Following: oPlayer,
Horizontal Border: 128, Vertical Border: 32, Horizontal Speed: -1, Vertical Speed: -1
 

neutro

Member
Views are updated during the Pre-Draw event. So stick the layer scrolling in the Begin Draw event. From what I can tell, the background layer doesn't get drawn until after the Begin Draw event.

No sprite tiling needed.

Verified with room_speed of 1 fps.
THAT'S THE TRICK!! :D
Draw Begin Event in oCamera:
GML:
var mountains = layer_get_id("Bg_Mountains");
layer_x(mountains, ceil(camera_get_view_x(view_camera[0]) * 0.90) );
So thankful for your input guys!

EDIT: It also works with floor and round. And also without any of those in the code.
 
Last edited:

TheouAegis

Member
THAT'S THE TRICK!! :D
Draw Begin Event in oCamera:
GML:
var mountains = layer_get_id("Bg_Mountains");
layer_x(mountains, ceil(camera_get_view_x(view_camera[0]) * 0.90) );
So thankful for your input guys!

EDIT: It also works with floor and round. And also without any of those in the code.
Keep the idea of using floor and the back of your mind. If the background appears to ever be too blurry, then you should put floor back in.
 
Top