简体   繁体   中英

How to slow down animation

So I just have this animation for my game and I was wondering how to slow it down, the code I put in slows down my animation and my player but I only want it to slow down my animation, I don't know why but it is not working for me.https://gyazo.com/61d174e123e8745f170ff313029c2caf

This is what I wrote to slow down my image but it is not working, It's in class Player

self.fps = 10
self.clock = pygame.time.Clock()

My full code

import pygame
pygame.init()

window = pygame.display.set_mode((700,500))
pygame.display.set_caption("Noobs First Game")


move = pygame.image.load("WASD.png")


# Playerman
class Player:
    def __init__(self,x,y,width,height,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.speed = 5
        self.isJump = False
        self.JumpCount = 10
        self.idle =[pygame.image.load("player_idel_1.png"),
                            pygame.image.load("player_idel_2.png"),
                            pygame.image.load("player_idel_3.png"),
                            pygame.image.load("player_idel_4.png"),
                            pygame.image.load("player_idel_5.png"),
                            pygame.image.load("player_idel_6.png"),
                            pygame.image.load("player_idel_7.png"),
                            pygame.image.load("player_idel_8.png")
                            ]


        self.fall = 0
        self.rect = pygame.Rect(x,y,height,width)
        self.idle = [pygame.transform.scale(image,(image.get_width()*1,image.get_height()*1)) for image in self.idle]
        self.fps = 10
        self.clock = pygame.time.Clock()
        self.anim_index = 0
        self.direction = "idle"
    def get_rect(self):
        self.rect.topleft = (self.x,self.y)
        return self.rect
    
    def draw(self):
        pygame.draw.rect(window,self.color,self.get_rect())
        if self.direction == "idle":
            self.clock.tick(self.fps)
            image_list = self.idle

            
        if self.anim_index >= len(image_list):
            self.anim_index = 0
        player_image = image_list[self.anim_index]
        self.anim_index += 1
        window.blit(player_image,self.rect)


class Platform:
    def __init__(self,x,y,width,height,color):
        self.x = x
        self.y =y
        self. width = width
        self.color = color
        self.height = height
        self.color = color
        self.speed = 4
        self.rect = pygame.Rect(x,y,width,height)
    def get_rect(self):
        self.rect.topleft = (self.x,self.y)
        return self.rect
    def draw(self):
        pygame.draw.rect(window,self.color,self.get_rect())


class Rule:
    def __init__(self,x,y,width,height,color):
        self.x = x
        self.y =y
        self. width = width
        self.color = color
        self.height = height
        self.color = color
        self.speed = 4
        self.rect = pygame.Rect(x,y,width,height)
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)


# Colors for hitbox
white = (255,255,255)
green = (0,255,0)

# Drawing Player
playerman = Player(350,445,40,40,white)

#Drawing Platforms
platform1 = Platform(300,-9.1,40,500,green)
platform2 = Platform(330,451,2000,40,green)
platform3 = Platform(2300,-9.1,40,500,green)

# Drawing Rule
rule1 = Rule(340,-9.1,220,500,green)
rule2 = Rule(20000,-9,1,5,green)

# List
platforms = [platform1,platform2,platform3]

rules = [rule1,rule2]


# draws map
platformGroup = pygame.sprite.Group
Level = [
"                                         1   1",
"                                         1    ",
"                         1  1        111 1    ",
"                         1  1       111  1    ",
"                         11 1      1111 11    ",
"                         1  1     11111  1    ",
"                         1  1    1111111 1    ",
"           1   1   111   1 11   1111111  1    ",
"           1   1  11111     1  11111111          ",]

for iy,row in enumerate(Level):
    for ix, col in enumerate(row):
        if col == "1":
            new_platforms = Platform(ix*50,iy*50.2,50,50,(255,255,255))
            platforms.append(new_platforms)
    
            

# Windows color
def redrawwindow():
    window.fill((0,0,0))

    # Drawing the player and other stuff to the screen
    playerman.draw()

    for Platform in platforms:
        Platform.draw()
    for Rule in rules:
        Rule.draw()

x = 10
y = 10
x_change = 0
y_change = 0
old_x = x
old_y = y
fps = (30)
clock = pygame.time.Clock()

run = True
while run:
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False


    playerman.direction = "idle"


    if playerman.y < 250:
        playerman.y += 1
        for Platform in platforms:
            Platform.y += playerman.speed

    if playerman.y > 410:
        playerman.y -= playerman.fall
        for Platform in platforms:
            Platform.y -= playerman.fall

    
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_d:
            x_change = -7
        if event.key == pygame.K_a:
            x_change = 7

    if event.type == pygame.KEYUP:
        if event.key == pygame.K_d or event.key == pygame.K_a:
            x_change = 0

        x += x_change
        if x > 500 - playerman.width or x < 0:
            x = old_x
           
        # lets player move
    keys = pygame.key.get_pressed()
    px, py = playerman.x, playerman.y


    if keys[pygame.K_d]:
        for Platform in platforms:
            Platform.x -= playerman.speed
        for Rule in rules:
            Rule.x -= playerman.speed
        
 

    if keys[pygame.K_a]:
        for Platform in platforms:
            Platform.x += playerman.speed
        for Rule in rules:
            Rule.x += playerman.speed



    platform_rect_list = [p.rect for p in platforms]
    player_rect = playerman.get_rect()
    player_rect.topleft = (px, py)

    playerman.y = py
    if player_rect.collidelist(platform_rect_list) < 0:
        playerman.x = px

    move_right = keys[pygame.K_d]
    move_left = keys[pygame.K_a]
    if move_right: 
        for Platform in platforms:
            Platform.x -= playerman.speed
        for Rule in rules:
            Rule.x -= playerman.speed     # <---
    if move_left:
        for Platform in platforms:
            Platform.x += playerman.speed
        for Rule in rules:
            Rule.x += playerman.speed     # <---

    platform_rect_list = [p.get_rect() for p in platforms] # get_rect()
    player_rect = playerman.get_rect()
    player_rect.topleft = (px, py)

    playerman.y = py
    cI = player_rect.collidelist(platform_rect_list)
    if cI >= 0:
        # undo movement of platforms dependent on the direction and intersection distance
        dx = 0
        if move_right: 
            dx = platform_rect_list[cI].left - player_rect.right
        if move_left:
            dx = platform_rect_list[cI].right - player_rect.left
        for Platform in platforms:
            Platform.x -= dx
            Platform.get_rect() # update rectangle
        for Rule in rules:
            Rule.x -= dx             # <---

##############                
  
    # About isJump
    if not playerman.isJump:
        playerman.y += playerman.fall
        playerman.fall += 1
        playerman.isJump = False

        # this part lets you jump on platform only the top 
        collide = False
        for Platform in platforms:
            if playerman.get_rect().colliderect(Platform.rect):
                collide = True
                playerman.isJump = False
                playerman.y = Platform.rect.top - playerman.height
                if playerman.rect.right > Platform.rect.left and playerman.rect.left < Platform.rect.left - playerman.width:
                    playerman.x = Platform.rect.left - playerman.width
                if playerman.rect.left < Platform.rect.right and playerman.rect.right > Platform.rect.right + playerman.width:
                    playerman.x = Platform.rect.right
                       
            # colliding with floor      
            if playerman.rect.bottom >= 500:
                collide = True
                playerman.isJump = False
                playerman.Jumpcount = 10
                playerman.y = 500 - playerman.height

        # Jumping
        if collide:
            if keys[pygame.K_SPACE]:
                playerman.isJump = True
                py -= playerman.speed
            playerman.fall = 0

    # Jump Count

    else:
        if playerman.JumpCount >= 0:
            playerman.y -= (playerman.JumpCount*abs(playerman.JumpCount))*0.3
            playerman.JumpCount -= 1
        else:
            playerman.isJump = False
            playerman.JumpCount = 10

    redrawwindow()
    if playerman.rect.colliderect(rule1.rect):
        window.blit(move,(-40,-100))
    
    pygame.display.update()
pygame.quit()

The clock.ticks() will slow down the frame-rate of your whole application, so it's not ideal to have this in your sprite update function.

An easy way to slow-down the frame rate for just your player sprite is to look at the real-time millisecond clock provided by pygame.time.get_ticks() , and then change the "current frame" based on a delay.

Simply changing your Player.draw() function should be enough:

class Player:
    def __init__(self,x,y,width,height,color):
        # ...
        self.next_frame_time = 0           # when to move to the next frame

    def draw(self):
        if self.direction == "idle":
            image_list = self.idle

        # Is it time to show the next animation frame?
        time_now = pygame.time.get_ticks()
        if ( time_now > self.next_frame_time ):
            # set the time for the next animation-frame
            inter_frame_delay = 1000 // self.fps   
            self.next_frame_time = time_now + inter_frame_delay  # in the future
            # move the current image to the next (with wrap-around)
            self.anim_index += 1
            if self.anim_index >= len( image_list ):
                self.anim_index = 0

        pygame.draw.rect( window, self.color, self.get_rect() )
        player_image = image_list[self.anim_index]
        window.blit( player_image, self.rect )

So what we're doing here is calculating a delay to give the correct FPS animation. You set the FPS in Player.fps , so we convert this to an amount of milliseconds by dividing 1000 by fps . In the above code, this would give us 100 (as fps is 10 ).

So when the frame is drawn, we calculate and remember the time for the next frame, which is now plus that 100ms delay. If the millisecond-clock is greater than this time, then the wait period has elapsed, and it's time to move to the next animation frame.

Otherwise we just keep drawing the current frame. So with the screen updating at 60FPS, we will get a change every 6 frames or so. That means most calls to Player.draw() simply re-paint the same image.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM