Jump to content


Photo

Smooth Rotation that won't glitch up


  • Please log in to reply
27 replies to this topic

#1 kikjezrous

kikjezrous

    Seer of Spaaace

  • GMC Member
  • 637 posts
  • Version:GM8.1

Posted 02 March 2012 - 02:44 AM

This question has been asked a thousand times, so I'm dragging my code out of the heart of Crash! and sticking it here.

This is a function that you can stick in a destination angle, the current angle, a speed cap, and a motion speed, and it will return the new angle.
Use -1 for no cap.
//rot_smooth(dest_angle,angle_value,speed,cap)
var dest_angle, diff;
dest_angle = argument0; angle_value = argument1; diff = dest_angle - angle_value;

//This is where the action is!
if (diff >= 180 && angle_value < 180) { angle_value += 360; }
else if (diff <= -180) { angle_value -= 360; return angle_value; }

//Check the cap
if (argument3 == -1) { angle_value += diff / argument2; }
else {
	if (diff / argument2 < argument3) { angle_value += diff / argument2; }
	else { angle_value += argument3*sign(diff); } }
	
//Spit it out...
return angle_value;;

Now, if you don't want it to have variable speed, and instead have it rotate at a constant speed until it hits the destination, then:
//rot_constant(dest_angle,angle_value,speed)
var dest_angle, diff;
dest_angle = argument0; angle_value = argument1; diff = dest_angle - angle_value;

//This is where the action is!
if (diff >= 180 && angle_value < 180) { angle_value += 360; }
else if (diff <= -180) { angle_value -= 360; }
else { 
	if (angle_value != dest_angle) {
	var diff; diff = dest_angle - angle_value;
	if (abs(diff) < argument2) { angle_value += diff; }
	else { angle_value += argument2*sign(diff); } } }

//Spit it out...
return angle_value;

This will have one small hiccup, but it is hardly noticeable. Take these codes and paste them into a script, and to call them in an object, just use the instructions in the first line of each script.

BTW: When speed = 1, it moves instantly. When it is 100, it will move 1/100 of the distance every frame.

You don't have to refrence me, but I sure wouldn't mind! Posted Image

Edited by Anzkji, 02 March 2012 - 08:51 PM.

  • 5
MXfDv0N.png > braveadventurer@quest-DUTIMS:~$ _ don tseethebr akuhhuh Thread - Mirror - Tumblr

 nIdGebz.png


#2 Cobalt Co.

Cobalt Co.

    Launch All missiles

  • New Member
  • 11 posts
  • Version:GM8

Posted 07 March 2012 - 01:00 AM

Ah yes very good information to be used... any other wise words master? ::lmao::
  • 0

To Destroy ALL.

And make games.


#3 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 07 March 2012 - 09:50 PM

moved to Scripts forum
  • 0

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#4 bjulin

bjulin

    GMC Member

  • GMC Member
  • 6 posts
  • Version:GM8

Posted 14 August 2012 - 02:06 AM

OK, uh... my head is spinning!

At first, thanks for that script (even if it´s an old post)!! But here comes that nooby question...
HOW do I implement it into my game?

My enemies are moving along a path... while they do that, they´re looking into the direction they´re moving.

image_anlge=direction
If they path has stopped, they look into the direction of where my ship is.

if path_position = 1 { image_angle = point_direction(x,y,obj_myplane.x,obj_myplane.y) }
But here´s the problem: they jump, instead of turning around smoothly. So, I wanted to use your script... but I don´t understand what I have to adjust.

it would be easy to say that they should look into the direction of myplane from the beginning, but that just looks a bit cheap and simply not cool...
I hope you guys can help me out!

THX a lot!!

Edited by bjulin, 14 August 2012 - 02:07 AM.

  • 0

#5 kikjezrous

kikjezrous

    Seer of Spaaace

  • GMC Member
  • 637 posts
  • Version:GM8.1

Posted 14 August 2012 - 02:49 PM

In the step event, call

//Set where you want to face
if path_position = 1 { dest_angle = point_direction(x,y,obj_myplane.x,obj_myplane.y) }
else { dest_angle = direction }

//This actually is what changes the angle
image_angle = rot_smooth(dest_angle,image_angle,10*,-1)
Note the '*'. If th:s is f:ve, your th:ng:e w:ll move 1/5 of the way every step, so at ten, it w:ll move a tenth of the rema:n:ng d:stance every frame.

So the bigger, the slower.

Hope it helps!

Edited by kikjezrous, 13 June 2013 - 07:33 PM.

  • 1
MXfDv0N.png > braveadventurer@quest-DUTIMS:~$ _ don tseethebr akuhhuh Thread - Mirror - Tumblr

 nIdGebz.png


#6 bjulin

bjulin

    GMC Member

  • GMC Member
  • 6 posts
  • Version:GM8

Posted 15 August 2012 - 02:25 PM

Uh, ok... tried this one, but I get an error while loading the game, that says that there is no rot_smooth function.
Well, I thought, I have to creat a variable in the creation event, but that doesnīt work. Iīm a bit confused, too... I thought, it will do the script, when the enemy comes into view.
Why does gamemaker now recognize, that there is no variable in an object, thatīs not even loaded?

What Iīve done:

I pasted your code into a script.
I called that script in the step event of my enemy, leaving the arguments blank.
Than, I executed the second code (that one you wrote yesterday) after the set_path action, again in the step event.

So, where did I do things wrong? Or what did I forget to do? I think thereīs something, I donīt know yet, about using scripts, I guess. But I canīt seem to find, what it is.
Again, I hope you could help me out!

THANKS in advance!
  • 0

#7 bjulin

bjulin

    GMC Member

  • GMC Member
  • 6 posts
  • Version:GM8

Posted 29 August 2012 - 04:28 PM

hey there...

sometimes you have to leave things as they are, learn some other things... and than, if you come back and use what you have learned so far... guess what -> YES, YOU GET IT TO WORK! So... I just wanted to say thanks! ;)

cheers, Bjulin
  • 0

#8 kikjezrous

kikjezrous

    Seer of Spaaace

  • GMC Member
  • 637 posts
  • Version:GM8.1

Posted 30 August 2012 - 12:08 PM

::D ::D ::D ::D ::D

Good work!
Glad I could help you~!
  • 0
MXfDv0N.png > braveadventurer@quest-DUTIMS:~$ _ don tseethebr akuhhuh Thread - Mirror - Tumblr

 nIdGebz.png


#9 Monstr Gaming

Monstr Gaming

    GMC Member

  • GMC Member
  • 431 posts
  • Version:GM:Studio

Posted 03 September 2012 - 07:14 PM

thank you greatly :biggrin:
This is my greatest flaw and you solved it.
  • 0

youtube.png


#10 FatalSleep

FatalSleep

    FatalSheep?

  • GMC Member
  • 3974 posts
  • Version:GM:Studio

Posted 13 September 2012 - 02:58 PM

Smooth rotations. Ah I have a script for this... about 10 lines less of code too!

 var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
   if dir >= 360 {
      dir -= 360;
   }
   if dir <= 0 {
      dir += 360;
   }
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );

Hope this is helpful. :)

Edited by FatalSleep, 13 September 2012 - 02:59 PM.

  • 2

#11 Primoz128

Primoz128

    GMC Member

  • GMC Member
  • 323 posts
  • Version:GM:Studio

Posted 06 October 2012 - 09:17 PM

So which one is better ? My game is gona be heavly dependant on rotations, and well good script is needed ^^.
  • 0

Looking for a coding partner for my space RTS solar conquest project. More information: http://gmc.yoyogames...opic=563123&hl=


#12 FatalSleep

FatalSleep

    FatalSheep?

  • GMC Member
  • 3974 posts
  • Version:GM:Studio

Posted 07 October 2012 - 04:00 AM

Mine is shorter in code and easier to manipulate.
However shorter codes don't always mean that
they are faster codes.

Since I posted my code, I'll say use mine. Posted Image
  • 0

#13 kikjezrous

kikjezrous

    Seer of Spaaace

  • GMC Member
  • 637 posts
  • Version:GM8.1

Posted 12 October 2012 - 01:50 PM

His is a lot prettier, which means a lot for a coder like me. But mine is a lot easier to understand, and I've never had any slowdown experience with it.

Sooooo... I honestly don't really care. ::P
  • 0
MXfDv0N.png > braveadventurer@quest-DUTIMS:~$ _ don tseethebr akuhhuh Thread - Mirror - Tumblr

 nIdGebz.png


#14 FatalSleep

FatalSleep

    FatalSheep?

  • GMC Member
  • 3974 posts
  • Version:GM:Studio

Posted 12 October 2012 - 05:55 PM

With mine you won't learn much if you can't understand the functions used.
So I guess if you want to learn something use his.
If you want short and sweet use mine. Posted Image
  • 0

#15 Zapchu25

Zapchu25

    GMC Member

  • GMC Member
  • 21 posts
  • Version:Unknown

Posted 21 May 2013 - 06:49 AM

Love this function. I use it as a basic tween with any variable!


  • 0

---Are you looking for an Experienced Spriter for hire for one of your GameMaker projects?---

---Check out my work---

kh.gif http://zapchu25.deviantart.com kh.gif

---Contact me---

kh.gif ad.meredith@yahoo.com kh.gif

 

 


#16 gff1979

gff1979

    GMC Member

  • GMC Member
  • 26 posts
  • Version:GM:Studio

Posted 01 March 2014 - 10:09 PM

Sorry to necro this, but I didn't see anywhere in the rules about necros and usually forums disable posts that are old enough. I wanted to state that when using the first example as a follow mouse to rotate, as with a SmashTV or asteroids clone, The first one does "hiccup" as stated (I think that's what you mean). I think that's because you clamped the values to only be between 0 and 360, and it jumps when it comes to interpolating from 360 to 0. While the second one doesn't hiccup since it doesn't clamp. It simply keeps counting up or down depending on the direction of rotation... not sure what might happen when that value overflows (32 bit float?) but in most cases I imagine it would wrap around automagically? there could be a hiccup by that point but it'll take many thousands of rotations to get there. Still very useful stuff in either case.

 

edit> heh, the 4th option clamps it between 0-360... wasn't paying attention...


Edited by gff1979, 02 March 2014 - 04:47 AM.

  • 0

#17 iMilchshake

iMilchshake

    GMC Member

  • GMC Member
  • 135 posts
  • Version:GM:Studio

Posted 03 September 2015 - 02:44 PM

Smooth rotations. Ah I have a script for this... about 10 lines less of code too!
 

 var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
   if dir >= 360 {
      dir -= 360;
   }
   if dir <= 0 {
      dir += 360;
   }
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );
Hope this is helpful. :)

 

Yo Man! I know your post is some years old. But it helped me alot in my current project. thx man<3!


  • 0

ad2e5cf943724799dd60d3970d49be19.jpg


#18 FatalSleep

FatalSleep

    FatalSheep?

  • GMC Member
  • 3974 posts
  • Version:GM:Studio

Posted 03 September 2015 - 02:55 PM

 

Smooth rotations. Ah I have a script for this... about 10 lines less of code too!
 

 var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
   if dir >= 360 {
      dir -= 360;
   }
   if dir <= 0 {
      dir += 360;
   }
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );
Hope this is helpful. :)

 

Yo Man! I know your post is some years old. But it helped me alot in my current project. thx man<3!

Glad it helps! That said a nice huge thanks to Nocturne who actually came up with the

actual smooth rotation part. No idea why I didn't cite him. I did the angle fixing.

 

NOTE: When dealing with angles, always fixate your angles within 0-359 degrees. Also, to fix something,

the angle fixing here is actually a bit terrible, so I'd like to give you a script which actually fixes it correctly

and efficiently:

//fixangle( angle )
if ( angle >= 0 ) {
    return ( argument0 % 360 );
} else {
    return 360 + ( argument0 % -360 );
}

So you can just replace the code in the "if correct == true {.." with a call to this script, like so:

var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
    dir = fixangle( dir );
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );

Edited by FatalSleep, 03 September 2015 - 02:56 PM.

  • 0

#19 iMilchshake

iMilchshake

    GMC Member

  • GMC Member
  • 135 posts
  • Version:GM:Studio

Posted 04 September 2015 - 12:24 PM

 

 

Smooth rotations. Ah I have a script for this... about 10 lines less of code too!
 

 var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
   if dir >= 360 {
      dir -= 360;
   }
   if dir <= 0 {
      dir += 360;
   }
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );
Hope this is helpful. :)

 

Yo Man! I know your post is some years old. But it helped me alot in my current project. thx man<3!

Glad it helps! That said a nice huge thanks to Nocturne who actually came up with the

actual smooth rotation part. No idea why I didn't cite him. I did the angle fixing.

 

NOTE: When dealing with angles, always fixate your angles within 0-359 degrees. Also, to fix something,

the angle fixing here is actually a bit terrible, so I'd like to give you a script which actually fixes it correctly

and efficiently:

//fixangle( angle )
if ( angle >= 0 ) {
    return ( argument0 % 360 );
} else {
    return 360 + ( argument0 % -360 );
}

So you can just replace the code in the "if correct == true {.." with a call to this script, like so:

var dir , dest , spd , correct;
dir = argument0; //direction we are rotating
dest = argument1; //destination direction to rotate to
spd = argument2; //speed at which to rotate
correct = argument3; //whether or not to correct dir to a value between 0-360

if correct = true {
    dir = fixangle( dir );
}

//Smoothly rotates dir towards dest in the quickest direction...
return ( dir + ( sin( degtorad( dest - dir ) ) * spd ) );

Oh Thanks man!

I really appreciate your Help! <3


  • 0

ad2e5cf943724799dd60d3970d49be19.jpg


#20 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 05 September 2015 - 12:53 AM

///turn_towards(afrom,ato,aspeed)
var afrom = argument0,
    ato = argument1,
    aspeed = argument2;

var a = angle_difference(afrom,ato);
return afrom+clamp(a,-aspeed,aspeed); //snappy
//return afrom+lengthdir_y(aspeed,a); //natural
I may have mixed afrom-ato in angle difference

Edited by icuurd12b42, 05 September 2015 - 12:55 AM.

  • 1

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#21 VainTeddyBear

VainTeddyBear

    GMC Member

  • GMC Member
  • 46 posts
  • Version:GM:Studio

Posted 21 October 2015 - 12:09 AM

...I need help with this.

 

This GMZ GM project: https://drive.google.com/file/d/0By-LpR7PyiS_OThFb0kxZ3VOZ3M/view 

is a slightly simplified version of the movement system in my game which probably could be a lot more efficient. Anyway, what I was hoping to achieve was the character turning quickly towards the direction hes going when you move by clicking. I don't understand what arguments are needed or anything honestly.

 

Not asking for anyone to waste their valuable time doing it for me, but I'll admit im really confused at this point.  

 

EDIT: I forgot to mention the model import / animation system is made by DarkLewa, its paused in this project.

2: All good now.


Edited by VainTeddyBear, 31 October 2015 - 09:19 AM.

  • 0

#22 NNY

NNY

    GMC Member

  • New Member
  • 4 posts
  • Version:GM:Studio

Posted 28 October 2015 - 08:08 PM

Like VainTeddyBear I would also like to know what exactly the smooth rotationg code does, to better understand what to fill in for the arguments. What is it actually that makes the edges pixelated when I rotate an object... Because now when I try to rotate an object the edges are not smooth, even with the interpolate between pixels function on.


  • 0

Trace And Tap

It's all about recognizing colors, patterns and details

Download for iOS | Download for Android


#23 FatalSleep

FatalSleep

    FatalSheep?

  • GMC Member
  • 3974 posts
  • Version:GM:Studio

Posted 28 October 2015 - 09:35 PM

The smooth rotation code simply takes a value--e.g. rotation in degrees(0-359)--and alters that value

to "rotate" towards the destination rotation in degrees.

 

For example if you're pointing at 45 degrees and want to point to 270 degrees, the script alters the

original rotation to be closer to 270 each time the script is run until you reach 270 degrees. To do this,

it has to take the shortest path--this is the angle difference.

 

It basically says: "Take rotation x and rotate a little closer to rotation y."

 

So in example: (using Icuurd's script)

var destination_direction = point_direction( x, y, mouse_x, mouse_y );
var rotation_speed = 4;
source_direction = turn_towards( source_direction, destination_direction, rotation_speed );

What we want is for source_direction to point towards destination_direction, but we want it to point

to it smoothly. Since we want it to point smoothly--over time--we can't simply point source_direction

to destination_direction. To do this we call the script every step and each step the script takes the

source_direction and nudges it towards the destination_direction this happens until they're the same.

 

 

 

Like VainTeddyBear I would also like to know what exactly the smooth rotationg code does, to better understand what to fill in for the arguments. What is it actually that makes the edges pixelated when I rotate an object... Because now when I try to rotate an object the edges are not smooth, even with the interpolate between pixels function on.

As for smoothing out the look of the rotated sprite--that can't really be helped. You'd have to scale the image up, rotate it and then scale it back down,

Which would usually be done via surfaces or shaders.


Edited by FatalSleep, 28 October 2015 - 09:36 PM.

  • 0

#24 VainTeddyBear

VainTeddyBear

    GMC Member

  • GMC Member
  • 46 posts
  • Version:GM:Studio

Posted 31 October 2015 - 09:18 AM

Thank you everyone for your input. Especially Fatalsleep for helping me - It works now! I have it in my 3D game implemented as I wanted it to be. If anyone wants to see what I did then i'm happy to show you. 

How come you can ignore the ato and afrom variables and make them source_direction destination_direction, is Icuurd's script quicker than yours, and that script doesn't keep running if source_direction and destination_direction are the same right?

 

Oh and sorry I took so long to respond - I have exams on and whatnot.  :whistle:


  • 0

#25 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 31 October 2015 - 05:40 PM

the code I gave is the shortest code. not sure about the quickest. You can remove the vars which I put in there simply to make the code easy to understand, but it can be a one liner.

and yes it runs even if the angle are the same. you can put an extra if in the there... I never really bothered going that deep in optimising it.
  • 0

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#26 VainTeddyBear

VainTeddyBear

    GMC Member

  • GMC Member
  • 46 posts
  • Version:GM:Studio

Posted 31 October 2015 - 11:05 PM

Yeah I put this if statement; if afrom != to {     }, that's fine isn't it. They all seem to be really fast anyway too and I got both working the same way.


  • 0

#27 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 01 November 2015 - 12:58 AM

I never considered using an if myself because in most my uses afrom and ato are almost never the same... chasing the mouse for example. or a moving target in top down, meaning 99.9% of the time that IF is basically an extra instruction
  • 0

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#28 VainTeddyBear

VainTeddyBear

    GMC Member

  • GMC Member
  • 46 posts
  • Version:GM:Studio

Posted 01 November 2015 - 04:44 AM

Well the anathema of the programmer that I am, I rely very heavily on if statements as I don't know how to write anything any other way zzzzz, scripts are one thing to cut down on it, then there is for, else, while, with and do (which I recently discovered F2 is a hotkey for).

But the game i'm making is kind of like Diablo or something? I don't know never played that game but what I mean is the character is controlling by right click and stops often


Edited by VainTeddyBear, 01 November 2015 - 04:48 AM.

  • 0