I am writing a game in Python with Pygame.
The co-ords (of my display window) are
( 0 , 0 ) at the top left and
(640,480) at the bottom right.
The angle is
0° when pointing up,
90° when pointing to the right.
I have a player sprite with a centre position and I want the turret on a gun to point towards the player. How do I do it?
Say,
x1,y1 are the turret co-ords
x2,y2 are the player co-ords
a is the angle's measure
First, math has a handy atan2(denominator, numerator) function. Normally, you'd use atan2(dy,dx) but because Pygame flips the y-axis relative to Cartesian coordinates (as you know), you'll need to make dy negative and then avoid negative angles. ("dy" just means "the change in y".)
from math import atan2, degrees, pi
dx = x2 - x1
dy = y2 - y1
rads = atan2(-dy,dx)
rads %= 2*pi
degs = degrees(rads)
degs ought to be what you're looking for.
Considering a triangle
sin(angle)=opposed side / hypotenuse
You'll probably want something like this - you may need to fiddle a bit - I may be off by 180 degrees. You'll also need to special-case the situation where dy==0, which I didn't do for you.
import math
# Compute x/y distance
(dx, dy) = (x2-x1, y2-y1)
# Compute the angle
angle = math.atan(float(dx)/float(dy))
# The angle is in radians (-pi/2 to +pi/2). If you want degrees, you need the following line
angle *= 180/math.pi
# Now you have an angle from -90 to +90. But if the player is below the turret,
# you want to flip it
if dy < 0:
angle += 180
OK, using a combination of your answers and some other websites I have found the working code:
dx,dy = x2-x1,y2-y1
rads = math.atan2(dx/dy)
degs = math.degrees(rads)
The rest of my code isn't fussy about a negative value of degs; anyway, it works now and I'd like to say thanks for your help.
Related
I want to find red points count below picture. Using python. How can I do that? Using given angle, and distance according to placemark..
Every point has coordinate(latitude,longitude). Placemark also has coordinate.
Fro example, You can use angle 85 degress and its beamwitdh can be taken 50 degress.
there are many red dots in given area. I have some limitations (angle and distance). How can I count red dots?
BR,
Your question is relatively vague so for the time being I am going to assume that this is a circle.
Well, using some math, we can figure out how to get the distance, d, and angle, theta, coordinates based off of the x and y coordinates.
We know:
x^2 + y^2 = d^2
tan(theta) = y/x
For the actual math behind this, you can draw a right triangle with angle theta, hypotenuse length d, horizontal length x, and vertical length y.
Solving for theta and d:
d = sqrt(x^2 + y^2)
theta = arctan(y/x)
Our algorithm will be taking in a list of tuples (to represent points), and seeing if the angle each point makes is within a certain range. Additionally, we will check if the distance each point makes is less than our limit. If both of these conditions are met, then we will increase our total.
Now that we know how to find our coordinates based on the distance and angle, we can easily make our function:
import math
def countPoints(maxDist, angle1, angle2, points):
tot = 0
for (x,y) in points:
theta = math.atan(y/x)
dist = math.sqrt(x ** 2 + y ** 2)
if theta > angle1 and theta < angle2:
if dist < maxDist:
tot += 1
return tot
Sample:
points = [(1,1),(2,3),(3,5),(4,6)]
print(countPoints(4,0,1.2,points))
Output:
2
The first two points have an angle within 0 and 1.2 radians and a distance less than 4.
Note: For this function, we are assuming angle1 < angle2, and that if angle1 dips below the horizontal axis, it will be negative. If your input has angle1 as positive, but is below the horizontal axis, just multiply it by -1 before inputting it into the function.
I hope this helped! Please let me know if you need any further help or clarification!
Im helping my friend out with a pygame but we are stuck
so were are trying to get the direction of a projectile but we cant find out how
for example:
[1,1] will go SE
[1,-1] will go NE
[-1,-1] will go NW
and [-1,1] will go SW
we need an equation of some sort that will take the player pos and the mouse pos and find which direction the projectile needs to go
here is where we are plugging in the vectors:
def update(self):
self.rect.x += self.vector[0]
self.rect.y += self.vector[1]
then we are blitting the projectile at the rects coords
So, first you want to get the vector distance from the player to the cursor. Subtracting two points gives you the vector between them:
distance = [mouse.x - player.x, mouse.y - player.y]
Now, you want to normalize that to a unit vector. To do that, you just get the norm (by the Pythagorean theorem), and divide the vector by the norm:
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1] / norm]
Finally, you want the velocity vector. You get that by multiplying the direction (the unit vector) by the speed.
Since you want a bullet fired to the SE to have vector [1, 1], you (presumably) want all bullets to move at the speed of that velocity vector, which is sqrt(2) (by the Pythagorean theorem again). So:
bullet_vector = [direction[0] * math.sqrt(2), direction[1] * math.sqrt(2)]
And that's it.
Here you can see this code working. (That's an interactive visualizer, so you can step through it piece by piece if there's any part you don't understand.)
I create a player at [10.0, 25.0], and a mouse pointer off a generally (but not exactly) south-easterly direction at [30.0, 70.0], and bullet_vector ends up as [0.5743665268941905, 1.2923246855119288], a vector pointing in that same general south-easterly direction with speed sqrt(2).
This shows that it can go southeast (if you want to go exactly southeast, change line 8 to mouse = Point(30.0, 45.0)), it can go in directions other than the 8 compass points, and it always goes at the same speed.
I'm trying to draw an ellipse using Turtle module in Python, my plan is as follow:
Let the starting point be the focal point of the ellipse
Set the initial theta value to 0
Let the turtle forward, let the distance of the forwarding be a*(1-ee)/(1-emath.cos(theta))
Let it turn around and back to the original spot
Make a very small turn, update the theta value
Repeat the above process
Here's my actual code:
import turtle
import math
wn = turtle.getscreen()
wn.bgcolor("red")
My_Turtle = turtle.Turtle()
My_Turtle.penup()
My_Turtle.speed(9)
i=0
j=0
a=200
e=0.5
x_0 = 20
theta = 0
while(i<5000):
#Plotting squares
My_Turtle.penup()
ellipse = a*(1-e*e)/(1-e*math.cos(theta))
My_Turtle.forward(ellipse)
My_Turtle.pendown()
My_Turtle.forward(1)
My_Turtle.left(180)
My_Turtle.penup()
My_Turtle.forward(ellipse+1)
However, the results were really off like this:(Not the complete image but can see that it's already off)
enter image description here
Can anyone explain to me where I get it wrong ? Thank you very much!
I'm used to drawing ellipses from the center, not from one focal point so I read up on ellipse math to get my head around this. Your key formula appears to be correct:
ellipse = a*(1-e*e)/(1-e*math.cos(theta))
The issue is how you do your drawing. First you need to add setheading() to point your turtle in the correct direction. (Remember that by default it's in degrees so we need to either convert or change turtle's default). Second, how you bridge between steps in your drawing isn't sufficient.
I've reworked your code below, and have compared it to a center-based solution to confirm it generates the same ellipse:
import math
from turtle import Turtle, Screen
my_screen = Screen()
my_turtle = Turtle(visible=False)
my_turtle.speed('fastest')
my_turtle.radians()
my_turtle.penup()
e = 0.5 # linear eccentricity
a = 200 # semi major axis
c = e * a # distance from center to focal point
my_turtle.goto(-c, 0) # starting at a focal point
there = (2 * c, 0) # initialize previous point visited
step = 0.1
theta = step # already at starting point, so calculate next point
while theta < math.pi * 2 + step: # overshoot to close curve
# draw ellipse from one focus point
my_turtle.setheading(theta)
distance = a * (1 - e * e) / (1 - e * math.cos(theta))
my_turtle.forward(distance)
here = my_turtle.position()
my_turtle.pendown()
my_turtle.goto(there) # draw line from last position to this one
my_turtle.penup() # comment out to demonstrate algorithm
my_turtle.goto(-c, 0) # return to focal point
there = here
theta += step
my_screen.exitonclick()
OUTPUT
I left the pen down for this illustrution so it's obvious that it's forming the ellipse from one focal point.
Please forgive me, but I only really know how to somewhat code in VB, and python is not what I'm used to. I did try to see if other people have made and or shown an algorithm that I'm trying to accomplish.
I have a visualizer design in my head and What I have been trying to do is get a number of cubes (variable input for now) to be placed a certain distance (maybe 5-10 blender units) from the center of the scene and angle the faces so that there will be one face pointing to the center and one face pointing the opposite direction. I'm trying to just start with 10 cubes because I feel like it will be a fair number to hopefully show a circle shape.
I made an image to help describe what I am trying to do:
All I have been able to figure out so far is that I need to add a cube with a certain rotation, and that rotation needs to be stepped for each cube. so a small equation is needed, something like this.
(10) (36)
360 / numberOfCubes = steppedAngle
That's all I have been able to figure out because I don't know how to program python to do such.
Any help is greatly appreciated, and will be credited in the final render.
Update: 1
Thanks to the help from the answer below, I finally got it to work how i wanted.
img http://vvcap.net/db/bKKUz3Uw4WUqL_WVDU0j.png
and here is the code written in help from the answer below.
'
import bpy
import math
##num of cubes
n = 10
##distange from center
radius = 7
for i in range(1, n + 1):
angle = (i - 1) * math.pi * 2 / n
xcoord=(radius * math.cos(angle))
ycoord=(radius * math.sin(angle))
bpy.ops.mesh.primitive_cube_add(location=(xcoord,ycoord,0),rotation=(0,0,angle))
'
Let's start with cubes in a circle, and we will work our way from there.
You have N cubes, and you want to place them in a circle of radius R around the center of the universe (0,0,0).
Applying basic trigonometry:
Each cube is on one of the radius of the circle, when you divide the circle by N. Therefore, your first cube is at 0 rad, your second cube is at 2*pi/N rad, your third cube is at 2 * 360/N rad, ... your N cube is at (N-1) * 2*pi/N rad. Now we have a formula:
Location of the cube in the circle = (i - 1) * 2*pi/N in radians, for each i from 1 to N.
Now, the location in space coordinates is (r*cos(angle), r*sin(angle), 0) for a circle that is placed on the XY plane and it's center is on (0,0,0).
My Blender Python is very rusty, so I won't provide you a complete solution, but it should be this way:
import math
for i in range(1, N + 1):
angle = (i - 1) * math.pi * 2 / N
x_coord = radius * math.cos(angle)
y_coord = radius * math.sin(angle)
z_coord = 0
cube = place_cube(x_coord, y_coord, z_coord)
This will place the cubes on the right coordinates, but it won't turn them the right way. Fortunately, you can rotate each cube by angle, and get it in the right orientation. So you can do:
import math
for i in range(1, N + 1):
angle = (i - 1) * math.pi * 2 / N
x_coord = radius * math.cos(angle)
y_coord = radius * math.sin(angle)
z_coord = 0
cube = place_cube(x_coord, y_coord, z_coord)
cube.rotate_around_z(angle)
I have not provided the place_cube and rotate_around_z functions because I hardly remember the Blender Python api, but it shouldn't be too hard.
I noticed there was a sin, cos and tan function in Python.
So, I thought I would use these to make a way of aiming in my game, unfortunately, the word description of sin,cos,tan,asin,acos and atan are very confusing.
I know how to do all the sin, cos and tan rules from school, I just need to apply them to the code. So, here's what I need to do, I just need to know which one I must use:
I have
The Angle
The Hypotenuse
(I'm just keeping that the value of how far I want the object to travel before I blit it again)
From the angle, I want to work out either/both the opposite and adjacent.
The hypotenuse is going to be sin/asin and cos/acos. Which one? I don't know.
How to I input my numbers? Do I just do aim = cos(angle,hyp) or do I have to apply some other calculations?
The formulae are:
adjacent = hypothenuse * math.cos(angle)
opposite = hypothenuse * math.sin(angle)
where angle is in radians.
Your wording is a bit confusing... but what I understand is that you have a point in the 2D space and you want to advance it a particular distance (hypotenuse) aiming a specified angle above the horizon. If so:
newX = oldX + dist * cos(angle)
newY = oldY + dist * sin(angle)
That assumes that angle is in radians, that the Y axis is positive upwards and that the angle is 0 aiming to the right and PI/2 to the top. If these are not the case you may need to wiggle the signs a little.