Game Maker

GMS2: Simple Camera / Surface Set Up

After slaving away doing the same old configurations every time I create a new room in Game Maker Studio 2 I had to come up with a way to optimise my workflow. By creating a set up room with a persistent camera controller object, I’ve been able to eliminate the mundane task of messing with views/ports (and now cameras) every time I create a new room.

The startup room is responsible for setting the window width/height, and from that the camera controller will store the window dimensions and set a game width/height which a surface will be initiated with. This is handy for when I’m working with small graphics and wish to scale up to the window size, as the surface is stretched to fill giving an effect like this:

The sample above is using a 32×32 tileset with a resolution of 768×480. The camera is rendering a surface at only half of those pixels at 384×240 and which is then stretched to fit the window resolution giving the zoomed in effect. Like this I’m quickly able to get up and running with a camera that follows my player and a surface for handling drawing.

Moving the view

So let’s jump into some code:


Create Event

//Grab the window width/height from the viewport in the set-up room
global.window_width = view_get_wport(0);
global.window_height = view_get_hport(0);

//Set up dimensions for camera view and surface (divide by a higher number to zoom in further)
global.game_width = global.window_width / 2;
global.game_height = global.window_height / 2;

//Initialise the camera with nothing
camera = noone;

//Create the surface
surf = surface_create(global.game_width, global.game_height);

//Now go to the main game room: This will skip the first room_start event (in the set-up room)
room = rmDungeonReborn;

Room Start Event

//Turn on the use of views
view_enabled = true;
view_visible[0] = true;

//Create a camera and instruct it to follow the player
camera = camera_create_view(0, 0, global.game_width, global.game_height, 0, objPlayer, -1, -1, global.game_width, global.game_height);

//Set the view to use our new camera
view_set_camera(view_current, camera);

//Instruct the camera to render to the surface
view_set_surface_id(0, surf);

Room End Event

//Destroy any leftover camera
if (camera != noone){

Draw GUI Event

//Draw the surface stretched to the window size
draw_surface_stretched(surf, 0, 0, global.window_width, global.window_height);

//Debug: Draw FPS in top left corner
draw_text(10, 10, fps);

Destroy Event

//Clean up the surface

This is just the bare minimum of what can be accomplished using a persistent camera controller. It can set up each room with consistent functionality that is often required by games that span numerous rooms. If I decide to change my resolution or have the camera zoom in more/less, I don’t have to worry about going through all my views and updating each view to a new setting.

However, more could be done with this and there are a few problems to consider such as recreating a surface should the memory be cleared by a garbage collector – mostly evident on mobile. These are problems I don’t need to face just yet and are easily corrected when the time comes. For now it fits my purpose and maybe I’ll do a follow up after more rigorous use providing it evolves over time.