'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()
Solution 1:[1]
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()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rabbid76 |

