How do you point the barrel towards mouse in pygame? - python

I have fixed the problem pointed out in this post, but now I am confused on how to point the gray rectangle (barrel) towards my mouse. Could somebody please help? Thanks!
Here is my code:
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("diep.io")
screen.fill((255,255,255))
auto_shoot = False
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.x_move = x_move
self.y_move = y_move
self.x_loc = x_loc
self.y_loc = y_loc
self.bullet_rect = self.image.get_rect()
def update(self):
self.x_loc += self.x_move
self.y_loc += self.y_move
self.bullet_rect.center = round(self.x_loc), round(self.y_loc)
rect = screen.blit(self.image, self.bullet_rect)
if not screen.get_rect().contains(rect):
bullets.remove(self)
if self.x_loc > 400 or self.y_loc > 400:
bullets.remove(self)
bullet = None
bullets = []
while True:
screen.fill((255, 255, 255))
pygame.draw.rect(screen, (100, 100, 100), (205, 193, 25, 15)) # This is the rectangle I want to point at my mouse
pygame.draw.circle(screen, (82, 219, 255), (200, 200), 15)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
pythag = float(math.sqrt(x**2 + y**2))
bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
for bullet in bullets:
bullet.update()
pygame.display.update()
pygame.time.delay(10)
Note: This is different from other problems because I am trying to point a rectangle at my mouse, and other posts are pointing an image at the mouse. That is not what I want to do. Secondly, pygame rectangles are defined by their bottom left corner, so this further complicates things.

For the rotation of the bullets see How to move a sprite according to an angle in Pygame and calculating direction of the player to shoot PyGmae.
Compute the angle of the direction vector grees(math.atan2(-y_move, x_move)) and rotate the bullet image:
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))
Rotating the rectangle is a little trickier. Draw the cannon on a pygame.Surface:
cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)
See How do I rotate an image around its center using PyGame?.
Write a function to rotate and blit a Surface:
def blitRotateCenter(surf, image, center, angle):
rotated_image = pygame.transform.rotate(image, angle)
new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
surf.blit(rotated_image, new_rect)
Use the function in the application loop to draw the cannon:
while True:
# [...]
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
angle = math.degrees(math.atan2(-y, x))
blitRotateCenter(screen, cannon, (200, 200), angle)
# [...]
See also How to rotate an image(player) to the mouse direction? and How can you rotate the sprite and shoot the bullets towards the mouse position?.
Complete example:
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("diep.io")
screen.fill((255,255,255))
clock = pygame.time.Clock()
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
#self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.image = pygame.Surface((20, 5), pygame.SRCALPHA)
self.image.fill((255, 0, 0))
self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))
self.x_move = x_move
self.y_move = y_move
self.x_loc = x_loc
self.y_loc = y_loc
self.bullet_rect = self.image.get_rect()
def update(self):
self.x_loc += self.x_move
self.y_loc += self.y_move
self.bullet_rect.center = round(self.x_loc), round(self.y_loc)
rect = screen.blit(self.image, self.bullet_rect)
if not screen.get_rect().contains(rect):
bullets.remove(self)
if self.x_loc > 400 or self.y_loc > 400:
bullets.remove(self)
cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)
def blitRotateCenter(surf, image, center, angle):
rotated_image = pygame.transform.rotate(image, angle)
new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
surf.blit(rotated_image, new_rect)
bullet = None
bullets = []
auto_shoot = False
run = True
while run:
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
angle = math.degrees(math.atan2(-y, x))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONUP:
pythag = float(math.sqrt(x**2 + y**2))
bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
screen.fill((255, 255, 255))
for bullet in bullets:
bullet.update()
blitRotateCenter(screen, cannon, (200, 200), angle)
pygame.display.update()
clock.tick(100)
pygame.quit()
exit()

Related

How do I make a sprite rotate around another moving sprite?

I am currently making a game and I want to add a power up. I am essentially trying to make something similar to the spell book from Castlevania. I found a code to help me get the initial position and rotation. The problem is, the cross doesn't move from it's initial location. It just circles in place while the other one leaves it. I am still new to pygame and the math that goes with game dev. It is still pretty confusing.
import pygame
class Crucifix(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.sprite = pygame.image.load('image'). convert_alpha()
self.image = self.sprite
self.rect = self.image.get_rect()
self.rect.x =500
self.rect.y = 500
self.mask = pygame.mask.from_surface(self.image)
def update(self):
self.rect.x -= 2
if self.rect.x == -100:
self.kill()
class EnemiesStrong(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.original_image = pygame.image.load('image').convert_alpha()
self.image = self.original_image
self.rect = self.image.get_rect()
self.angle = 0
def initLoc(self, pos, radius):
self.pos = pos
self.radius = radius
def update(self):
center = pygame.math.Vector2(self.pos) + pygame.math.Vector2(0, -self.radius).rotate(-self.angle)
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = (round(center.x), round(center.y)))
def turnLeft(self):
self.angle = (self.angle + 4) % 360
pygame.init()
window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()
cross1= Crucifix()
enemy_s = EnemiesStrong()
pos = cross1.rect.x, cross1.rect.y
enemy_s.initLoc(cross1.rect.center, 100)
all_sprites = pygame.sprite.Group(enemy_s)
all_sprites.add(cross1)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
all_sprites.update()
window.fill(0)
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I am not exactly sure what to try at this point. Any help would be appreciated.
You have to update the position of enemy_s in every frame depending on the position of cross1. Add a updatePos method to the EnemiesStrong class:
class EnemiesStrong(pygame.sprite.Sprite):
# [...]
def updatePos(self, new_pos):
self.pos = new_pos
Call updatePos in the application loop:
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
enemy_s.updatePos(cross1.rect.center) # <---
all_sprites.update()
window.fill(0)
all_sprites.draw(window)
pygame.display.flip()
Complete and minimal example based on your original code:
import pygame, math
class Crucifix(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 40), pygame.SRCALPHA)
pygame.draw.circle(self.image, "white", (20, 20), 20)
pygame.draw.line(self.image, "magenta", (20, 0), (20, 40), 5)
pygame.draw.line(self.image, "magenta", (0, 20), (40, 20), 5)
self.rect = self.image.get_rect(center = (400, 400))
self.mask = pygame.mask.from_surface(self.image)
self.px = 400
self.a = 0
def update(self):
offset_x = math.sin(self.a) * 100
self.a += 0.05
self.rect.x = round(self.px + offset_x)
class EnemiesStrong(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.original_image = pygame.Surface((40, 40), pygame.SRCALPHA)
pygame.draw.circle(self.original_image, "red", (20, 20), 20)
pygame.draw.polygon(self.original_image, "yellow", ((20, 0), (40, 20), (20, 40), (0, 20)))
self.image = self.original_image
self.rect = self.image.get_rect()
self.angle = 0
def initLoc(self, pos, radius):
self.pos = pos
self.radius = radius
def update(self):
center = pygame.math.Vector2(self.pos) + pygame.math.Vector2(0, -self.radius).rotate(-self.angle)
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = (round(center.x), round(center.y)))
def turnLeft(self):
self.angle = (self.angle + 4) % 360
def updatePos(self, new_pos):
self.pos = new_pos
pygame.init()
window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()
cross1 = Crucifix()
enemy_s = EnemiesStrong()
pos = cross1.rect.x, cross1.rect.y
enemy_s.initLoc(cross1.rect.center, 100)
all_sprites = pygame.sprite.Group(enemy_s)
all_sprites.add(cross1)
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *background.get_size(), (32, 32, 32), (48, 48, 48)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
enemy_s.updatePos(cross1.rect.center)
all_sprites.update()
window.blit(background, (0, 0))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()

How to draw a circle onto a surface and rotate it while moving?

I am trying to:
draw a circle onto my window
let it move AND rotate at the same time to simulate a rolling ball.
Appreciate anyone's solutions! Attached below is my code.
import pygame
#create win
W, H = 700, 700
win = pygame.display.set_mode((W, H))
pygame.display.set_caption("Rotating Ball Simul")
#color lib
BG = (20,20,20)
BLUE = (0,0,255)
#draw circle
ballX, ballY = 0, 0
ballW = 20
ballH = ballW
ball = pygame.draw.circle(win, BLUE, (ballX, ballY), ballW, 1)
def redraw_window():
win.fill(BG)
win.blit(ball, (ballX, ballY))
pygame.display.update()
def main():
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
redraw_window()
if __name__ == '__main__':
main()
A circle always looks the same when you rotate it. You must use a sphere image to see the rotation. Read about How do I rotate an image around its center using PyGame? and move the ball image and change the rotation of the image depending on the movement. The angle of rotation depends on the movement and the diameter of the ball:
angle -= (self.x - prev_x) / self.diameter * 180 / math.pi
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
Minimal example:
repl.it/#Rabbid76/PyGame-FollowInGrid
import os
import math
import pygame
class MarbelSprite(pygame.sprite.Sprite):
def __init__(self, x, ground, diameter, velocity, filename):
pygame.sprite.Sprite.__init__(self)
try:
self.image = pygame.transform.smoothscale(pygame.image.load(filename).convert_alpha(), (diameter, diameter))
except:
self.image = pygame.Surface((diameter, diameter), pygame.SRCALPHA)
pygame.draw.circle(self.image, (255, 128, 0), (diameter // 2, diameter // 2), diameter // 2)
self.original_image = self.image
self.rect = self.image.get_rect(midbottom = (x, ground))
self.diameter = diameter
self.x = x
self.velocity = velocity
self.move_x = 0
self.follow = None
self.angle = 0
def update(self, time, restriction):
move_x = 0
prev_x = self.x
if self.move_x != 0:
move_x = self.move_x * self.velocity * time
elif self.follow:
dx = self.follow.rect.centerx - self.x
move_x = (-1 if dx < 0 else 1) * min(self.velocity * time, abs(dx))
self.x += move_x
self.x = max(restriction.left + self.diameter // 2, min(restriction.right - self.diameter // 2, self.x))
self.rect.centerx = round(self.x)
self.angle -= (self.x - prev_x) / self.diameter * 180 / math.pi
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
pygame.init()
window = pygame.display.set_mode((500, 300))
clock = pygame.time.Clock()
ground_level = 220
object = MarbelSprite(window.get_rect().centerx, ground_level, 100, 0.4, 'BaskteBall.png')
follower = MarbelSprite(window.get_width() // 4, ground_level, 50, 0.2, 'TennisBall.png')
all_sprites = pygame.sprite.Group([object, follower])
run = True
while run:
time = clock.tick(60)
for events in pygame.event.get():
if events.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
object.move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
follower.follow = object
all_sprites.update(time, window.get_rect())
window.fill((32, 64, 224))
pygame.draw.rect(window, (80, 64, 64), (0, ground_level, window.get_width(), window.get_height()-ground_level))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()

Pygame mask collision

I'm trying to get proper collision detection with rotating surfaces in pygame. I decided to try using masks. It somewhat works, but it is not as precise as I'd liked/thought. I tried updating the mask at the end of the cycle to get a "fresh" hitbox for the next frame, but it didn't work as expected. What is my mistake?
import pygame
import random
WHITE = [255, 255, 255]
RED = [255, 0, 0]
pygame.init()
FPS = pygame.time.Clock()
fps = 6
winW = 1000
winH = 500
BGCOLOR = WHITE
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_caption('')
pygame.display.set_icon(win)
class Box(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([w, h], pygame.SRCALPHA)
self.image.fill(random_color())
self.mask = pygame.mask.from_surface(self.image)
self.rect = pygame.Rect(x, y, w, h)
self.angle = 0
def move(self):
self.rect.center = pygame.mouse.get_pos()
def draw(self):
blits = self.rotate()
win.blit(blits[0], blits[1])
self.mask = pygame.mask.from_surface(blits[0])
def rotate(self):
self.angle += 3
new_img = pygame.transform.rotate(self.image, self.angle)
new_rect = new_img.get_rect(center=self.rect.center)
return new_img, new_rect
def update_display():
win.fill(BGCOLOR)
player.draw()
for p in platforms:
p.draw()
pygame.display.update()
def collision():
return pygame.sprite.spritecollide(player, plat_collide, False, pygame.sprite.collide_mask)
def random_color():
return [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]
player = Box(100, 400, 50, 50)
platforms = [Box(300, 400, 100, 50)]
plat_collide = pygame.sprite.Group(platforms)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
hits = collision()
if hits:
BGCOLOR = RED
else:
BGCOLOR = WHITE
player.move()
update_display()
FPS.tick(fps)
pygame.quit()
Your application works fine. But note, pygame.sprite.collide_mask() use the .rect and .mask attribute of the sprite object for the collision detection.
You have to update self.rect after rotating the image:
class Box(pygame.sprite.Sprite):
# [...]
def rotate(self):
self.angle += 3
new_img = pygame.transform.rotate(self.image, self.angle)
new_rect = new_img.get_rect(center=self.rect.center)
# update .rect attribute
self.rect = new_rect # <------
return new_img, new_rect
See also Sprite mask
Minimal example: repl.it/#Rabbid76/PyGame-SpriteMask
import pygame
class SpriteObject(pygame.sprite.Sprite):
def __init__(self, x, y, w, h, color):
pygame.sprite.Sprite.__init__(self)
self.angle = 0
self.original_image = pygame.Surface([w, h], pygame.SRCALPHA)
self.original_image.fill(color)
self.image = self.original_image
self.rect = self.image.get_rect(center = (x, y))
self.mask = pygame.mask.from_surface(self.image )
def update(self):
self.rotate()
def rotate(self):
self.angle += 0.3
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
self.mask = pygame.mask.from_surface(self.image )
pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((400, 400))
size = window.get_size()
moving_object = SpriteObject(0, 0, 50, 50, (128, 0, 255))
static_objects = [
SpriteObject(size[0] // 2, size[1] // 3, 100, 50, (128, 128, 128)),
SpriteObject(size[0] // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128)),
SpriteObject(size[0] * 3 // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128))
]
all_sprites = pygame.sprite.Group([moving_object] + static_objects)
static_sprites = pygame.sprite.Group(static_objects)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
moving_object.rect.center = pygame.mouse.get_pos()
all_sprites.update()
collide = pygame.sprite.spritecollide(moving_object, static_sprites, False, pygame.sprite.collide_mask)
window.fill((255, 0, 0) if collide else (255, 255, 255))
all_sprites.draw(window)
pygame.display.update()
pygame.quit()
exit()

Pygame - Python - 360-degree angle on a cube, cursor / pointer / mouse orientation

I am trying to solve this problem of the angle, I noticed that there are two 0,0 in the coordinates, maybe that is what is preventing the cube from making a 360 degree turn, follows the video and the code.
Can someone help me?
video here
import pygame
import sys
import os
import math
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([1000, 500])
pygame.display.set_caption('Example 1')
player = pygame.image.load(os.path.join('img', 'rect.png')).convert_alpha() #path to cube ./img/rect.png
pygame.font.init()
font = pygame.font.get_default_font()
font_angle = pygame.font.SysFont(font, 44, True)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
clock.tick(60)
screen.fill((255, 255, 255)) #screen background color
player_rect = player.get_rect() #player rect (for center position)
mouse_x, mouse_y = pygame.mouse.get_pos() #mouse position (x, y)
#to define angle - start
hypo = math.sqrt(math.pow(mouse_x - (player_rect[0] + player_rect.centerx), 2) +
math.pow(mouse_y - (player_rect[1] + player_rect.centery), 2))
cos = (mouse_x - (player_rect[0] + player_rect.centerx)) / hypo
sin = (mouse_y - (player_rect[1] + player_rect.centery)) / hypo
angle = (180 / math.pi) * - math.atan2(sin, cos)
#end
newplayer = pygame.transform.rotate(player, angle) #rotate cube
screen.blit(newplayer, [300, 100]) #show cube in screen
text = font_angle.render(str("%.2f" % angle), 1, (255, 0, 0)) #show angle in mouse position
screen.blit(text, ((mouse_x+20), mouse_y)) #show text
pygame.display.update() #update frames
main()
You can just subtract the player_rect.centerx position from the mouse_x position (the same for y) and pass it to math.atan2:
dist_x = mouse_x - player_rect.centerx
dist_y = mouse_y - player_rect.centery
angle = -math.degrees(math.atan2(dist_y, dist_x))
Create the rect before the while loop starts and pass the desired center coordinates. Use get_rect to create a new rect after the image is rotated and pass the center coords of the previous rect to keep it centered. And blit the image at the player_rect (that means at its topleft coordinates).
import pygame
import sys
import os
import math
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([1000, 500])
# player = pygame.image.load(os.path.join('img', 'rect.png')).convert_alpha() #path to cube ./img/rect.png
player = pygame.Surface((50, 30), pygame.SRCALPHA)
pygame.draw.polygon(player, (100, 200, 255), [(0, 0), (50, 15), (0, 30)])
player_rect = player.get_rect(center=(500, 250)) # player rect (for center position)
font = pygame.font.get_default_font()
font_angle = pygame.font.SysFont(font, 44, True)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
clock.tick(60)
screen.fill((255, 255, 255))
mouse_x, mouse_y = pygame.mouse.get_pos()
dist_x = mouse_x - player_rect.centerx
dist_y = mouse_y - player_rect.centery
angle = -math.degrees(math.atan2(dist_y, dist_x))
newplayer = pygame.transform.rotate(player, angle)
# Create a new rect and pass the center of the old rect.
player_rect = newplayer.get_rect(center=player_rect.center)
screen.blit(newplayer, player_rect) # Blit it at the player_rect.
text = font_angle.render(str("%.2f" % angle), 1, (255, 0, 0))
screen.blit(text, ((mouse_x+20), mouse_y))
pygame.display.update()
main()

How to make the rotation (by the center) of this pygame sprite work?

I'm having a great difficulty to create a single sprite rotation using pygame.
I'm following this code (https://stackoverflow.com/a/47688650/5074998) to obtain a center rotation of a sprite. And here is my current code:
import pygame
FPS: int = 100
W = 600
H = 400
MAGENTA = (255, 0, 255)
BLACK = (0, 0, 0)
pygame.init()
screen = pygame.display.set_mode([W, H])
pygame.display.set_caption("Cars")
clock = pygame.time.Clock()
class sp():
def __init__(self):
self.image = pygame.Surface((122, 70), pygame.SRCALPHA)
pygame.draw.polygon(self.image, pygame.Color('dodgerblue1'),
((1, 0), (120, 35), (1, 70)))
self.orig_image = self.image
self.rect = self.image.get_rect(center=[W / 2, H / 2])
self.angle = 0
def update(self):
self.angle += 2
self.rotate()
screen.blit(self.image, [100, 100])
def rotate(self):
self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
sp1 = sp()
out = pause = False
while not out:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
out = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pause = not pause
if not pause:
screen.fill(BLACK)
sp1.update()
pygame.display.flip()
But I can't understand why I get this:
Could anyone help me?
That happens because you're blitting the self.image at the position [100, 100] instead of the self.rect (that means at the self.rect.topleft coordinates). The size of the image is different after each rotation and if you just blit it at the same top left coordinates, the image will wobble like that because the center is somewhere else each frame. You can see that by drawing the bounding rect at [100, 100]:
pygame.draw.rect(screen, (255, 0, 0), [(100, 100), self.image.get_size()], 1)
To fix this problem, you have to create a new rect each time and set its center coordinates to the center coords of the previous rect. That will adjust the topleft coordinates (where the image gets blitted) as well, so that the image stays centered. Then just blit the image at the rect:
screen.blit(self.image, self.rect)
Draw the self.rect to see how the topleft coord changes all the time now whereas the center won't move:
pygame.draw.rect(screen, (255, 0, 0), self.rect, 1)

Categories