GML Assigning A Variable To Custom Speed

mentalredux

Member
Hello there. I currently have a bit of code that controls the playable character's speed and I like how it works. If the cursor is far away the object speeds up and gradually slows down as it reaches the cursor to simulate a running speed and walking speed. It is in a step event but I would like to assign it to a variable that takes it's place when the steps are being checked and move it to over the the create event area.

GML:
if distance_to_point (mouse_x,mouse_y)>200{speed=10};
else
if distance_to_point (mouse_x,mouse_y)>170{speed=8};
else
if distance_to_point (mouse_x,mouse_y)>150{speed=7};
else
if distance_to_point (mouse_x,mouse_y)>50{speed=4};
else
if distance_to_point (mouse_x,mouse_y)>25{speed=3};
else
if distance_to_point (mouse_x,mouse_y)>5{speed=2};
else
if distance_to_point (mouse_x,mouse_y)>3{speed=1};
else
if distance_to_point (mouse_x,mouse_y)<1{speed=0};
I am having difficulty with this code and collision checking. Is there a way that I can apply the above code to a variable that I can use instead of speed so I can use the code below for collision control?


GML:
//H
if(place_meeting(x + speed, y, objWall))
{
  while(!place_meeting(x + sign(speed), y, objWall))
  {
   x += sign(speed);
  }
   speed = 0;
}

x += speed;

//V
if(place_meeting(x, y + speed, objWall))
{
  while(!place_meeting(x, y + sign(speed), objWall))
  {
   y += sign(speed);
  }
   speed = 0;
}
Thank you.
 

mentalredux

Member
GML:
if(place_meeting(x + spd, y, obj_02))
{
  while(!place_meeting(x + sign(spd), y, obj_02))
  {
   x += sign(spd);
  }
   spd = 0;
}

x += spd;

//V
if(place_meeting(x, y + spd, obj_02))
{
  while(!place_meeting(x, y + sign(spd), obj_02))
  {
   y += sign(spd);
  }
   spd = 0;
}

y += spd;
This is doing something put the player is colliding with what seems to be empty space.
 

sp202

Member
I assume obj_02 is the wall? You've separated x and y but you're only using one spd variable. This means when you collide in x, spd will get set to 0 and you'll be unable to move in y. I posted this in your previous thread and it is what I would recommend using
GML:
var dir=point_direction(x,y,mouse_x,mouse_y)
var spd=10 //The speed to move at
if !place_meeting(x+lengthdir_x(spd,dir),y+lengthdir_y(spd,dir),objWall)
{
    x+=lengthdir_x(spd,dir)
    y+=lengthdir_y(spd,dir)
}
else
{
    while(!place_meeting(x+lengthdir_x(1,dir),y+lengthdir_y(1,dir),objWall))
    {
        x+=lengthdir_x(1,dir)
        y+=lengthdir_y(1,dir)
    }
}
There's no need for the move_towards_point if you're already moving x and y manually. Also rather than using so many if statements, you can use something like the exponential function to determine spd depending on distance to the mouse.
 

mentalredux

Member
I assume obj_02 is the wall? You've separated x and y but you're only using one spd variable. This means when you collide in x, spd will get set to 0 and you'll be unable to move in y. I posted this in your previous thread and it is what I would recommend using
GML:
var dir=point_direction(x,y,mouse_x,mouse_y)
var spd=10 //The speed to move at
if !place_meeting(x+lengthdir_x(spd,dir),y+lengthdir_y(spd,dir),objWall)
{
    x+=lengthdir_x(spd,dir)
    y+=lengthdir_y(spd,dir)
}
else
{
    while(!place_meeting(x+lengthdir_x(1,dir),y+lengthdir_y(1,dir),objWall))
    {
        x+=lengthdir_x(1,dir)
        y+=lengthdir_y(1,dir)
    }
}
There's no need for the move_towards_point if you're already moving x and y manually. Also rather than using so many if statements, you can use something like the exponential function to determine spd depending on distance to the mouse.
Thank you! With your code the character does stop when it touches the wall but it seems like there is friction, is there a way to make it quickly slide along the walls rather that slowly move? I'll spend some time reading up about exponential functions because I really like the slow speed when close to the cursor and quicker when further effect. The character also spazzes when the cursor hovers directly over them.
 

sp202

Member
If you want it to slide along walls then I suppose you'll have to separate x and y like you were doing before, but you'll need to use separate spd variables for each axis; hspd and vspd which will be the x and y component of spd respectively. Try this for setting the value of spd instead of the if statements spd=exp(0.01*distance_to_point(mouse_x,mouse_y))
 

mentalredux

Member
If you want it to slide along walls then I suppose you'll have to separate x and y like you were doing before, but you'll need to use separate spd variables for each axis; hspd and vspd which will be the x and y component of spd respectively. Try this for setting the value of spd instead of the if statements spd=exp(0.01*distance_to_point(mouse_x,mouse_y))
Ya know I haven't thought of just multiplying the speed based on distance like that! It seems like the obvious thing to do, but I'm not the sharpest tool in the shed most of the time. Thank you so so much for helping me work through this. After I get some sleep I'm going to work on separating the x and y speed values.
 

mentalredux

Member
GML:
spd=(0.03*distance_to_point(mouse_x,mouse_y));

move_towards_point(mouse_x,mouse_y,spd);
This is so perfect and the code is so compact. How cool!
 

mentalredux

Member
GML:
spd=(0.03*distance_to_point(mouse_x,mouse_y));

if distance_to_point(mouse_x,mouse_y)>200
{spd=7};

move_towards_point(mouse_x,mouse_y,spd);
Added a speed cap. <3
 
Not only is it possible, it's the recommended way. No-one above a certain level of experience really uses speed or direction as intended by the engine (or at least, won't use them most of the time). The GMS variable "speed" is exactly the same as creating your own variable, let's call it "spd" and using that to manipulate the x and y variables of the instance. There's nothing special about speed or direction or anything, they are just standard variables that hold a standard real, but their namespace is simply reserved by the engine (somewhat annoyingly).
 

sp202

Member
You can make that one line by using min spd=min(7,(0.03*distance_to_point(mouse_x,mouse_y)));
 

mentalredux

Member
You can make that one line by using min spd=min(7,(0.03*distance_to_point(mouse_x,mouse_y)));
That is really cool, do you know the reason behind why min works but max doesn't? I read the manual but I'm still confused. I thought max would be the way to go since the way in my head is, "I want to speed up .03 of a px every step to get to the cursor but you can't go over 7px per step." With the min it sounds like I want it to stay under 7px per step and it totally throws me off. When I swapped the min with max to see what would happen, the object did the thing where it shakes when the cursor is hovering over it.
 

Sybok

Member
With Max, it's likely that it will always choose 7 because distance_to_point * 0.03 would always be a smaller value.

With the shaking, in this case, even if your cursor is over the object you are setting the speed to 7. As a result the object will move the 7px that you just told it to, moving it away from the cursor . Then the next frame it wants to move towards the cursor by 7px again. In effect causing the object to shake about in a certain area.

Just in case you aren't aware, Min and Max choose the lowest or highest value of whatever is in the parentheses, respectively.
 

mentalredux

Member
With Max, it's likely that it will always choose 7 because distance_to_point * 0.03 would always be a smaller value.

With the shaking, in this case, even if your cursor is over the object you are setting the speed to 7. As a result the object will move the 7px that you just told it to, moving it away from the cursor . Then the next frame it wants to move towards the cursor by 7px again. In effect causing the object to shake about in a certain area.

Just in case you aren't aware, Min and Max choose the lowest or highest value of whatever is in the parentheses, respectively.
That answered my question perfectly, thank you for explaining it to me.
 

mentalredux

Member
I worked on seperating the horizontal and vertical movement but I'm not sure if I did it right. If I remove the bit of code under //Also Collision the character doesn't move at all. Would you guys mind giving it a look and see if there is anything that I should either add, remove, or move around? Thank you. I also experimented with removing the code in //H Collision and //V Collision just in case it wasn't doing anything and there was a noticeable difference. The character sticks to the wall a little less with it included.

GML:
//Direction
var dir=point_direction(x,y,mouse_x,mouse_y);

//Speed
var spd=min(7,(0.03*distance_to_point(mouse_x,mouse_y)));

//H Collision
if(place_meeting(x+lengthdir_x(spd,dir),y,obj_02))
{ while(!place_meeting(x+lengthdir_x(spd,dir),y,obj_02))
{ x+=lengthdir_x(spd,dir)}
spd=1}

else {spd=min(7,(0.03*distance_to_point(mouse_x,mouse_y)))};

//V Collision
if(place_meeting(x,y+lengthdir_y(spd,dir),obj_02))
{ while(!place_meeting(x,y+lengthdir_y(spd,dir),obj_02))
{ y+=lengthdir_y(spd,dir)}
spd=1}

else {spd=min(7,(0.03*distance_to_point(mouse_x,mouse_y)))};

//Also Collision
if !place_meeting(x+lengthdir_x(spd,dir),y+lengthdir_y(spd,dir),obj_02)
{
    x+=lengthdir_x(spd,dir)
    y+=lengthdir_y(spd,dir)
}
else
{
    while(!place_meeting(x+lengthdir_x(1,dir),y+lengthdir_y(1,dir),obj_02))
    {
        x+=lengthdir_x(1,dir)
        y+=lengthdir_y(1,dir)
    }
}
 
Top