Utilizing 3D Cameras in 2D Games

Jan. 31, 2020
protect

There’s an amazing little trick, or rather, feature in GameMaker Studio 2, that you maybe didn’t know about! Let’s take a look at it in this blog.

I was working on the town area for one of my side-projects and was struggling with how to build it. I didn’t want to create a generic, 2D tiled area, with just one layer to fill the background; I wanted it to be a little more complex and three-dimensional, while still being a 2D game...

And you know what GameMaker Studio 2 has? 3D cameras, and depth-based layers.

 

Cameras

 

Let’s learn how this magic can be incorporated into any game!

Side-Note:

  • You can download the project here, and have it open on the side, as you read this blog.

  • There is also a video version of this tutorial (but make sure to also read this post as it covers more than the video):

 

 

THE THIRD DIMENSION

If you’ve used the Room Editor, you’ll know that each layer has a “depth” value. So, a layer with a lower depth would be drawn above a layer that has a higher depth.

 

Cameras
Three visible layers with depths 0, 100 and 200

 

What’s interesting about this, is that the depth value actually corresponds to the “z” value in 3D space! So the third dimension, z, would be the distance of a layer from the camera.

This means that we only need to set up our 3D camera properly, and the rest will be handled by the layer system!

3D CAMERAS

Using a 3D camera in GML mainly consists of setting up a projection matrix and a view matrix.

  • The view matrix defines where the camera is, and where it’s looking.

  • The projection matrix defines how the world is rendered; for example, whether the view is orthographic or perspective, what the field of view is, etc.

VIEW MATRIX

The view matrix can be set up using the function “matrix_build_lookat”:


var _viewMat = matrix_build_lookat(cam_x, cam_y, cam_z, look_x, look_y, look_z, 0, 1, 0);

The function name itself explains how it works: it lets you “look at” a point in 3D space, from another point.

The arguments “cam_x, cam_y, cam_z” represent the 3D position of the camera. Then, the arguments “look_x, look_y, look_z” represent the 3D point where the camera is looking.

And finally, the last three arguments “0, 1, 0” (in order: x, y, z) represent the “UP” vector of the camera. It’s basically the camera asking you: “which direction is up?”

Although we are setting up a 3D world, we still want it to retain the old 2D view, where x represents left-to-right movement and y represents up-to-down movement. So to set the UP vector on the y axis, we set the UP vector to “0, 1, 0” (again: x, y, z).

PROJECTION MATRIX

Our projection matrix will be set up using the function “matrix_build_projection_perspective_fov”:


var _projMat = matrix_build_projection_perspective_fov(70, 16/9, 3, 30000);

For the projection matrix, these are the arguments, in order: FOV, Aspect Ratio, ZNear, ZFar

So we pass in the field of view of the camera, and the aspect ratio that it needs to maintain. And then we pass in the ZNear and ZFar values. Anything drawn outside of this z range, whether it’s too close to the camera, or too far away, will not be rendered.

IMPLEMENTATION

Before starting the implementation, make sure you have these things ready inside your room:

  1. Layers, with proper depth order. Additionally, you can use the padlock button next to the layer depth, to set a custom depth value.

  2. camera view following an object, which can easily be set up in the Room Properties.

    a. If your camera view is set up through code, make sure that it is set up before you run the code below.

This is what I’ll be working with:

 

Cameras
A simple 2D game -- without anything “3D”

 

For managing the 3D camera, we’re gonna use a separate “oCamera” object. Alternatively, you can also do this in a game controller/manager object, if you already have one.

Now let’s set up some variables, in the Create event:


// Camera
camera  = view_camera[0];

// 3D camera properties
camDist = -300;
camFov  = 90;
camAsp  = camera_get_view_width(camera) / camera_get_view_height(camera);

First, we get the camera ID, and store it in camera.

Then we set up some 3D camera properties:

  • camDist: z value where the camera is positioned

  • camFov: Field of view

JikGuard.com, a high-tech security service provider focusing on game protection and anti-cheat, is committed to helping game companies solve the problem of cheats and hacks, and providing deeply integrated encryption protection solutions for games.

Read More>>