(trying to make a whack-a-mole game)Whenever I move the mouse, the position of the image of the mole seems to move 3-5x slower than when I'm not moving the mouse, and I'm not sure what's causing it since the position should update based on how much time has passed.
The screen for the game is 500x500 pixels, the images are 50x50 pixels and there's a 10x10 array that acts as a map to decide where the moles are allowed to appear
The code:
get a random position from a 10x10 map
update the position of the mole picture by one pixel every 30 ticks
get the position of the mouse (one the screen of 500x500 pixels)
get the position of the block the mole is supposed to go (on the 10x10 map)
order in which the images are drawn on the screen:
the map
the hammer while moving
the block above the mole
the mole (goes up by 1 pixel)
the block at the original position of the mole
the hammer while not moving
the issue is, the mole goes up much slower when I'm moving the mouse and I'm not sure what's the problem. I also used print statements to check.
def moleGoUp(self):
nbPixel = 0
#returns a random position
initialPos = self.returnRandPosition()
while nbPixel < 50:
tickCounter = pygame.time.get_ticks() % 30
if tickCounter == 0:
nbPixel += 1
#gets position of mouse
mousePos = pygame.mouse.get_pos()
#blits the background block that the mole is supposed to go to
blockAbovePos = [initialPos[1] * 50, initialPos[0] * 50 - 50]
#blits the mole at position (goes up by one pixel every 20 ticks)
newPos = [initialPos[1] * 50, (initialPos[0]*50 - nbPixel)]
initPosToBlit = [initialPos[1] * 50, initialPos[0] * 50]
for event in pygame.event.get():
mousePos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
sys.exit()
#draws the map
self.drawMap()
# blits the hammer
display_surf.blit(imagePlayer, tuple(mousePos))
# counts how many ticks has passed
tickCounter = pygame.time.get_ticks() % 30
print("in event loop")
display_surf.blit(imageWall, tuple(blockAbovePos))
display_surf.blit(imageTarget, tuple(newPos))
#blits the background at the original position of the mole
display_surf.blit(imageWall,tuple(initPosToBlit))
#blits the hammer
display_surf.blit(imagePlayer, tuple(mousePos))
print("out of event loop")
#blits the background over the mole
if nbPixel == 50:
display_surf.blit(imageWall, (initialPos[1]*50, initialPos[0]*50 - nbPixel))
pygame.display.update()
output from the print:
in event loop
out of event loop
in event loop
out of event loop
in event loop
out of event loop
in event loop
out of event loop
in event loop
out of event loop
The performance drop is a caused because you are calling self.drawMap()
in the event loop. The event loop is called once per event. Multiple events per frame can occur, especially when the mouse is moved.
I recommend creating the map only when needed. Render the map into a pygame.Surface
object and blit
the map Surface onto the display in each frame. When the map has changed then recreate the map Surface.
Create a "draw" method that renders on a target Surface rather than directly on the display Surface:
def drawMap(self, traget_surf):
# draw on traget_surf
# [...]
Add a variable map_surf
and map_changed = True
. Render the map in the application loop if map_changed
is set and set map_changed == False
. blit
the map_surf
Surface to the display in each frame. Whenever the map needs to be changed, it is sufficient to set map_changed = True
:
map_surf = pygame.Surface(display_surf.get_size())
map_changed = True
while nbPixel < 50:
# [...]
if map_changed:
self.drawMap(map_surf)
map_changed = False
# [...]
display_surf.blit(map_surf, (0, 0))
display_surf.blit(imageWall, tuple(blockAbovePos))
display_surf.blit(imageTarget, tuple(newPos))
display_surf.blit(imageWall,tuple(initPosToBlit))
display_surf.blit(imagePlayer, tuple(mousePos))