Windows Make the player's rotation anchored on a single point?

Hey all-Let me start off by saying I am SUPER new to GameMaker and coding in general. I'm using Drag n' Drop for my first project as I'm sure it's a lot easier to learn.

Some background: The game is set in space, playing as a ship. There is no gravity. I am very early on to the project.

Outside of combat, the player can move around freely with Asteroid-esque controls. However, when I hold my mouse down, a cursor appears at the first point I held it at and the player's motion is halted. This is how the combat in the game will work - shooting causes the player to stop and (hopefully) enter a state of controlled orbit around the cursor. *Note, the cursor object stays in the first position the mouse was held down until the button is released. Using WASD controls, A and D would be used to guide yourself around this invisible circle centered around the cursor. The player could of course choose to not rotate at all, but they will not be able to dodge attacks or move forward/backward until the LMB is lifted.

So far, I've got basic movement outside of combat down and I've gotten the player to halt and lose the ability of accelerating in this state. What I do not have is the means to provide the relative rotation about the cursor object.

I've found a free asset on the store that focuses on relative rotation, but it's not working quite how I'd like it to... or at all, for that matter.

If anyone can offer any help on this, it'd be greatly appreciated! If you need further elaboration or any other details or resources, I'll be happy to give it.

Thank you!
 

Sabnock

Member
First off, welcome to to the family. IMO Drag & Drop is ok but if you want to progress you'll want to start doing the GML tutorials. I know "Coding" seems daunting but you will thank yourself in the long run.

The thing you are trying to achieve is actually not that difficult to do in GML. How's your maths? look at the point_distance(), point_direction(), Lengthdir_x() and lengthdir_y() functions as well as the mouse_x & mouse_y built in variables if your maths doesn't include any trig.

You mention "STATE" are you familiar with state machines?

See how you get on and if you get stuck then shout and we'll help out.
 
Last edited:

TheouAegis

Member
Code:
if mouse_check_button(mb_left) {
var dir = point_direction(mouse_x,mouse_y,x,y);
var dist = point_distance(mouse_x,mouse_y,x,y);
dir += keyboard_check(ord("D")) - keyboard_check(ord("A"));
dist += keyboard_check(ord("S")) - keyboard_check(ord("W"));
x = lengthdir_x(dist, dir) + mouse_x;
y = lengthdir_y(dist, dir) + mouse_y;
}
I brainstormed that just now while in bed. Not sure if it will work. I could make it DnD, but not while I'm just on my phone. If you really wanted it in DnD, search the list of DnD actions for similar functions; every variable with "var" before it is temporary.
 
Last edited:
Code:
if mouse_check_button(mb_left) {
var dir = point_direction(mouse_x,mouse_y,x,y);
var dist = point_distance(mouse_x,mouse_y);
dir += keyboard_check(ord("D")) - keyboard_check(ord("A"));
dist += keyboard_check(ord("S")) - keyboard_check(ord("W"));
x = lengthdir_x(dist, dir) + mouse_x;
y = lengthdir_y(dist, dir) + mouse_y;
}
I brainstormed that just now while in bed. Not sure if it will work. I could make it DnD, but not while I'm just on my phone. If you really wanted it in DnD, search the list of DnD actions for similar functions; every variable with "var" before it is temporary.
Code:
if mouse_check_button(mb_left)
    {
    var dir = point_direction(obj_ui_cursor.x, obj_ui_cursor.y, x, y);
    var dist = point_distance(obj_ui_cursor.x, obj_ui_cursor.y, x, y);
    image_angle = point_direction(obj_ui_cursor.x, obj_ui_cursor.y, x, y) - 180;
    if keyboard_check(ord("D")){
    dir += 2.7
    }
    if keyboard_check(ord("A")){
    dir -= 2.7
    }
    if keyboard_check(ord("S")){
    dist += 1.2
    }
    if keyboard_check(ord("W")){
    dist -= 1.2
    }
    x = lengthdir_x(dist, dir) + obj_ui_cursor.x;
    y = lengthdir_y(dist, dir) + obj_ui_cursor.y;
    }
Hey! Thanks so much. I made some modifications to your code, specifically dealing with mouse_x/y being changed to the x/y values of the cursor object, which stays in place after the mouse is first clicked, until it is released then clicked again. Only one problem remains, if the mouse is pressed when A/D is being held down, the rotation and x and y values get thrown off. I'm not sure exactly why this is, but I can't seem to find a way to fix it. I learned a ton just from the code you've shown here and adapting it to work in my specific project! However, I was wondering if you might know the cause as to why the x/y are getting thrown off when the mouse is pressed at the same time A/D are being held. Other than that, the code works perfectly! I can't thank you enough. I know my explanation here is probably a bit dodgy so please feel free to ask me to elaborate more if needed. P.S., the controls outside of 'combat' for A and D are simple DnD operations linked to both the A and D buttons, with only two blocks in each. One checks that the mouse is not being held down, the next block is an offshoot of that block that controls the instance rotation.
 

TheouAegis

Member
image_angle = point_direction(obj_ui_cursor.x, obj_ui_cursor.y, x, y) - 180;
Just swap x,y and obj_ui_cursor.x,obj_ui_cursor.y around. You don't need to subtract 180.

What do you mean the rotation is thrown off? Do you just need to swap A and D around (so D subtracts 2.7 instead of adding)?

Are you sure the check for A and the check for D are both inside (or branched off from) the check for the mouse not being held? Which DnD actions are you using?

.....Wait, are you referring to the mouse's coordinates wobbling around? Maybe you want to make a Mouse Button PRESSED event and save the coordinates of obj_ui_cursor inside two instance variables right then. Then instead of checking obj_ui_cursor.x,obj_ui_cursor.y, you'd check those two variables instead.
Code:
//Mouse Button Pressed event//
cursor_x = obj_ui_cursor.x;
cursor_y = obj_ui_cursor.y;
Code:
if mouse_check_button(mb_left)
    {
    var dir = point_direction(cursor_x, cursor_y, x, y);
    var dist = point_distance(cursor_x, cursor_y, x, y);
    image_angle = point_direction(x, y, cursor_x, cursor_y);
    if keyboard_check(ord("D")){
    dir += 2.7
    }
    if keyboard_check(ord("A")){
    dir -= 2.7
    }
    if keyboard_check(ord("S")){
    dist += 1.2
    }
    if keyboard_check(ord("W")){
    dist -= 1.2
    }
    x = lengthdir_x(dist, dir) + cursor_x;
    y = lengthdir_y(dist, dir) + cursor_y;
    }
 
Just swap x,y and obj_ui_cursor.x,obj_ui_cursor.y around. You don't need to subtract 180.

What do you mean the rotation is thrown off? Do you just need to swap A and D around (so D subtracts 2.7 instead of adding)?

Are you sure the check for A and the check for D are both inside (or branched off from) the check for the mouse not being held? Which DnD actions are you using?

.....Wait, are you referring to the mouse's coordinates wobbling around? Maybe you want to make a Mouse Button PRESSED event and save the coordinates of obj_ui_cursor inside two instance variables right then. Then instead of checking obj_ui_cursor.x,obj_ui_cursor.y, you'd check those two variables instead.
Code:
//Mouse Button Pressed event//
cursor_x = obj_ui_cursor.x;
cursor_y = obj_ui_cursor.y;
Code:
if mouse_check_button(mb_left)
    {
    var dir = point_direction(cursor_x, cursor_y, x, y);
    var dist = point_distance(cursor_x, cursor_y, x, y);
    image_angle = point_direction(x, y, cursor_x, cursor_y);
    if keyboard_check(ord("D")){
    dir += 2.7
    }
    if keyboard_check(ord("A")){
    dir -= 2.7
    }
    if keyboard_check(ord("S")){
    dist += 1.2
    }
    if keyboard_check(ord("W")){
    dist -= 1.2
    }
    x = lengthdir_x(dist, dir) + cursor_x;
    y = lengthdir_y(dist, dir) + cursor_y;
    }
Thanks for the correction on the - 180 line!
So, what I mean by being thrown off is that they behave correctly both inside and outside of combat, A and D do what they're intended to. However, if the player enters combat by holding the mouse down while also holding A and D, the player's coordinates get thrown off. For example, the player could be to the left of the cursor, but if they're holding A or D at the time they click the mouse, they'll be teleported to somewhere on the right side of the cursor instantaneously.

For the DnD lines for the A and D key, they're:
If mouse down (mb left) (not) -> Set instance rotation -/+5 (relative)

Thanks!
 

TheouAegis

Member
So if you click the mouse while NOT holding A or D, and THEN press A or D only after you clicked the mouse, the code works fine?

And you are setting cursor_x and cursor_y in the Mouse Button Left PRESSED event, not the normal Mouse Button Left event?

Dammit, I might have to test this in a dummy project, but I still can't see what would be causing this.

Code:
if mouse_check_button(mb_left) {
    var dir = point_direction(cursor_x, cursor_y, x, y);
    var dist = point_distance(cursor_x, cursor_y, x, y);
    image_angle = point_direction(x, y, cursor_x, cursor_y);
    if keyboard_check(ord("D"))
        dir += 2.7
    if keyboard_check(ord("A"))
        dir -= 2.7
    if keyboard_check(ord("S"))
        dist += 1.2
    if keyboard_check(ord("W"))
        dist -= 1.2
    x = lengthdir_x(dist, dir) + cursor_x;
    y = lengthdir_y(dist, dir) + cursor_y;
}
(just cleaned up the code so I could make sure the brackets were in the right place
 
So if you click the mouse while NOT holding A or D, and THEN press A or D only after you clicked the mouse, the code works fine?

And you are setting cursor_x and cursor_y in the Mouse Button Left PRESSED event, not the normal Mouse Button Left event?

Dammit, I might have to test this in a dummy project, but I still can't see what would be causing this.

Code:
if mouse_check_button(mb_left) {
    var dir = point_direction(cursor_x, cursor_y, x, y);
    var dist = point_distance(cursor_x, cursor_y, x, y);
    image_angle = point_direction(x, y, cursor_x, cursor_y);
    if keyboard_check(ord("D"))
        dir += 2.7
    if keyboard_check(ord("A"))
        dir -= 2.7
    if keyboard_check(ord("S"))
        dist += 1.2
    if keyboard_check(ord("W"))
        dist -= 1.2
    x = lengthdir_x(dist, dir) + cursor_x;
    y = lengthdir_y(dist, dir) + cursor_y;
}
(just cleaned up the code so I could make sure the brackets were in the right place
Yes, that is exactly the case! I can try to record what's happening and link it here, if it would help.

*edit, here is said link
 
Last edited:

TheouAegis

Member
Find the option to generate a "Live Preview" of the Step event. Copy the contents of that and paste it here. Mayne other DnD actions are conflicting. The Live Preview will make it clear if that's the case.
 
GML:
// GameMaker Language Preview (Read-Only)

// Execute Code
if mouse_check_button(mb_left)
    {
    var dir = point_direction(obj_ui_cursor.x, obj_ui_cursor.y, x, y);
    var dist = point_distance(obj_ui_cursor.x, obj_ui_cursor.y, x, y);
    image_angle = point_direction(obj_ui_cursor.x, obj_ui_cursor.y, x, y) - 180;
    if keyboard_check(ord("D")){
    dir += 2.7
    }
    if keyboard_check(ord("A")){
    dir -= 2.7
    }
    if keyboard_check(ord("S")){
    dist += 1.2
    }
    if keyboard_check(ord("W")){
    dist -= 1.2
    }
    x = lengthdir_x(dist, dir) + obj_ui_cursor.x;
    y = lengthdir_y(dist, dir) + obj_ui_cursor.y;
    }

// If Key Pressed
var l65CD3D18_0;
l65CD3D18_0 = keyboard_check_pressed(ord("W"));
if (!l65CD3D18_0)
{
    // Execute Code
    speed *= 0.95;
        if speed < 0 speed = 0
}

// If Mouse Down
var l6601D116_0;
l6601D116_0 = mouse_check_button(mb_left);
if (l6601D116_0)
{
    // Function Call
    motion_set(speed, 0);
}
Step Function for the main Ship object

Code:
// GameMaker Language Preview (Read-Only)

// If Mouse Down
var l093BBF02_0;
l093BBF02_0 = mouse_check_button(mb_left);
if (!l093BBF02_0)
{
    // Set Instance Rotation
    image_angle += 5;
}
Code:
// GameMaker Language Preview (Read-Only)

// If Mouse Down
var l7BE3CDEA_0;
l7BE3CDEA_0 = mouse_check_button(mb_left);
if (!l7BE3CDEA_0)
{
    // Set Instance Rotation
    image_angle += -5;
}
A and D Key (Note, in DnD form, the 'If mouse down' is set to 'Not.' I don't believe that is made clear on this live preview.)
 
Top