Skip to content

STANNcam Instance

Brent Frymire edited this page Oct 26, 2024 · 12 revisions

new stanncam([x], [y], [width], [height], [surface_extra_on], [smooth_draw])

This creates a new stanncam camera instance, you can use to follow a player object or other and then display it's contents to the screen.

Returns: Struct.stanncam

Argument Type Description
[x] Float Camera's starting x position
Default: 0
[y] Float Camera's starting y position
Default: 0
[width] Integer Camera's width
Default: global.game_w
[height] Integer Camera's height
Default: global.game_h
[surface_extra_on] Boolean This will enable the camera to draw to an extra surface, allowing it to render itself recursively
Default: false
[smooth_draw] Boolean Whether the camera should move smoothly, or snap to nearest integer. If you want your display to be pixel perfect, set this to false. However, it will be a bit stuttery if the camera moves slowly due to the nature of upscaling pixels.
Default: true

Example:

stanncam_init(320, 240, 1920, 1080);
cam1 = new stanncam(obj_player.x, obj_player.y, global.game_w, global.game_h);
cam1.follow = obj_player;

This makes a new stanncam instance, and sets it to follow the player object.

 

Variables

These are all variables that you can get or set.

Variable Type Getter or Setter Description
x Float Get Camera's x position
Default 0
y Float Get Camera's y position
Default 0
width Integer Get Camera's width
Default global.game_w
height Integer Get Camera's height
Default global.game_h
offset_x Integer Get Camera's horizontal offset
Default 0
offset_y Integer Get Camera's vertical offset
Default 0
follow Id.Instance, Asset.GMObject, noone Get & Set Instance for the camera to follow. Set to noone to stop following.
Default: noone
spd Float Get & Set How fast the camera moves towards the follow instance
Default: 10
spd_threshold Float Get & Set The minimum distance the follow target is away for the speed to be in full effect
Default: 50
room_constrain Boolean Get & Set Whether the camera should be constrained to the room dimensions
Default: false
bounds_w,
bounds_h
Float Get & Set Bounding box the followed object has to to leave in order for the camera to start moving
Default: 20
bounds_dist_w,
bounds_dist_h
Float Get Distance the followed object is from the bounding box edges. This is useful, for example, if you want to make the camera offset to look ahead of the player when moving horizontally
smooth_draw Boolean Get & Set If camera movement should be smooth
zoom_amount Float Get Current zoom amount set by .zoom(zoom_amount, duration) if duration is more than 0 you can see the value gradually increase.
If .smooth_draw is turned off, you should be using .get_zoom_x and .get_zoom_y instead. To maintain pixel-perfection if you use this value to match anything
x_frac,
y_frac
Float Get When smooth_draw is on, the fractional part of the camera's x and y positions are separated. So when the camera's surface is drawn, it can be used to make stuff appear to move smoothly. If you want to draw sprites that move with the camera, and they appear stuttery, adding these values might help
anim_curve Asset.GMAnimCurve Get & Set The animation curve used when the camera moves
anim_curve_zoom Asset.GMAnimCurve Get & Set The animation curve used when the camera zooms in/out
anim_curve_size Asset.GMAnimCurve Get & Set The animation curve used when the camera is resized
anim_curve_offset Asset.GMAnimCurve Get & Set The animation curve used when the camera gets offset
debug_draw Boolean Get & Set Draws a visual indication of the bounding box when enabled
surface Id.Surface Get The surface the camera draws to, if you need to do something fancy you can draw it manually
surface_extra_on Boolean Get & Set Whether the camera should draw to an extra surface, allowing it to draw itself recursively
surface_extra Id.Surface Get If surface_extra_on is true, this surface will copy the contents from surface at the end of every frame onto itself
paused Boolean Get & Set Whether the camera should update

 

Methods

.clone()

Creates an exact clone of the current stanncam camera and returns it.

Returns: stanncam

Example:

// Creates a new camera and sets it to follow player #2
cam2 = cam1.clone();
cam2.follow = obj_player2;

This will make a clone of the first camera, and set it to follow the second player.

 

.move(x, y, [duration])

Moves the camera to a specific location in the room. Doesn't work if it's currently following an instance.

This uses anim_curve for the movement, you can set this to your own animation curve.

Argument Type Description
x Float X coordinate to move the camera to
y Float Y coordinate to move the camera to
[duration] Float Duration (in frames) it takes for the camera to move to its new position
Default: 0

Example:

// Moves the camera to where the player clicks on screen
var _new_x = cam1.get_mouse_x();
var _new_y = cam1.get_mouse_y();
cam1.move(_new_x, _new_y, game_get_speed(gamespeed_fps) * 0.5);

 

.set_size(width, height, [duration])

Sets camera size.

Argument Type Description
width Integer Camera width
height Integer Camera height
[duration] Float The duration (in frames) it takes for the size change to be complete
Default: 0

This uses anim_curve_size for the animation, you can set this to your own animation curve

Example:

// Sets both cameras to be half the games width
cam1.set_size(global.game_w * 0.5, global.game_h);
cam2.set_size(global.game_w * 0.5, global.game_h);

 

.offset(x, y, [duration])

Displaces the camera's position with an offset amount.

Argument Type Description
x Float Horizontal camera offset
y Float Vertical camera offset
[duration] Float The duration it takes for the camera to move to its new position (in frames)
Default: 0

This uses anim_curve_offset for the offsetting, you can set this with your own animation curve.

Example:

In the Step Event:

// Makes the camera look ahead in the direction the player is going
if(cam1.bounds_dist_w != 0){
	if(!lookahead){
		cam1.offset(60 * sign(cam1.bounds_dist_w), 0, game_get_speed(gamespeed_fps) * 0.5);
		lookahead = true;
	}
} else {
	lookahead = false;
}

 

.zoom(zoom, [duration])

Zooms the camera in or out.
zoom 1 is default.
zoom 0.5 is zoomed in.
zoom 2 is zoomed out.

Argument Type Description
zoom Float The new zoom level
[duration] Float The duration it takes for the zoom_amount to be changed (in frames)
Default: 0

Example 1:

// When holding down the "O" key, the camera zooms out to reveal more of the level
if(keyboard_check_pressed(ord("O"))){
	cam1.zoom(2, game_get_speed(gamespeed_fps) * 0.5);
}
if(keyboard_check_released(ord("O"))){
	cam1.zoom(1, game_get_speed(gamespeed_fps) * 0.5);
}

Example 2:

// Zoom in and out using the mouse scroll wheel
var _dir = mouse_wheel_down() - mouse_wheel_up();
if(_dir != 0){
	var _zoom_amount = cam1.zoom_amount;

	_zoom_amount = clamp(_zoom_amount + _dir * 0.05, 0.1, 2);
	
	cam1.zoom(_zoom_amount, 0);
}

 

.get_zoom_x()

.get_zoom_y()

Gets the camera's current .zoom_amount.

The reason it is split in two separate functions is in case you have smooth_draw turned off, then the zoom amount needs to be split in 2 axis to maintain pixel-perfection. If you exclusively have smooth_draw turned on (which it is by default), you can easily grab the .zoom_amount value directly.

 

.shake_screen(magnitude, duration)

Shakes the camera.

Argument Type Description
magnitude Float How far (in pixels) the camera will move when shaking at max duration
duration Integer For how long (in frames) the camera will shake before standing still again

Example:

// When the player gets hurt the camera shakes for 2 seconds
function hurt_player(damage){
	obj_player.health -= damage;
	cam1.shake_screen(10, game_get_speed(gamespeed_fps) * 2);
}

 

.set_speed(spd, threshold)

Sets the speed and threshold variables. You can also set either of the variables manually with no issues.

Argument Type Description
spd Float How fast the camera can move when following an instance
threshold Float The minimum distance the follow target is away for the speed to be in full effect

Example:

// When holding the running button the camera also goes faster
if(keyboard_check_pressed(vk_shift)){
	cam1.set_speed(10, 50);
}
if(keyboard_check_released(vk_shift)){
	cam1.set_speed(1, 10);
}

 

.get_x()

.get_y()

Get the camera's top left corner position.

If you need the middle of the camera use .x or .y.

Returns: Float

 

.get_mouse_x()

.get_mouse_y()

mouse_x and mouse_y do not work using STANNcam so you must use these methods instead to get the mouse position.

Gets the mouse position within the room relative to the camera.

This assumes that the camera view is drawn at the (0, 0) position with no scaling.

So if you've drawn the camera at another position you need to offset this value to match.

Returns: Float

Example:

// Moves the camera to where the player clicks on screen
var _new_x = cam1.get_mouse_x();
var _new_y = cam1.get_mouse_y();
cam1.move(_new_x, _new_y, game_get_speed(gamespeed_fps) * 0.5);

 

.room_to_gui_x(x)

.room_to_gui_y(y)

Returns where the specified position in the room would be on the GUI relative to the camera.

This assumes that the camera view is drawn at the 0, 0 position with no scaling.

So if you've drawn the camera at another position you need to offset this value to match.

Returns: Float

Example:

// Draws pointer over players head on the GUI
var _arrow_x = cam1.room_to_gui_x(obj_player.x);
var _arrow_y = cam1.room_to_gui_y(obj_player.y);
draw_sprite(spr_arrow, 0, _arrow_x, _arrow_y);

 

.room_to_display_x(x)

.room_to_display_y(y)

Returns where the specified position in the room would be on the game window relative to the camera.

This assumes that the camera view is drawn at the 0, 0 position with no scaling.

So if you've drawn the camera at another position you need to offset this value to match.

Returns: Float

 

.out_of_bounds(x, y, [margin])

Returns whether or not the position is outside the stanncam camera's view.

Argument Type Description
x Float x value within room position
y Float y value within room position
[margin] Float The margin of the bounds to check
Default: 0

Returns: Boolean

Example:

// When the player is outside the camera view,
// draw an arrow at the edges of the GUI surface pointing towards the player
if(cam1.out_of_bounds(obj_player.x, obj_player.y, 8)){

	var _x = cam1.room_to_gui_x(obj_player.x);
	var _y = cam1.room_to_gui_y(obj_player.y);
	
	var _gui_scale_x = stanncam_get_gui_scale_x();
	var _gui_scale_y = stanncam_get_gui_scale_y();
	
	_x = clamp(_x, 0, cam1.width  * _gui_scale_x);
	_y = clamp(_y, 0, cam1.height * _gui_scale_y);
	
	var _dir = point_direction(_x, _y, cam1.room_to_gui_x(obj_player.x), cam1.room_to_gui_y(obj_player.y));

	draw_sprite_ext(spr_arrow, 0, _x, _y, 1, 1, _dir, -1, 1);
}

 

.destroy()

This function destroys the associated GameMaker camera, removes it from the manager's cameras, and frees any surfaces for that camera. The STANNcam is marked as "destroyed", but it still exists until it gets cleaned up by Garbage Collection.

Returns: Undefined

 

.is_destroyed()

Returns whether or not the camera is marked as destroyed.

Returns: Boolean

 

Pausing

.set_paused(paused)

Sets the camera paused state.

Argument Type Description
paused Boolean Whether or not to pause the camera

Returns: Undefined

Example:

// Toggles the game paused state and sets the stanncam camera as the same state
if(keyboard_check_pressed(vk_escape)){
	global.game_paused = !global.game_paused;
	cam1.set_paused(global.game_paused);
}

 

.get_paused()

Gets the camera paused state.

Returns: Boolean

Example:

// Draw GUI Event
// Draw text on the screen while the stanncam camera is paused
if(cam1.get_paused()){
	draw_text(global.game_w * 0.5, global.game_h * 0.5, $"Camera {cam1.cam_id} Paused");
}

 

.toggle_paused()

Toggles the camera paused state to the opposite value.

Returns: Undefined

Example:

// Toggles both the game pause state and stanncam camera pause state
if(keyboard_check_pressed(vk_escape)){
	global.game_paused = !global.game_paused;
	cam1.toggle_paused();
}

 

Drawing

.draw(x, y, [scale_x], [scale_y])

Draws the camera contents to the screen, the size will match the camera's width and height.

Argument Type Description
x Float The x position on the game's display to draw the camera's view
y Float The y position on the game's display to draw the camera's view
[scale_x] Float The horizontal scale at which the camera's view will be drawn
Default: 1
[scale_y] Float The vertical scale at which the camera's view will be drawn
Default: 1

Example:

In the your camera object's Post-Draw Event:

cam1.draw(0, 0);

Or

cam1.draw(0, 0);
cam2.draw(global.width * 0.5, 0);

This draws 2 cameras next to each other as a vertical split-screen.

 

.draw_no_compensate(x, y, [scale_x], [scale_y])

Works exactly the same as .draw but doesn't compensate for when the window doesn't match the aspect ratio.

Image example:

GameMaker_TmH45npKFr-small GameMaker_vwhQvzEzLj-small

Example: In the your camera object's Post-Draw Event:

//draws the camera in the top left corner of the window
//regardless of how the window is stretched
cam1.draw_no_compensate(0, 0);

 

.draw_part(x, y, left, top, width, height, [scale_x], [scale_y])

This will draw a cropped version of the camera's view to the display. It works similar to GameMaker's native draw_sprite_part() function.

Argument Type Description
x Integer x position where to draw part of the camera's view on the display
y Integer y position where to draw part of the camera's view on the display
left Integer Left position of the camera view to crop from
top Integer Top position of the camera view to crop from
width Integer Width of the camera view to draw from the left part
height Integer Height of the camera view to draw from the top part
[scale_x] Float Horizontal scale at which to draw the part of the camera's view
Default: 1
[scale_y] Float Vertical scale at which to draw the part of the camera's view
Default: 1

Example:

In the your camera object's Post-Draw Event:

// Draw the camera contents cropped
cam1.draw(0, 0, 1, 1, 10, 10, 200, 200);

 

.draw_special(draw_func, x, y, [surf_width], [surf_height], [scale_x], [scale_y])

With this you can include a callback and draw anything, and still have it scaled and conform to the camera system. This could be useful if you want to draw a fancy background or foreground that conforms to the game.

Argument Type Description
draw_func Function Function that gets called to draw to the surface
x Integer x position on the display to draw the camera's view
y Integer y position on the display to draw the camera's view
[surf_width] Integer Width of the surface
Default: width, width of the camera
[surf_height] Integer Height of the surface
Default: height, height of the camera
[scale_x] Float Horizontal scale to draw the camera's view
Default: 1
[scale_y] Float Vertical scale to draw the camera's view
Default: 1

Example:

In the your camera object's Post-Draw Event:

// Background is scaled up so it appears smooth when being parallaxed
parallax_background = function(){
	var _scale_x = stanncam_get_res_scale_x();
	var _scale_y = stanncam_get_res_scale_y();
	
	// Offset the camera from the middle of the room
	var _offset_x = (-cam_.get_x() - cam_.__x_frac) * _scale_x;
	var _pos_x = cam_.__x_frac - 200;
	var _pos_y = cam_.__y_frac;
	
	draw_sprite_ext_tiled(spr_bg_layer00, 0, _pos_x + (_offset_x * 0.0), _pos_y, 2, 1, _scale_x, _scale_y);
	draw_sprite_ext_tiled(spr_bg_layer01, 0, _pos_x + (_offset_x * 0.5), _pos_y, 2, 1, _scale_x, _scale_y);
	draw_sprite_ext_tiled(spr_bg_layer02, 0, _pos_x + (_offset_x * 1.0), _pos_y, 2, 1, _scale_x, _scale_y);
}

// The parallax drawing is scaled down again
var _scale_x = 1 / stanncam_get_res_scale_x();
var _scale_y = 1 / stanncam_get_res_scale_y();

// Draw a fancy parallax background before the main camera gets drawn
cam1.draw_special(parallax_background, 0, 0, global.res_w, global.res_h, _scale_x, _scale_y);
cam1.draw(0, 0);

 

.draw_surf(surface, x, y, [scale_x], [scale_y], [left], [top], [width], [height], [ratio_compensate])

Draws the supplied surface with the proper size and scaling.

Argument Type Description
surface Id.Surface Surface to draw
x Integer x position on the display to draw the camera's view
y Integer y position on the display to draw the camera's view
[scale_x] Float Horizontal scale the camera's view should be drawn at
Default: 1
[scale_y] Float Vertical scale the camera's view should be drawn at
Default: 1
[left] Integer Left position of the camera view to crop from
[top] Integer Top position of the camera view to crop from
[width] Integer Width of the camera view to draw from the left part
[height] Integer Height of the camera view to draw from the top part
[ratio_compensate] Boolean Whether or not to add an offset amount to the draw position to compensate for different aspect ratios
Default: true

Example:

In the your camera object's Post-Draw Event:

// Draw the camera, and then draw a smiley on top of it in the middle of the game window
var _bg_surf = surface_create(global.game_w, global.game_h);
surface_set_target();
draw_sprite(spr_smiley, 0, global.game_w * 0.5, global.game_h * 0.5);
surface_reset_target();
cam1.draw(0, 0);
cam1.draw_surf(_bg_surf, 0, 0);