Darius Otincelescu
Darius Otincelescu

Reputation: 23

Pygame rendering surface to screen without clearing the screen

When you click on a specific card it should appear above, when clicked again it should drop down below. Momentarily when you click on a card, it doesn't just move the card up, it basically duplicates the card.

This is the script:

from utilities import *
import pygame
import sys

def main():
    pygame.init()
    size = width, height = 1920, 1020
    screen = pygame.display.set_mode(size)
    screen.fill((10, 200, 100))

    def display_card(card):
        screen.blit(pygame.image.load(card.img), card.coordonates)

    game = MackaoGame("Test1", "Test2")
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                game.change_card_status(pygame.mouse.get_pos())
        
        card_count = 0
        for player, deck in game.player_decks.items():
            new_cards = []
            for card in deck:
                card_image = pygame.image.load(card.img)
                card.make_coordonates((50 * card_count + 500, 500))
                if card.status == "selected":
                    card.coordonates[1] -= 100
                new_cards.append(card)
                card_count += 1
            game.player_decks[player] = new_cards

        for player, deck in game.player_decks.items():
            for card in deck:
                display_card(card)
        pygame.display.update()

if __name__ == "__main__":
   main()

This is the utilities file:

from random import sample
from PIL import Image

class Card:

    def __init__(self, num, symbol, img, status):
        self.num = num
        self.symbol = symbol
        self.img = img
        self.status = status
        with Image.open(img) as image:
            self.img_width, self.img_height = image.size
        self.coordonates = [0, 0]
        self.velocity = 0
    
    def __repr__(self):
        return "This card is a {num} of {symbol}.".format(num = self.num, symbol = self.symbol)
    
    def __eq__(self, other):
        if self.num == other.num and self.symbol == other.symbol:
            return True
        return False
    
    def make_coordonates(self, center):
        self.coordonates = [center[0] - self.img_width / 2, center[1] - self.img_height / 2]

class MackaoGame:
    def __init__(self, *players):
        self.players = players
        self.player_wait_times = {player: 0 for player in players}
        self.give_cards()
        self.card_debt = 0
        self.round = 0

    def make_deck(self):
        deck = []
        width_total = 543
        height_total = 278
        signs = ["clubs", "hearts", "spades", "diamonds"]
        row = -1
        with Image.open("playing_cards.png") as card_img:
            for i in range(4):
                row += 1
                for j in range(13):
                    box = (width_total / 13 * j, height_total / 4 * i, width_total / 13 * (j + 1), height_total / 4 * (i + 1))
                    card_img.crop(box).save("{j}_{i}.png".format(j = j, i = i))
                    deck.append(Card(j, signs[i], "{j}_{i}.png".format(j = j, i= i), "ready"))
        return deck
        
    def mix_deck(self, deck):
        return sample(deck, len(deck))

    def give_cards(self):
        remaining_deck = self.mix_deck(self.make_deck())
        main_deck = []
        player_decks = {}
        for name in self.players:
            if player_decks.get(name) is None:
                cards = []
                for i in range(5):
                    cards.append(remaining_deck.pop())
                player_decks[name] = cards
        main_deck.append(remaining_deck.pop())
        self.main_deck, self.remaining_deck, self.player_decks = main_deck, remaining_deck, player_decks

    def get_curent_player(self):
        self.round += 1
        self.curent_player = self.players[(round - 1) % len(self.players)]

    def put_cards(self):
        for player, deck in self.player_decks.items():
            for card in deck:
                if card.status == "selected":
                    self.main_deck.append(card)
                    self.player_decks[player].remove(card)
            
                if card.num == 2:
                    self.card_debt += 2
                if card.num == 3:
                    self.card_debt += 3
                if card.num == 4:
                    self.player_wait_times[player] = 0
                if card.num == 7:
                    self.card_debt = 0
                    self.player_wait_times[player] = 0
    
    def can_change_status(self, card):
        return True

    def change_card_status(self, coordonates):
        for player, deck in self.player_decks.items():
            new_cards = []
            for card in deck:
                if coordonates[0] > card.coordonates[0] and coordonates[0] < card.coordonates[0] + card.img_width and coordonates[1] > card.coordonates[1] and coordonates[1] < card.coordonates[1] + card.img_height:
                    if card.status == "ready":
                        if self.can_change_status(card):
                            card.status = "selected"
                            print(card.status)
                    elif card.status == "selected":
                        card.status = "ready"
                        print(card.status)
                new_cards.append(card)
            self.player_decks[player] = new_cards

"playing_cards.png": ! "playing_cards.png"

This is how it looks now:

This is how it looks now

This is how I would want it to look, no card down below after clicking on it:

desired

Upvotes: 1

Views: 363

Answers (1)

Roni
Roni

Reputation: 649

The card gets duplicated because you aren't clearing the screen within each frame, so the previous frames still appear. In pygame, we can clear the screen by using the fill function. We use the fill function like this: screen.fill((0, 0, 0)) (this fills the screen with the color black and also hides the previous frames). If you add that to your game loop, the card won't get duplicated.

Change your game loop to this:

while True:
    screen.fill((0, 0, 0)) # You can change this to the color of your choice
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            game.change_card_status(pygame.mouse.get_pos())
    
    card_count = 0
    for player, deck in game.player_decks.items():
        new_cards = []
        for card in deck:
            card_image = pygame.image.load(card.img)
            card.make_coordonates((50 * card_count + 500, 500))
            if card.status == "selected":
                card.coordonates[1] -= 100
            new_cards.append(card)
            card_count += 1
        game.player_decks[player] = new_cards

    for player, deck in game.player_decks.items():
        for card in deck:
            display_card(card)
    pygame.display.update()

Upvotes: 1

Related Questions