Reputation: 43
So I've been working on an ant simlulation like project and I've encountered this issue and replicated it here. In essence what I did is draw a circle every surface update at the location of the cursor using pygame.mouse.get_pos().
But somehow I'm getting this issue where the location of the circle is way off the cursur by growing intervals when you move the cursor away from the top-left side of the window. There's also this graphical glitch where it seems that the cursor brings along a fixed surface of the window itself that contains the surface update of the objects behind the circle and the circle itself moving inside it. It also blocks the object's actual surface behind this window as you can see from the link below.
https://i.gyazo.com/c8b268cf072d040bb4000764d4955cd7.mp4
I've looked around online and so far I'm not even close to solving this issue. I'm not sure if it's a surface layering problem, a problem with my logic or if it's a glitch inside pygame. In any case here's the code below to replicate the problem.
"""
import sys
from random import randint, uniform
import pygame
from pygame.sprite import Sprite
class MainGame:
"""Main pygame class."""
def __init__(self):
"""Initialize game assets."""
pygame.init()
self.resolution = (1280, 720)
self.screen = pygame.display.set_mode(
self.resolution
)
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption('Circle Test')
# Insert game objects below this line.
self.ccirc = CursorCircle(self)
self.sample1 = pygame.sprite.Group()
self.sample2 = pygame.sprite.Group()
for _ in range(10):
self.sample1.add(SampleObject(self))
sample = SampleObject(self)
sample.front = 0
self.sample2.add(sample)
def start(self):
"""Main game loop."""
while True:
self._keyboard_basic()
# Insert object update below this line.
self.ccirc.update()
self._update_screen()
def _update_screen(self):
"""Game screen update."""
self.screen.fill((77, 77, 77))
# Insert surface update below this line. ###
for i in self.sample2:
i.blitme()
self.ccirc.blitme()
for i in self.sample1:
i.blitme()
pygame.display.flip()
def _keyboard_basic(self):
"""Response to keypress and mouse events"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._event_keydown(event)
elif event.type == pygame.KEYUP:
self._event_keyup(event)
def _event_keydown(self, event):
"""Keydown events."""
if event.key == pygame.K_UP:
print('Pressed ↑')
elif event.key == pygame.K_DOWN:
print('Pressed ↓')
elif event.key == pygame.K_LEFT:
print('Pressed ←')
elif event.key == pygame.K_RIGHT:
print('Pressed →')
elif event.key == pygame.K_q:
sys.exit()
def _event_keyup(self, event):
"""Keyup events."""
pass
class SampleObject(Sprite):
"""Sample object on screen."""
def __init__(self, main_game):
"""Initialize class assets."""
super().__init__()
self.screen = main_game.screen
self.screen_rect = self.screen.get_rect()
self.image = pygame.image.load('pointer.png')
self.image = pygame.transform.rotate(self.image, randint(1, 360))
self.image1 = pygame.image.load('pointer-.png')
self.image1 = pygame.transform.rotate(self.image1, randint(1, 360))
self.rect = self.image.get_rect()
self.rect.centerx = randint(1, main_game.resolution[0])
self.rect.centery = randint(1, main_game.resolution[1])
self.front = 1
def blitme(self):
"""Surface update."""
if self.front:
self.screen.blit(self.image, self.rect)
else:
self.screen.blit(self.image1, self.rect)
class CursorCircle(Sprite):
"""Circle that follows the cursor."""
def __init__(self, main_game):
"""Initialize class assets."""
super().__init__()
self.screen = main_game.screen
self.screen_rect = self.screen.get_rect()
self.color = (0, 102, 204)
# self.center = [self.screen_rect.centerx, self.screen_rect.centery]
# self.center = [0,0]
self.radius = 100
def update(self):
"""Loop update."""
self.center = pygame.mouse.get_pos()
def blitme(self):
"""Surface update."""
self.circle = pygame.draw.circle(self.screen, self.color, self.center, self.radius)
self.screen.blit(self.screen, self.circle)
if __name__ == '__main__':
game = MainGame()
game.start()
"""
Versions *Python 3.9.1 *pygame 2.0.1
Upvotes: 1
Views: 197
Reputation: 210968
pygame.draw.circel
draws a circle on the screen
. This function doesn't generate something like a circle object. See how to draw shapes.
self.screen.blit(self.screen, self.circle)
doesn't do what you'd expect, however. It copies the entire screen onto itself in the place of the circle.
Remove this instruction:
class CursorCircle(Sprite):
# [...]
def blitme(self):
"""Surface update."""
pygame.draw.circle(self.screen, self.color, self.center, self.radius)
#self.screen.blit(self.screen, self.circle) <--- DELETE
Alternatively you can draw the circle on a pygame.Surface
object with a per pixel alpha format (pygame.SRCALPHA
) and blit
the Surface on the screen:
class CursorCircle(Sprite):
"""Circle that follows the cursor."""
def __init__(self, main_game):
"""Initialize class assets."""
super().__init__()
self.screen = main_game.screen
self.color = (0, 102, 204)
self.radius = 100
self.circle = pygame.Surface((radius*2, radius*2), pygame.SRCALPHA)
pygame.draw.circle(self.circle, self.color, (radius, radius), radius)
self.rect = self.circle.get_rect()
def update(self):
"""Loop update."""
self.rect.center = pygame.mouse.get_pos()
def blitme(self):
"""Surface update."""
self.screen.blit(self.circle, self.rect)
Upvotes: 2