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

Rotation Not Working [SOLVED] - With link

T

Tiidriioblaan

Guest
I have a game where the user clicks directional buttons (Forward, Rotate Clockwise, and Rotate Counter-Clockwise), and the code for them is in scripts. The Forward script works, but the rotational scripts do not work.

Basically, an object will follow the commands given to it by the user clicking the directional buttons. Again, the rotation code doesn't work.

I've tried:
Code:
for
Code:
do/until
and
Code:
while
.
Currently, the code is
Code:
dir=direction+90;

while (dir!=direction)
{
direction+=5;
image_angle=direction;
}

image_angle=direction;
It doesn't rotate correctly, which confuses me as to why it's not working. It was working perfectly when the code was just
Code:
direction+=90;
image_angle=direction;

EDIT: Problem solved, and I thought I'd share the project. Get it Here
 
Last edited by a moderator:
I'm assuming you are thiniking you should see the instance slowly rotaty by 5 degrees until it has rotated 90 degrees total. This will not happen, because a) that while loop will execute in about a millionth of a second, and b) even if it took longer than that, your game will come to a complete halt while that loop is executing. In other words you wont see anything happen except your game freeze.

If you want to see a gradual transition, you have to do a little bit of a rotation once every step until the rotation is complete.

And there's another problem.

dir = direction + 90 can result in a number greater than 360.

However the variable "direction" is always within 0 to 360.

Look into modulo division (sometimes called clockwork arithmetic):
http://docs.yoyogames.com/source/dadiospice/002_reference/001_gml language overview/401_04_expressions.html

One more thing: Using a modulo operation on a negative number will produce results that might seem to be wrong. What you can do to fix that is to add an ammount equal to some multiple of the number being divided by.

Exmaple: dir = (direction - 90 + 360) mod 360;
 
Last edited:
T

Tiidriioblaan

Guest
I'm assuming you are thiniking you should see the instance slowly rotaty by 5 degrees until it has rotated 90 degrees total. This will not happen, because a) that while loop will execute in about a millionth of a second, and b) even if it took longer than that, your game will come to a complete halt while that loop is executing. In other words you wont see anything happen except your game freeze.

If you want to see a gradual transition, you have to do a little bit of a rotation once every step until the rotation is complete.

And there's another problem.

dir = direction + 90 can result in a number greater than 360.

However the variable "direction" is always within 0 to 360.

Look into modulo division (sometimes called clockwork arithmetic):
http://docs.yoyogames.com/source/dadiospice/002_reference/001_gml language overview/401_04_expressions.html
That's not the main problem I'm having. I'm testing this with the direction initially set to 0, and I'm just making sure it works. What I tried saying is the rotation is not working at all. It doesn't go from direction 0 to 90, it stays at 0. I have the image angle set to direction, so if it would turn, it would show. If it doesn't show the turn, then it would at least show the sprite changing its image angle.
 
T

Tiidriioblaan

Guest
are you sure the script is being called? And that image_angle nor direction are being overwritten somewhere?
I know the script is being called, but I'm not sure if it is overwriting the image_angle. I'll check that.

What's in the object's Draw Event?
There is no draw event. I've never used Draw Events for image_angle, and since it works without one, I don't think I need one.
 

Tsa05

Member
I see that you're using direction, a built-in variable. Are you using hspeed, vspeed, move_towards_point, move_contact_all, or any other built-in gameMaker function for your movement? Those can all affect the built-in speed and direction variables. Maybe Direction is changing in unexpected ways each step?

Edit: also, if this evaluates properly, your image should spin continuously, jumping 90 degrees per step, 30 steps per second...
 
T

Tiidriioblaan

Guest
Checked if the image_angle was being overwritten by anything. I didn't find anything that would assume that it is being overwritten, but nothing that it isn't.

Just in case there's something I missed, here is all the code.

object0: Object being controlled.
Create
Code:
for (a=0; a<100; a++)
{
global.command[a]=sc_placeholder; //Sets a max array of 100 commands.
}

global.cmd=0;

run=0; //Used for local command

global.game_start=false;

Step
Code:
if (global.game_start==true)
{
    if (instance_exists(o_goto))
    {
        move_towards_point(o_goto.x, o_goto.y, 3);
    }
    else
    {
    speed=0;
        if (run<=99)
        {
        script_execute(global.command[run]);
        run++;
        }
    }
}

Press Enter
Code:
if (global.game_start==false)
{
global.game_start=true;
}

object1: Forward Arrow
Left Clicked
Code:
global.command[global.cmd]=sc_go_forward;
global.cmd++;

object2 and object3: Clockwise and Counter-Clockwise Rotational Arrows
Left Pressed (object2)
Code:
global.command[global.cmd]=sc_rotate_clockwise;
global.cmd++;

Left Pressed (object3)
Code:
global.command[global.cmd]=sc_rotate_c_clockwise;
global.cmd++;

o_goto
Collision with object0
Code:
instance_destroy();


Scripts
Move Forward
Code:
xx=x+32
xxt=x-32
yy=y+32
yyt=y-32

if (direction==0 || direction==360)
{
instance_create(xx,y,o_goto);
}
else if (direction==90)
{
instance_create(x,yyt,o_goto);
}
else if (direction==180)
{
instance_create(xxt,y,o_goto);
}
else if (direction==270)
{
instance_create(x,yy,o_goto);
}

Rotate Clockwise (Updated)
Code:
dir=direction-90;
image_angle=direction;

while !(dir==direction)
{
direction-=5;
image_angle=direction;
    if (dir==direction) {break;}
}

Rotate Counter-Clockwise (Updated)
Code:
dir=direction+90;
image_angle=direction;

while !(dir==direction)
{
direction+=5;
image_angle=direction;
    if (dir==direction) {break;}
}

The updated codes are updated as of 8/8/2016 at 4:30 Eastern Time.
Updated codes still do not work.

Placeholder - Used for blank commands
Code:
x=x;
y=y;
 
That seems way more complicated than it needs to be. Why are you putting commands into an array? It also looks like you are running up to 100 empty scripts every step. That cannot be good! Why not use global.cmd to limit the length of that loop? And where are you resetting run to zero, otherwise it will only execute the commands once.
 
T

Tiidriioblaan

Guest
That seems way more complicated than it needs to be. Why are you putting commands into an array? It also looks like you are running up to 100 empty scripts every step. That cannot be good! Why not use global.cmd to limit the length of that loop? And where are you resetting run to zero, otherwise it will only execute the commands once.
I was using the array to run them in sequential order. The placeholder is there to act as a NULL -- it doesn't do anything. The global.cmd is for the initial setup of the commands into the array. Also, it was meant to be run only once, as to have one chance to program all commands needed to complete the levels which I will eventually be making.
 
Oh okay. I think I get it. One problem though... as it is written now, all the commands will execute instantly, you will just see the final result of applying all of the commands. Is that what you intend?

I would replace the placeholder script with just the constant -1.

and then inside your loop

if (next_command != -1) { script_execute(next_command); }

that way you aren't running a whole bunch of scripts that do nothing.
 
T

Tiidriioblaan

Guest
Oh okay. I think I get it. One problem though... as it is written now, all the commands will execute instantly, you will just see the final result of applying all of the commands. Is that what you intend?
The way it works now, through the Step Event of object0, if it is currently not moving toward the o_goto object, then it will execute the next command. It moves forward fine, and it rotates fine when the code is two lines adding/subtracting 90 to the direction and then setting the image_angle to the direction. I understand that it will execute them almost instantaneously, but it does so in sequential order as it should.

I'm just having trouble getting the rotation to work that shows the object rotating smoothly to the next direction. With the two lines of code, it just jumps to the next direction with no smooth transition. I got the moving forward transition smoothed out from the original code (which was unfortunately deleted, so all of this is original built from scratched based on the original), just not smooth rotating - or rotating at all.

If I input the commands Forward, Forward, Rotate Clockwise, Forward, the object will go forward (with a very slight stop), go forward again, stop, and at the rotation code is where it stops working altogether.
 
Is the problem that the object doesn't rotate smoothly or that it never rotates at all? Doesn't it appear rotated while it is heading to the next waypoint?
 
C

ConsolCWBY

Guest
Excuse me, but your code:
Code:
dir=direction+90;
image_angle=direction;

while !(dir==direction)
{
direction+=5;
image_angle=direction;
    if (dir==direction) {break;}
}
is incorrect.
Firstly, no matter what the while() loop does, you set image_angle TO DIRECTION before. This is redundant. I'm not really sure why you want your code to do this, but:you should think about WHY the code should do this. You should also trap for when an angle exceeds 360 (dir I am looking at you!)

Would you believe, your script will change the image angle 90 degrees?... or not at all? I don't think this should be a script if you are using variables local to the object unless you pass the script the instance id. Even then, dir is looking suspect for being greater than 360.
Code:
// sc_calc_rotation (arg0, arg1, arg2) - where arg0 = direction, arg1 = rotation, arg2 = true if clockwise or false if counter-clockwise
sc_calc_rotation
{
   var v_dir = argument0;
   var v_rot  = argument1;
   var v_is_clockwise = argument2;
   if (v_is_clockwise)
   {
     v_dir += v_rot;
   }
   else
   {
     v_dir -= v_rot;
   }
   if (v_dir > 360)
   {
     v_dir -=360;
   }
   if (v_dir < 0)
   {
     v_dir +=360;
   }
   return v_dir;
}

***
Rotate Clockwise
***
var obj = argument0; // calling instance must be given! obj = id
with (obj)
{
   if (dir_flag != true)
   {
     dir = direction - 90;
     dir_flag = true;
   }
   else
   {
     direction = sc_calc_rotation (direction, 5, true);
     image_angle = direction;
     if (direction ==  dir)
     {
       dir_flag = false;
     }
   }
}

***
Rotate Counter Clockwise
***

var obj = argument0; // calling instance must be given! obj = id
with (obj)
{
   if (dir_flag != true)
   {
     dir = direction + 90;
     dir_flag = true;
   }
   else
   {
     direction = sc_calc_rotation (direction, 5, false);
     image_angle = direction;
     if (direction ==  dir)
     {
       dir_flag = false;
     }
   }
}
When called as in: global.command[global.cmd]=sc_rotate_c_clockwise;
would be used as: global.command[global.cmd]=sc_rotate_c_clockwise(id);
etc...
You would need to control the dir_flags - I should've made them in the create event, but you get the idea! (I still hate changing an object's variables inside a script ... makes me feel dirty!)
 
Last edited by a moderator:
T

Tiidriioblaan

Guest
Is the problem that the object doesn't rotate smoothly or that it never rotates at all? Doesn't it appear rotated while it is heading to the next waypoint?
It doesn't rotate at all, is the problem, and won't continue to the next command.

Excuse me, but your code:
Code:
dir=direction+90;
image_angle=direction;

while !(dir==direction)
{
direction+=5;
image_angle=direction;
    if (dir==direction) {break;}
}
is incorrect.
Firstly, no matter what the while() loop does, you set image_angle TO DIRECTION before. This is redundant. I'm not really sure why you want your code to do this, but:you should think about WHY the code should do this. You should also trap for when an angle exceeds 360 (dir I am looking at you!)

Would you believe, your script will change the image angle 90 degrees?... or not at all? I don't think this should be a script if you are using variables local to the object unless you pass the script the instance id. Even then, dir is looking suspect for being greater than 360.
If you look at the code, it sets before and during the while loop.
 
C

ConsolCWBY

Guest
If you look at the code, it sets before and during the while loop.
Why? Won't direction be the same until rotation starts? Will it have changed between rotations? I probably don't get it, but it reminds me of a primer read, why set it - loop to 90 - then set it, loop to 90, etc?... Besides, a while loop will knock it to 90 before the draw.
 

TheouAegis

Member
Rotation script
Code:
dir=direction+90;
Step:
Code:
if dir!=direction
{
    direction+=5 * sign(dir-direction);
    image_angle=direction;
}
There is no draw event. I've never used Draw Events for image_angle, and since it works without one, I don't think I need one.
It's not that you need one, but that having one can make it look like image_angle doesn't work.
 
T

Tiidriioblaan

Guest
Rotation script
Code:
dir=direction+90;
Step:
Code:
if dir!=direction
{
    direction+=5 * sign(dir-direction);
    image_angle=direction;
}
Put this code in (and modified it a little), and change the scripts to

Code:
dir=direction-90;
object0.rotate=-1;

if (dir <= 0)
{
dir=270
}

Code:
dir=direction+90;
object0.rotate=1;

if (dir==360)
{
dir=0
}

I added a variable called 'rotate' which can be 1 or -1 to multiply against the rotation. It corrects the rotation direction, positive for CCW to turn CCW, and negative for CW to turn CW.

The updated code is
Code:
{
    if (instance_exists(o_goto))
    {
        move_towards_point(o_goto.x, o_goto.y, 3);
    }
    else
    {speed=0;
        if (dir!=direction)
        {
            direction+=5 * rotate;
            image_angle=direction;
        }
        else if (run<=99)
        {
        script_execute(global.command[run]);
        run++;
        }
    }
}

Thanks for all the help. It works wonderfully now.
 
T

Tiidriioblaan

Guest
Quick change

I changed
Code:
dir=direction-90;
object0.rotate=-1;

if (dir <= 0)
{
dir=270
}
to

Code:
dir=direction-90;
object0.rotate=-1;

if (dir < 0)
{
dir=270
}
At first, if you rotated four times, it would add an extra. Now it doesn't.
 
Top