• 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!

GML Trying to get smooth and snapped rotation

Paul Green

Member
Hey All,

I've tried a few searches in the forums, found a few things I've tried, but they don't quite work the way I want.

I'm using image_angle and direction and I have an object that can rotate 360 degree's, but I want it to be able to snap it too, 0, 22, 45, 67,90, etc (I know half of 45 is 22.5, but I didn't want to confuse myself even more, as maths is not one of strongest subjects) but, and this is were I can't combine code, I want it to smoothly get to that 'turning too' angle, but if you were to press the opposite key, it would stop the current rotation and go back the other way and then snap again.

At the moment, I'm using the step block to control my simple rotation with

Code:
var turn = keyboard_check(ord("A")) - keyboard_check(ord("D"));
if (turn != 0)
{
direction += turn * 4;
image_angle = direction;
}
Can anybody help me with this issue, the old grey matter isn't as good as it used to be.
 

Rob

Member
You want it to rotate to the nearest "snapped" position and stop and reverse direction if the other key is pressed?
 

Paul Green

Member
Yeah, if that is how it's explained/described, I think it called snapping (if it's called something else and I confused you, I'll apologize now ) so there is only a hand full of angles (12 points around 360) the object can rotate to, but the object doesn't have to wait until it reaches a 'snapped' position before it can turn around. It's a space ship and I'm doing a clone of an old game that operated like that. Back in the day, they didn't have the luxury of smooth scrolling like we do today.
 

Carolusclen

Member
From my understanding of what i read, it sounds like you have a top down image that you want it to rotate in sections of 22.5. So basically the rotation of the ship with have 16 different angels it can face, as a pose to a full smooth 360 angle
 

Carolusclen

Member
there is a little bug in this to do with the angles 365 and 0 being the same thing so you will need to iron this out a little
but i think this is what you are looking for.

so create event
Code:
dir = 0
image_dir = 0
step event
Code:
if(keyboard_check_released(ord("A")))
{
    if(dir = 342.5)
    {
        dir = 0;
    }
    else
    {
        dir += 22.5;
    }
}

if(keyboard_check_released(ord("D")))
{
    if(dir = 0)
    {
        dir = 342.5;
    }
    else
    {
        dir -= 22.5;
    }
}

if(image_dir < dir)
{
    image_dir += 0.5;
}
else
{
    if(image_dir > dir)
    {
        image_dir -= 0.5;
    }
    else
    {
        image_dir = dir;
    }
}
draw event
Code:
draw_sprite_ext(sprite0,-1,x,y,1,1,image_dir,c_white,1)
 

Paul Green

Member
there is a little bug in this to do with the angles 365 and 0 being the same thing so you will need to iron this out a little
but i think this is what you are looking for.
I had something similar myself, even at one point, just using arrays to store the angles I wanted to step through, but the problem is, it's not smooth, i.e. going from 0 to 22.5 smoothly. It snaps, but it's 'jerky' so to speak.
 

Carolusclen

Member
ahh, the code I gave is smooth though. The movement will snap in 22.5 intervals but the image will rotate smooth to each angle.
When i get home and no one else has suggested anything Ill do another example for you :)
 

Paul Green

Member
ahh, the code I gave is smooth though. :)
Yeah, it would appear a typo stopped it being smooth, one of the things I did notice, just putting your code right in there, I press D to go right and it goes left to get to the right position. After that once it gets to the first position, but the wrong way around, pressing A takes it all the way back to the start point.

Thoughts?
 

Rob

Member
Yeah, it would appear a typo stopped it being smooth, one of the things I did notice, just putting your code right in there, I press D to go right and it goes left to get to the right position. After that once it gets to the first position, but the wrong way around, pressing A takes it all the way back to the start point.

Thoughts?
Swap "A" and "D" around!
 

Paul Green

Member
Lol, no, not literally like that, I press a and it rotates to get to the first d position. It doesn't stop at the first 22.5 degrees, it goes right past. If you need an animated gif to show / explain, I'll have to wait until I'm on my pc later
 

Carolusclen

Member
woops my bad.

ok, so a minor tweak, it will work now between 0 and 360 without going back the other way.

Code:
if(keyboard_check_released(ord("A")))
{
    if(dir = 342.5)
    {
        dir = 360;
    }
    else
    {
        dir += 22.5;
    }
}

if(keyboard_check_released(ord("D")))
{
    if(dir = 0)
    {
        image_dir = 360;
        dir = 342.5;
    }
    else
    {
        dir -= 22.5;
    }
}

if(image_dir < dir)
{
    image_dir += 0.5;
}
else
{
    if(image_dir > dir)
    {
        image_dir -= 0.5;
    }
    else
    {
        image_dir = dir;
    }
}

for the image I use, the A and D keys are right, but just change them if its opposite for you :)
if you put this in the draw event too, you can see what it does while it does it.

Code:
draw_text(mouse_x+16,mouse_y,string(dir))
draw_text(mouse_x+16,mouse_y+16,string(image_dir))
 

Sabnock

Member
I have looked at this as well and I come up with a different way.

create code
Code:
image_angle = 0;
rotate_speed = 2;
rotate_step = 0;
target_angle = 0;

Step Event
Code:
var rotate_direction = keyboard_check(vk_left) - keyboard_check(vk_right);

if (rotate_direction != 0) {
 rotate_step = rotate_direction * rotate_speed;
 
 var temp = (image_angle div 22.5) * 22.5;
 
 if (rotate_direction > 0) {
  target_angle = temp + 22.5;
 } else {
  if (image_angle == target_angle) {
   target_angle -= 22.5;
  }
 }
}

image_angle += rotate_step;

if (rotate_step > 0) {
 if (image_angle > target_angle) {
  rotate_step = 0;
  image_angle = target_angle;
 }
}

if (rotate_step < 0) {
 if (image_angle < target_angle) {
  rotate_step = 0;
  image_angle = target_angle;
 }
}
 
Last edited:

Sabnock

Member
Ok so there was a bug in my previous code that meant that if you changed direction quickly the ship would snap to far. the below code fixes this.

Create Event
Code:
image_angle = 0;
rotate_speed = 6; // the code is flexible to allow this to be any speed, 6 seems a good speed but I will depend of FPS I guess.
rotate_step = 0;
target_angle = image_angle; // target speed should always equal image_angle at the start.
Step Event
Code:
var rotate_direction = keyboard_check(vk_left) - keyboard_check(vk_right);

if (rotate_direction != 0) {
 rotate_step = rotate_direction * rotate_speed;
 
 var temp = (image_angle div 22.5) * 22.5;
 
 if (rotate_direction > 0) {
  target_angle = temp + 22.5;
 } else {
  if (image_angle == target_angle) {
   target_angle -= 22.5;
  } else {
  if (image_angle - temp > 1) target_angle = temp; // small buffer for anti-clockwise rotation so that it doesn't get stuck.
  }
 }
}

image_angle += rotate_step;

// test to see if target angle has been achieved.
if (rotate_step > 0) {
 if (image_angle > target_angle) {
  rotate_step = 0;
  image_angle = target_angle;
 }
}

if (rotate_step < 0) {
 if (image_angle < target_angle) {
  rotate_step = 0;
  image_angle = target_angle;
 }
}
 
Last edited:
Top