Home > Software engineering >  pygame animation slow down not really working
pygame animation slow down not really working

Time:07-03

I am coding a simple game and in this game you click a bubble and it pops. Well I wanted to add some more detail to it so I made 4 images for the frames and when a user clicks the bubble it does go through them just really fast. I have tried using a solution posted on here: How to slow down animation but I am still having some trouble I am new to pygame and am still learning would someone be able to help me identify where I went wrong in implementing the code?

Edit: I have made a proper example that can be tested I hope this helps better.

import pygame, random, sys, os
from pygame.locals import *

#Path to program folder
basePath = os.path.dirname(sys.argv[0]) "\\"
#Initiating pygame and the pygame mixer for audio file
pygame.init()
#setting fps lock for game and startign clock (Both are needed for fps)
fps = 30
fClock = pygame.time.Clock()
#Setting up pygame display size and window
res = pygame.display.Info()
tv = pygame.display.set_mode((res.current_w, res.current_h), pygame.FULLSCREEN)
pygame.display.set_caption("Bubble Poparoo 1.0")
#Bubble sprite class

#Bubble sprite class
class Bubble(pygame.sprite.Sprite):
    def __init__(self):
        #88 -Entry by my son Quintin Wargel 06:54:00 AM 07/02/22 Age 8 Months old.

        #Bubble settings for setup and creation
        self.radius = int((res.current_h*40)/100)
        self.imFrames = [pygame.image.load(basePath "Images\\bPopF1.png").convert_alpha(),
                         pygame.image.load(basePath "Images\\bPopF2.png").convert_alpha(),
                         pygame.image.load(basePath "Images\\bPopF3.png").convert_alpha(),
                         pygame.image.load(basePath "Images\\bPopF4.png").convert_alpha()]
        self.sImg = pygame.transform.scale(self.imFrames[0], (self.radius/2, self.radius/2))
        self.rect = self.sImg.get_rect()
        self.baseX = random.randint(self.radius, res.current_w)
        self.way = 0
        self.rect.x = self.baseX
        self.rect.y = res.current_h self.radius 10
        self.hide = False
        self.index = 0
        self.nTime = 0
        self.anit = False
    #Check if sprite has been clicked
    def clickCheck(self, pos):
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            #Play animation
            self.anit = True
            self.aGo()
            
    def aGo(self):
        if self.anit:
            self.animate()

    def animate(self):
        tNow = pygame.time.get_ticks()
        if (tNow > self.nTime):
            fDelay = 40000 // 30
            self.nTime = tNow   fDelay

            self.index  = 1
            print(self.index)
            if self.index >= len(self.imFrames):
                self.index = 0
                self.anit = False
                
        tv.blit(pygame.transform.scale(self.imFrames[self.index], (self.radius/2, self.radius/2)), (self.rect.x, self.rect.y))
    
    def move(self):
        #Placing/Moving sprite on the screen
        if self.hide == False:
            if self.anit == False:
                tv.blit(self.sImg, (self.rect.x, self.rect.y))
        else:
            pass
        #Bubble movment
        self.rect.y -=3
        if self.rect.x == self.baseX 20:
           self.way = 1
        elif self.rect.x == self.baseX-20:
            self.way = 0
        else:
            pass

        if self.way == 0:
            self.rect.x  = 1
        else:
            self.rect.x -= 1
        #If the bubble is above the screen and out of view then resets to bottom of screen
        if self.rect.y <= -self.radius-10:
            self.baseX = random.randint(self.radius, res.current_w)
            self.rect.x = self.baseX
            self.rect.y = res.current_h self.radius 10
            self.radius = random.randint(10,50)
            self.hide = False
            
#Loop value and buuble list
go = True
sTime = 0
bList = []
#Main loop
while go:
    #Reseting the background
    tv.fill((0,0,0))
    #event checks
    for event in pygame.event.get():
        if event.type == QUIT:
            go = False
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                go = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            for b in bList:
                b.clickCheck(event.pos)
    #Every 5 seconds spawn a new bubble if there is less than 8
    if pygame.time.get_ticks() > sTime:
        sTime  = 5000
        if len(bList) < 8:
            bList.append(Bubble())
    #Looping through the bubble list to spawn/move them
    for b in bList:
        b.move()
    #Update the display and fps clock.
    pygame.display.update()
    fClock.tick(fps)
#Closing pygame and closing all functions
pygame.quit()
sys.exit()

CodePudding user response:

The problem is that self.index is incremented twice. Once in clickCheck (very often) and once in animate (delayed). Remove self.index = 1 from clickCheck.
Your animation stops if the mouse is not on the bubble. The animation only runs once when the mouse button is clicked. Set an attribute when the mouse is on the bubble and run the animation depending on that attribute in the application loop (move method) instead of the event loop (clickCheck method):

class Bubble(pygame.sprite.Sprite):
    def __init__(self):
        # [...]
        self.run_animation = False

    def clickCheck(self, pos):
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            pygame.mixer.music.play()
            self.run_animation = True

    def move(self):
        if self.run_animation:
            self.animate()
        # [...]

    def animate(self):
        tNow = pygame.time.get_ticks()
        if tNow > self.nTime:
            fDelay = 4000 // 30
            self.nTime = tNow   fDelay
            self.index  = 1
            if self.index >= len(self.imFrames):
                self.index = 0
                self.run_animation = False
                self.rect.y = -self.radius-10
        tv.blit(pygame.transform.scale(self.imFrames[self.index], (self.radius/2, self.radius/2)), (self.rect.x, self.rect.y))

See also How can I show explosion image when collision happens? and Spawning multiple instances of the same object concurrently in python

  • Related