Python while statement turtle.distance - python

It is my understanding that the following code
turtle.forward(50)
means moving the turtle on the screen.
Here is a code I am trying to learn:
def forward(distance):
while distance > 0:
if turtle.distance(0,0) > 100:
angle = turtle.towards(0,0)
turtle.setheading(angle)
turtle.forward(1)
distance = distance - 1
I don't really understand how
turtle.forward(1)
distance = distance -1
works here. I understand that if the distance is greater than 100, then the turtle turns back and moves from the end position to the position less than 100. I experimented with it but it is still not clear to me what the code turtle.forward(1) means. Is the turtle supposed to move by 1 pixel? And the final distance is less by another pixel? When I put in different numbers instead of 1, I get strange results. Sorry for asking this question - I am learning very slowly.
Thanks.

turtle.forward(1) is telling the turtle to move forward in the current direction by one pixel.
if turtle.distance(0,0) > 100 checks how far away the turtle is from the origin (center of the pane) and see if it's greater than 100.
angle = turtle.towards(0,0) turtle.setheading(angle) turns the turtle towards the origin
Here's how it comes together:
def forward(distance):
while distance > 0: # loop this while there's still distance
if turtle.distance(0,0) > 100: # check if the distance from the origin is greater that 100
angle = turtle.towards(0,0) # find the angle for the origin from turtle's current location
turtle.setheading(angle) # turns the turtle toward the angle
turtle.forward(1) # move title forward in the current angle by one pixel
distance = distance - 1 # act as a counter for the while loop, so when distance is finally 0, the while loop breaks

The code is kind of contradictory to what it tries to achieve. It looks like the forward function is trying to move towards position (0, 0) in distance number of steps.
def forward(distance):
while distance > 0:
# if the turtle is more than 100 distance away from (0, 0)
# change orientation to face (0, 0)
if turtle.distance(0,0) > 100:
angle = turtle.towards(0,0)
turtle.setheading(angle)
# Make the turtle move one step towards (0, 0)
turtle.forward(1)
# IMO, distance should've been called steps_left
distance = distance - 1
LOGICAL INCONSISTENCY
The code seems like it is trying to make the turtle move towards the origin (0, 0) BUT at the same time it has a counter of sorts called distance - that acts more like steps_allowed_to_take - which might cause the turtle to reach the origin but still attempt to move towards the origin. The turtle.forward(1) in this scenario would actually cause the turtle to move one step away from the origin and in the next loop, the turtle would move back to the origin. Doesn't make sense.

This function is a replacement for turtle.forward() that keeps a turtle that's on a random walk within a circular boundary.
Consider a simplified version of the function:
def forward(distance):
while distance > 0:
turtle.forward(1)
distance = distance - 1
It does exactly what turtle.forward(distance) does, though less efficiently. It moves the turtle forward one pixel at a time until it goes the entire distance, rather then go the whole distance in one motion via turtle.forward(distance). Why? This allows the code to make a decision on each pixel of the move regarding whether the turtle has violated the boundary and adjust its heading:
if turtle.distance(0, 0) > 100:
angle = turtle.towards(0, 0)
turtle.setheading(angle)
Let's embed this function in code to illustrate what it does:
from random import randint
import turtle
def forward(distance):
while distance > 0:
if turtle.distance(0, 0) > 100:
angle = turtle.towards(0, 0)
turtle.setheading(angle)
turtle.forward(1)
distance = distance - 1
boundary = turtle.Turtle(visible=False)
boundary.color("red")
boundary.penup()
boundary.sety(-100)
boundary.pendown()
boundary.circle(100)
turtle.shape("turtle") # default turtle
for _ in range(1000): # akin to while True:
turtle.left(randint(0, 90))
forward(randint(1, 50))
turtle.done()
OUTPUT

Related

Im currently making a game with pygame and I need an explanation on some vector code

So I'm making a game and I've got some help from another post to make bullets fly towards the mouse cursor. The original person who showed me this did explain it to me and I have a rough idea what it does but I didn't quite understand it. So I'm posting here for further explanation.
def Shoot(self):
pos = self.rect.centerx, self.rect.centery
mpos = py.mouse.get_pos()
direction = py.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])
direction.scale_to_length(10)
return Bullet(pos[0], pos[1], round(direction[0]), round(direction[1]))
Edit: well I know what it does I just don't how I do it. I know It allows for projectiles to a fly towards the mouse even on diagonals but I don't know how it does it.
Whats happening is your getting the position of the cube/player with pos.
mpos is the mouse position on the screen
direction gets the direction between the player and the mouse. for example it the direction could be 10 pixels down and 100 pixels to the right.
The next line scales the direction down to 10, so instead of moving 100 pixels right and 10 down, its close to about 1 down and 10 right (not exactly but pretty close)
The last line creates the bullet with the x position, y position, x speed, y speed. rounding the speed as i said above, its not exactly 1 down and 10 right, it will be some decimal so to make it a nice number, you round it
I've tried to explain that in the answer to your previous question (Im currently making a game with pygame and Ive run into an Issue.), but I'll try it again.
The instruction
direction = py.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])
Computes the distance from the point pos (A) to the point mpos (B) along the x-axis and y-axis. Such a tuple of axis aligned distances is called Vector:
At this point the Euclidean distance from point A to point B is unknown.
In the following the vector is scaled to a length of 10, by the operation pygame.math.Vector2.scale_to_length:
direction.scale_to_length(10)
That means that the x and y component of the vector is changed in that way (xd, yd), that the Euclidean length of the vector is 10 (d = 10):
If the components of the vector are added to the components of the point A, once per frame, then the point A steps towards the point B (A1, A2, ...):

Get Python turtle to face in direction of line being plotted

I'm trying to get the turtle shape to follow the direction of a line.
I have a simple parabola and I want the turtle shape to follow the direction of the line - when the graph goes up, the turtle faces up and when the graph comes down, the turtle faces down.
I am using goto() for the position of the turtle and x=x+1 for the x position on the graph:
t.goto(x,y)
t.right(??) - this?
t.left(??) - this?
t.setheading(??) or this?
What is the best method to achieve this? When I have tried using t.right() in a while loop (I am looping until x is complete), the turtle continues to spin in a circle as it moves, which is not what I want.
Still not getting this. I added the extra code that was suggested - here is the EDIT and the full code for what I am trying to achieve...
I am using the physics formula for trajectory (I used this so I know my values outputted are correct).
http://www.softschools.com/formulas/physics/trajectory_formula/162/
import math
import turtle
import time
w=turtle.Turtle()
i=0
angle=66.4
velocity=45.0
g=9.8
t=math.tan(math.radians(angle))
c=math.cos(math.radians(angle))
turtle.delay(9)
w.shape("turtle")
w.setheading(90)
while i < 150:
start = i * t
middle = g*(i**2)
bottom =(2*(velocity**2)*c**2)
total = start-middle/bottom
print(total)
w.setheading(turtle.towards(i,total))
w.goto(i,total)
i=i+1
turtle.exitonclick()
The orientation of the turtle can be determined from the derivative of your function at the current position.
If you have the function as a sympy function, you can ask Python to do the differentiation. Or you could just do it on your own. If your function is
y = x^2
, then the derivative is
dy = 2 * x
Given that derivative at the current position, its arc tangent gives you the turtle's heading:
t.setheading(math.atan(dy))
Make sure that the angle mode of the turtle is set to radians or convert them to degrees
t.setheading(math.degrees(math.atan(dy)))
I agree with #NicoSchertler that the arc tangent of the derivative is the way to go mathematically. But if it's just for good visuals, there's a simpler way. We can combine turtle's setheading() and towards() methods, constantly setting the turtle's heading towards the next position just before we go there:
from turtle import Screen, Turtle
turtle = Turtle(shape='turtle', visible=False)
turtle.penup()
turtle.goto(-20, -400)
turtle.pendown()
turtle.setheading(90)
turtle.showturtle()
for x in range(-20, 20):
y = -x ** 2
turtle.setheading(turtle.towards(x, y))
turtle.goto(x, y)
screen = Screen()
screen.exitonclick()

How to add friction in pong by using python?

I want to add friction in pong. When the ball hits the paddle and paddle is moving, the ball's speed can be changed and the ball's direction can be also changed. This is my idea. However, I don't know how to specifically do this. I hope my explanation is clear. Here is my code snippet:
def moveDot(surface,center, ball_speed,ball_radius,right_paddle,left_paddle):
size = surface.get_size()
for coord in range(0, 2):
center[coord] = center[coord] + ball_speed[coord]
# Left edge or the top edge
if center[coord] < ball_radius:
ball_speed[coord] = -ball_speed[coord]
# Right edge or the bottom edge
if center[coord] + ball_radius > size[coord]:
ball_speed[coord] = -ball_speed[coord]
# Left paddle bounce and go through
if left_paddle.collidepoint(center) and ball_speed[0] < 0:
ball_speed[0] = -ball_speed[0]
# Right paddle bounce and go through
if right_paddle.collidepoint(center) and ball_speed[0] > 0:
ball_speed[0] = -ball_speed[0]
The original pong game use a system of detection of the collision point. If the ball collides the paddle, it will be moved toward 45° and it will be less if the ball hits the side of the paddle.
So, the relation between the input and the output incidence is a function of the collision point (you can choose any function you want such as splitting the paddle in two parts or setting a linear factor).
Here, you can see that the green ray hits the center of the paddle, so, the output angle = the input angle. The blue ray shows output angle > input angle.
However that requires some tweaking for the coefficient between input and output angle depending of the game speed, the size of the paddle, the wanted behaviour, ...
Some other version implement a paddle that can change the reflection angle depending on the speed of the paddle.
If you want a real friction system, you can also use a physic engine and tune the different parameters (drag, ...). But, generally, simple implementations are sufficient and more fun.
I suggest you to try different versions and to choose that one which feels the best for your game.
You'll want to convey some portion of the paddle's velocity to the ball's y velocity, the portion being expressed as a coefficient of friction.
Example:
if left_paddle.collidepoint(center) and ball_speed[0] < 0:
ball_speed[0] = -ball_speed[0]
ball_speed[1] += 0.5 * left_paddle.speed
When the ball bounces against the left paddle, half of the paddle's velocity is applied to the ball.
(Note that I'm mentioning velocity, not speed, which has a direction, positive or negative along the respective axis, whereas speed is an absolute scalar. I've used speed in the example, as that fits with the naming you have used, but your implementation is really a velocity; you might want to consider renaming the variables for the sake of consistency.)

How to measure distance at angle in image python

I'm working on a particle filter for an autonomous robot right now, and am having trouble producing expected distance measurements by which to filter the particles. I have an image that I'm using as a map. Each pixel represents a certain scaled area in the enviroment. Space the robot can occupy is white, walls are black, and areas that are exterior to the enviroment are grey.
If you are unfamiliar with what a particle filter is, my python code will create a predetermined number of random guesses as to where it might be (x,y,theta) in the white space. It will then measure the distance to the nearest wall with ultrasonic sensors at several angles. The script will compare these measurements with the measurements that would have been expected at each angle for each guessed location/orientation. Those that most closely match the actual measurements will survive while guesses that are less likely to be right will be eliminated.
My problem is finding the nearest wall AT a given angle. Say the sensor is measuring at 60°. For each guess, I need to adjust the angle to account for the guessed robot orientation, and then measure the distance to the wall at that angle. It's easy enough find the nearest wall in the x direction:
from PIL import Image
#from matplotlib._png import read_png
from matplotlib.pyplot import *
mapp = Image.open("Map.png")
pixels = mapp.load()
width = mapp.size[0]
height = mapp.size[1]
imshow(mapp)
pixelWidth = 5
for x in range(width):
if mapp.getpixel((x, 100)) == (0,0,0,255): #Identify the first black pixel
distance = x*pixelWidth self.x
The problem is that I can't tell the script to search one pixel at a time going at a 60°, or 23°, or whatever angle. Right now the best thing I can think of is to go in the x direction first, find a black pixel, and then use the tangent of the angle to determine how many pixels I need to move up or down, but there are obvious problems with this, mostly having to do with corners, and I can't imagine how many if statements it's going to take to work around it. Is there another solution?
Okay, I think I found a good approximation of what I'm trying to do, though I'd still like to hear if anyone else has a better solution. By checking the tangent of the angle I've actually traveled so far between each pixel move, I can decide whether to move one pixel in the x-direction, or in the y-direction.
for i in range(len(angles)):
angle = self.orientation+angles[i]
if angle > 360:
angle -= 360
x = self.x
y = self.y
x1 = x
y1 = y
xtoy_ratio = tan(angle*math.pi/180)
if angle < 90:
xadd = 1
yadd = 1
elif 90 < angle < 180:
xadd = -1
yadd = 1
elif 180 < angle < 270:
xadd = -1
yadd = -1
else:
xadd = 1
yadd = -1
while mapp.getpixel(x,y) != (0,0,0,255):
if (y-y1)/(x-x1) < xtoy_ratio:
y += yadd
else:
x += xadd
distance = sqrt((y-y1)^2+(x-x1)^2)*pixel_width
The accuracy of this method of course depends a great deal on the actual length represented by each pixel. As long as pixel_width is small, accuracy will be pretty good, but if not, it will generally go pretty far before correcting itself.
As I said, I welcome other answers.
Thanks

Need a solution for 2D collision handling in Python

I have a program written for simple 2D collision detection and handling on my current billiards simulation, however it is rubbish am looking for a solution that involves proper physics, i.e. newtons laws of motion for coliisions. what I have so far, which does not conserverve momentum and simplifies physics is
def collide(ball1,ball2):
dx = ball1.x - ball2.x
dy = ball1.y - ball2.y
dist = (dx)**2+(dy)**2
if dist < (ball1.radius + ball2.radius)**2:
tangent = atan2(dy, dx)
angle = 0.5 * pi + tangent
angle1 = 2*tangent - ball1.angle
angle2 = 2*tangent - ball2.angle
speed1 = ball2.speed*e
speed2 = ball1.speed*e
(ball1.angle, ball1.speed) = (angle1, speed1)
(ball2.angle, ball2.speed) = (angle2, speed2)
ball1.x += sin(angle)
ball1.y -= cos(angle)
ball2.x -= sin(angle)
ball2.y += cos(angle)
and what i have to run the collisions is this, where the bounce() is for hitting against the wall
running = True
while running:
background()
for i,ball in enumerate(balls,1):
ball.bounce()
ball.move()
for ball2 in balls[i:]:
collide(ball,ball2)
ball.display()
pygame.display.flip()
i'm still pretty new to this so please change whatever is useless/stupid
I recall I did a simple billiard simulator a while back. As you mentioned this is for educational purposes I will spare you from the whole code (and I don't have to dig around for it too :) )
But basically, I kept track of how long time has elapsed since the last frame. I used this time to find out new positions of each ball given a speed vector of each ball. For collisions in a frame I had to figure out at which exact time two balls would collide, and then apply each collision at that exact time. Pseudo code would look something like:
while running:
frame_time_ms = time elapsed since last frame
collisions = all collisions that will happen during this frame, with the exact time of collision. (1)
while collisions:
collision = first collision in collisions
collision_time_ms = time of collision (1)
move all balls to collision_time_ms
collide the two balls in the collision (2)
collisions = all remaining collisions after the time of collision (1)
move all balls to the end time of the frame
So, you will need to bring back your geometry and physics knowledge to find out the key formulas to:
Given the start and end position of two balls in a frame (or part of
a frame), do they collide, and at which point do they collide.
Remember to include the radius of the balls as well here. This will
give you the time of collision.
Given two balls at exact collision position, how will their new speed vectors look like afterwards. Some hints is to use elastic collisions, and experiment with how elastic it actually is:
http://en.wikipedia.org/wiki/Elastic_collision For bonus points you
could also include rotation of the balls :)
Good luck! =)
Circle on circle collision is simple. Take the center point co ordinance, subtract them to determine the distance between each circle.
Then, if the distance is greater than the sum of both circles radii, than they do not touch. If it is equal they are touching, if it's less they are overlapping.
Simply, if they are touching, have them repel each other. You can do this in a few ways. If you keep track of the directions they move in, have them move in the opposite direction.
As for walls, just use each wall with > < statements. So if the pos of a circle has x coordinates less than the west wall, than it has passed that wall. Again, just have them repel the walls.
Circle Collison is very simple if however you want to do other shapes it will be unbelievably difficult. Unless you just pit circles around those shapes or use pixel perfect collision (this is very high performance demand.)
If you want highly accurate collision of non circles, get a physics engine.

Categories

Resources