Tag Archives: pygame

I tried to recreate an optical illusion

My friend Tyrone posted something he recorded from TV.
It was an illusion, using rotated images.

The effect is that it seems that the card is rotating at different speeds, when pressing the s (show/unshow) key, you see the card rotating at the same speed as before.

So I wanted to try to recreate this using python.
The effect is there, but a little less.
What can I improve?


Around the 30 seconds mark I disable the background, you’ll see the card rotating as before.


Better version, larger and using s key to toggle water off, to see the card rotating

import pygame
import math

# 20240409 added s to toggle 

screen = pygame.display.set_mode((1600, 900))
clock = pygame.time.Clock()

def blitRotate(surf, image, pos, originPos, angle):

    image_rect = image.get_rect(topleft = (pos[0] - originPos[0], pos[1]-originPos[1]))
    offset_center_to_pivot = pygame.math.Vector2(pos) - image_rect.center
    rotated_offset = offset_center_to_pivot.rotate(-angle)
    rotated_image_center = (pos[0] - rotated_offset.x, pos[1] - rotated_offset.y)
    rotated_image = pygame.transform.rotate(image, angle)
    rotated_image_rect = rotated_image.get_rect(center = rotated_image_center)
    surf.blit(rotated_image, rotated_image_rect)

    image = pygame.image.load('cards.png').convert_alpha()
    image2 = pygame.image.load('clear+sea+water-2048x2048.png').convert_alpha()
    text = pygame.font.SysFont('Times New Roman', 50).render('imagemissing', False, (255, 255, 0))
    image = pygame.Surface((text.get_width()+1, text.get_height()+1))
    image2 = image
    image.blit(text, (1, 1))

w, h = image.get_size()
angle = 0
angle2 = 0
done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    pos = (screen.get_width()/2, screen.get_height()/2)
    keys = pygame.key.get_pressed()
    if (not keys[pygame.K_s]):
        blitRotate(screen, image2, pos, (900, 900), angle2)
    blitRotate(screen, image, pos, (w/2, h/2), angle)
    angle += 1
    angle2 += math.sin(math.radians(angle))