I'm creating a game in python that you can move around and try to collect points by colliding with a coin. I want to add 2D physics to it to make it realistic. Is there any way to do that? Thanks
The nature of simulations is that they are different than reality. As we perform a simulation, we create a mathematical model of the behavior of objects. Let's consider simulation of gravity. We define a ball, then we displace the location of the ball as time flows. Newton modeled the falling of a ball by x=gt^2. Therefore we must define an acceleration for the ball towards the ground. Much more information about simulation is available in this video.
You can use this code in order to simulate gravity:
yvel=5*(time()-start_t)
where time() cames from from time import time
This is how to do it:
The explanation is inside the code.
#Importing all the modules
import turtle
from turtle import *
import math
#Creating the screen
screen=Screen()
#Creating the turtle
vector1=Turtle("classic")
vector1.speed(-1)
vector1.penup()
#Declaring all the needed variables
Vx=0
Vy=0
V=0
A=0
#Starting the while loop
while True:
#Updating the screen for better preformence
screen.update()
#Carculating the velocity
V=math.sqrt(Vx**2+Vy**2)
#Carculating the angle
if Vx!=0:
A=math.degrees(math.atan(Vy/Vx))
if Vy<0 and Vx<0 or Vy>0 and Vx<0:
A=A-180
elif Vy <0:
A=270
else:
A=90
#Moving the turtle
vector1.seth(A)
vector1.fd(V)
#Changing the values of the velocities
Vy-=0.5
if Vx>0:
Vx-=0.2
elif Vx<0:
Vx+=0.2
If there are any questions, please ask!
Related
I am trying to make a turtle analog clock, and to make the second, minute, an hour hands I am making a shape with turtle, and using .tilt() to tilt it 6 degrees every second.
The thing is, when I run .tilt() it rotates the ship from the middle, whereas I want to have it rotate from the bottom point (like an analog clock).
Is there a way to do that, or do I need to find another way to make this program?
Here is my code:
from turtle import *
import time
turtle = Turtle()
turtle.shape("square")
turtle.shapesize(6, .1)
tilt_amnt = 0
for x in range (60):
turtle.tilt(tilt_amnt)
tilt_amnt = tilt_amnt + 6
time.sleep(1)
I don't think there is a way to tilt the turtle in such a way where it turns from the bottom but you can rewrite the code to essentially do the same thing but using forward instead. Check this out.
from turtle import *
import time
turtle = Turtle()
turtle.pensize(2)
turtle.hideturtle()
turtle.speed(0)
tilt_amnt = 0
for x in range (60):
turtle.right(tilt_amnt)
turtle.forward(100)
turtle.backward(100)
tilt_amnt = tilt_amnt + 6
time.sleep(1)
turtle.clear()
Some thoughts: first, I wouldn't use tilt() (high overhead, forces an update), even if you do use turtles as hands, consider using right() or setheading(); second, I would use mode('logo') as this makes 0 degrees the top of the screen and makes headings clockwise (like, say a 'clock') instead of counterclockwise; third, if you want accuracy, don't use sleep() but rather extract the current time from the system and set your hands accordingly.
Large real world clocks do turn their hands from the middle, or more specifially, the center of gravity. This keeps the hands from slowing the mechanism on the way up, or rushing it on the way down. The trick is to make the hands look visually asymmetric but keep the weight symmetric. Here's a solution I came up with earlier that does something like this with turtles as the hands, turning from their centers.
Finally, here's a rewrite of the example #AlexJoslin provided to use realtime accuracy, potentially updating hand positions multiple times within a second:
from turtle import Screen, Turtle
from time import localtime as time
def tick():
second.setheading(6 * time().tm_sec)
second.clear()
second.forward(150)
second.backward(150)
screen.update()
screen.ontimer(tick)
screen = Screen()
screen.mode('logo')
screen.tracer(False)
second = Turtle()
second.hideturtle()
second.pensize(2)
tick()
screen.exitonclick()
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()
I'm creating a python program and one of the methods must allow two different turtles to approach or 'try' to converge at a single location
The dependency of whether the turtles converge or not depends on the random speeds of the turtles.
But my immediate concern is trying to make two different turtles move at different speeds towards the same location.
Or an alternate idea I've had it to try and run two lines of code simultaneously ( the movement for both turtles ) but I'm an intermediate programmer and I'm not too sure if that's even possible.
Thank you for thanking the time to reply to my question
You cannot move two objects simultaneously, you can only simulate it.
This is what I gave my grade 10's as a hint on this same question.
Not perfect, but it shows the concept.
##turtleChase.py
##Randomly place the turtles on the screen
##one turtle will then chase the other as it moves across the screen
##
##input: mouseclick events
##output: graphics on screen, text in Shell
##pseudocode:
##setup your screen
##setup the turtles
##randomly place both turtles
##randomly find a location to move the first turtle to
##turn the first turtle towards the desired location
##in a loop:
##move the first turtle a small distance
##determine the heading to move the second turtle to the first turtle
##move the second turtle a small distance
##is the second turtle at the same position of the first turtle?
##if it is
##quit the loop
##if not
##continue the loop
import turtle, random
random.seed()
# setup the output window
picSize = (400,600)
playGround = turtle.Screen()
playGround.screensize(picSize[0], picSize[1])
#setup the turtles
bob = turtle.Turtle()
bob.ht()
bob.color('red')
jeff = turtle.Turtle()
jeff.ht()
jeff.color('blue')
# find random positions for the turtles
# use the picSize variable so that we can change the screensize easily
# without having to change a lot of code.
# if the screen is 600 pixels tall, then the y-coordinates go from
# -300 to +300, just like in math.
jeffx = random.randint(-picSize[0]/2,picSize[0]/2)
jeffy = random.randint(-picSize[1]/2,picSize[1]/2)
bobx = random.randint(-picSize[0]/2,picSize[0]/2)
boby = random.randint(-picSize[1]/2,picSize[1]/2)
# find a point to move bob to
bobNewx = random.randint(-picSize[0]/2,picSize[0]/2)
bobNewy = random.randint(-picSize[1]/2,picSize[1]/2)
newBobPos = (bobNewx,bobNewy)
print(jeffx,jeffy)
print(bobx,boby)
# place the turtles and show them
bob.setpos(bobx,boby)
jeff.setpos(jeffx,jeffy)
jeff.st()
bob.st()
#rotate bob towards its target location
bobTurn = bob.towards(newBobPos)
bob.setheading(bobTurn)
while bob.position() != jeff.position():
bob.fd(1)
jeffTurn = jeff.towards(bob)
jeff.setheading(jeffTurn)
jeff.fd(1.5)
So if the location is predetermined, and the speed of the turtles is something calculated ahead of time, you can have one loop that simply moves both turtles (at the same time, in the same frame) towards that point, where how far they move would be dependent upon their speed.
Another way to make turtles move simultaneously at different speeds is to use timer events. Here I revise #dougc905's fun example to use timers instead:
from turtle import Turtle, Screen
from random import seed, randint
seed()
DELAY = 100 # milliseconds
# setup the output window
picSize = (400, 600)
playGround = Screen()
playGround.screensize(*picSize)
# setup the turtles
bob = Turtle(shape='turtle', visible=False)
bob.penup()
bob.color('red')
bob.speed('slow')
jeff = Turtle(shape='turtle', visible=False)
jeff.penup()
jeff.color('blue')
jeff.speed('normal')
x_quadrant = -picSize[0] // 2, picSize[0] // 2
y_quadrant = -picSize[1] // 2, picSize[1] // 2
# find random positions for the turtles
jeff_xy = randint(*x_quadrant), randint(*y_quadrant)
bob_xy = randint(*x_quadrant), randint(*y_quadrant)
# find a point to move bob to and rotate towards its target location
bobNew_xy = randint(*x_quadrant), randint(*y_quadrant)
bob.setheading(bob.towards(bobNew_xy))
# place the turtles and show them
jeff.setpos(jeff_xy)
jeff.showturtle()
jeff.pendown()
bob.setpos(bob_xy)
bob.showturtle()
bob.pendown()
# bob's motion is in a straight line
def moveStraight():
bob.fd(bob.speed())
playGround.ontimer(moveStraight, DELAY)
# jeff's motion is towards bob
def moveToward():
if bob.position() != jeff.position():
jeff.setheading(jeff.towards(bob))
jeff.fd(jeff.speed())
playGround.ontimer(moveToward, DELAY)
moveStraight()
moveToward()
playGround.exitonclick()
I am writing a program for the Python Turtle module and I would like it to choose a position X distance away. So basically, from the turtle's present position it needs to choose a point no further or less than X distance away and have the ability to draw a line to that position. Additionally, it should chose this position at random so it is different almost every time.I know I should use the Pythagorean theorem and perhaps the randint module, but I can't figure out how to implement either.
Any help greatly appreciated!
Cheers!
5813
Say in this case, you want x to be 50
import turtle
from random import randint
x = 50
turtle = turtle.Turtle()
degrees = randint(0, 360)
turtle.left(degrees)
turtle.forward(x)
turtle.getscreen()._root.mainloop()
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.