@@ -989,9 +989,6 @@ impl Turtle {
989989 ///
990990 /// If the coordinates are the same as the turtle's current position, no rotation takes place.
991991 /// 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.
995992 pub fn turn_towards ( & mut self , target : Point ) {
996993 let target_x = target[ 0 ] ;
997994 let target_y = target[ 1 ] ;
@@ -1000,19 +997,24 @@ impl Turtle {
1000997 let x = position[ 0 ] ;
1001998 let y = position[ 1 ] ;
1002999
1000+ // If the target is (approximately) on the turtle don't turn
10031001 if ( target_x - x) . abs ( ) < 0.1 && ( target_y - y) . abs ( ) < 0.1 {
10041002 return ;
10051003 }
10061004
10071005 let heading = self . window . fetch_turtle ( ) . heading ;
10081006
1007+ // Calculate the target angle to reach
10091008 let angle = ( target_y - y) . atan2 ( target_x - x) ;
10101009 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
10111012 let angle = ( angle - heading) % radians:: TWO_PI ;
10121013 // Try to rotate as little as possible
10131014 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 ( ) )
10161018 }
10171019 else {
10181020 angle
@@ -1156,4 +1158,22 @@ mod tests {
11561158 assert_eq ! ( turtle. position( ) [ 1 ] . round( ) , 100.0 ) ;
11571159 assert_eq ! ( turtle. heading( ) , 51.0 ) ;
11581160 }
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+ }
11591179}
0 commit comments