• 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

Object Storage Arubacloud
+1 głos
443 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ź 180 wizyt
pytanie zadane 23 maja 2020 w Python przez Mikisali Początkujący (320 p.)
0 głosów
1 odpowiedź 160 wizyt
pytanie zadane 4 sierpnia 2020 w Systemy operacyjne, programy przez lubie internet Użytkownik (780 p.)
+1 głos
1 odpowiedź 272 wizyt
pytanie zadane 20 czerwca 2023 w Python przez Bondrusiek Maniak (61,370 p.)

92,551 zapytań

141,393 odpowiedzi

319,523 komentarzy

61,936 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...