• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

stuck with camera rotation help! [Solved]

R

Reggies

Guest
Im trying to make camera to rotate relatively to the object. kind of like a 3rd person where camera follows your character and rotates when your character rotate. except my game is topdown 2D.


camera_set_view_angle(view_camera[0], point_direction(x, y, mouse_x, mouse_y);

doesnt seem to work well
 

samspade

Member
Im trying to make camera to rotate relatively to the object. kind of like a 3rd person where camera follows your character and rotates when your character rotate. except my game is topdown 2D.


camera_set_view_angle(view_camera[0], point_direction(x, y, mouse_x, mouse_y);

doesnt seem to work well
So you can use camera_set_view_angle, but if you are going to do that, you have to use all of the other GM function for the camera as well (if I remember correctly). I've done it before but it was awhile ago and I don't remember the code (top down space fighter game where the camera always rotated with the ship so that the ship appeared to 'point' straight up which I think is what you're going for). However, the built in GM functions for cameras, while great because they are relatively simple to use, have some limitations. The biggest one, for me, being that they don't let the camera move out of the room. You can see my original post with this question here. It never got an answer, and I didn't include any code, but I did include the basic process for how i did it with the built in functions.

However, I did later figure out how to do it using the camera matrix functions. Basic code for setting up your own camera looks like this:

Code:
//create event
CAMERA = camera_create();
var view_mat = matrix_build_lookat(xx, yy, -10, xx, yy, 0, 0, 1, 0);
var proj_mat = matrix_build_projection_ortho(camera_width, camera_height, 1, 10000);
camera_set_view_mat(CAMERA, view_mat);
camera_set_proj_mat(CAMERA, proj_mat);


//view variables
view_camera[0] = CAMERA;

//step event
var view_mat = matrix_build_lookat(xx, yy, -10, xx, yy, 0, 0, 1, 0);
camera_set_view_mat(CAMERA, view_mat);
Both Shaun Spalding and Gloomy Toad Studios have some good camera tutorials.

However, if you set up a camera like this, you then have to rotate it yourself. Depending upon what you want, this is actually really easy to do. But understanding it can be a little hard to explain. I'll try, but in case I do a bad job, here was the post that originally explained it well enough for me to understand:

https://forum.yoyogames.com/index.p...pdating-the-view-correctly.43952/#post-271079

So, the above code, creates your own camera, creates the thing the camera sees, the matrix, and how the camera sees it, the projection (ortho means traditional 2D, look it up in the manual for some examples). The primary thing with creating your own camera like this is you are essentially telling it how to draw what it sees every frame - that's what the code in the step event does. Tells the camera where and how to position itself each frame. This gives you a lot of control but also requires a little more knowledge.

I'm sorry in advance for how complicated this will seem without pictures. I promise that if I could draw pictures it would actually be super easy and intuitive to visualize. The best thing I can suggest is to either draw graphs in your head or on actual paper to see what I'm saying - and watching Shaun Spalding's tutorial might be good for background purposes as well.

The first fundamental piece is to understand what a vector is. There are tons of YouTube videos on this, but essentially a vector is a direction and a magnitude. Or in other words a line segment that points in a certain direction. You can visualize a vector by drawing in on a graph starting at 0, 0. For example, a 2D vector of 2, 2, would be a line going from 0, 0 to 2, 2 on a graph. This is generally how vectors are represented in programming (in regular math they are often represented as an angle and a magnitude, e.g. - 45 degrees with a magnitude of 2.82). The shortest way to explain it is a vector is an arrow that points somewhere (and has a length). If a 2D vector is normally represented as coordinantes on a 2D graph. a 3D vector uses three (x, y, and z). Camera matrices use a 3D vector even for 2D view, so they take 3 coordinates, x, y, and z.

This is important because, the function matrix_build_lookat asks for 3 vectors: a "from", "to" and "up" vector.
It will put the camera at the "from" vector.
It will turn the camera so that the "to" vector is shown in the middle of the screen of the camera.
The distance between from and to don't matter, only the direction between them (at least with an ortho projection).

So, in the above code, the from vector is being calculated each step as xx, yy, -10, where xx and yy are whatever you want, for example the x and y locations of your character. -10 is the z, or 'up' direction. This is actually important even in a 2D game. Shaun Spaldings tutorial has a good visualization for it, but essentially image one 2D plane which is your game world. Your camera needs to look at this world thus it must be 'above' or 'below' it. So you are putting your camera directly above your player but 'above' him. The important thing to keep in mind here is that the from and to vector, the arrow, is not the arrow between from and to, but the the location of each point as drawn from 0, 0, 0. The camera's direction is then the 'arrow' formed by looking from those two points.

To visualize this, draw a graph with three axis (x, y, and z) and then draw one arrow from 0, 0, 0, to 5, 5, 5, the from point, and another arrow from 0, 0, 0, to 5, 5, 0, the to point, and then a third arrow from 5, 5, 5, to 5, 5, 0. This third arrow is the direction your camera is facing. The location of your camera (from) to the location of your target (to).

Finally, to answer you actual question, you have the up vector. The camera rotates around the center of its screen based on the up vector. This is what you want to control if you want to control your own rotation. For 2D ortho you always want your z variable to be 0 (unless you're doing something weird), so I'm going to ignore it for now. If you draw 0, 1 on a x, y chart, you will see an arrow point straight up. This is the 'default' view. What I mean by that is this is what we generally think of when we think of 'up' in top down 2D game. Now, changed the up vector to 1, 0 you would see the game world rotate 90 degrees. You can visualize this by drawing 1, 0 on an x, y graph. 1, 1, would tilt it 45 degrees, again, exactly what you would expect to see if you drew a 1, 1, arrow on a graph. This is all true for negative numbers as well.

So, if you want to rotate the camera, you manipulate the up vector. And while a vector has both angle and magnitude, here we only care about the angle - e.g. it doesn't matter how long the vector is, just what way it points (though it is important to remember that a 1, 1, vector does not have the same angle as a 1, 10 vector).

So, if you wanted the camera angle to be based off of the player direction, you have half of what you want - the direction. But again, because of the way we program vectors (off of coordinates) you have to find a vector that matches that direction. So if your player always faced at a 45 degree angle you could just hard code an up matrix of 1, 1, 0 because you know that that will be 45 degrees. Here I admit that I would have to go look at what I did before (and I'm not next to my computer with GM on it today) to be certain, but if I remember right that isn't necessary, because you can easily calculate it with point_direction(0, 0, hsp, vsp); And in our matrix example, 0, 0, for the purpose of the 'up' vector is the camera's to location so we don't need it, which means that you can code your up vector in a matrix as hsp, vsp, 0. Or in full:

Code:
//assuming this code was in the player object which would actually be bad form, but just as an example

///step event

var view_mat = matrix_build_lookat(x, y, -1,           x, y, 0,           hsp, vsp, 0);
camera_set_view_mat(CAMERA, view_mat);
If you want to visualize that, pick some numbers for x, y, hsp, and vsp, and draw a 3D graph and draw a point at the from coordinates, a point at the the to coordinates, an arrow between them, and then pretend that the 'to' point is 0, 0, and draw and arrow using that point as 0, 0, 0, to hsp, vsp, 0. Then image holding a camera at the from point, so it points to the to point rotated so that up, for the camera, is in the direction of the up vector.

Again, it's been awhile since I've done this, and I don't have my code in front of me, so I might be forgetting something or slightly misstating something, but the basic ideas are correct. You might just have to experiment a little to see how it works.

Sorry, that was a long explanation, but I actually just started working on a camera asset that can do stuff like this and explaining it helps me as well.
 
Last edited:
R

Reggies

Guest
So you can use camera_set_view_angle, but if you are going to do that, you have to use all of the other GM function for the camera as well (if I remember correctly). I've done it before but it was awhile ago and I don't remember the code (top down space fighter game where the camera always rotated with the ship so that the ship appeared to 'point' straight up which I think is what you're going for). However, the built in GM functions for cameras, while great because they are relatively simple to use, have some limitations. The biggest one, for me, being that they don't let the camera move out of the room. You can see my original post with this question here. It never got an answer, and I didn't include any code, but I did include the basic process for how i did it with the built in functions.

However, I did later figure out how to do it using the camera matrix functions. Basic code for setting up your own camera looks like this:

Code:
//create event
CAMERA = camera_create();
var view_mat = matrix_build_lookat(xx, yy, -10, xx, yy, 0, 0, 1, 0);
var proj_mat = matrix_build_projection_ortho(camera_width, camera_height, 1, 10000);
camera_set_view_mat(CAMERA, view_mat);
camera_set_proj_mat(CAMERA, proj_mat);


//view variables
view_camera[0] = CAMERA;

//step event
var view_mat = matrix_build_lookat(xx, yy, -10, xx, yy, 0, 0, 1, 0);
camera_set_view_mat(CAMERA, view_mat);
Both Shaun Spalding and Gloomy Toad Studios have some good camera tutorials.

However, if you set up a camera like this, you then have to rotate it yourself. Depending upon what you want, this is actually really easy to do. But understanding it can be a little hard to explain. I'll try, but in case I do a bad job, here was the post that originally explained it well enough for me to understand:

https://forum.yoyogames.com/index.p...pdating-the-view-correctly.43952/#post-271079

So, the above code, creates your own camera, creates the thing the camera sees, the matrix, and how the camera sees it, the projection (ortho means traditional 2D, look it up in the manual for some examples). The primary thing with creating your own camera like this is you are essentially telling it how to draw what it sees every frame - that's what the code in the step event does. Tells the camera where and how to position itself each frame. This gives you a lot of control but also requires a little more knowledge.

I'm sorry in advance for how complicated this will seem without pictures. I promise that if I could draw pictures it would actually be super easy and intuitive to visualize. The best thing I can suggest is to either draw graphs in your head or on actual paper to see what I'm saying - and watching Shaun Spalding's tutorial might be good for background purposes as well.

The first fundamental piece is to understand what a vector is. There are tons of YouTube videos on this, but essentially a vector is a direction and a magnitude. Or in other words a line segment that points in a certain direction. You can visualize a vector by drawing in on a graph starting at 0, 0. For example, a 2D vector of 2, 2, would be a line going from 0, 0 to 2, 2 on a graph. This is generally how vectors are represented in programming (in regular math they are often represented as an angle and a magnitude, e.g. - 45 degrees with a magnitude of 2.82). The shortest way to explain it is a vector is an arrow that points somewhere (and has a length). If a 2D vector is normally represented as coordinantes on a 2D graph. a 3D vector uses three (x, y, and z). Camera matrices use a 3D vector even for 2D view, so they take 3 coordinates, x, y, and z.

This is important because, the function matrix_build_lookat asks for 3 vectors: a "from", "to" and "up" vector.
It will put the camera at the "from" vector.
It will turn the camera so that the "to" vector is shown in the middle of the screen of the camera.
The distance between from and to don't matter, only the direction between them (at least with an ortho projection).

So, in the above code, the from vector is being calculated each step as xx, yy, -10, where xx and yy are whatever you want, for example the x and y locations of your character. -10 is the z, or 'up' direction. This is actually important even in a 2D game. Shaun Spaldings tutorial has a good visualization for it, but essentially image one 2D plane which is your game world. Your camera needs to look at this world thus it must be 'above' or 'below' it. So you are putting your camera directly above your player but 'above' him. The important thing to keep in mind here is that the from and to vector, the arrow, is not the arrow between from and to, but the the location of each point as drawn from 0, 0, 0. The camera's direction is then the 'arrow' formed by looking from those two points.

To visualize this, draw a graph with three axis (x, y, and z) and then draw one arrow from 0, 0, 0, to 5, 5, 5, the from point, and another arrow from 0, 0, 0, to 5, 5, 0, the to point, and then a third arrow from 5, 5, 5, to 5, 5, 0. This third arrow is the direction your camera is facing. The location of your camera (from) to the location of your target (to).

Finally, to answer you actual question, you have the up vector. The camera rotates around the center of its screen based on the up vector. This is what you want to control if you want to control your own rotation. For 2D ortho you always want your z variable to be 0 (unless you're doing something weird), so I'm going to ignore it for now. If you draw 0, 1 on a x, y chart, you will see an arrow point straight up. This is the 'default' view. What I mean by that is this is what we generally think of when we think of 'up' in top down 2D game. Now, changed the up vector to 1, 0 you would see the game world rotate 90 degrees. You can visualize this by drawing 1, 0 on an x, y graph. 1, 1, would tilt it 45 degrees, again, exactly what you would expect to see if you drew a 1, 1, arrow on a graph. This is all true for negative numbers as well.

So, if you want to rotate the camera, you manipulate the up vector. And while a vector has both angle and magnitude, here we only care about the angle - e.g. it doesn't matter how long the vector is, just what way it points (though it is important to remember that a 1, 1, vector does not have the same angle as a 1, 10 vector).

So, if you wanted the camera angle to be based off of the player direction, you have half of what you want - the direction. But again, because of the way we program vectors (off of coordinates) you have to find a vector that matches that direction. So if your player always faced at a 45 degree angle you could just hard code an up matrix of 1, 1, 0 because you know that that will be 45 degrees. Here I admit that I would have to go look at what I did before (and I'm not next to my computer with GM on it today) to be certain, but if I remember right that isn't necessary, because you can easily calculate it with point_direction(0, 0, hsp, vsp); And in our matrix example, 0, 0, for the purpose of the 'up' vector is the camera's to location so we don't need it, which means that you can code your up vector in a matrix as hsp, vsp, 0. Or in full:

Code:
//assuming this code was in the player object which would actually be bad form, but just as an example

///step event

var view_mat = matrix_build_lookat(x, y, -1,           x, y, 0,           hsp, vsp, 0);
camera_set_view_mat(CAMERA, view_mat);
If you want to visualize that, pick some numbers for x, y, hsp, and vsp, and draw a 3D graph and draw a point at the from coordinates, a point at the the to coordinates, an arrow between them, and then pretend that the 'to' point is 0, 0, and draw and arrow using that point as 0, 0, 0, to hsp, vsp, 0. Then image holding a camera at the from point, so it points to the to point rotated so that up, for the camera, is in the direction of the up vector.

Again, it's been awhile since I've done this, and I don't have my code in front of me, so I might be forgetting something or slightly misstating something, but the basic ideas are correct. You might just have to experiment a little to see how it works.

Sorry, that was a long explanation, but I actually just started working on a camera asset that can do stuff like this and explaining it helps me as well.
Thanks for taking time to explain about camera, vector and matrix, now I know what to focus on learning. I didn't know that there is much more to learn about if I am to do this kind of camera.
 

samspade

Member
It's probably less complicated than it sounds like with just text. Really, it would be a lot easier to convey with drawings. Mostly, it is learning vectors. If you get a solid grasp of what vectors are and how they are used in computer programming the rest of the stuff just sort of makes sense. You might also be able to figure it out with a little trial and error.

Shaun Spaldings tutorial will get you the basics of using a camera in GM without the GM functions. And at this point all you really need to do is manipulate the up vector - the final three numbers in the matrix look at function. And the final number will always be 0. So essentially, once you can set up and run a camera using the matrix version, you just need to learn how to set two numbers to achieve the result you want. That's a lot easier if you understand vectors, but even if you don't, just think about it like drawing arrows on a graph.

As a side note, I see in your original example you were using direction towards the mouse. I honestly don't know what this would do as direction towards the mouse might be changing as the view is changing. The only time I've messed with camera rotation I wasn't using a mouse. So I don't know if rotating the camera changes mouse x and y. If it does, setting the camera based on mouse x and y will yield some strange results because once you've moved the camera you've moved the mouse, meaning you have to move the camera again, meaning you've moved the mouse, etc. forever.

Otherwise, I looked up my old code doing it with the built in functions and it looks like this is what I was using to make the camera always point in the same direction as my ship (e.g. making it so my ship was always headed up on the screen):

Code:
camera_set_view_angle(view_camera[0], -image_angle + 90);
Substitute image angle with the angle of you're choosing. I honestly don't remember why it had to be negative or plus 90. But I believe I ultimately arrived at both of these numbers through trial and error.
 
R

Reggies

Guest
It's probably less complicated than it sounds like with just text. Really, it would be a lot easier to convey with drawings. Mostly, it is learning vectors. If you get a solid grasp of what vectors are and how they are used in computer programming the rest of the stuff just sort of makes sense. You might also be able to figure it out with a little trial and error.

Shaun Spaldings tutorial will get you the basics of using a camera in GM without the GM functions. And at this point all you really need to do is manipulate the up vector - the final three numbers in the matrix look at function. And the final number will always be 0. So essentially, once you can set up and run a camera using the matrix version, you just need to learn how to set two numbers to achieve the result you want. That's a lot easier if you understand vectors, but even if you don't, just think about it like drawing arrows on a graph.

As a side note, I see in your original example you were using direction towards the mouse. I honestly don't know what this would do as direction towards the mouse might be changing as the view is changing. The only time I've messed with camera rotation I wasn't using a mouse. So I don't know if rotating the camera changes mouse x and y. If it does, setting the camera based on mouse x and y will yield some strange results because once you've moved the camera you've moved the mouse, meaning you have to move the camera again, meaning you've moved the mouse, etc. forever.

Otherwise, I looked up my old code doing it with the built in functions and it looks like this is what I was using to make the camera always point in the same direction as my ship (e.g. making it so my ship was always headed up on the screen):

Code:
camera_set_view_angle(view_camera[0], -image_angle + 90);
Substitute image angle with the angle of you're choosing. I honestly don't remember why it had to be negative or plus 90. But I believe I ultimately arrived at both of these numbers through trial and error.

Yes, It did go on forever like you said. Thanks for teaching me about the matrix. Now I'm trying to find a way how to not make it go forever.
 
Top