You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python的Pygame中为卡牌精灵实现属性并解决抽卡重复问题

问题:为Pygame卡牌游戏添加攻击力属性并解决抽卡重复问题

我正在使用Pygame开发一款简化版游戏王卡牌游戏,目前仅包含怪兽卡且仅支持攻击功能,因此卡牌仅需具备攻击力(atk)属性。但在实现战斗系统时遇到两个核心问题:

  • 当前所有卡牌均由同一个Card类中的精灵列表生成,而非独立类实例,无法为每张卡牌单独添加攻击力属性;
  • 曾考虑为每张卡牌创建独立类实例,但无法跟踪已抽取卡牌,无法从card.py的self.deck列表中正确过滤可抽取卡牌以避免重复。

主游戏文件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(mouse_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()

card.py文件

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."""
    ...

注:代码中的‘hover’指鼠标悬停时显示卡牌放大图,此功能无关当前问题。


内容的提问来源于stack exchange,提问作者rbeze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:32:04