Pygame button widget'ı

arkadaşlar pygame de button widget’ını yapmaya çalışıyorum
ama mouse tıklamasında tepki vermesini nasıl yapacağımı bilmiyorum

import pygame as pg

class Button(pg.sprite.Sprite):
    def __init__(self, pos = None, image = None):
        pg.sprite.Sprite.__init__(self)
        assert type(pos) == tuple
        assert type(image) == str
        self.image = pg.image.load(image)
        self.rect = self.image.get_rect(topleft=pos)

araştırdığım kaynaklarda herkez:

for event in pygame.event.get():
            if event.type == MOUSEBUTTONDOWN:
                mouse = pygame.mouse.get_pos()
                if button.pressed(mouse):   #Button's pressed method is called
                    print ('button hit')

şeklinde yapmış ama ben bunu istemiyorum başka türlü nasıl yaparım
yani başka türlü mouse’a basıldığında bilgisayarın tepki vermesini nasıl sağlarım

Bu şekilde yapmak istememenizin sebebi tam olarak ne? Pygame’in kendi arayüz sınıfları bulunmadığı için butonu kendimiz yazıyoruz. Butonların asıl amacı zaten farenin belli bir yere basılıp basılmadığını anlamak. Verdiğiniz örnekte de bu yapılıyor. İstiyorsanız bu kodu da inceleyebilirsiniz:

import pygame as pg


display = pg.display.set_mode((500,500))


class Button():
    butonlar = []
    def __init__(self, *, command, image_path, pos):
        self.command = command
        self.sprite = pg.image.load(image_path)
        self.rect = self.sprite.get_rect(topleft= pos)
        self.butonlar.append(self)

    def delete(self):
        self.butonlar.remove(self)


buton1 = Button(command = lambda event: print("1. buton basıldı"), image_path="1.png", pos=(100,100))
buton2 = Button(command = lambda event: print("2. buton basıldı"), image_path="2.png", pos=(200,200))


while True:

    display.fill((255,255,255))
    
    for event in pg.event.get():
        if event.type == pg.MOUSEBUTTONDOWN:
            mouse = pg.mouse.get_pos()
            for buton in Button.butonlar:   
                if buton.rect.collidepoint(mouse):
                    buton.command(mouse)

    for buton in Button.butonlar:
        display.blit(buton.sprite,buton.rect)
    
    pg.display.update()

1 Beğeni

Neden bunu istemedigini (veya alternatif olarak ne istedigini) soylemedigin icin alternatif bulmakta zorlaniyoruz.

Mesela if event.type == MOUSEBUTTONDOWN yerine if MOUSEBUTTONDOWN == event.type diyebilirsin?

Event loop kullanmak istemiyorsan pygame gibi low level bir kutuphane kullanmaman lazim.

2 Beğeni

Burada buton sinifini ikiye bolmek yerine event’i butona paslayip iceride isletmen daha dogru olur.

Global listeyi sinif icinden yonetmek kotu kokuyor (code smell). Sinif degiskeni yapabilirsin, ama butonlari nerede tutacagina butonlari yaratan insanin karar vermesi lazim. Belki hashtable’da tutmak istiyor?

Bu satira da gerek yok, yazmazsan zaten fonksiyon bittigi icin self degiskeni siliniyor.

2 Beğeni

Evet, global namespace’i kirletmemek ve bir sınıf değişkeni yapmak daha uygun olur.

Benim kodum bir örnekti zaten. İnceleyerek istediği gibi kullanabilir.

Yine burada da aynı şey geçerli. Eğer butona basılıp basılmadığı sadece rect’e göre belirlenmeyecekse veya butondan butona değişecek ise gereken değişimler yapılabilir. Mouse koordinatları zaten buton.command(mouse) kısmında veriliyor. Bunu yazarken aklıma tkinter’deki buton sistemi gelmişti.

Doğru. self değişkeni unmutable bir nesneyi sakladığı için bu satır onu silecekmiş gibi düşünmüşüm. Oysaki sadece değişken ismini serbest bırakıyor. refcount 0 olmazsa bir anlamı yok. Ama zaten fonksiyon bittiğinde silinecek.

1 Beğeni

benim istediğim klavyeden örnek
şu:

key = pg.key.get_pressed()
if key[pg.K_SPACE]:
   print("Boşluk Tuşu çalışıyor")

aslında tam istediğim buttonun tıklandığındaki tepki verme olayının button classı içinde olması

Dediğimiz gibi burada bir döngü yapman lazım. Çünkü verdiğin örnekteki gibi bunu kontrol eden bir fonksiyon pygame'de bulunmuyor.

Buradan kastın gerekli işlemleri yapacak fonksiyonun sınıfın içinde olması ise yukarıdaki örneğimi bu hale getirebilirsiniz.

başka oyun yapımı için kullanılacak kütphane varmı(öğrenmek için kaynak çok olan)

peki bu fonksiyon ne yapıyor o zaman
pygame.mouse.get_pressed()

Öğrenmek için çok kaynak olmasa da pyglet var. Çoğu işi de sizin için hallediyor.
Eğer python için oyun kütüphanelerinin listesini görmek istiyorsanız buraya bakabilirsiniz.

Üç elemana sahip bir tuple döndürüyor. Elemanlar ya 1 ya da 0. 1 tuşun basılı olduğu, 0 ise basılı olmadığı anlamına geliyor. İlk eleman sol click, ikinci eleman scrool, üçüncü eleman ise sağ click için. Fonksiyonların ne işe yaradığını bize sormak yerine pygame belgelerine de başvurabilirsiniz: https://www.pygame.org/docs/

sormamın sebebi event döngüsü yerine Button classının update kısmına bu kodu kullanarak bir kod yazsam ayrıca bu link için teşekkür ederim

arkadaşlar mouse kullanmadan deniyeyim dedim ama çalışmadı sizce neden?
çalışmadı derken herhangi bir değer 1 olmadı

import pygame as pg
pg.init()
while True:
    clicked = pg.mouse.get_pressed()
    print(clicked)

Oyun penceresini oluşturmuyorsunuz. Pygame’e ait olan pencerenin üstüne basmıyorsanız neden algılasın?

dediğinize göre event döngüsü olmadan olmaz
ama pygame.mouse.get_pressed() metodu ile basma olayının olup olmadığını öğrenebiliyoruz neden öyle dediniz

Basma olayının olup olmadığını öğrendikten sonra hangi Button (faredeki değil, oyundaki) üzerine basıldığını nasıl anlayacaksınız?

self.pos = pg.mouse.get_pos() yardımıyla ve self.rect.collidepoint(self.pos)

Tamam işte, burada bir döngü kullanmış oluyoruz. Bütün butonları teker teker kontrol ediyoruz.

ben döngü kullanmıcam demedimki ben event döngüsü kullanmıcam dedim

hem döngü dediğinizi anlamadım benim yapacağım
şöyle olmazmı:

def update(self, *args):
      self.pos = pg.mouse.get_pos()
      self.click = pg.mouse.get_pressed()
      if self.rect.collidepoint(self.pos):
           #eğer cursor buton üstünde ise butonun üstünde değişiklik
      if self.click[0] :
          #tıklama olayı
           

bu olmazmı sizce eğer yanlışım varsa lütfen düzeltin

Tamam ama bizim demek istediğimiz bu update metodunu her buton için kendinizin çağırmanız gerektiği.

Sanırım burada bir event hook kullanmak istiyorum dediniz. Ama bu pygame’de bulunmuyor diye biliyorum. Az önce pygame böyle bir hooka sahip mi diye araştırırken buraya denk geldim. Pygame üzerine kurulu sizin istediğiniz gibi bazı kolaylıklar sağlayan bir kütüphane.