[Python] How can I implement attributes to an object/sprite in Python?

Discussão em 'Python' iniciado por Stack, Maio 22, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to make a Yu-Gi-Oh! card game with Pygame that works as a very simplified version of the video game versions (i.e. monster cards only, and they can only attack, thus for now they should only have attack points as attributes).

    But now I'm struggling to implement the cards' atk points as attributes for the battle system, since each card is represented by a pygame sprite taken from a list of sprites from the very same class, instead of each card being its own instance of its own class for allowing proper attribute implementation. I'm really stuck on this, so would really really appreciate any solutions. I thought about implementing each card on its own class as just mentioned, but since i wouldn't be able to know which cards have already been drawn at a given moment, i don't see how i would be able to properly filter the available cards to be drawn from the deck (the list named self.deck at card.py) at a given moment through the card list without repeating some of them that should be unavailable.

    These are the relevant parts of code from the project:

    From the main game file (card_game.py)

    import sys

    import pygame

    from card import Card
    from card import EnemyCards
    from board import Board
    from life_points import LifePoints
    from deck import Deck
    from deck import CPUDeck
    from settings import Settings

    import random, os

    class CardGame:
    """Overall class to manage game assets and behavior."""

    def __init__(self):
    """Innitialize the game and create game resources."""
    pygame.init()
    self.settings = Settings()

    self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
    self.screen_rect = self.screen.get_rect()
    self.settings.screen_width = self.screen.get_rect().width
    self.settings.screen_height = self.screen.get_rect().height
    pygame.display.set_caption("Card Game")

    self.lp = LifePoints(self)

    self.cards = Card(self)

    self.card_1_rect = self.cards.rect_1
    self.card_2_rect = self.cards.rect_2
    self.card_3_rect = self.cards.rect_3
    self.card_4_rect = self.cards.rect_4
    self.card_5_rect = self.cards.rect_5

    self.cpu_cards = EnemyCards(self)
    self.cpu_card_1_rect = self.cpu_cards.rect_1
    self.cpu_card_2_rect = self.cpu_cards.rect_2
    self.cpu_card_3_rect = self.cpu_cards.rect_3
    self.cpu_card_4_rect = self.cpu_cards.rect_4
    self.cpu_card_5_rect = self.cpu_cards.rect_5

    self.board = Board(self)

    self.deck = Deck(self)
    self.deck.position_deck()
    self.cpu_deck = CPUDeck(self)
    self.cpu_deck.position_deck()

    def run_game(self):
    """Start the main loop for the game."""
    while True:
    # Watch for keyboard and mouse events.
    self._check_events()
    self._update_screen()

    def _check_events(self):
    """Respond to keypresses and mouse events."""
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    sys.exit()
    elif event.type == pygame.MOUSEBUTTONDOWN:
    mouse_pos = pygame.mouse.get_pos()

    if self.player_turn == True:
    self._check_card_clicked(mouse_pos)
    else:
    self._check_cpu_card_clicked(mouse_pos)

    if self.deck.deck_image_rect.collidepoint(mouse_pos):
    self.cards.draw_card()
    elif self.cpu_deck.deck_image_rect.collidepoint(mouse_pos):
    self.cpu_cards.draw_card()

    def _check_card_clicked(self, mouse_pos):
    """Checks if the player clicked on the card and if so, puts it on the board."""
    card_1_clicked = self.card_1_rect.collidepoint(mouse_pos)
    card_2_clicked = self.card_2_rect.collidepoint(mous e_pos)
    card_3_clicked = self.card_3_rect.collidepoint(mouse_pos)
    card_4_clicked = self.card_4_rect.collidepoint(mouse_pos)
    card_5_clicked = self.card_5_rect.collidepoint(mouse_pos)

    if card_1_clicked:
    self.card_1_rect.center = (419, 594)
    elif card_2_clicked:
    self.card_2_rect.center = (563, 585)
    elif card_3_clicked:
    self.card_3_rect.center = (715, 593)
    elif card_4_clicked:
    self.card_4_rect.center = (862, 591)
    elif card_5_clicked:
    self.card_5_rect.center = (1020, 593)

    self.battle_phase()

    def _check_cpu_card_clicked(self):
    """Selects an enemy card randomly and puts it on the field."""
    cpu_card_1_clicked = self.cpu_card_1_rect.collidepoint(mouse_pos)
    cpu_card_2_clicked = self.cpu_card_2_rect.collidepoint(mouse_pos)
    cpu_card_3_clicked = self.cpu_card_3_rect.collidepoint(mouse_pos)
    cpu_card_4_clicked = self.cpu_card_4_rect.collidepoint(mouse_pos)
    cpu_card_5_clicked = self.cpu_card_5_rect.collidepoint(mouse_pos)

    if cpu_card_1_clicked:
    # Places the CPU's first card on hand on the board's first spot
    # if there's no other card there already.
    self.cpu_card_1_rect.center = (419, 442)
    elif cpu-card_2_clicked:
    self.cpu_card_2_rect.center = (570, 444)
    elif cpu_card_3_clicked:
    self.cpu_card_3_rect.center = (712, 449)
    elif cpu_card_4_clicked:
    self.cpu_card_4_rect.center = (860, 441)
    elif cpu_card_5_clicked:
    self.cpu_card_5_rect.center = (1018, 446)

    def _update_screen(self):
    """Updates images on the screen and flip to the new screen."""
    self.screen.fill(self.settings.bg_color)
    self.board.blitme()
    self.deck.blitme()
    self.cpu_deck.blitme()
    self.cards.blitme_1()
    self.cards.blitme_2()
    self.cards.blitme_3()
    self.cards.blitme_4()
    self.cards.blitme_5()
    self.cpu_cards.blitme_1()
    self.cpu_cards.blitme_2()
    self.cpu_cards.blitme_3()
    self.cpu_cards.blitme_4()
    self.cpu_cards.blitme_5()

    if hasattr(self.cards, 'drawn_card_6'):
    self.cards.blitme_6()
    if self.cards.rect_6.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_6()

    if hasattr(self.cpu_cards, 'drawn_card_6'):
    self.cpu_cards.blitme_6()
    if self.cpu_cards.rect_6.collidepoint(pygame.mouse.get_pos()):
    self.cpu_cards.blitme_hover_6()

    if self.cards.rect_1.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_1()

    if self.cards.rect_2.collidepoint(pygame.mouse.get_ pos()):
    self.cards.blitme_hover_2()

    if self.cards.rect_3.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_3()

    if self.cards.rect_4.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_4()

    if self.cards.rect_5.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_5()

    if self.cpu_cards.rect_1.collidepoint(pygame.mouse.get_pos()):
    self.cpu_cards.blitme_hover_1()
    elif self.cpu_cards.rect_2.collidepoint(pygame.mouse.get_pos()):
    self.cpu_cards.blitme_hover_2()
    elif self.cpu_cards.rect_3.collidepoint(pygame.mouse.get_pos()):
    self.cpu_cards.blitme_hover_3()
    elif self.cpu_cards.rect_4.collidepoint(pygame.mouse.get_pos()):
    self.cards.blitme_hover_4()
    elif self.cpu_cards.rect_5.collidepoint(pygame.mouse.get_pos()):
    self.cpu_cards.blitme_hover_5()

    # Draw Life Points information.
    self.lp.show_life_points()

    pygame.display.flip()


    if __name__ == '__main__':
    # Make a game instance, and run the game.
    cg = CardGame()
    cg.run_game()


    and these are the relevant parts of the card.py file, where cards' functionalities are present:

    import pygame
    from pygame.sprite import Sprite
    from settings import Settings

    import random, os


    class Card(Sprite):
    """A class to manage a card."""

    def __init__(self, ai_game):
    """Initialize a card and set its starting position."""
    super().__init__()
    self.screen = ai_game.screen
    self.screen_rect = ai_game.screen.get_rect()

    self.deck = [
    "starter_deck/abyss_flower.bmp",
    "starter_deck/acid_crawler.bmp",
    "starter_deck/acrobat_monkey.bmp",
    "starter_deck/akakieisu.bmp",
    "starter_deck/alinsection.bmp",
    "starter_deck/alligators_sword.bmp",
    "starter_deck/ancient_brain.bmp",
    "starter_deck/ancient_elf.bmp",
    "starter_deck/ancient_jar.bmp",
    "starter_deck/bickuribox.bmp",
    "starter_deck/celtic_guardian.bmp",
    "starter_deck/curse_of_dragon.bmp",
    "starter_deck/gemini_elf.bmp",
    "starter_deck/la_jinn.bmp",
    "starter_deck/skull_knight.bmp"
    ]

    # Load the cards' images and get their rects.
    self.cards = [pygame.image.load(c) for c in self.deck]

    self.drawn_card_1 = random.choice(self.cards)
    self.drawn_card_2 = random.choice(self.cards)

    # This whole while loop section is intended to make sure that we get
    # 5 distinct cards from one another.
    while self.drawn_card_1 == self.drawn_card_2:
    self.drawn_card_2 = random.choice(self.cards)

    self.drawn_card_3 = random.choice(self.cards)

    while (self.drawn_card_1 == self.drawn_card_3
    or self.drawn_card_2 == self.drawn_card_3):
    self.drawn_card_3 = random.choice(self.cards)

    self.drawn_card_4 = random.choice(self.cards)

    while (self.drawn_card_1 == self.drawn_card_4
    or self.drawn_card_2 == self.drawn_card_4
    or self.drawn_card_3 == self.drawn_card_4):
    self.drawn_card_4 = random.choice(self.cards)

    self.drawn_card_5 = random.choice(self.cards)

    while (self.drawn_card_1 == self.drawn_card_5
    or self.drawn_card_2 == self.drawn_card_5
    or self.drawn_card_3 == self.drawn_card_5
    or self.drawn_card_4 == self.drawn_card_5):
    self.drawn_card_5 = random.choice(self.cards)



    class EnemyCards(Sprite):
    """A class to manage the CPU's cards."""
    ...


    P.S.: The term 'hover' present in the names of some variables and methods refers to displaying a bigger image of the card while hovering over them with the cursor, but that's not important I guess.

    Continue reading...

Compartilhe esta Página