mMcFab
Member
MUHAHA! I WILL TAKE OVER THE FORUM WITH ALL MY GUIDES!
I've seen a lot of questions regarding cameras, so I'm aiming to make this into the definitive guide for using them! Hence, if I've got something wrong or there are better ways of doing something, tell me and I'll update it!
Again, if and when the forum has a category for GMS2 tutorials, I shall request this topic be moved, but for now, here it is.
I AM NO LONGER UPDATING THIS PAGE. FURTHER UPDATES OF THIS GUIDE CAN BE FOUND ON MY WEBSITE
Updated Guide Here: https://maddestudiosgames.com/gms2-meet-the-camera-system/
The website features full syntax highlighting and documentation links too, to make guide-writing much easier.
***NOTE: THIS GUIDE IS FOR THE BETA VERSION OF GAMEMAKER STUDIO 2. AS THE BETA CHANGES/UPDATES, SO MAY THIS GUIDE***
Luckily, I will leave a (dd/mm/yy) formatted date here, so you know when it was last updated: 22/11/16 (Room views are now Viewports under "Viewports and Cameras" - Images will update soon)
I'll also update the guide if there a better methods that I haven't thought of/found out about yet, or if it turns out I'm using some function totally inappropriately.
Okay, getting on with it! I'm using the forum template now! I'll update the other guide soon too, I just want to be ready for when dedicated GMS2 tutorial forums are up!
GM Version: IDE: 2.0.2.44, RUNTIME: 2.0.1.27
Target Platform: ALL
Download: Built Project
Links: N/A
Summary:
This guide aims to give you a basic insight into the new camera system, and using it with views. Since cameras are totally new, I'm going to write this from the PoV of someone very new to views, but also understands basic GML.
The included project, which uses information from all of these guides, looks like this:
Not spectacular, but demostrates camera creation + assigning, view moving, zooming and interpolation.
The example controls for the project are simply "click to focus" and "scroll to zoom"
Relevant Documentation Links:
Tutorial:
So firstly, I'm going to point someting out - you don't actually need a camera to have a view - the room editor still has views which work in very much the same way as before. However, they are now far less flexible - you can no longer change view_[x,y,h,w]view through code anymore - unless you set up a camera to do more advanced tweaking.
If you are strictly no-code, then you will have to use the views with the room editor anyway, as there are no Drag&Drop camera functions currently.
Important things to know about this guide
I recommend that you get @YellowAfterlife's plugin for forum code syntax highlighting. It makes reading code here way easier: https://yellowafterlife.itch.io/syntax-highlighting-for-gamemaker-forum
Here are the things we'll cover in this guide:
From this point on, it's all code!
Creating and deleting a Camera and Assigning cameras to views
Setting a camera to follow an object through code (using the standard object tracking system)
The other way to draw a camera without binding it to a view
Camera scripts - update, begin and end
Simple camera position interpolation
Camera Zooming
Clamping a Camera to the Room Bounds
Other camera functions and what they do
So that's that. That should be enough information to get you going with the new cameras, but if you need something more - some help, another guide with context - let me know, and I'll see what I can do!
I've seen a lot of questions regarding cameras, so I'm aiming to make this into the definitive guide for using them! Hence, if I've got something wrong or there are better ways of doing something, tell me and I'll update it!
Again, if and when the forum has a category for GMS2 tutorials, I shall request this topic be moved, but for now, here it is.
I AM NO LONGER UPDATING THIS PAGE. FURTHER UPDATES OF THIS GUIDE CAN BE FOUND ON MY WEBSITE
Updated Guide Here: https://maddestudiosgames.com/gms2-meet-the-camera-system/
The website features full syntax highlighting and documentation links too, to make guide-writing much easier.
***NOTE: THIS GUIDE IS FOR THE BETA VERSION OF GAMEMAKER STUDIO 2. AS THE BETA CHANGES/UPDATES, SO MAY THIS GUIDE***
Luckily, I will leave a (dd/mm/yy) formatted date here, so you know when it was last updated: 22/11/16 (Room views are now Viewports under "Viewports and Cameras" - Images will update soon)
I'll also update the guide if there a better methods that I haven't thought of/found out about yet, or if it turns out I'm using some function totally inappropriately.
Okay, getting on with it! I'm using the forum template now! I'll update the other guide soon too, I just want to be ready for when dedicated GMS2 tutorial forums are up!
GM Version: IDE: 2.0.2.44, RUNTIME: 2.0.1.27
Target Platform: ALL
Download: Built Project
Links: N/A
Summary:
This guide aims to give you a basic insight into the new camera system, and using it with views. Since cameras are totally new, I'm going to write this from the PoV of someone very new to views, but also understands basic GML.
The included project, which uses information from all of these guides, looks like this:
Not spectacular, but demostrates camera creation + assigning, view moving, zooming and interpolation.
The example controls for the project are simply "click to focus" and "scroll to zoom"
Relevant Documentation Links:
Tutorial:
So firstly, I'm going to point someting out - you don't actually need a camera to have a view - the room editor still has views which work in very much the same way as before. However, they are now far less flexible - you can no longer change view_[x,y,h,w]view through code anymore - unless you set up a camera to do more advanced tweaking.
If you are strictly no-code, then you will have to use the views with the room editor anyway, as there are no Drag&Drop camera functions currently.
Important things to know about this guide
- I will be referring to "GameMaker Studio 2" as "GMS2" throughout the guide, because I am too lazy to keep writing it in full.
- I'll be going through cameras in GML - There are no D&D camera functions - so it helps if you understand code
- If you want to check out a function, or something is confusing you, remember to check the manual!
- If you have any other questions or corrections, please let me know!
I recommend that you get @YellowAfterlife's plugin for forum code syntax highlighting. It makes reading code here way easier: https://yellowafterlife.itch.io/syntax-highlighting-for-gamemaker-forum
Here are the things we'll cover in this guide:
- Setting up a view (to use with cameras)
- Creating and deleting a Camera and Assigning cameras to views
- Setting a camera to follow an object through code (using the standard object tracking system)
- The other way to draw a camera without binding it to a view
- Camera scripts - update, begin and end
- Simple camera position interpolation
- Simple Camera Zooming
- Clamping the camera to the room bounds
- Other camera functions and what they do
Okay, you may want to skip this one, depending on whether or not you already know this stuff. This is literally just going to be enabling a view in a room either through the editor, or through code.
There are two ways you can set up views in your game. One is to use the view tools in the room editor, the second is to set them up with code.
I personally prefer the latter, as it means you do not have to set up views in every single room. You can just run the same code on room start, and it's done. However, the code version will not resize the game window based on viewport, where as the room editor set up will, assuming it is the first room in the game - sometimes referred to as the "boot room". If you need to change window size later for whatever reason, there are "window_*" functions for dealing with this.
For both methods, we'll be setting up view 0 with a view port and size of 640x480, as a throwback to pre-GM:S.
Here's how to set up a view in the room editor
Here's how to set up a view through code
There are two ways you can set up views in your game. One is to use the view tools in the room editor, the second is to set them up with code.
I personally prefer the latter, as it means you do not have to set up views in every single room. You can just run the same code on room start, and it's done. However, the code version will not resize the game window based on viewport, where as the room editor set up will, assuming it is the first room in the game - sometimes referred to as the "boot room". If you need to change window size later for whatever reason, there are "window_*" functions for dealing with this.
For both methods, we'll be setting up view 0 with a view port and size of 640x480, as a throwback to pre-GM:S.
Here's how to set up a view in the room editor
First, open up your room. Conveniently, GMS2 now starts with a room already created, named room0. This is located in the resource tree. You can either double click the room, or drag it into the workspace to open it.
Now, navigate to the "Viewports and Cameras". By default, this is located at the bottom left of the room editor. Click to open the settings up:
Next, you'll need to check "Enable Viewports"
Open up the settings for "Viewport 0", and edit the settings to appear as follows:
Okay, done! Basic view set up.
Note that we've not changed view borders, view speed or "Object Following". Even though the focus here is on cameras, I'm going to quickly explain what they are and what they do:
Now, navigate to the "Viewports and Cameras". By default, this is located at the bottom left of the room editor. Click to open the settings up:
Next, you'll need to check "Enable Viewports"
Open up the settings for "Viewport 0", and edit the settings to appear as follows:
Okay, done! Basic view set up.
Note that we've not changed view borders, view speed or "Object Following". Even though the focus here is on cameras, I'm going to quickly explain what they are and what they do:
The "Object Following" makes the camera follow a chosen object.
The view border is how close the object needs to be to the bounds of the view (in pixels) before the camera follows it.
View speed is how fast the camera will follow the object when it moves past the border. Setting speeds of -1 makes the view move instantly to contain the object.
The view border is how close the object needs to be to the bounds of the view (in pixels) before the camera follows it.
View speed is how fast the camera will follow the object when it moves past the border. Setting speeds of -1 makes the view move instantly to contain the object.
Here's how to set up a view through code
This code is best fitted to go in the "Room Start" event. You could probably put it in room creation code, however you can write the code only once in a persistent instance this way, saving a little time. (Although, using the new room parenting system, creating default views in the editor is now easier then before)
Instead of writing a whole paragraph here, I'm just going to show you the commented code:
Setting these bounds here will not automatically resize the game window to fit - even in a boot room. The boot room must be (or have an enabled view of) the size you wish your game window to be to do this automatically.
You can still manualy resize the window to fit, using the "window_set" functions. However, calling "window_set_size()" and "window_center()" in the same event doesn't work, as the window only resizes AFTER the current event.
If you wish to resize the game window and center it all at once, add this quick snippet:
This will resize the window to the view port of view 0, and resize the "application_surface" to this size too.
We haven't actually set a view size, location, target object, border or speed through code - this is because we have to do it with cameras. This is explained in the next part.
Instead of writing a whole paragraph here, I'm just going to show you the commented code:
Code:
//Enable the use of views
view_enabled = true;
//Make view 0 visible
view_set_visible(0, true);
//Set the port bounds of view 0 to 640x480
view_set_wport(0, 640);
view_set_hport(0, 480);
You can still manualy resize the window to fit, using the "window_set" functions. However, calling "window_set_size()" and "window_center()" in the same event doesn't work, as the window only resizes AFTER the current event.
If you wish to resize the game window and center it all at once, add this quick snippet:
Code:
//Resize and center
window_set_rectangle((display_get_width() - view_wport[0]) * 0.5, (display_get_height() - view_hport[0]) * 0.5, view_wport[0], view_hport[0]);
surface_resize(application_surface,view_wport[0],view_hport[0]);
We haven't actually set a view size, location, target object, border or speed through code - this is because we have to do it with cameras. This is explained in the next part.
From this point on, it's all code!
Creating and deleting a Camera and Assigning cameras to views
If you are used to views, cameras are going to be a little different. Instead of thinking that they are "just there" and usable (like with views), it's useful to understand that they are now more like instances - you have to create a camera, assign information to it, and delete it when you are done with it.
This section also shows you how to set view parameters through code, since they are now managed by cameras.
When creating a camera, there are two functions:
"camera_create()" and "camera_create_view()"
Both functions return a unique camera ID to be used with all other camera related functions.
"camera_create()" creates a camera that is effectively a blank canvas - you need to specify location and size manually before it can be used properly in 2D - I say this because you can use it in 3D without specifying these.
"camera_create_view()" is much better in regards to 2D development as it forces you to specify all the view parameters on creation.
We will be using "camera_create_view()" for the purpose of this guide, as we're working in the context of 2D. If you want to see basic use of "camera_create()" with 3D, check out my guide on "Getting Started with 3D in GMS2".
Here's how to create the camera. Again, 640x480 size, position will be 0, and we'll set the object following parameters to the default:
If you read the above, you'll see that we can also define an "angle" on view creation - this partially replaces view_angle[0..7]. Other view angle functions are "camera_get_view_angle" and "camera_set_view_angle".
So, that covers camera creation. To destroy a camera you are finished using, use:
Alright, so that's creating and destroying cameras covered.
Now we need to look at binding a camera to a view. This is done rather simply with this little bit of code:
From here on, when wanting to update a view, we should now reference a bound camera instance with "view_camera[view_index]" (in this case, "view_camera[0]". This is simply because we want to guarantee that the camera we are updating is the camera assigned to the view, which may not always be the instance that was returned by "camera_create"
**I have observed cameras working when using "view_camera[X] = camera". While this works, I still feel that it is probably safer and more reliable to use "view_set_camera()"**
We don't actually have to bind a camera to a view to use it - I will cover how that works shortly - but binding makes life a lot easier as it grants access to automatic camera "update/begin/end" scripts, which I will also be covering.
You can get the ID of camera a view is using with both "view_camera[0..7]" and "view_get_camera(view)".
This section also shows you how to set view parameters through code, since they are now managed by cameras.
When creating a camera, there are two functions:
"camera_create()" and "camera_create_view()"
Both functions return a unique camera ID to be used with all other camera related functions.
"camera_create()" creates a camera that is effectively a blank canvas - you need to specify location and size manually before it can be used properly in 2D - I say this because you can use it in 3D without specifying these.
"camera_create_view()" is much better in regards to 2D development as it forces you to specify all the view parameters on creation.
We will be using "camera_create_view()" for the purpose of this guide, as we're working in the context of 2D. If you want to see basic use of "camera_create()" with 3D, check out my guide on "Getting Started with 3D in GMS2".
Here's how to create the camera. Again, 640x480 size, position will be 0, and we'll set the object following parameters to the default:
Code:
//Camera creation
//Build a camera at (0,0), with size 640x480, 0 degrees of angle, no target instance, instant-jupming hspeed and vspeed, with a 32 pixel border
camera = camera_create_view(0, 0, 640, 480, 0, -1, -1, -1, 32, 32);
So, that covers camera creation. To destroy a camera you are finished using, use:
Code:
camera_destroy(camera);
Now we need to look at binding a camera to a view. This is done rather simply with this little bit of code:
Code:
//Set view0 to use the camera "camera"
view_set_camera(0, camera);
**I have observed cameras working when using "view_camera[X] = camera". While this works, I still feel that it is probably safer and more reliable to use "view_set_camera()"**
We don't actually have to bind a camera to a view to use it - I will cover how that works shortly - but binding makes life a lot easier as it grants access to automatic camera "update/begin/end" scripts, which I will also be covering.
You can get the ID of camera a view is using with both "view_camera[0..7]" and "view_get_camera(view)".
Setting a camera to follow an object through code (using the standard object tracking system)
If you set up a view through the room editor, you don't even have to worry about this. However, if you want to set up the view to follow an object through code, you have 2 options:
The first is to set up the standard parameters in "camera_create_view()" to follow an object. e.g
{code]
//Build a camera at (0,0), with size 640x480, 0 degrees of angle, targeting instance "objPlayer", instant-jupming hspeed and vspeed, with a 32 pixel border
camera = camera_create_view(0, 0, 640, 480, 0, objPlayer, -1, -1, 32, 32);
[/code]
Your next option is to build each parameter yourself - this also allows changing the fields on the fly e.g. increasing border size, focusing on an enemy object etc.
Setting up to be exactly the same as above looks like this:
And that's it! All you need to do to set up a camera to act like the default views when following an instance.
The first is to set up the standard parameters in "camera_create_view()" to follow an object. e.g
{code]
//Build a camera at (0,0), with size 640x480, 0 degrees of angle, targeting instance "objPlayer", instant-jupming hspeed and vspeed, with a 32 pixel border
camera = camera_create_view(0, 0, 640, 480, 0, objPlayer, -1, -1, 32, 32);
[/code]
Your next option is to build each parameter yourself - this also allows changing the fields on the fly e.g. increasing border size, focusing on an enemy object etc.
Setting up to be exactly the same as above looks like this:
Code:
//Basic set up
camera_set_view_pos(view_camera[0], 0, 0);
camera_set_view_size(view_camera[0], 640, 480);
//Setting up object target information
camera_set_view_target(objPlayer);
camera_set_view_speed(view_camera[0], -1, -1);
camera_set_view_border(view_camera[0], 32, 32);
The other way to draw a camera without binding it to a view
If, for whatever reason, you do not want your camera applied to a view (or want to use it without even creating a view), we have the "camera_apply" function.
The code is just this:
If you want the camera to be applied only to certain views (without binding) you just need to wrap it in a "view_current" test, like so:
After applying, jsut run the draw code as normal.
To reset a camera to default after applying, just call this:
This resets the camera view to the GameMaker default camera - the one it uses when no views are enabled. Note that you can set a default camera with "camera_set_default", though I can't think of (nor have I tested) a reasonable usage case yet.
The one major issue with using "camera_apply" over binding a camera to a view is that it does not automatically call camera "update/begin/end" scripts - which are incredibly useful, for reasons I will explain soon. Though, if you made your scripts to suit the apply method, you could call them separately anway
The code is just this:
Code:
//Apply camera settings for drawing
camera_apply(camera);
Code:
if(view_current == 0)
{
camera_apply(camera);
...
}
...
To reset a camera to default after applying, just call this:
Code:
camera_apply(camera_get_default());
The one major issue with using "camera_apply" over binding a camera to a view is that it does not automatically call camera "update/begin/end" scripts - which are incredibly useful, for reasons I will explain soon. Though, if you made your scripts to suit the apply method, you could call them separately anway
Camera scripts - update, begin and end
Okay, we're finally on to one of may favorite things about the new camera functions - scripts!
There are three types of camera script - "update", "begin" and "end". By looking at the manual, we get this information:
The cameras for all visible and active view ports have their update script called
Then for each individual view:
The begin script for the camera for that view is called
The draw events are executed for that view (includes draw begin and draw end)
The end script for the camera is called
So, what's nice about this? Well, first of all, the scripts are only called for visible cameras assigned to views - this means you can put code in these scripts, and it won't waste time running if the view isn't being drawn - this is good when skipping frames. You also no longer have to have a High-Depth object run setup code in draw begin either.
These scripts only seem to run automatically for cameras that are bound to views, which makes a lot of sense. If your script isn't runnning, check that it is properly bound!
Okay, these functions all work and are used in similar ways - you can tell WHEN they work from the above. In this case, I assign a script to the "begin" function of our camera for view 0.
The script, which is called "update_script", contains the following - a simple, yet very bad screenshake implementation:
We use "view_camera[view_current]" to make sure we can bind this script to any view camera, and it will just work.
So, that's the function. now let's bind it to a view. We just use this code to bind to "camera_begin":
In order to bind to the other camera events, we can just use one of these two:
NOTE: As of writing, there is no way to retrieve which camera is running the current update script from within the script (just use "view_camera[view_current]" or "camera_get_active()" to identify in "begin" and "end" scripts), unless you set it up all the variable connections rigidly. I've submitted a bug report, but I don't really know if it'll be considered a bug (since drawing hasn't actually started)
To clear a script from a camera, just run the functions as normal, but use "-1" for the script argument instead.
Each of these script setting functions has a "getter" equivelant, which returns what script is currently bound to a camera.
Another Note: You cannot perform any drawing within camera scripts. This stuff must still be done in the draw event (or onto surfaces)
That just about covers the camera script feature.
There are three types of camera script - "update", "begin" and "end". By looking at the manual, we get this information:
The cameras for all visible and active view ports have their update script called
Then for each individual view:
The begin script for the camera for that view is called
The draw events are executed for that view (includes draw begin and draw end)
The end script for the camera is called
So, what's nice about this? Well, first of all, the scripts are only called for visible cameras assigned to views - this means you can put code in these scripts, and it won't waste time running if the view isn't being drawn - this is good when skipping frames. You also no longer have to have a High-Depth object run setup code in draw begin either.
These scripts only seem to run automatically for cameras that are bound to views, which makes a lot of sense. If your script isn't runnning, check that it is properly bound!
Okay, these functions all work and are used in similar ways - you can tell WHEN they work from the above. In this case, I assign a script to the "begin" function of our camera for view 0.
The script, which is called "update_script", contains the following - a simple, yet very bad screenshake implementation:
Code:
//Shake the camera assigned to the current view
camera_set_view_pos(view_camera[view_current], random_range(-6,6), random_range(-6,6));
So, that's the function. now let's bind it to a view. We just use this code to bind to "camera_begin":
Code:
//Bind the bad screenshake script "update_script" to the desired cameras "begin"
camera_set_begin_script(view_camera[target_view],update_script);
Code:
camera_set_end_script(view_camera[target_view],update_script);
camera_set_update_script(view_camera[target_view],update_script);
To clear a script from a camera, just run the functions as normal, but use "-1" for the script argument instead.
Each of these script setting functions has a "getter" equivelant, which returns what script is currently bound to a camera.
Another Note: You cannot perform any drawing within camera scripts. This stuff must still be done in the draw event (or onto surfaces)
That just about covers the camera script feature.
Simple camera position interpolation
For this bit, we're just going to make a camera interpolate from its current position, to center wherever the user clicks. This code can be easily adapted e.g. for tracking objects, but this is a nice, easy thing to start off with.
Things we'll assume here - you've already created a 2D camera, and it is assigned to view 0. If you don't know how to do this, check the guides above.
Firts, let's initialize two variables in the create event:
these will be used to store the last position the mouse was clicked at. Because of this, when we first launch the project it will center the camera on the origin, as I have set these values to "0".
The next bit of code lies entirely in the step event (of the same object)
As a summary - this code checks if the left mouse button is pressed. If it is, it updates the "clicked position".
Then, regardless of anything else, the view is interpolated to ceter around the last position the mouse was pressed.
How is this done?
-We retrieve the current (top-left) position and size of the view.
-We half the view size
-We establish the variable "rate", which specifies the rate of interpolation (it makes changin it later easier)
-We determine the new position of the view by lerping the current position to the click position. The halved width and heights of the view are removed from the click position, making the view focus it intothe center
-The new coordinates are set to the view, ending the process
And that's a simple view interpolation demo!
Things we'll assume here - you've already created a 2D camera, and it is assigned to view 0. If you don't know how to do this, check the guides above.
Firts, let's initialize two variables in the create event:
Code:
click_x = 0;
click_y = 0;
The next bit of code lies entirely in the step event (of the same object)
Code:
//Check if the mouse is clicked. If so, update the click position.
if(mouse_check_button_pressed(mb_left))
{
click_x = mouse_x;
click_y = mouse_y;
}
//Get target view position and size. size is halved so the view will focus around its center
var vpos_x = camera_get_view_x(view_camera[0]);
var vpos_y = camera_get_view_y(view_camera[0]);
var vpos_w = camera_get_view_width(view_camera[0]) * 0.5;
var vpos_h = camera_get_view_height(view_camera[0]) * 0.5;
//The interpolation rate
var rate = 0.2;
//Interpolate the view position to the new, relative position.
var new_x = lerp(vpos_x, click_x - vpos_w, rate);
var new_y = lerp(vpos_y, click_y - vpos_h, rate);
//Update the view position
camera_set_view_pos(view_camera[0], new_x, new_y);
Then, regardless of anything else, the view is interpolated to ceter around the last position the mouse was pressed.
How is this done?
-We retrieve the current (top-left) position and size of the view.
-We half the view size
-We establish the variable "rate", which specifies the rate of interpolation (it makes changin it later easier)
-We determine the new position of the view by lerping the current position to the click position. The halved width and heights of the view are removed from the click position, making the view focus it intothe center
-The new coordinates are set to the view, ending the process
And that's a simple view interpolation demo!
Camera Zooming
Camera zooming works similarly to before - you change your view width and height, but maintain port size. The only difference is that now you need a camera and to use some functions.
Things we'll assume here - you've already created a 2D camera, and it is assigned to view 0. If you don't know how to do this, check the guides above.
To get started, lets just define zoom variables in the create event (after a camera has been created:
You'll then need this code in the step event (of the same object)
What does this do? Let's break it down:
-Adjust the zoom level, based on how the mouse is currently scrolling - mouse up zooms in while mouse down zooms out. The zoom level is also clamp to prevent over-zooming
-Get the current size of the view
-Set to interpolation rate - makes it easier to change later
-Figure out what the new sizes should by interpolating the current view size to the original size, multiplied by the zoom level
-Update the view size
And that's how that works.
Remember though, the view size changes from the upper-left corner, not the center. If you want the view to stay centered, you'll need this code:
This uses the difference in view width and height in order to determine how to translate the view to re-center it, and then applies the new position
That wraps everything up for that!
Things we'll assume here - you've already created a 2D camera, and it is assigned to view 0. If you don't know how to do this, check the guides above.
To get started, lets just define zoom variables in the create event (after a camera has been created:
Code:
zoom_level = 1;
//Get the starting view size to be used for interpolation later
default_zoom_width = camera_get_view_width(view_camera[0]);
default_zoom_height = camera_get_view_height(view_camera[0]);
Code:
//Move the zoom level based on mouse scrolling. Clamp the value so stuff doesn't get too silly.
zoom_level = clamp(zoom_level + (((mouse_wheel_down() - mouse_wheel_up())) * 0.1), 0.1, 5);
//Get current size
var view_w = camera_get_view_width(view_camera[0]);
var view_h = camera_get_view_height(view_camera[0]);
//Set the rate of interpolation
var rate = 0.2;
//Get new sizes by interpolating current and target zoomed size
var new_w = lerp(view_w, zoom_level * default_zoom_width, rate);
var new_h = lerp(view_h, zoom_level * default_zoom_height, rate);
//Apply the new size
camera_set_view_size(view_camera[0], new_w, new_h);
-Adjust the zoom level, based on how the mouse is currently scrolling - mouse up zooms in while mouse down zooms out. The zoom level is also clamp to prevent over-zooming
-Get the current size of the view
-Set to interpolation rate - makes it easier to change later
-Figure out what the new sizes should by interpolating the current view size to the original size, multiplied by the zoom level
-Update the view size
And that's how that works.
Remember though, the view size changes from the upper-left corner, not the center. If you want the view to stay centered, you'll need this code:
Code:
//Get the shift necessary to re-align the view.
var shift_x = camera_get_view_x(view_camera[0]) - (new_w - view_w) * 0.5;
var shift_y = camera_get_view_y(view_camera[0]) - (new_h - view_h) * 0.5;
//Update the view position
camera_set_view_pos(view_camera[0],shift_x, shift_y);
That wraps everything up for that!
Clamping a Camera to the Room Bounds
I was asked about this on Twitter, so I thought it might be worth me quickly adding this little snippet of code:
This code basically gets the position of the camera with the ID stored in "Camera_ID" and locks its position between (0,0) and the room bound minus the camera size.
If you've already calculated or have the camera size and position ready, you can use those values instead of the "camera_get_view_*" functions.
Code:
camera_set_view_pos(Camera_ID,
clamp( camera_get_view_x(Camera_ID), 0, room_width - camera_get_view_width(Camera_ID) ),
clamp( camera_get_view_y(Camera_ID), 0, room_height - camera_get_view_height(Camera_ID) ));
If you've already calculated or have the camera size and position ready, you can use those values instead of the "camera_get_view_*" functions.
Other camera functions and what they do
Well, after the rest of the guide, you should know enough about the new system to make some magic happen. Regardless, here's a few other handy functions:
-We can change viewport related stuff with view_set_[x,y,w,h]port() functions
-Views can be told to draw to a surface instead, using view_set_surface_id()
-"camera_get_active()" returns the unique ID of the currently active camera (the one that is being drawn to)
-There are two functions that use matrices - "camera_set_view_mat()" and "camera_set_proj_mat()". These are used primarily to set up 3D projections
-"camera_set_proj_mat()" takes a projection matrix, usually built with one of three matrix functions - "matrix_build_projection_ortho", "matrix_build_projection_perspective" or "matrix_build_projection_perspective_fov"
-"camera_set_view_mat()" takes a view matrix, usually built with "matrix_build_lookat"
-Fun fact - I go over basic usage of these matrix functions in my other guide "Getting Started in 3D with GMS2"
-All of the "setter" functions discussed in the guide come with "getters" too.
It is really worth me also stating that you can draw stuff relative to a camera view with the "camera_get_view_[x/y/width/height]()", though it is probably far better to draw HUD elements using the draw GUI events.
-We can change viewport related stuff with view_set_[x,y,w,h]port() functions
-Views can be told to draw to a surface instead, using view_set_surface_id()
-"camera_get_active()" returns the unique ID of the currently active camera (the one that is being drawn to)
-There are two functions that use matrices - "camera_set_view_mat()" and "camera_set_proj_mat()". These are used primarily to set up 3D projections
-"camera_set_proj_mat()" takes a projection matrix, usually built with one of three matrix functions - "matrix_build_projection_ortho", "matrix_build_projection_perspective" or "matrix_build_projection_perspective_fov"
-"camera_set_view_mat()" takes a view matrix, usually built with "matrix_build_lookat"
-Fun fact - I go over basic usage of these matrix functions in my other guide "Getting Started in 3D with GMS2"
-All of the "setter" functions discussed in the guide come with "getters" too.
It is really worth me also stating that you can draw stuff relative to a camera view with the "camera_get_view_[x/y/width/height]()", though it is probably far better to draw HUD elements using the draw GUI events.
So that's that. That should be enough information to get you going with the new cameras, but if you need something more - some help, another guide with context - let me know, and I'll see what I can do!
Last edited: