Dev Log Entry 13: Dynamically allocated camera size (and other lies)

This is a dev log about creating a game called Newtius in GameMaker Studio 2 (Indie edition). Starting with entry one might make this easier to follow.

In entry 12 I just posted some code for controls via the step event and implemented it in to Newtius.

In this post I’m going to explain a minor setback, speculate on a cause and go into a side thing I’ve started in the form of a Udemy course.

As always, the official Newtius project page on itch.io is up, featuring the last playable version. Which may or may not have sound since it’s HTML5 (the fix to this turns out is clicking the game in the browser – then the sound works).


A different version of a camera system

I’ve moved on to the next section of the Udemy course. Which, on an unrelated note, is actually pretty good. I can’t decide if they’re better than most or all YouTube video playlists. But this one at least is pretty good.

I’m on section 4, part 18 of the course: full screen advanced.

There’s something about the course instructor saying “I have trouble conceptually myself” at the start of a 19 minute video that makes me wonder if I want to start what I think I’m starting.

The first three videos of section 4 just briefly covered cameras, rooms and viewports conceptually then did one minor coding thing involving switching between full screen.

It’s pretty basic actually, it just involves a “controller object” in my main room which simply sets a “fullscreen” variable to an initial Boolean value of true in the create event than in the “escape key pressed” event is the line fullscreen = !(fullscreen); followed by the line window_set_fullscreen(fullscreen);. In other words: whatever the state of the full screen status is now, set it to to opposite of that.

This is about to be replaced in a minute anyway after this 19 minute video so it may not really matter.

I guess I re-re-re-learned the terminology also:

  • display – the literal resolution of the players physical screen resolution
  • view port – the size of the actual “room” as defined in GMS2
  • view – what the camera sees
  • camera – the part of the view port the player can see, usually centered on the player character

(later)

This turned out to be a much rougher 19 minutes than I was expecting. And I also ran into a minor set back.

It’s rough because – I assume due to my non-standard monitor resolution – the camera setup doesn’t actually work.

At first I thought perhaps I had put something in incorrectly but after trying the instructor’s version of the project I got the same results. What the instructor is trying to do is create a viewable area that scales to whatever resolution it happens to be displayed on. The problem is my horizontal is 5120 pixels, far wider than any reasonable game of this complexity should ever expect to encounter.

I actually managed to find a work around for the issue – which I’ll get to in a moment – I just thought it was kind of interesting and made me at least understand the code a little better or at least enough to find some kind of work around.

It also made it quite clear I need to go on to a side project to have some fun-with-cameras. Luckily, as mentioned in a prior post, I now have a “skunkworks” git repository I can use for such diversions.

It’s also become clear – assuming I want to utilize a camera/viewport/etc into Newtius – that I really need to dissect how these work down to its barest of bare bones. Or deep dive. Whichever metaphor you prefer. I’m sure I’ve lamented over whether to bother with a custom camera for Newtius, but I think I’ve decided I will. Just for practice of future games if nothing else.

So I think I’ll finish the current section of the Udemy course and then start doing some experimenting.

Oh, the minor setback I was referring to was my taking the instructors GMS project – that’s what I thought it was – and trying to put it in the root folder of my own version of the Udemy course project. Little did I know this would nuke both my own GMS project and the git repository along with it. It’s not that big of a deal. Not because I know how to revert changes with git since I don’t. But just because I can always re-clone the most recent version of the project from GitHub and then if I have to copy/paste the code back in to bring it up to speed. The only thing I really lost were some collections of comments I put in to the project as I went along. And some custom formatting. Other than that may as well just use the instructors known good working code anyway.

To pay off above, the issue was the code from the course created a window with this extra black space. Moving the ship into that area produced something of a strange overlapping sort of effect. Like the graphics weren’t deleting/re-writing to screen as they were meant to. I know I had the right code and I know it worked since I watched the guy write it and run it. And also downloaded his version.

The work around I mentioned was actually to use specific numbers instead of the calculated values. There’s a specific number for an “ideal height” he sets to 768 and then a calculation and and number-over-number for an “aspect ratio” variable. I think the problem is that 768 is limiting what the value of “aspect ratio” could be. So I set the aspect ratio variable to 1920 / 1080 instead of the variables. And it works after that. Still exactly what the instructor has but no more black void part of the window.

(Even more later)

I ended up continuing further along in the Udemy course rather than doing the planned dissection of cameras and viewports. I found it really interesting and followed almost all of it. But I need to pause the Udemy course and do a deeper dive into what I’m actually learning before continuing. I mean for real this time.

I brought up the YoYo Games document on the game camera system as well as my version of the “Space Mods” project, the Udemy course project I’ve been working on and the cameras and viewports skunkworks project I apparently already started a while ago.

So I’m going go through, line by line if necessary, and figure this camera system out. Or at least practice for about two hours then stop on at a very unsatisfying point as is normal for me.

There are a lot of different terms many of which are used interchangeably and used in different contexts seemingly as different terms. Or it could be the terminology has changed over versions of GMS and I’m reading a document from 2018. It’s hard to tell when YoYo doesn’t bother dating all their guides and documents.

The YoYo document has this image as a visualization of cameras and camera views.

A visualization aid borrowed from the yoyo document: https://www.yoyogames.com/en/tutorials/cameras-and-views

This seems like the best possible way of explaining at cameras and camera views if nothing else.

It doesn’t explain viewports but I’m sure I’ll get to that.

Actually, since I seem to be having such an issue with the vocabulary here, why don’t I just paste in the paragraph from that document:

The most obvious analogy to understand what is going on is to use that of an actual video camera. You have a scene that you want to film (the GameMaker Studio 2 room where your game happens), you have a camera to film it with (the GameMaker Studio 2 camera obviously), you have a lens that captures what you see (the GameMaker Studio 2 view) and you have a screen that displays what you see (the GameMaker Studio 2 view port).

YoYo’s “Cameras and views” document (linked below)

That simple paragraph actually helps a lot more than it should at this stage.

There’s two ways of setting up cameras and view ports in GMS2: the more visual way that involves clicking checkboxes the in the room properties and the more detailed way by writing it out in GML.

The first chunk of the article talks about setting up a camera and viewport in the properties of a room in GMS2. This might be everything I need but I’d rather understand the coding half of it.

Basically you enable viewports/cameras with a checkbox and then mark a “visible” checkbox. Which makes some height/width properties editable. Appears quite easy to set the camera from there to follow a specific object.

There’s still more things to worry about from here though. For instance GMS uses the dimensions of the initial room for the rest of the rooms of the game. And some adjustments still have to be made for proper scaling.

If I go down to the GML section of the article though – with the header “creating cameras” – there’s a little bit more going on.

Looking at my Fun with cameras and viewports project, the camera system I have now actually works pretty well. The code is from the Space Mods YouTube playlist (by FriendlyCosmonaut). I think I’m going to start over though and just go through the GML part of this article pretty much line by line. Not by deleting code though, God forbid. Instead I’ll comment out the code in the existing obj_camera object and re-add code from the article.

The view and camera setup seems to be basically the same in every example I’ve looked at it. Maybe in different events (“create” as opposed to “room start” for instance).

First they start with enabling a view and setting that view visibility to true.

Then there’s setting the x and port 0 to 0.

Then setting the width and height of the viewport.

//This is my camera object, in the "create" event
// enable a view and make said view visible
// these global settings/variables can be overwritten, something to keep in mind
view_enabled = true;
view_visible[0] = true;

// set the x and port to 0
view_xport[0] = 0;
view_yport[0] = 0;

// set the width and height of the port
// quite arbitrary values
view_wport[0] = 960;
view_hport[0] = 540;

With those values set, the camera is created using those variables. I’ll include my comments just for completeness.

//camera object, also in the "create" event
// create the camera using above variables
// cameras are "dynamic resources" - must be destroyed when done using to avoid memory leaks
// this only /prepares/ the camera, it's not showing anything yet.
// so multiple cameras could be setup at once then utilized/turned on at different points
// the viewcamera[0] variable now holds the idea of that camera create view function
// so it will know what to show
view_camera[0] = camera_create_view(0, 0, view_wport[0], view_hport[0], 0, obj_player, -1, -1, 400, 250);

// side note: above code changed from the prior version when running the game (in room start event) in at least two ways:
// player object is no longer "squished" like it's a scaling error
// there's a horizontal and vertical scroll, which prior code didn't have
// the room and the camera top/bottom were the same edges in other words
// left/right scrolling appears the same

I ran this to compare it to the code I was using from FriendlyCosmonaut and it’s actually a little better in that my placer holder player object sprite wasn’t squished any longer. It still needs some work though.

This where things amble off in a different direction than I had in mind for Newtius: first, it takes the physical dimensions of the physical display and sets that to a couple of variables. Then, it does some math against those values so the “camera view” is looking at a relative small area around the player object.

Below that it sets a window size as expressed by a rectangle and then everyone’s favorite because it makes so much sense…surface resize/application surface. That’s the thing I speculated was some kind of abstraction layer from a win32 API. Although I could be wrong about that.

Here’s the code. Also in the create event.

//camera object, also in the "create" event
var _dwidth = display_get_width();
var _dheight = display_get_height();
var _xpos = (_dwidth / 2) - 480;
var _ypos = (_dheight / 2) - 270;
window_set_rectangle(_xpos, _ypos, 960, 540);

surface_resize(application_surface, 960, 540);

This has those upper/lower scrollable edges that I didn’t really have in mind for Newtius. So I’m going to step here and see if I can modify it to only scroll left/right and have nothing scrollable up/down.

It only took a few minutes but I found a version of what I wanted. And then I figured it out a second time and realized it was even less of a modification than I thought.

all I did was change the camera create view line:

// still in camera/create event
view_camera[0] = camera_create_view(0, 0, view_wport[0], view_hport[0], 0, obj_player, -1, -1, 400, 0);

It’s that last bit at the end. The 400, 0. The 0 is the “y border” so I set it to the default of zero. Every place else the width and height are pretty consistently 960×540 except in that one place. So the “viewable” area is 400 pixels across and the “height” is the default amount of height, which is 540 in this case.

The documentation the camera_create_view covers this pretty well:

y_border: The minimum vertical space between the edge of the view area and the instance it is set to follow (before the view begins moving and if it is set to follow an instance, default is 0).

GML Language reference manual

So the sprite of the player object now appears as its intended shape (a square) and there is no vertical camera scrolling.

Since cameras are a resource that have to be “destroyed” when done, I’ll go ahead and mention the Clean Up event in the camera object:

/// @description Clean Up Cameras
// camera object, "clean up" event
camera_destroy(view_camera[0]);

Dynamic Aspect Ratio scaling?

What the Udemy course instructor tried to do is calculate scaling based on the aspect ratio of the screen and a few assumptions.

I’m actually not going to dissect it that much. He uses a lot of variables for the various values of the display, camera and port width and height then uses a static number anyway to come up with a window_set_rectangle line acceptable to most any resolution. But it doesn’t work for me. Like I said before, I have a weird horizontal and that makes for an unexpected aspect ratio.

I think what you’d have to do really is actually calculate the aspect ratio from scratch based on the display resolution then based on the calculated aspect ratio take a best guess at what would be best for both a windowed and full screen scaled version of the game.

Or just a set a bunch of global constants listing every conceivable resolution and aspect ratio and use a big switch/case statement to find which it is. That won’t necessarily be “future proof”. So maybe once at a max resolution just default to that. I won’t have to worry about this for a really long time. And I think for Newtius I’ll just use some static numbers and not worry quite yet about full screen.

My next step is to take what I’ve learned from my skunk works project and pretty much copy/paste the code over. There shouldn’t be any problems with that.

(One attempt later)

Well that went about as well as I expected. Which isn’t well. I created a camera object, I dropped in it in the game room and the camera doesn’t work even slightly. And now I can’t even get it (Newtius) back to where it was before I started messing it with it. I have no idea how I broke it, why identical code isn’t working the same from project to another or why trying to set it back to the way it was previously doesn’t seem to help. So I’ll have to save that for the next adventure.

Hopefully.


Reference links:


The latest version/progress of Newtius can always be found at my GitHub repo:
https://github.com/tildesarecool/newtius

One thought on “Dev Log Entry 13: Dynamically allocated camera size (and other lies)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s