首页 > 解决方案 > 如何调用特定对象的方法并仅影响作为pygame中字典键值的对象?

问题描述

我是编程新手。我正在练习 python 并使用 pygame 编写一个小游戏。我在 pygame 窗口上有十个圆圈,每个圆圈都有一个计数器。单击圆圈时,我想将计数器增加 1。我首先使用 .sprite.Group() 创建了组,但我无法获得所需的结果。因为那时计数器甚至没有得到更新。所以我创建了两个列表,一个用于圆圈,一个用于计数器。对于圆圈列表中的每个圆圈,我创建了一个以圆圈为键的字典,圆圈列表中的每个计数器都是圆圈的值。现在,当点击圆圈时,所有计数器都会更新,而不是圆圈持有的计数器。但目标是为其圈子更新特定的计数器。(孔==圆)

dig_hole.py(这是主文件。)

import pygame
import sys

from pygame.sprite import Group

from counter import Counter
from hole import Hole
from settings import Settings

class DigHole:

    def __init__(self):
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("Dig Hole")
        pygame.display.set_icon(Hole(self).image)

        self.count = Counter(self)
        self.counter_group = list()
        self.holes = list()

        self.dict = dict()

        self._create_holes()
        self.hole = Hole(self)

        self.mouse_pos = (0, 0)

    def run_dig_hole(self):
        while True:
            self._check_events()
            self._update_screen()

    def _check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                self.mouse_pos = pygame.mouse.get_pos()
                self._check_hole_clicked_events(self.mouse_pos)

    def _check_hole_clicked_events(self, mouse_pos):
        for key in self.dict:
            if key.rect.collidepoint(mouse_pos):
                self.dict[key].count_clock += 1
                self.dict[key].prep_counter()
                self.count.prep_counter()

    def _create_holes(self):
        for row_number in range(2):
            for hole_number in range(5):
                self._create_hole(row_number, hole_number)

        for hole in self.holes:
            counter = Counter(self)
            counter.counter_rect.midbottom = hole.rect.midtop
            self.counter_group.append(counter)

        for hole in self.holes:
            for counter in self.counter_group:
                self.dict[hole] = counter

        
    def _create_hole(self, row_number, hole_number):
            hole = Hole(self)
            hole_width, hole_height = hole.rect.size
            available_space_x = self.settings.screen_width - (2 * hole_width)
            available_space_y = self.settings.screen_height - (2 * hole_height)
            hole.x =(((available_space_x // 5) - hole_width) // 2) + (available_space_x // 5) * hole_number 
            hole.rect.x = hole.x
            hole.rect.y = 2 * hole.rect.height + (available_space_y - (4 * hole_height)) * row_number
            self.holes.append(hole)

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        for key in self.dict:
            key.draw()
        
        for key in self.dict:
            self.dict[key].counter_rect.midbottom = key.rect.midtop
            self.dict[key].show_counter()

        self.count.show_counter()
        pygame.display.flip()

if __name__ == '__main__':
    dh = DigHole()
    dh.run_dig_hole()

孔.py

import pygame
from pygame.sprite import Sprite 

class Hole():
    def __init__(self, dh):
        # super().__init__()
        self.screen = dh.screen

        self.image = pygame.image.load("images/circle.bmp")
        self.rect = self.image.get_rect()

        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        self.x = float(self.rect.x)

    def draw(self):
        self.screen.blit(self.image, self.rect)

计数器.py

import pygame.font
from pygame.sprite import Sprite 

class Counter():
    def __init__(self, dh):
        # super().__init__()
        self.screen = dh.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = dh.settings

        self.count_clock = 0        

        self.text_color = (30, 30, 30)
        self.font = pygame.font.SysFont(None, 48)
        self.prep_counter()

    def prep_counter(self):
        counter_str = str(self.count_clock)
        self.counter_image = self.font.render(counter_str, True, self.text_color, self.settings.bg_color)
        self.counter_rect = self.counter_image.get_rect()
        self.counter_rect.right = self.screen_rect.right - 20
        self.counter_rect.top = 20

    def show_counter(self):
        self.screen.blit(self.counter_image, self.counter_rect)

谢谢你。这是程序的窗口。这里所有的圈子都得到了更新,但是一个被点击了。

标签: pythondictionarypygamemouse

解决方案


问题在于,在 中_create_holes,您将每个圆圈的计数器设置为相同的 Counter 对象。

        for hole in self.holes:
            for counter in self.counter_group:
                self.dict[hole] = counter

展开内部循环,这与

        for hole in self.holes:
            self.dict[hole] = self.counter_group[0]
            self.dict[hole] = self.counter_group[1]
            self.dict[hole] = self.counter_group[2]
            ...
            self.dict[hole] = self.counter_group[-1]

第一个分配都立即被覆盖,因此此代码将每个self.dict值设置为self.counter_group[-1]. 你想做的是

        for hole, counter in zip(self.holes, self.counter_group):
            self.dict[hole] = counter

self.holes它同时迭代两者self.counter_group。在您的情况下,您实际上可以将其重写为

        self.dict = dict(zip(self.holes, self.counter_group))

哪个更好。

我不确定,但我认为你打算self.count成为一个总。如果是这种情况,它就不会起作用了:你从_check_hole_clicked_events. 它应该如下所示:

    def _check_hole_clicked_events(self, mouse_pos):
        for key in self.dict:
            if key.rect.collidepoint(mouse_pos):
                self.dict[key].count_clock += 1
                self.dict[key].prep_counter()
                self.count.count_clock += 1
                self.count.prep_counter()

作为旁注,我注意到您还编写list()dict()创建了空列表和字典。仅编写文字 ([]{}) 会更有效和更惯用。


推荐阅读