# GML rotiation based off ground angle

Discussion in 'Programming' started by jr carey, Jul 11, 2019.

1. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
How would I go about implementing this?

so, I understand I have to get the left red value distance, and the right value distance, divide it, and put that value in the image angle, but I cant see to figure out how to go about doing that, I don't want it to only be a 45 degree slope though, it needs to be dynamic.

ive tried:
var obj = instance_nearest(x,y,obj_ground)
var d1 = point_distance(x-(sprite_width/2),y+(sprite_height/2),
obj.x,obj.y)
var d2 = point_distance(x+(sprite_width/2),y+(sprite_height/2),
obj.x,obj.y)
image_angle = (d1/d2)*100

but it flips out, gets stuck in walls, all I want it do is rotate to the floors angle, even if its a round

2. ### FocksbotMember

Joined:
Jul 5, 2016
Posts:
84
Why don't you do it using point_direction? Just find the angle between two points on your ground object and use that to direct the image_angle.

3. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
the hardest part currently having is measuring the distance from one point of the player exact spot on the slopes, that way i can calculate the angle of it, point direction would be nice, but i still need to find a way to mark to points on the top of the slope, right below the player, in order to calculate it

4. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
an update, I may have found a viable soultion

Code:
```var xx1 = x-(sprite_width/2)
var xx2 = x+(sprite_width/2)
var yy = y+(sprite_height/2)
var dis1 = -5;
var dis2 = 0;
while (!position_meeting(xx1,yy+dis1,obj_ground)){
dis1+=1;
}
while (!position_meeting(xx2,yy+dis2,obj_ground)){
dis2+=1;
}
draw_line(xx1,yy,xx1,yy+dis1)
draw_line(xx2,yy,xx2,yy+dis2)
draw_line(xx1,yy+dis1,xx2,yy+dis2)
image_angle = point_direction(xx1,yy+dis1,xx2,yy+dis2)```
its only in the draw event so I can see whats going on, I quite like the effect of how its being drawn, it works nicely, theres a bug where it occasionally gets stuck, or it randomly teleports to the right side of the screen, but other than that it works

5. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
almost final version:
Code:
```var xx1 = x-(sprite_width/2)+1
var xx2 = x+(sprite_width/2)-2
var yy = y-(sprite_height/2)-1
var dis1 = 0;
var dis2 = 0;
while (!position_meeting(xx1,yy+dis1,obj_ground)){
dis1+=1;
}
while (!position_meeting(xx2,yy+dis2,obj_ground)){
dis2+=1;
}
var angle = arctan((dis2-dis1)/(xx2-xx1))
angle = angle*(180/pi)
draw_line(xx1,yy,xx1,yy+dis1)
draw_line(xx2,yy,xx2,yy+dis2)
draw_line(xx1,yy+dis1,xx2,yy+dis2)
image_angle = -angle
show_debug_message(angle)```
this one is a lot smoother and doesn't seem to glitch, need to do more testing, I really like the effect of the lines

6. ### Annoyed GruntMember

Joined:
Jun 20, 2016
Posts:
136
Assuming that every line of code after
Code:
`angle = angle*(180/pi)`
Is debugging stuff, could you explain more about your implementation? How do you currently handle slopes (since this code seems to be purely graphical in nature I assume you handle collision elsewhere)?
I see that you check for obj_ground, I assume that you have multiple types of objects for ground (sloped/non-sloped) that are children of obj_ground?

Assuming the size of slopes doesn't change (i.e. the slope instance may even move around, but its steepness remains constant) you should be able to find a solution that requires no on-the-fly calculation.

7. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
yes! i will post the slope collision sometime around 3-4 PM
as for this code, this is what its doing:

// this is a dynamic system which rotates the player based on 2 of the ground points
// it works in both directions
// to use it play it in the step event and your player will rotate base on the current terrain
// please note that if you jump it will still rotate in the air unless you make an "inair" var, which is pretty easy
var xx1 = x-(sprite_width/2)+1 //get the far most left of the sprite
var xx2 = x+(sprite_width/2)-2 // get the far most right of the sprite
var yy = y-(sprite_height/2)-1 // gets the top of the sprite
var dis1 = 0; // just a starting value
var dis2 = 0; // just a starting value

//this is the left side
while (!position_meeting(xx1,yy+dis1,obj_ground)){ // this will check the distance from the player to the ground
dis1+=1;
}
//this is the right side
while (!position_meeting(xx2,yy+dis2,obj_ground)){ // this will check the distance from the player to the ground
dis2+=1;
}
var angle = arctan((dis2-dis1)/(xx2-xx1)) // this is a basic rise over run function, but it return radians not degrees
angle = angle*(180/pi) // this converts the radians into degrees
image_angle = -angle //this has to be a -angle otherwise it wont work correctly

8. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
also! the slopes do change in size / steepness, direction, and the slopes dont move around, the player moves around the slopes, ill try to make a video demonstrating this, but you are correct about the parenting obj_ground

9. ### Annoyed GruntMember

Joined:
Jun 20, 2016
Posts:
136
Mmh, let me specify, when I say "change", I don't mean different instances having different steepnesses, I mean the same slope changing in size, which seems unlikely. Anyway, regardless of how you do it, I would simply calculate the angle in the create event. Then, in your collision handling, you save the last ground instance while you do your standard collision checking and you set your angle to that when the player is not in the air.
If the slope changes then you can make it recalculate its angle, so really it doesn't really matter if the steepness changes or not, I just think it's better to have the actual ground calculate its own attributes rather than have the player instance do that.

10. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
i would do it in the create event, however it wouldnt be able to change dynamically, i dont have the same slope changing sizes, i have multiple slopes with a bunch of different steepness and different angles, diffferent shapes, some pointy, other ones round, this way wont be as efficient as the idea your doing, but it makes it more life like, and it doesnt take up as much cpu as would think, while loops are quite fast

11. ### Annoyed GruntMember

Joined:
Jun 20, 2016
Posts:
136
I see! I assumed you just had standard linear slopes, didn't really think about round ones.

12. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
Nope! otherwise i woulda done what you were talking about!

13. ### jr careyMember

Joined:
Sep 22, 2016
Posts:
172
here some of my collision code:
Code:
```if(place_meeting(x+hspeed_,y,obj_ground)){
yplus = 0;
while(place_meeting(x+hspeed_,y-yplus,obj_ground) && yplus <= abs(1*hspeed_)){
yplus+=1;
}
if(place_meeting(x+hspeed_,y-yplus,obj_ground)){
while(!place_meeting(x+sign(hspeed_),y,obj_ground)){
x+=sign(hspeed_);
}
hspeed_=0
}else{
y-=yplus;
}
}else{
yMinus = 0;
while(!place_meeting(x+hspeed_,y+yMinus,obj_ground) && yMinus <= abs(1*hspeed_)){
yMinus +=1;
}
//still not sure why exactly this needs to be here, but it does for math reasons.
yMinus -= 1;

//if there is a place of meeting at yMinus (speed+1) but not at yMinus (speed) AND we're already on the ground, move down
if(place_meeting(x+hspeed_, round(y+yMinus)+1,obj_ground) &&
!place_meeting(x+hspeed_, round(y+yMinus),obj_ground) &&
place_meeting(x, y+1,obj_ground)) {
y = round(y+yMinus);
}
}```
and heres the updated angle code, there was a problem I found, when theres no ground it stays in the loop forever (I forgot to break it)
Code:
```var xx1 = x-(sprite_width/2)+1
var xx2 = x+(sprite_width/2)-2
var yy = y-(sprite_height/2)-1
var dis1 = 0;
var dis2 = 0;
while (!position_meeting(xx1,yy+dis1,obj_ground)){
dis1+=1;
if(dis1>5000){
show_debug_message("no ground found")
game_end();
break
}
}
while (!position_meeting(xx2,yy+dis2,obj_ground)){
dis2+=1;
if(dis2>5000){
show_debug_message("no ground found")
game_end();
break
}
}
var angle = arctan((dis2-dis1)/(xx2-xx1))
angle = angle*(180/pi)
image_angle = -angle```