Menüsü, oynanışı ve bitiş ekranı olan bir oyun. Öğrendiklerimizin hepsi tek sketch’te.
KurallarDurum tasarımıKodu parça parça okumakGeçişleri sınamakHafıza kartları projesi
Önce oynayalım
Tuvale tıklayın, SPACE’e basın. Ok tuşları ya da WASD ile yeşil hedefleri toplayın; turuncu topa değmeyin. Bitince R.
Az önce oynadığınız oyunda kaç farklı ekran gördünüz?
Her ekranda hangi tuşlar işe yarıyordu? Hangi olay sizi bir ekrandan diğerine götürdü?
Kurallar ve üç durum
Menü: “SPACE — başla” yazısı.
Oyun: kare oyuncu WASD ya da oklarla hareket eder; top duvarlardan sekerek dolaşır.
Oyuncu yeşil hedefe değince skor 1 artar; hedef başka bir yere taşınır.
Top oyuncuya değerse bitiş ekranı gelir; skor gösterilir.
Bitişte R ile menüye dönülür.
MENÜ→ SPACE →OYUN→ çarpışma →BİTİŞ
BİTİŞ→ R →MENÜ
Küçük bir tasarım kararıSkor yalnızca hedefe dokununca artıyor. Köşede beklemek işe yaramaz; puan için topun yakınına gitmeyi göze almanız gerekir. Oyun tasarımında buna risk ve ödül dengesi denir.
Bu oyunda yeni hiçbir şey yok
Bölüm 2Fonksiyonlar: cizMenu, guncelleOyun, cizOyun… Güncelle ve çiz ayrımı.
Bölüm 3deltaTime ile hız. keyIsDown ile hareket, keyPressed ile tek basış. constrain.
Bölüm 4Seken top. dist ile temas testi. oyunDurumu ve geçişler.
Yeni olan tek şey, bunların hepsini bir araya getirmek. Kodun tamamı 137 satır; parça parça okuyacağız.
Sabitler ve oyunun verisi
Üç durum sabiti.
Boyutlar ve hızlar da sabit: oyunun “ayar düğmeleri”. Değiştirip dengeyi deneyebilirsiniz.
oyunDurumu: hangi ekrandayız?
Oyuncu, top, hedef ve skor: oyunun verisi. Durumdan bağımsız değişkenlerde duruyor.
setup ve yönlendirici draw
Oyun menüde başlar. draw yalnızca duruma bakar ve işi dağıtır.
Okuma sırasıBir oyunun kodunu okurken hep draw’dan başlayın. Üç daldan yalnızca biri, oyunDurumu’nun o anki değerine göre çalışır.
Menü ekranı
Arka plan, başlık, iki satır talimat. Burada hareket yok, çarpışma yok; yalnızca çizim.
guncelleOyun (1/2): oyuncu ve top
guncelleOyun (2/2): iki temas testi
Oyuncu bir kare; merkezi (px, py). İki test de aynı kalıp: dist < yarıçapların toplamı. İlki skoru artırır, ikincisi durumu değiştirir.
Top oyuncuya değdi ve oyunDurumu = DURUM_BITIS atandı. Aynı frame’de ekrana ne çizilir?
Oyun sahnesi, son bir kez
draw başladığında durum hâlâ DURUM_OYUN; ikinci dala girilir.
guncelleOyun() çarpışmayı bulur ve durumu DURUM_BITIS yapar.
Aynı dalın devamı çalışır: cizOyun() çarpışma anını çizer.
Bir sonrakidraw çağrısında üçüncü dal çalışır: cizBitis().
Geçiş bir sonraki frame’de görünürif / else if zincirinde dal bir kez seçilir. Durumu dalın ortasında değiştirmek, o frame’de başka bir dala atlatmaz.
Oyun ekranını çizmek
Sıra önemli: önce hedef, sonra oyuncu, en üstte top.
Skor sol üstte: küçük bir HUD.
Bu fonksiyon hiçbir şeyi değiştirmez; yalnızca değişkenlere bakıp ekrana aktarır.
Bitiş ekranını çizmek
Farklı bir arka plan rengi: oyuncu ekranın değiştiğini hemen anlar.
Skor, oyun ekranındaki aynı skor değişkeninden okunuyor.
Son satır, oyuncuya bundan sonra ne yapabileceğini söylüyor. Her ekranda bir sonraki adım yazılı olmalı.
Yeni hedef tam oyuncunun üstünde doğarsa ne olur?
Hedef rastgele bir yere konuyor. Şans eseri oyuncunun durduğu yere denk gelirse?
hedefYerlestir: uzak bir yer bulana kadar dene
Oyuncu hiçbir şey yapmadan puan alırdı. Bu yüzden hedef, oyuncuya UZAK_MESAFE’den yakınsa yeniden çekiliyor.
while ve güvenlik sınırı
while’ın doğal yeriKaç denemede uygun yer bulunacağı baştan belli değil. “Yeterince uzak bir yer bulana kadar dene.”
deneme < 50 neden var?UZAK_MESAFE tuvale göre çok büyük seçilirse uygun yer hiç bulunamaz. Sınır olmasa döngü hiç bitmez; draw o frame’i tamamlayamaz ve oyun donar.
Oyunlarda yaygın bir kalıpRastgele yerleştirme yapan her sistem (düşman doğurma, ödül koyma, harita üretme) bir deneme sınırı taşır. Yer bulunamazsa en son denenen konumla yetinilir.
Yeni tur: oyunuSifirla
Oyuncu ortada başlar.
Top üstte, rastgele bir x konumunda ve rastgele bir hızla doğar: her tur biraz farklı.
Skor sıfırlanır, ilk hedef yerleştirilir.
Yalnızca menüden oyuna geçerken çağrılır.
Geçişler: keyPressed
Menüde SPACE: önce sıfırla, sonra oyuna geç.
Bitişte R: menüye dön.
Geçişlerin ikisi de tek satırlık atama.
Başka durumlarda bu tuşlar hiçbir şey yapmaz.
Kodun tamamı geçiş tablosunun çevirisi
Mevcut durum
Olay
Yeni durum
Kodda nerede?
Menü
SPACE
Oyun
keyPressed · oyunuSifirla() ile birlikte
Oyun
Hedefe temas
Oyun (değişmez)
guncelleOyun · skor artar, hedefYerlestir()
Oyun
Topa temas
Bitiş
guncelleOyun
Bitiş
R
Menü
keyPressed
Geçişler iki yerde olurTuşla tetiklenenler keyPressed içinde; oyunun kendi kuralından doğanlar (çarpışma) guncelleOyun içinde.
Geçişleri sınayın
Oyunu açın ve tablodaki olmaması gereken şeyleri deneyin. Her biri için ne olduğunu yazın.
Menüdeyken ok tuşlarına basılı tutun, sonra SPACE’e basın. Oyuncu ortada mı başlıyor?
Menüdeyken R’ye basın.
Oyun sırasında SPACE’e basın. Skor sıfırlanıyor mu?
Bitiş ekranında SPACE’e basın. Bitişte ok tuşlarına basın.
Kodda UZAK_MESAFE’yi 600 yapın. Oyun donuyor mu? Neden donmuyor?
Oyunu geliştirin
Her 5 puanda topun hızı %15 artsın.
En yüksek skoru tutun ve bitiş ekranında gösterin. İpucu: oyunuSifirla onu sıfırlamamalı.
Oyuna DURUM_DURAKLAT ekleyin: P ile duraklat, P ile devam.
Bitiş ekranından R ile menüye, SPACE ile doğrudan yeni oyuna geçilebilsin.
Zorlu: ikinci bir top ekleyin. Topların konum ve hızlarını paralel dizilerde tutun; her 10 puanda yeni bir top gelsin.
Yapay zekâyla: bir oyundan durum makinesi çıkarmak
Önce siz: bildiğiniz bir oyun seçin (satranç, Tetris, hafıza kartları…). En az üç durum bulun. Her biri için: ekranda ne görünür, hangi girdi işe yarar?
Sorun: “Şu oyunu durum makinesi gözüyle anlat: 3–5 durum, her durumda görünenler ve anlamlı girdiler, en az 5 satırlık geçiş tablosu. Durum makinesi olmasa hangi hatalar kolay çıkardı? Kod yazma.”
Denetleyin: yanlış ya da gereksiz bir durum var mı? Yapay zekâ bazen olmayan kurallar ya da fazladan durumlar ekler.
Kendi mini oyununuz için yanıtlayın: hangi üç durum şart, her biri ne işe yarar, neden bu üçü yeterli?
Yapay zekâyla: Mermaid diyagramı çizdirmek
Kaç-Kaç Top ya da kendi oyununuz için geçiş tablosunu yazın: en az dört satır ve bir olmayan geçiş (örneğin menüde R).
Tabloyu verip stateDiagram-v2 metnine çevirtin. Başlangıç için [*] --> … kullansın.
Metni mermaid.live adresinde açın. Çizilmezse ya da ok eksikse düzelttirin.
Makyaj: kutuları renklendirtin; oyun --> bitis okunu belirginleştirtin. Her değişikliği yeniden deneyin.
İsteğe bağlı: “Bu diyagramdaki her ok p5.js’te nereye yazılır: draw içine mi, keyPressed içine mi?”
DikkatYapay zekâ bazen durum diyagramı yerine akış şeması (flowchart) üretir ya da olmayan bir duruma ok çizer. Önce doğru geçişler, sonra makyaj.
Sıradaki hedef: Hafıza kartları
Üstteki “Durum” yazısını izleyin: İlk kart → İkinci kart → Eşleşme kontrolü → yeniden İlk kart. Kontrol sırasında tıklamalar yok sayılıyor.
Hafıza kartları (1/2): plan ve kod
Mekaniği anlayın. Bu oyuna İngilizcede Memory, Concentration ya da Matching pairs denir. Çevrimiçi bir örneğini birkaç dakika oynayın.
Önce diyagram. Geçiş tablonuzu yazın, Mermaid ile çizin. İsterseniz başa bir Menü, sona bir Bitti ekleyin. Diyagram netleşmeden koda geçmeyin.
Kodu siz yazın. Küçük bir ızgara: 4 × 3, yani 6 çift. Önce 2 × 2 bile yeter.
Durum sabitleri ve oyunDurumu.
Kart değerleri ve açık / kapalı bilgisi için paralel diziler. Class yok.
draw(): duruma göre çiz. Kapalı kart gri, açık kartta sayı ya da renk.
mousePressed(): yalnızca uygun durumda tıklanan kartı aç.
Eşleşmezse kısa bekleme (millis ya da bir sayaç), sonra kartları kapat.
Hafıza kartları (2/2): takılınca ve kontrol
Yapay zekâdan onarım ve açıklama isteyin“Şu sorun var: [ikinci kart açılmıyor]. Önce öğretmen gibi anlat: hata hangi durum geçişinde olabilir? Sonra yalnızca gerekli satırları düzelt; oyunu baştan yazma. En sonda neyi neden değiştirdiğini madde madde açıkla.”
Yazamadığınız tek bir parça için“Class kullanmadan yalnızca kartlariKaristir() fonksiyonunu yaz: 6 çift (0–5, her biri iki kez) üretip karıştırsın.”
Kontrol listesi
Eşleşme kontrolü sırasında yeni kart tıklanabiliyor mu? Tıklama yok sayılmalı.
Menüdeyken kart tıklanınca oyun bozuluyor mu?
İkinci kart açılmadan “eşleşti mi?” soruluyor mu?
Durum adları sabit mi, yoksa "ilk" ile "İlk kart" karışıyor mu?
Yapay zekâ neyi gereksiz uzattı?
Oyunun tamamını yapay zekâya baştan yazdırmayın. Kaç-Kaç Top’taki oyunDurumu + draw dallanması + oyunuSifirla kalıbını yeniden kullanın.
Yapay zekâyla: eksik geçiş
Menüden oyuna geçişi olan ama bitişten menüye dönüşü “unutulmuş” bir iskelet yazın ya da yazdırın.
Yapay zekâya hatayı buldurun. Teşhisi sizinkiyle aynı mı?
Düzeltmeyi kendi sketch’inizde uygulayın; üç ekranı da gezerek doğrulayın.
oyunuSifirla() çağrısını keyPressed’den silersek ilk oyunda ne olur?
Hiçbir şey değişmez.
Oyuncu, top ve hedef çizilemez: konumlarına hiç değer verilmedi.
Oyun menüde kalır.
Bu değişkenler en üstte yalnızca tanımlandı; değerlerini oyunuSifirla veriyor. Çağrılmazsa hepsi undefined kalır.
Hedef testini ve top testini yer değiştirsek, aynı frame’de ikisine birden değen oyuncuya ne olur?
Oyun biter, puan alamaz.
İki sırada da hem puan alır hem oyun biter.
Puan alır, oyun bitmez.
İki test bağımsız iki if; arada return ya da else yok. Sıra değişse de ikisi de çalışır. “Ölürken puan almasın” isteseydik top testini öne alıp return eklerdik.
Oyuncu karesinin sol üst köşesi (100, 100), BOYUT 36. Merkezi nerede?
(100, 100)
(136, 136)
(118, 118)
(82, 82)
rect köşeden çizer; dist ise merkez ister. Bu yüzden kodda px = oyuncuX + BOYUT / 2.