@@ -989,9 +989,6 @@ impl Turtle {
989
989
///
990
990
/// If the coordinates are the same as the turtle's current position, no rotation takes place.
991
991
/// Always rotates the least amount necessary in order to face the given point.
992
- ///
993
- /// ## UNSTABLE
994
- /// This feature is currently unstable and completely buggy. Do not use it until it is fixed.
995
992
pub fn turn_towards ( & mut self , target : Point ) {
996
993
let target_x = target[ 0 ] ;
997
994
let target_y = target[ 1 ] ;
@@ -1000,19 +997,24 @@ impl Turtle {
1000
997
let x = position[ 0 ] ;
1001
998
let y = position[ 1 ] ;
1002
999
1000
+ // If the target is (approximately) on the turtle don't turn
1003
1001
if ( target_x - x) . abs ( ) < 0.1 && ( target_y - y) . abs ( ) < 0.1 {
1004
1002
return ;
1005
1003
}
1006
1004
1007
1005
let heading = self . window . fetch_turtle ( ) . heading ;
1008
1006
1007
+ // Calculate the target angle to reach
1009
1008
let angle = ( target_y - y) . atan2 ( target_x - x) ;
1010
1009
let angle = Radians :: from_radians_value ( angle) ;
1010
+ // Calculate how much turning will be needed (angle - heading)
1011
+ // And clamp it make sure the turtle doesn't turn more than 360 degrees
1011
1012
let angle = ( angle - heading) % radians:: TWO_PI ;
1012
1013
// Try to rotate as little as possible
1013
1014
let angle = if angle. abs ( ) > radians:: PI {
1014
- // Using signum to deal with negative angles properly
1015
- angle. signum ( ) * ( radians:: TWO_PI - angle. abs ( ) )
1015
+ // Use signum to make sure the angle has the right sign
1016
+ // And the turtle turns the right way
1017
+ -angle. signum ( ) * ( radians:: TWO_PI - angle. abs ( ) )
1016
1018
}
1017
1019
else {
1018
1020
angle
@@ -1156,4 +1158,22 @@ mod tests {
1156
1158
assert_eq ! ( turtle. position( ) [ 1 ] . round( ) , 100.0 ) ;
1157
1159
assert_eq ! ( turtle. heading( ) , 51.0 ) ;
1158
1160
}
1161
+
1162
+ #[ test]
1163
+ fn turn_towards ( ) {
1164
+ let mut turtle = Turtle :: new ( ) ;
1165
+
1166
+ // Turn from each cardinal direction to each cardinal direction
1167
+ for n in 0 ..16 as u32 {
1168
+ let original_angle = radians:: TWO_PI * n as f64 / 16.0 ;
1169
+ for i in 0 ..16 as u32 {
1170
+ turtle. turn_towards ( [ original_angle. cos ( ) , original_angle. sin ( ) ] ) ;
1171
+ assert_eq ! ( turtle. heading( ) . ceil( ) , original_angle. to_degrees( ) . ceil( ) ) ;
1172
+
1173
+ let target_angle = radians:: TWO_PI * i as f64 / 16.0 ;
1174
+ turtle. turn_towards ( [ target_angle. cos ( ) , target_angle. sin ( ) ] ) ;
1175
+ assert_eq ! ( turtle. heading( ) . ceil( ) , target_angle. to_degrees( ) . ceil( ) ) ;
1176
+ }
1177
+ }
1178
+ }
1159
1179
}
0 commit comments