• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED Sprites/Textures Seem to Shiver Depending on Camera Position [Help needed]

Trex0n

Member
So I seem to be having some problems with sprite/texture rendering when I zoom the camera, or sometimes when the camera simply moves. I took this video so you can see what I mean. I have ticked the tile horizontally/vertically on the sprites but it hasn't really seemed to help. Any advice on how I can fix this would be much appreciated.

Create Event
GML:
///Resolution Stats
#macro ResolutionScale 1
#macro ResolutionWidth 1024/ResolutionScale
#macro ResolutionHeight 768/ResolutionScale

///Movement
Object = oPlayer;
Smoothness = .1;

///Camera Shake Variables
Shake = 0;
ShakePower = 1;
ShakeRotation = 0;
ShakeSpeed = .1;

///Zoom Variables
ZoomSpeed = .02;

///Create Camera
#region <Create Camera>
//Enable views
view_enabled = true;
view_visible[0] = true;

//Create Camera
CameraID = camera_create_view(0,0,ResolutionWidth,ResolutionHeight);
view_set_camera(0,CameraID);

//Resize Window & Application Surface
window_set_size(ResolutionWidth*ResolutionScale,ResolutionHeight*ResolutionScale);
surface_resize(application_surface,ResolutionWidth*ResolutionScale,ResolutionHeight*ResolutionScale);
display_set_gui_size(ResolutionWidth,ResolutionHeight);

//Center Window
var _DisplayWidth = display_get_width();
var _DisplayHeight = display_get_height();

var _WindowWidth = ResolutionWidth*ResolutionScale;
var _WindowHeight = ResolutionHeight*ResolutionScale;

window_set_position(_DisplayWidth/2 - _WindowWidth/2,_DisplayHeight/2 - _WindowHeight/2);
#endregion
End Step Event
GML:
#region <Calculate Movement>
//Current Camera Position
var _xCurrent = camera_get_view_x(CameraID);
var _yCurrent = camera_get_view_y(CameraID);
var _CamWidth = camera_get_view_width(CameraID);
var _CamHeight = camera_get_view_height(CameraID);

//Set Target Position
var _xTarget = Object.x - _CamWidth/2;
var _yTarget = Object.y - _CamHeight/2;

//Clamp to Room Boundries
_xTarget = clamp(_xTarget,0,room_width - _CamWidth);
_yTarget = clamp(_yTarget,0,room_height - _CamHeight);

//Smooth Movement
_xCurrent = lerp(_xCurrent,_xTarget,Smoothness);
_yCurrent = lerp(_yCurrent,_yTarget,Smoothness);
#endregion

///Zoom
#region <Zoom>
var _ZoomInput = keyboard_check(vk_down) - keyboard_check(vk_up);
_ZoomInput *= ZoomSpeed;

if (_ZoomInput != 0) {
    _CamWidth += _CamWidth*_ZoomInput;
    _CamHeight += _CamHeight*_ZoomInput;
    
    _xCurrent -= (_CamWidth*_ZoomInput)/2;
    _yCurrent -= (_CamHeight*_ZoomInput)/2;
}
#endregion

///Camera Shake
#region <Apply Camera Shake>
var _Shake = power(Shake,2)*ShakePower;

_xCurrent += random_range(-_Shake,_Shake);
_yCurrent += random_range(-_Shake,_Shake);

if (Shake > 0) Shake -= ShakeSpeed;
#endregion

///Apply Camera Transformations
#region <Apply Camera Transformations>
camera_set_view_pos(CameraID,_xCurrent,_yCurrent);
camera_set_view_size(CameraID,_CamWidth,_CamHeight);
camera_set_view_angle(CameraID,random_range(-_Shake,_Shake)*ShakeRotation);
#endregion
Thanks!
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Okay, two things...

1) Ensure that your camera SIZE is set to rounded integers and that those values are also a scaled factor of the display and window.
2) Ensure that the camera position is also set to integer positions

Basically, when you zoom in like this and the camera is set to something like x125.4 and/or y33.8 the GPU has to choose whether the pixels that fall along the .4 axis should be drawn or not, and this can lead to flickering. If the camera size is a correct integer value and the camera movement is always full pixels then this issue won't appear. The downside is that with low resolution games this can make the camera look "jerky" as it moves by full pixels. The workaround for THAT is to keep the camera code you have, but to make the application surface bigger, essentially creating "sub-pixels" that will make all the movement much smoother and remove the flickering (eg: instead of a 480x320 app surface, set it to 860x640). This has it's own issues though, as it'll mean you then get "rotated pixels" in your game... this is something I personally have no issue with and think that it looks fine, but some people hate it!
 

Trex0n

Member
Okay, two things...

1) Ensure that your camera SIZE is set to rounded integers and that those values are also a scaled factor of the display and window.
2) Ensure that the camera position is also set to integer positions

Basically, when you zoom in like this and the camera is set to something like x125.4 and/or y33.8 the GPU has to choose whether the pixels that fall along the .4 axis should be drawn or not, and this can lead to flickering. If the camera size is a correct integer value and the camera movement is always full pixels then this issue won't appear. The downside is that with low resolution games this can make the camera look "jerky" as it moves by full pixels. The workaround for THAT is to keep the camera code you have, but to make the application surface bigger, essentially creating "sub-pixels" that will make all the movement much smoother and remove the flickering (eg: instead of a 480x320 app surface, set it to 860x640). This has it's own issues though, as it'll mean you then get "rotated pixels" in your game... this is something I personally have no issue with and think that it looks fine, but some people hate it!
Thanks for the help! I thought it might be something like this so I appreciate you clearing it up. You mention changing the app. surface to fix this, but how would I be able to do that? I'm very inexperienced working with cameras, views and app. surfaces in GMS, I don't have much clue what I'm doing tbh šŸ˜…
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Simply call surface_resize in the CREATE event of the controller/camera object eg:

surface_resize(application_surface, view_wview[0], view_hview[0]);

The above code will set the surface to be 1:1 with the resolution of the View Port.
 

Trex0n

Member
Simply call surface_resize in the CREATE event of the controller/camera object eg:

surface_resize(application_surface, view_wview[0], view_hview[0]);

The above code will set the surface to be 1:1 with the resolution of the View Port.
Thankyou!
 
Top