• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z kodem w pythonie(pygame) - drugim

Cloud VPS
+1 głos
768 wizyt
pytanie zadane 24 maja 2020 w Python przez Mikisali Początkujący (320 p.)
import pygame
import random
czarny = (0,0,0)
pygame.init()
ekran = pygame.display.set_mode([800,600])
pygame.display.set_caption("Eksplozja buziek")
mysz_w_dol = False
dalej = True
licznik = pygame.time.Clock()
rys = pygame.image.load("Buzka_obrazek.bmp")
kolor_kluczowy = rys.get_at((0,0))
rys.set_colorkey(kolor_kluczowy)
lista_duszkow = pygame.sprite.Group()
class buzka(pygame.sprite.Sprite):
    pos = (0,0)
    xvel = 1
    yvel = 1
    scale = 100
    def __init__(self,pos,xvel,yvel):
        self.image = rys
        self.rect = self.image.get_rect
        self.pos = pos
        self.scale = random.randrange(10,100)
        self.image = pygame.transform.scale(self.image,(self.scale,self.scale))
        self.rectx = pos[0] - self.scale/2
        self.recty = pos[1] - self.scale/2
        self.xvel = xvel
        self.yvel = yvel
    def udpate(self):
        self.rectx += self.xvel
        self.recty += self.ywel
        if self.rectx <= 0 or self.rectx > ekran.width() - self.scale:
            self.xvel = -self.xvel
        if self.recty <= 0 or self.recty > ekran.height() - self.scale:
            self.yvel = -self.yvel
while dalej:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            dalej = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            mysz_w_dol = True
        if event.type == pygame.MOUSEBUTTONUP:
            mysz_w_dol = False
    ekran.fill(czarny)
    lista_duszkow.update()
    lista_duszkow.draw(ekran)
    licznik.tick(60)
    pygame.display.update()
    if mysz_w_dol:
        szybkosc_x = random.randint(-5,5)
        szybkosc_y = random.randint(-5,5)
        nowa_buzka = buzka(pygame.mouse.get_pos(),szybkosc_x,szybkosc_y)
        lista_duszkow.add(nowa_buzka)
pygame.quit()

Zgłszałem już problem z podobnym kodem.

Jak uruchamiam to pokazuje mi się coś takiego:

Traceback (most recent call last):
  File "C:\Users\User\Desktop\Uczymy dzieci programowania\Rozdział 9 - Komunikacja z użytkownikiem(wejdź do gry)\Rozdział 9.6(Eksplozja uśmiechniętych buziek i przebijanie jej błąd).py", line 52, in <module>
    lista_duszkow.draw(ekran)
  File "C:\Python27\lib\site-packages\pygame\sprite.py", line 409, in draw
    self.spritedict[spr] = surface_blit(spr.image, spr.rect)
TypeError: invalid destination position for blit

Proszę o pomoc i z góry dziękuję

1 odpowiedź

+2 głosów
odpowiedź 24 maja 2020 przez Nelson89 Dyskutant (7,720 p.)

Cześć,

Z nazwy pliku, rozumiem, że są to zadania z książki Uczymy dzieci Programowania Bryson Payne. Jest to książka z 2018 roku więc wydaje mi się, że autor realizuje zadania w Python w wersji 3. Widzę, że Ty korzystasz z wersji 2.7. -> "C:\Python27\lib\site-packages\pygame\sprite.py". Ale jeżeli inne ćwiczenia zostały zrealizowane i nie pojawił się błąd to prawdopodobnie w tym wypadku też nie powinno stanowić to problemu.

Druga sprawa, w komunikacie błędu masz informacje o tym, że błąd występuje w linii 52, gdzie powinna znaleźć się instrukcja "lista_duszkow.draw(ekran)". W podanym przez Ciebie kodzie ta instrukcja znajduję się w linii 46. Brakuje 6 linii kodu, jeżeli brakujące linie kodu to komentarze to w takim wypadku to ok.

Po skopiowaniu Twojego kodu, stworzeniu własnej buźki i uruchomieniu kodu w interpreterze wyświetliło mi się czarne okno. Po kliknięciu w dowolnym obszarze program został zatrzymany z błędem:

Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "test.py", line 54, in <module>
    lista_duszkow.add(nowa_buzka)
  File "/home/*****/.virtualenvs/pi/lib/python3.6/site-packages/pygame/sprite.py", line 361, in add
    sprite.add_internal(self)
  File "/home/*****/.virtualenvs/pi/lib/python3.6/site-packages/pygame/sprite.py", line 163, in add_internal
    self.__g[group] = 0
AttributeError: 'buzka' object has no attribute '_Sprite__g'

Problem ten wynika z tego, że klasa buzka nie ma atrybutu _Sprite__g. A w kodzie klasa buzka, dziedziczy atrybuty klasy pygame.sprite.Sprite. Więc dodałem do konstruktora klasy buzka wywołanie konstruktora klasy nadrzędnej:

class buzka(pygame.sprite.Sprite): 
    ...
    def __init__(self,pos,xvel,yvel):
        super().__init__() # <- wywołanie konstruktora klasy nadrzędnej
        ...

Dopiero po dodaniu tej linii pojawił mi się błąd, który opisujesz - dlatego zastanawia mnie brakujące 6 linii kodu, bo teoretycznie mając taki kod jaki podałeś, to ten problem powinien pojawić się jako pierwszy, a dopiero po rozwiązaniu tego problemu powinien pojawić się opisywany przez Ciebie problem.

 

Przechodząc do sedna sprawy to problem tkwi w linii 22

self.rect = self.image.get_rect

get_rect jest metodą obiektu image. Poprawna wersja tej linijki to:

self.rect = self.image.get_rect()

Po tym wszystkim program działa u mnie (Python w wersji 3.6.9 i pygame w wersji 1.9.6) - po kliknięci na dowolny obszar okna, lewym górnym rogu pojawiają się obrazy, o różnym rozmiarze które pochodzą z załadowanego pliku.

Daj znać czy to rozwiązało u Ciebie ten problem.

Jakbyś miał jakieś dodatkowe pytania, coś jest nie jasne w tym co napisałem to śmiało, pisz.

Pozdrawiam,

Nelson89

1
komentarz 25 maja 2020 przez Nelson89 Dyskutant (7,720 p.)

Teraz jest dobrze. To rozwiązanie ma tylko jedną wadę, bo jak kiedyś zmienisz rozmiar okna gry, to będziesz musiał pamiętać o tym, by to zmienić także w tym miejscu. Lepszym rozwiązaniem byłoby wykorzystanie tego co jest już w obiekcie ekran. Spróbuj pod instrukcją, którą masz w kodzie:

ekran = pygame.display.set_mode([800,600])

wpisać:

print(dir(ekran))

Po uruchomieniu kodu, wyświetlą się wszystkie atrybuty obiektu ekran. Jak dobrze poszukasz to znajdziesz.

Ta literówka znajduję się w pierwszej linii tego framgmentu.

    def update(self):
        if self.rect.x <= 0 or self.rect.x >= 800 - self.scale:
            self.xvel = -self.xvel
        if self.rect.y <= 0 or self.rect.y >= 600 - self.scale:
            self.yvel = -self.yvel
        self.rect.x += self.xvel
        self.rect.y += self.yvel

Ta metoda powinna zostać wywołana przez instrukcje znajdującą się pod koniec kodu:

lista_duszkow.update()

 

komentarz 26 maja 2020 przez Mikisali Początkujący (320 p.)

Niestety nadal buźki się nie ruszają w tym kodzie

pygame.display.set_caption("Eksplozja buziek")
mysz_w_dol = False
dalej = True
licznik = pygame.time.Clock()
rys = pygame.image.load("Buzka_obrazek.bmp")
kolor_kluczowy = rys.get_at((0,0))
rys.set_colorkey(kolor_kluczowy)
lista_duszkow = pygame.sprite.Group()
class buzka(pygame.sprite.Sprite):
    pos = (0,0)
    xvel = 1
    yvel = 1
    scale = 100
    def __init__(self,pos,xvel,yvel):
        self.image = rys
        self.rect = self.image.get_rect()
        self.pos = pos
        self.scale = random.randrange(10,100)
        self.image = pygame.transform.scale(self.image,(self.scale,self.scale))
        self.rect.x = pos[0] - int(self.scale / 2)
        self.rect.y = pos[1] - int(self.scale / 2)
        self.xvel = xvel
        self.yvel = yvel
    def udpate(self):
        lista_duszkow.update()
        self.rect.x += self.xvel
        self.rect.y += self.ywel
        if self.rect.x <= 0 or self.rect.x > ekran.width() - self.scale:
            self.xvel = -self.xvel
        if self.rect.y <= 0 or self.rect.y > ekran.height() - self.scale:
            self.yvel = -self.yvel
while dalej:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            dalej = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if pygame.mouse.get_pressed()[0]:
                mysz_w_dol = True
            elif pygame.mouse.get_pressed()[2]:
               pos = pygame.mouse.get_pos()
               klikniete_buzki = [s for s in lista_duszkow if s.rect.collidepoint(pos)]
               lista_duszkow.remove(klikniete_buzki)
        if event.type == pygame.MOUSEBUTTONUP:
            mysz_w_dol = False
    ekran.fill(czarny)
    lista_duszkow.update()
    lista_duszkow.draw(ekran)
    licznik.tick(60)
    pygame.display.update()
    if mysz_w_dol:
        szybkosc_x = random.randint(-5,5)
        szybkosc_y = random.randint(-5,5)
        nowa_buzka = buzka(pygame.mouse.get_pos(),szybkosc_x,szybkosc_y)
        lista_duszkow.add(nowa_buzka)
pygame.quit()

 

komentarz 26 maja 2020 przez Nelson89 Dyskutant (7,720 p.)
Popraw 24 linie:

teraz masz def udpdate, a powinno być def update.
komentarz 26 maja 2020 przez Mikisali Początkujący (320 p.)
Dzięki za pomoc
komentarz 26 maja 2020 przez Nelson89 Dyskutant (7,720 p.)
Nie ma sprawy.

Podobne pytania

0 głosów
1 odpowiedź 244 wizyt
pytanie zadane 23 maja 2020 w Python przez Mikisali Początkujący (320 p.)
0 głosów
1 odpowiedź 230 wizyt
pytanie zadane 4 sierpnia 2020 w Systemy operacyjne, programy przez lubie internet Użytkownik (780 p.)
+1 głos
1 odpowiedź 546 wizyt
pytanie zadane 20 czerwca 2023 w Python przez Bondrusiek Maniak (61,440 p.)

93,456 zapytań

142,451 odpowiedzi

322,721 komentarzy

62,837 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...