finding the angle between to points with pygame - python

I am making a game with pygame and i want the player the face the cross hair, this is the code I have, I made it print out the angle in my idle and I noticed that the angles where all wrong and the player didnt rotate at all anyway. I've seen some other questions like this and I've followed them but i still get the wrong angle and the image dosnt rotate anyway
here is my code for the angle and rotating image:
mouse_x, mouse_y = pygame.mouse.get_pos()
mouse_x -= crosshair.get_width() / 2
mouse_y -= crosshair.get_height() / 2
player_atan = math.atan2(player_x-player_y, mouse_x-mouse_y)
player_angle = degrees(player_atan)
pygame.transform.rotate(screen, player_angle)

You have to subtract the same components from the different points.
player_atan = math.atan2(mouse_y - player_y, mouse_x - player_x)

You should check out the python docs: it has some valuable info.
The reason why your sprite does not rotate is because rotate returns a new rotated surface.
A link to the docs:docs

Related

How to make ball bounce off of triangle in Py.Processing?

Im building a game in processing python. It is similar to pong except the paddles can rotate thus changing the direction of the ball. There is also supposed to be a feature where if you hit a smaller ball, triangles pop up on each the top and botton making it harder to get the ball through to the other side. So the ball is supposed to bounce off of the triangle and and make a 45 degree angle in reference to the x and y axels. Im having a hard time solving this problem. picture of game, white circle is the ball that I that is supposed to bounce on the triangle. My initial thought was to make an if statement containing two mx + c functions as follows.
if triangle_score == 1 and ball_y >= (ball_x * -1) + 350 and ball_y >= (ball_x - 450):
ball_dx = ball_dx * -1
ball_dy = ball_dy * -1
Needless to say it didn't work very well. Does anyone know processing. Would be sooo thankful for any help I can get.

How do you draw tiles/objects to the screen without collision detection in pygame? [duplicate]

This question already has answers here:
Blitting images onto a tile that is part of a grid in pygame
(1 answer)
Plotting pieces on a checkerboard using pygame
(1 answer)
Closed 1 year ago.
For the game I am making at the moment, I have just added collision detection to it. I draw the tiles on the screen and have an array with values of each tile. I'm using a for loop for checking each tile in my array to see if my character will collide with it, and stopping the movement if it is.
This is part of the player update function:
for tile in world.tiles:
#check collision in x-axis
if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height):
dx = 0
#check collision in y-axis
if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height):
#below ground
if self.vel_y < 0:
dy = tile[1].bottom - self.rect.top
self.vel_y = 0
#above ground
elif self.vel_y >= 0:
dy = tile[1].top - self.rect.bottom
Do you know any ways of drawing objects to the screen without the player being stopped by them? Could I make another list and draw that to the screen? The only problems I have with that idea is about more lag being created.
Please tell me if you need me to show you more of the code and thanks for any help you can give me

Graphics.py circle won't bounce off walls

I am trying to get a ball to bounce off of the walls of my bounds. Currently, my circle is supposed to hit the wall and then change velocities and move in the opposite direction but this is not happening. I would appreciate some help :) Thank you
from graphics import*
from random import*
from time import*
win = GraphWin('My Program', 600, 600)
win.setBackground('pink')
my_circle = Circle(Point(200,300),30)
my_circle.setFill('blue')
my_circle.setOutline('darkorchid1')
my_circle.draw(win)
key = win.checkKey()
while key == '':
vel_x = randint(-30,30)
vel_y = randint(-30,30)
my_circle.move(vel_x, vel_y)
sleep(0.1)
for bounce in range(600):
find_center = my_circle.getCenter()
center_x = find_center.getX()
center_y = find_center.getY()
if center_x == 600 or center_y == 600:
vel_x = -randint(30,-30)
vel_y = -randint(30,-30)
my_circle.move(vel_x, vel_y)
sleep(0.1)
key = win.checkKey()
Several things that may affect the problem.
You should set your velocities once, as you're doing in the first lines in the while loop. Whenever it bounces you should move in the opposite direction using vel_x = -vel_x and vel_y = -vel_y.
Right now you're updating both of velocities which might lead to some wierd bounces when only one of the centeres hits a wall.
It might be more logical to check wether the distance from the center to the wall is less than the radius of the circle. This will prevent the issue when the ball moves from x=599 to x=601 in one iteration, skipping the if statement. (This would also make it so that the circle bounces when its edge hits the wall instead of the center)
Currently you're only checking 2 walls, unless you meant to do this you should add the if statements for the other walls aswell.
Small other thing, the second time you draw the random velocities you draw from the range 30 to -30, which is invalid.

Handling sprite collisions against an angled rectangular obstacle that is static

So I have this obstacle that I want my sprite to collide with and it is at a particular angle.In this case, we are measuring from the positive x-axis to the top of the rectangle and in this instance it is 333.02 degrees with respect to the positive x-axis or 63.02 degrees with respect to the negative y-axis. So my issue is that how do I set up my pygame sprite to properly collide with the angle rectangle obstacle? Pygame sprite rectangles have no rotation attribute (to my knowledge) and I can't just say, "Hey when the right corner of my sprite collides with top, etc" because of this lack of rotation. My collisions work great for horizontal and even vertical surfaces but I am stuck on how to collide with angled obstacles.
Here is my collision code right now. It uses vectors and checks both x and y independently to see if anything is there. And below is a picture of the object I want to collide with created in the Tile Map Editor. It is at an angle of 333.02 degrees like I mentioned before. I also included a rough sketch of the axis in case that is relevant.
def update(self):
self.animate()
self.acc = vec(0, PLAYER_MASS * GRAVITY)
self.move()
# Equations of Motion
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
# Collision check in all 4 directions
self.pos.x += (
self.vel.x + 0.5 * self.acc.x * self.game.dt
) # Update x component (Frame-independent motion)
if abs(self.vel.x) < PLAYER_VELX_EPSILON:
self.vel.x = 0
self.rect.x = self.pos.x
hits = pg.sprite.spritecollide(self, self.game.platforms, False)
for hit in hits: # Horizontal collision
if self.vel.x > 0: # Rightward motion
self.rect.right = hit.rect.left
elif self.vel.y < 0: # Leftward motion
self.rect.left = hit.rect.right
self.pos.x = self.rect.x # Update true postion
self.pos.y += self.vel.y + 0.5 * self.acc.y * self.game.dt # Update y component
self.rect.y = self.pos.y + 5
# This prevents double jumping
if self.vel.y > 0:
self.onGnd = False
hits = pg.sprite.spritecollide(self, self.game.platforms, False)
for hit in hits: # Vertical Collision
if self.vel.y > 0: # Downward motion
self.rect.bottom = hit.rect.top
self.vel.y = 0
self.onGnd = True
elif self.vel.y < 0: # Upward motion
self.rect.top = hit.rect.bottom
self.vel.y = 0
self.pos.y = self.rect.y # Update true postion
# Limit Player's movement
if self.rect.bottom > HEIGHT:
self.vel.y = 0
self.rect.bottom = HEIGHT
self.pos.y = self.rect.y
Any help on this problem would be greatly appreciated!
The answer is coordinate translation. Imagine that the rotated object had its own coordinate system, where x runs along the bottom of the rectangle, and y up the side on the left. Then, if you could find the position of your sprite in that coordinate system, you could check for collisions the way you normally would with an unrotated rectangle, i.e., if x >=0 and x <= width and y >=0 and y <= height then there's a collision.
But how do you get the translated coordinates? The answer is matrices. You can use 2d transformation matrices to rotate, scale and translate vectors and coordinates. Unfortunately my experience with these types of transformations is in C#, not python, but this page for instance provides examples and explanations in python using numpy.
Note that this is quite simply the way 2d (and 3d) games work - matrix transformations are everywhere, and are the way to do collision detection of rotated, scaled and translated objects. They are also how sprites are moved, rotated etc: the pygame transform module is a matrix transformation module. So if the code and explanations looks scary at first glance, it is worth investing the time to understand it, since it's hard to write games without it beyond a certain point.
I'm aware this is not a full answer to your question, since I haven't given you the code, but it's too long for a comment, and hopefully points you in the right direction. There's also this answer on SO, which provides some simple code.
EDIT: just to add some further information, a full collision detection routine would check each collidable pixel's position against the object. This may be the required approach in your game, depending on how accurate you need the collision detection to be. That's what I do in my game Magnetar (https://www.youtube.com/watch?v=mbgr2XiIR7w), which collides multiple irregularly shaped sprites at arbitrary positions, scales and rotations.
I note however that in your game there's a way you could possibly "cheat" if all you need is collision detection with some angled slopes. That is you could have a data structure which records the 'corners' of the ground (points it change angle), and then use simple geometry to determine if an x,y point is below or above ground. That is, you would take the x value of a point and check which segment of the ground it is over. If it is over the sloped ground, work out how far along the x axis of the sloped ground it is, then use the sin of the angle times this value to work out the y value of the slope at that position, and if that is greater than the y value of the point you are checking, you have a collision.
The answer from seesharper may be the right way to go. I have no experience with that but it looks interesting and I will have to go read the links and learn something about this approach. I will still provide my immediate reaction to the question before I saw his answer though.
You could use pygames mask and mask collision detection routines. Create a mask that was the shape of the angled rectangle/platform and use the methods to detect collisions with that.
If you add a self.mask attribute to your Sprite subclass, the sprites will automatically use that mask in the collision detection.

Python & Pygame: Ball collision with interior of circle

I'm making a game in which balls bounce around the inside of a much larger circle. The larger circle doesn't move.
Here's the code that I'm currently using for these collisions:
def collideCircle(circle, ball):
"""Check for collision between a ball and a circle"""
dx = circle.x - ball.x
dy = circle.y - ball.y
distance = math.hypot(dx, dy)
if distance >= circle.size + ball.size:
# We don't need to change anything about the circle, just the ball
tangent = math.atan2(dy, dx)
ball.angle = 2 * tangent - ball.angle
ball.speed *= elasticity + 0.251
angle = 0.5 * math.pi + tangent
ball.x -= math.sin(angle)
ball.y += math.cos(angle)
It is based on the wonderful tutorial by Peter Collingridge over here.
The circle and ball objects are both classes, with (x,y), radius, angle and speed.
I am having two problems with this method, however:
The ball bounces from (what I suspect) is its "anchor point", which seems to be in the top right corner of the circle.
When colliding with the bottom 5% of the circle, is fails to bounce high enough and therefore "sinks" out of the screen. I am guessing that this is because the bounce is not high enough to move the ball above its (incorrectly placed) "anchor point"?
Having looked at possible solutions already on here, notably "Fast circle collision detection" [Link deleted due to spam link limit], which, although in Java is using the same method, these all deal with external collisions, whereas I am looking at bouncing a ball around the interior of a circle.
Here is also the class definitions of the Ball() and the Circle():
class Ball():
def __init__(self, (x,y), size):
"""Setting up the new instance"""
self.x = x
self.y = y
self.size = size
self.colour = (0,128,255)
self.thickness = 0
self.speed = 0.01
self.angle = math.pi/2
def display(self):
"""Draw the ball"""
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
def move(self):
"""Move the ball according to angle and speed"""
self.x += math.sin(self.angle) * self.speed
self.y -= math.cos(self.angle) * self.speed
(self.angle, self.speed) = addVectors((self.angle, self.speed), gravity)
self.speed *= drag
class Circle():
def __init__(self, (x,y), size):
"""Set up the new instance of the Circle class"""
self.x = x
self.y = y
self.size = size
self.colour = (236, 236, 236)
self.thickness = 0
self.angle = 0 # Needed for collision...
self.speed = 0 # detection against balls
def display(self):
"""Draw the circle"""
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness
Thanks in advance, Nathan
Without answering your question, I'd like to comment on your implementation strategy and recommend a new approach. You represent the velocity of the ball in polar coordinate form, as ball.angle and ball.speed.
I think that this is going to be generally inconvenient for you. For example, in your collision code you end up calling atan2 to turn the vector (dx, dy) into an angle, and then you call sin and cos to turn the angle back into a vector again. (Also, should you ever try to generalize your code to three dimensions, you will find yourself in a world of pain.) So, unless you have particular requirements that necessitate polar coordinates, I recommend that you do what everyone else does, namely represent the velocity of the ball in Cartesian coordinates as the vector (vx, vy).
I also recommend changing your physics approach from a static one ("is object A currently colliding with object B?") to a dynamic one ("will object A collide with object B during its next movement step?"). In a static physics system you often end up with objects intersecting each other at the end of a movement step, and then you have to figure out the best way to get them to separate again, which is hard to get right.
If you do both of these, it is straightforward to bounce the ball without any trigonometry.
Step 1. Transform circle/circle collision into point/circle collision using Minkowski addition:
Step 2. Consider a time segment in which the ball starts at p = (px,py) and moves by v = (vx,vy). Does it intersect with the circle? You can use a standard line segment/circle test for this except that the sense of the test is reversed.
Step 3. Find the point of collision c = (cx,cy). The ball bounces off the circle in the same way as it would bounce off the line t tangent to the circle at this point. For a circle centred at the origin, the tangent vector is just (−cy,cx) and I'm sure you can work out how to compute it for other circles.
See this answer for how to calculate the new path of the ball based on coefficients of friction and restitution.
Step 4. Don't forget that the ball may still have some distance to move along the new vector w. If the time step is large enough or the velocity high enough it may collide again during the same time segment.
I'm glad you liked my tutorial. I like your variation, it should actually be simpler.
First, I think you need change the test for collision to:
if distance >= circle.size - ball.size:
Because the larger the ball size, the smaller the distance between its centre and the centre of the circle can be. This should make the balls bounce at the right place (inside the circle).
Then I think you just need to swap the signs for the x and y and everything should work.
ball.x += math.sin(angle)
ball.y -= math.cos(angle)
To move the ball by the correct distance you can calculate the overlap:
overlap = math.hypot(dx, dy) - (circle.size - ball.size)
if overlap >= 0:
tangent = math.atan2(dy, dx)
ball.angle = 2 * tangent - ball.angle
ball.speed *= elasticity
angle = 0.5 * math.pi + tangent
ball.x += math.sin(angle)*overlap
ball.y -= math.cos(angle)*overlap
Good luck
Most graphics packages use upper-left as start for drawing code. You most likely want 2 sets of coordinates, the one's you collide/move/etc with and the one's for drawing (x-radius, y-radius).
Also, without having thought about it too much, should the check for intersection be distance + ball.size >= circle.size? The balls distance from the center plus its radius should be less than the circle's radius, if I understood the setup correctly.

Categories