Howdy, partners! Welcome to another GameMaker basics tutorial! Today we are going to talk about views which is the camera system in GameMaker. Views, like most things in GameMaker, have some tricky to understand variables and functions. How is view_xview different than view_wview and how are both of those different than view_xport and view_wport!? By the end of this blog, you should have a pretty solid grasp on the basics.
I remember the first time I tried to set up a camera in GameMaker, I was so confused. Looking at the GameMaker documentation was confusing because all of the variables are so similar, and there was way more information than what I was looking for. Today, we are going to focus on a small part of views that should help you learn the rest on your own.
Here are the key variables we are going to be using in this blog.
view_xview / view_yview
These variables always contain the x and y coordinates of the top left corner of your view. As soon as the room starts, these are usually zero and zero. If your view were to move 10 pixels to the right, and 10 pixels down, the coordinates would be 10 and 10 respectively. The important thing to remember is that xview and yview always refer to the current position of your view in the room.
view_wview / view_hview
The similarly named but completely different wview and hview variables refer to the size of the current view. wview is the width, and hview is the height. If these values are changed, the view is scaled along with it. So, for example, if the wview doubles in size, the image on the screen will be scaled to be twice as wide.
First things first. Before we can do anything, we need to enable views in our game.
Create a room and make it any size. My room used in this example is 1024 x 768. Name the room whatever you’d like, and move on over to the views tab. There are a few important things we need to do here.
Click the checkbox to “Enable the use of views." If you don’t do this, you won't be able to control a view at all since it will be disabled. You can ignore the list of views for now - we are only going to be working with a single view. Should you want to enable more than one view, you would do so from here.
Next, click the “Visible when room starts” checkbox. This will set the default view when your game runs to whatever the current view parameters are.
Now we need to set those parameters. The set of variables under “View in room” determine the X and Y position of the view in the room when the game starts, and the width and height in pixels of the view. If you wanted the entire room to be visible you would set the width and height to the width and height of the room itself. For my example, I am using 256 x 192, which is 1/4th of my overall room size.
Finally, we come to "Port on screen." This section determines the size of the game window. Whatever you have set for the "View in room" will be scaled to "Port on screen." I am using double my view size for the port size, which is half of my overall room size.
Check out the screenshot below for all of my view settings for the room.
By the way, if you haven’t put any objects, or a background in your room, you should do that now. Otherwise it will be impossible to tell that we are moving the camera around.
Now our room should be all set up. If you run the game, you should only see a small portion of your room in the game window.
I can only see 1/4th of my entire room!
Only seeing the top left corner of your screen isn’t exactly helpful in most cases, so let’s set this sucker up to move around. We are going to set this up to follow a certain point, which will be the center of the view. Create a new object and name it oGame. This will be our controller object that will handle all kinds of tasks. One of which will be the camera. Add the Create, Step, Begin Step, End Step, and Draw events to the object, and let's put some code on the Create event.
oGame Create
//point the camera is centered on
camTargetX = view_xview + view_wview * 0.5;
camTargetY = view_yview + view_hview * 0.5;
//camera pan
panSpeed = 5;
//camera zoom
zoomSpeed = 50;
//maximum zoom
maxZoomWidth = 512;
maxZoomHeight = 384;
//minimum zoom
minZoomWidth = 256;
minZoomHeight = 192;
The first set of variables camTargetX and camTargetY will store the x and y position of whatever we want the camera to follow. Right now we just want it to follow a point in the center of our screen. The center of our screen is determined by taking the xview and yview, adding the width and height of the view, and dividing it by 50%. This will give us the center of our view and it is where we will keep the view locked.
Next, we have panSpeed and zoom. panSpeed is how many pixels per frame our camera moves when we manually move it. The higher the number the faster it moves. zoomSpeed is the same thing, except for zoom! However in this case, the higher the number the slower the zoom speed. You’ll see why shortly.
Finally, we define our maximum and minimum zoom tolerances. For the maximum zoom I chose to use half of the room size. For minimum, I chose our starting view size. That will do it for our create event, so let's move on to Step and set up our keyboard inputs and start moving the view around.
oGame Step
//pan the view
if(keyboard_check(vk_left)){
camTargetX -= panSpeed;
}else if(keyboard_check(vk_right)){
camTargetX += panSpeed;
}
if(keyboard_check(vk_up)){
camTargetY -= panSpeed;
}else if(keyboard_check(vk_down)){
camTargetY += panSpeed;
}
We are going to start with panning the view (moving it left, right, up, and down). These are very simple if statements that move our camTargetX/camTargetY coordinates based on our panSpeed variable. Now that these are set up, we need to actually make the view follow those coordinates. On to the End Step event!
oGame End Step
//view follows the camtarget
view_xview = camTargetX - view_wview * 0.5;
view_yview = camTargetY - view_hview * 0.5;
//keep view inside the room
//x
if(view_xview <= 0){
view_xview = 0;
}
if(view_xview + view_wview >= room_width){
view_xview = room_width - view_wview;
}
//y
if(view_yview <= 0){
view_yview = 0;
}
if(view_yview + view_hview >= room_height){
view_yview = room_height - view_hview;
}
You’ll notice that our first couple of lines look exactly like what we initialized in the Create event. Putting it in End Step will ensure the camera is always following that center point. However, we need the following code to make sure the camera isn’t able to move outside of our room.
The checks to keep the view inside the room are pretty simple. If you remember, the view_xview and view_yview variables are always referring to the top left corner of the view itself. The first check makes sure that view_xview/yview cannot be less than zero, which ensures the view cannot be less than the left/top coordinates of the room.
The next set of checks do the opposite, and ensures the view cannot leave the right/bottom coordinates of the room. We do this by adding the width of the view to the view_xview/yview coordinates, and seeing if that value is greater than or equal to the size of the room.
Finally, add a bit of code to the Draw event so we can keep track of the center of the view a bit easier.
oGame Draw Event
//center of screen
draw_circle(camTargetX,camTargetY,2,0);
Place the oGame object in the room if you haven’t already. Now if you run your game you should be able to use your arrow keys to move the camera around the room, and it shouldn’t be able to leave the room boundaries.
Here is where stuff gets hard. When zooming in and out, you need to consider the width and height of your view, and figure out how much you need to adjust each value independently to ensure the zoom is smooth, and both values reach the min/max at the same time. We already established the variables we need in the Create event, so go jump right into the Step event.
oGame Step Event
//zoom the view
if(keyboard_check(ord("W"))){
view_wview += maxZoomWidth / zoomSpeed;
view_hview += maxZoomHeight / zoomSpeed;
}
if(keyboard_check(ord("S"))){
view_wview -= minZoomWidth / zoomSpeed;
view_hview -= minZoomHeight / zoomSpeed;
}
//pan the view
Add the above code above the camera pan code we added before. Zoom out as been assigned to the W key, and zoom in to the S key. Here is where our min/max variables come into play.
When zooming out, we increase the width and height of our view by the maximum width and height, divided by the speed at which we want to reach the maximum. If you are following along exactly, that should be divided by 50. Zoom in is the exact opposite. We subtract the width and height by out minimum zoom. Go ahead and run the game. You should be able to zoom in and out infinitely! Not exactly what we want, so let's throw some constraints on that. Open the End Step event.
oGame End Step
//zoom out max
if(view_wview >= maxZoomWidth){
view_wview = maxZoomWidth;
}
if(view_hview >= maxZoomHeight){
view_hview = maxZoomHeight;
}
//zoom in min
if(view_wview <= minZoomWidth){
view_wview = minZoomWidth;
}
if(view_hview <= minZoomHeight){
view_hview = minZoomHeight;
}
//view follows the camtarget
Like we did in the Step event, add this above your code that is already there. This is a set of checks that prevents the width and height of the room from exceeding out min and max values. If everything was set up correctly you should be able to zoom and pan while following a point and keep the camera inside the room!
Sorry if this gives you some motion sickness.
That about wraps it up for this entry. As I stated at the beginning of this blog, this is just the basic info you need to get started on more complex camera and view set ups. Thank you for taking the time to read over this, and I’ll catch you next time. As always, you can reach me on Twitter or visit my website for more gamedev stuff.
Thank you!
Nathan Ranney is the founder of punk house game dev shop, RatCasket. He’s best known for the creation and development of Kerfuffle, an online indie fighting game.