Search code examples
pythonpygame

How can I apply some animation for list of images in pygame?


I'm working on a card game using python pygame I want when the game start the cards move one by one from the center to left and right just one time . How can I apply some animation for list of images in pygame I did it for one image it worked well but I don't know how to do it with list of images any help thanks

from enum import Enum
from pygame.sprite import Sprite
import pygame
import random

type=Enum('type','Heart Diamond Club Spade')
value=Enum('value','2 3 4 5 6 7 8 9 10 J Q K A')

class Card(Sprite):
    def __init__(self,type,value,screen) :
        super(Card,self).__init__()
        self.card_type=type
        self.card_value=value
        self.screen=screen
        self.imgpath='./Resources/'+str(self.card_value.name)+' '+str(self.card_type.name)+'.jpg'
        self.card_img=pygame.image.load(self.imgpath)
        self.card_img=pygame.transform.scale(self.card_img, (70, 95))
        self.card_img.convert()
        self.card_rect=self.card_img.get_rect()
        

    def __str__(self) :
        txt=str(self.card_value.name)+' '+str(self.card_type.name)
        return txt

    def __eq__(self, __o: object) -> bool:
        if self.card_type==__o.card_type and self.card_value==__o.card_value:
            return True
        else:
            return False

    def __lt__(self,__o:object) -> bool:
        if self.card_type==__o.card_type and int(self.card_value.value)<int(__o.card_value.value):
            return True
        else:
            return False

    def __gt__(self,__o:object) -> bool:
        if self.card_type==__o.card_type and int(self.card_value.value)>int(__o.card_value.value):
            return True
        else:
            return False
    
    def blitme(self,x,y):
        self.card_rect.x=x
        self.card_rect.y=y
        self.screen.blit(self.card_img,self.card_rect)
        
    
        

def get_Deck(screen):
        cardlist=list()
        for t in type:
            for v in value:
                c=Card(t,v,screen)
                cardlist.append(c)
        random.shuffle(cardlist)
        return cardlist   

def deal(deck,cardNum):
    cardlist=list()
    for i in range(cardNum):
        c=random.choice(deck)
        deck.remove(c)
        cardlist.append(c)
    cardlist=sorted(cardlist,key=lambda x:(x.card_type.value,x.card_value.value) ) 
    return cardlist
        
class Player():
    def __init__(self,rank,screen) -> None:
        self.name=None
        self.hand=None
        self.score=None
        self.rank=rank
        self.screen=screen

    def draw_cards(self):
        screen_rect=self.screen.get_rect()
        if self.rank==0:
            x=screen_rect.left+((screen_rect.width-975)/2)
            y=screen_rect.bottom-100
            for c in self.hand:
                c.card_rect.bottom=screen_rect.bottom
                c.x=x
                c.blitme(x,c.card_rect.y)
                x+=75    
    
    def cards_animation(self):
        for c in self.hand:
            c.card_rect.x-=10



[![image description][1]][1]


  [1]: https://i.sstatic.net/L1NbQ.png

Solution

  • I played around with your code, while trying to assimilate what you ultimately wanted to do with moving and animation. What it seemed like was needed was an additional function to perform a redraw of your images which performed different location setting as opposed to the draw function which basically was resetting every position back to the initial spots.

    In the initiation of the player hands, the program could call the draw function.

        players[0].draw_cards()
    

    The down in the "while" loop, the program would then call the redraw function instead.

            screen.fill((3,99,14))
            players[0].redraw_cards()
            players[0].cards_animation()
    

    The redraw function would be a slimmed down version of the draw function.

        def redraw_cards(self):
            for c in self.hand:
                c.blitme(c.card_rect.x,c.card_rect.y) 
    

    For what it might be worth, here is a copy of your code with my tweaks. You can analyze it and if I went off on a tangent, just dispose of it.

    from enum import Enum
    from pygame.sprite import Sprite
    import pygame
    import random
    import sys
    
    type=Enum('type','hearts diamonds clubs spades')
    value=Enum('value','2 3 4 5 6 7 8 9 10 jack queen king ace')
    
    class Card(Sprite):
        def __init__(self,type,value,screen) :
            super(Card,self).__init__()
            self.card_type=type
            self.card_value=value
            self.screen=screen
            self.imgpath='/home/craig/images/PNG-cards-1.3/' + str(self.card_value.name)+'_of_' + str(self.card_type.name) +'.png'
            self.card_img=pygame.image.load(self.imgpath)
            self.card_img=pygame.transform.scale(self.card_img, (70, 95))
            self.card_img.convert()
            self.card_rect=self.card_img.get_rect()
            
        def __str__(self) :
            txt=str(self.card_value.name)+' '+str(self.card_type.name)
            return txt
    
        def __eq__(self, __o: object) -> bool:
            if self.card_type==__o.card_type and self.card_value==__o.card_value:
                return True
            else:
                return False
    
        def __lt__(self,__o:object) -> bool:
            if self.card_type==__o.card_type and int(self.card_value.value)<int(__o.card_value.value):
                return True
            else:
                return False
    
        def __gt__(self,__o:object) -> bool:
            if self.card_type==__o.card_type and int(self.card_value.value)>int(__o.card_value.value):
                return True
            else:
                return False
        
        def blitme(self,x,y):
            self.card_rect.x = x
            self.card_rect.y = y
            self.screen.blit(self.card_img,self.card_rect)
    
    def get_Deck(screen):
            cardlist=list()
            for t in type:
                for v in value:
                    c=Card(t,v,screen)
                    cardlist.append(c)
            random.shuffle(cardlist)
            return cardlist   
    
    def deal(deck,cardNum):
        cardlist=list()
        for i in range(cardNum):
            c=random.choice(deck)
            deck.remove(c)
            cardlist.append(c)
        cardlist=sorted(cardlist,key=lambda x:(x.card_type.value,x.card_value.value) ) 
        return cardlist
            
    class Player():
        def __init__(self,rank,screen) -> None:
            self.name=None
            self.hand=None
            self.score=None
            self.rank=rank
            self.screen=screen
    
        def draw_cards(self):
            screen_rect=self.screen.get_rect()
            if self.rank==0:
                x=screen_rect.left+((screen_rect.width-975)/2)
                y=screen_rect.bottom-120
                for c in self.hand:
                    c.card_rect.bottom=screen_rect.bottom
                    c.x=x
                    c.blitme(x,y)
                    x+=75    
            if self.rank==1:
                x=screen_rect.left+((screen_rect.width-975)/2)
                y=screen_rect.top + 20
                for c in self.hand:
                    c.card_rect.top=screen_rect.top
                    c.x=x
                    c.blitme(x,y)
                    x+=75    
            if self.rank==2:
                x= 80
                y=screen_rect.top + 20
                for c in self.hand:
                    c.card_rect.top=screen_rect.top
                    c.x=x
                    c.blitme(x,y)
                    y+=75    
                    
        def redraw_cards(self):
            for c in self.hand:
                c.blitme(c.card_rect.x,c.card_rect.y) 
        
        def cards_animation(self):
            for c in self.hand:
                c.card_rect.x += 2
                if c.card_rect.x > 1400:
                    c.card_rect.x = 40
                
    def run_game():
        pygame.init()
        infoObject=pygame.display.Info()
        w=infoObject.current_w-100
        h=infoObject.current_h-100
        screen=pygame.display.set_mode((w,h))
        screen.fill((3,99,14))
        pygame.display.set_caption('Game1')
        clock = pygame.time.Clock()
        # card1=Card(type['Club'],value['7'],screen)
        # card1.blitme(card1.card_rect.x,card1.card_rect.y)
        deck=get_Deck(screen)
        players=list()
        for i in range(4):
            p=Player(i,screen)
            p.hand=deal(deck,13)
            players.append(p)
        players[0].draw_cards()
        players[1].draw_cards()
        players[2].draw_cards()
        x = 0
        y = 0
        moving = False
        while True:
            clock.tick(4800)  
            screen.fill((3,99,14))
            # Watch for keyboard and mouse events.
            players[0].redraw_cards()
            players[1].redraw_cards()
            players[2].redraw_cards()
            if (x != 0 and y !=0):
                players[0].hand[8].blitme(x,y) 
                x = 0
                y = 0
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    moving = True
                elif event.type == pygame.MOUSEBUTTONUP:
                    moving = False
                elif event.type == pygame.MOUSEMOTION and moving:
                    x, y = event.pos
                    
            screen.fill((3,99,14))
            players[0].redraw_cards()
            players[0].cards_animation()
            players[1].redraw_cards()
            players[1].cards_animation()
            players[2].redraw_cards()
            players[2].cards_animation()
            pygame.display.flip()
    
    run_game()
    

    FYI, I had to hunt down a different set of open source card images so you would want to revert to your code for the card class.