Bölüm 4 · Sunum 2

Durum makinesi: oyun şu an hangi ekranda?

Menü, oyun ve bitiş ekranlarını birbirine karıştırmadan yönetmek.

Durum ve geçişDiyagram çizmekoyunDurumuDuruma göre draw ve girdiGeçiş tablosu

Bir oyunu açtınız. Karakter hemen koşmaya mı başlıyor?

Önce ne görüyorsunuz? Oyun bitince ne görüyorsunuz? Bu ekranların her birinde aynı tuşlar aynı işi mi yapıyor?

Durum makinesi

Durum makinesi (state machine)Sistemin her an yalnızca bir durumda olduğu; belirli olaylarla (tuş, tıklama, süre, çarpışma) başka durumlara geçebildiği yapıdır.
DurumEkranda ne görünür?Girdi ne işe yarar?
MenüBaşlık, “Başla” talimatıSPACE → oyunu başlat
OyunOyuncu, hedef, top, skorWASD hareket; çarpışma → bitiş
BitişSkor, “Tekrar dene”R → menüye dön

Durum oyunun aşamasıdır. Geçiş (transition), bir olay olunca durum değişkeninin güncellenmesidir.

Üç durum, üç geçiş

Durum makinesi: menü, oyun, bitiş geçişleri
Kutular durumlar, oklar geçişler, okun üstündeki yazı o geçişi tetikleyen olay.

Olay düğmelerine tıklayın

Menüdeyken WASD’ye ya da R’ye basın: hiçbir şey olmaz. Bir olay, yalnızca o durum için tanımlıysa geçiş yaptırır.

Bunu iki boolean ile yazsak olmaz mı?

Bir hata sonucu ikisi de true olursa ekranda ne görürsünüz?

Tek değişken, her an tek değer

Ayrı boolean’ların riskiİkisi birden true olursa draw aynı frame’de hem menüyü hem sahneyi çizer. Girdinin hangi bloğa gideceği belirsizleşir.
Tek oyunDurumuHer an yalnızca bir değer taşır. Geçiş tek bir atama satırıdır.
YaklaşımÖrnekNe zaman yeterli?
Tek booleanoyunBittiYalnızca devam / bitti
Metin durum"menu", "oyun", "bitis"Birkaç aşamalı akış
Ayrı boolean’larmenuAcik, oyunAcikÖnerilmez: çakışma riski

Daire Tıklama’daki oyunBitti aslında iki durumlu küçük bir makineydi: oynuyor / bitti.

Trafik ışığı: geçişi süre tetikler

Kırmızı → Sarı → Yeşil → Sarı → Kırmızı. Burada olay bir tuş değil; sürenin dolması.

Turnike: geçersiz olay yok sayılır

Turnike durum diyagramı
KilitliKart okutulursa “Doğrulanıyor”a geçer.
DoğrulanıyorKart geçerliyse “Açık”, geçersizse yeniden “Kilitli”.
AçıkBiri geçince ya da 5 saniye dolunca “Kilitli”.

Kilitliyken turnikeyi itmek bir olay değildir; sistem olduğu yerde kalır. Menüde WASD’nin hiçbir şey yapmamasıyla aynı mantık.

Medya oynatıcı: düğmelere tıklayın

Durduruldu ↔ Çalıyor ↔ Duraklatıldı. Oyuna “duraklat” eklemek istediğinizde de kalıp aynıdır: yeni bir durum, birkaç yeni geçiş.

Pac-Man’in hayaletleri de birer durum makinesi

Aynı hayalet, durumuna göre bambaşka davranıyor: kovalarken size doğru, korkmuşken sizden uzağa. Geçişi bir olay (güç hapı) ve bir süre tetikliyor.

Durum makinesi yalnızca menü için değil

Pac-Man hayaletleriKovala, dağıl, korkmuş, yenmiş. Her modda hedef farklı.
MarioKüçük, büyük, ateşli. Mantar ve çiçek geçişi tetikler; düşmana değmek geri döndürür.
Düşman yapay zekâsıDevriye gez → oyuncuyu gör → kovala → yaklaş → saldır → kaybet → devriyeye dön.
Kapı, sandık, tuzakKapalı → açılıyor → açık. Animasyon bitince geçiş olur.

Ortak nokta: nesne bir anda tek durumdadır ve neye izin verildiği o duruma bağlıdır.

Bilgisayar biliminde yeri

Sonlu durum makinesi (FSM)Finite state machine: sınırlı sayıda durum, olaylarla tanımlı geçişler. Biçimsel bir modeldir. Derleyiciler, ağ protokolleri, arayüz ekranları ve gömülü sistemler aynı fikri kullanır.
Nesne yönelimli tasarımla ilişkisiDurum sayısı arttıkça if / else if zinciri uzar. İleride her durumu ayrı bir sınıf yapacağız; her biri kendi guncelle() ve ciz() metodunu taşıyacak. Buna State deseni denir.

Bu derste otomat teorisinin matematiğine girmiyoruz. Metin sabitli basit sürüm hem yeterli hem okunması kolay.

Diyagramı kendiniz çizin

KutuDurum
OkGeçiş
Ok yazısıOlay

Kâğıt yeterlidir. Dijital için ücretsiz araçlar da var:

AraçAdresNot
Mermaid Livemermaid.liveMetinden otomatik şekil
diagrams.netapp.diagrams.netSürükle bırak
Excalidrawexcalidraw.comEl çizimi hissi, hızlı taslak
Amaç sanat değil“Hangi olay hangi duruma götürür?” sorusunu tek bakışta yanıtlamak. Kod yazarken bu diyagram, keyPressed() ve draw() dallarının kontrol listesi olur.

Mermaid: diyagramı metinle yazmak

SatırAnlamı
stateDiagram-v2Bu bir durum diyagramıdır
[*] --> menuSiyah nokta başlangıç; ilk durum menu
menu --> oyun : SPACEmenu iken SPACE → oyun
oyun --> bitis : carpismaoyun iken çarpışma → bitis
bitis --> menu : Rbitis iken R → menu

Kalıp: A --> B : olay. Metni mermaid.live adresine yapıştırınca şekil kendiliğinden oluşur. Metin olduğu için Git’te saklamak da kolaydır.

Kaynak metin ve oluşan diyagram

Mermaid stateDiagram: kaynak metin ve üretilen diyagram
Yapay zekâya geçiş tablonuzu verip “bunu stateDiagram-v2 olarak yaz” diyebilirsiniz. Çıkan metni mutlaka Live Editor’da açıp okları kontrol edin.

Satranç: sıra bir durumdur

Satranç durum diyagramı
Beyazın sırasıYalnızca beyaz taş oynanır.
Siyahın sırasıYalnızca siyah taş oynanır.
Oyun bittiMat ya da pat. Hamle kabul edilmez.

Hamle oyunu bitirmiyorsa sıra karşıya geçer; mat ya da pat üretiyorsa “Oyun bitti”.

Hafıza kartları: kaçıncı kartı açıyoruz?

Hafıza kartları durum diyagramı
İlk kartBir kart açılır; ikinci seçim beklenir.
İkinci kartBaşka bir kart açılır; iki yüz görünür.
Eşleşme kontrolüKısa bekleme. Eşleşirse açık kalır, değilse kapanır.
BittiBütün çiftler bulundu.

Bilgi yarışması: 10 soru da olsa 50 soru da olsa üç durum

Bilgi yarışması durum diyagramı
SoruSoru metni, şıklar ve süre.
Cevap kontrolüDoğru / yanlış geri bildirimi. Şıklar kilitli.
SonuçSorular bitince toplam puan.

Soru sayısı durum sayısını artırmaz. Kaçıncı soruda olduğumuz ayrı bir değişkende tutulur.

Tetris: kontrol ne zaman kapalı?

Tetris durum diyagramı
Parça düşüyorOklarla hareket ve döndürme.
Satır temizlemeDolu satırlar silinirken kontrol kapalı.
Oyun bittiYeni parça doğduğu yere sığmıyor: tepe dolmuş.

Bir ok kendi kutusuna dönüyor: parça yere oturdu, dolu satır yok, yeni parça geliyor. Durum aynı kalır.

Sıradaki oyunumuz XOX’ta da aynı omurga var

  • Menü: kurallar. SPACE ile başla.
  • X’in sırası: yalnızca X, boş bir hücreye konur.
  • O’nun sırası: yalnızca O konur.
  • Bitiş: üçlü ya da berabere. R ile menüye dön.
Kodda biraz farklı tutacağızX ve O sırası kavram olarak ayrı durumlar. Kodda ise tek bir DURUM_OYUN içinde, sira = "X" / "O" değişkeniyle tutulacak. Menü / oyun / bitiş omurgası aynı kalacak.

Oyun döngüsünde durum

  1. Mevcut durumu oku: oyunDurumu.
  2. Duruma göre güncelle: hareket ve çarpışma yalnızca oyun durumundayken.
  3. Duruma göre çiz: menü metni ya da oyun sahnesi.
  4. Olay fonksiyonlarında (keyPressed) duruma göre geçiş uygula.

Durumu saklamak: sabitler ve tek değişken

SabitAnlamı
DURUM_MENUBaşlangıç, ana menü
DURUM_OYUNAktif oyun
DURUM_BITISOyun bitti ekranı

Durum değerleri metin olarak tutulur. Karşılaştırmalarda === kullanılır.

SPACE’e basıyorsunuz, oyun başlamıyor. Hata mesajı da yok.

"menü" ile "menu" farklı metinlerdir

“menü” eşit mi “menu”?
🤖
JavaScript
Hayır. false. Şikâyet edecek bir şey yok.
🤐
hata mesajı yok
Sessiz hataKarşılaştırma yalnızca false döner. Sonuç: nedeni belirsiz bir “hiçbir şey olmuyor”.
Sabitlerin asıl kazancıDURUM_MENU yerine DURUM_MENÜ yazarsanız JavaScript tanımsız ad için hata verir ve sorunu doğrudan gösterir.

Yeni tur: her şeyi başa al

Skor, oyuncunun konumu, topun hızı gibi oyun verileri durumdan bağımsız değişkenlerde tutulur. Durum yalnızca hangi kodun çalışacağını belirler.

Neden bir fonksiyon?Oyun her başladığında aynı sıfırlama gerekir. Tek bir yerde durursa bir değişkeni unutma riski azalır. random sayesinde her tur biraz farklı başlar.

Duruma göre draw()

FonksiyonGörevi
cizMenu()Arka plan, başlık, talimat
guncelleOyun()Hareket, çarpışma, skor; yalnızca oyun aşamasında
cizOyun()Oyuncu, top, arayüz
cizBitis()Son skor, yeniden başlatma talimatı

draw artık bir yönlendirici: duruma bakıyor ve işi ilgili fonksiyonlara bırakıyor.

Her durumda başka bir ekran

draw: duruma göre dallanma ve ekran önizlemeleri

Hangi durumda ne çalışır?

Durumdraw() içindekeyPressed()Sürekli girdi (keyIsDown)
DURUM_MENUcizMenu()SPACE → oyuna geçYok sayılır
DURUM_OYUNguncelleOyun() + cizOyun()—WASD / ok tuşları
DURUM_BITIScizBitis()R → menüye dönYok sayılır

Girdi de duruma bağlıdır. Aynı tuş farklı aşamalarda farklı iş yapabilir ya da bilinçli olarak yok sayılır.

Geçişler keyPressed() içinde

  • Her if iki şeye birden bakıyor: hangi durumdayız ve hangi tuş.
  • SPACE ve R tek seferlik olaylar: yerleri keyPressed.
  • Oyun içi sürekli hareket keyIsDown ile guncelleOyun() içinde kalır.
Fare için de aynımousePressed() içinde de duruma bakın. Yoksa bitiş ekranındaki bir tıklama oyun mantığını tetikleyebilir.

Geçiş tablosu: önce kâğıtta

Mevcut durumOlay / koşulYeni durumEk işlem
DURUM_MENUSPACE basıldıDURUM_OYUNoyunuSifirla()
DURUM_OYUNOyuncu hedefe değdiDURUM_OYUN (değişmez)Skor artar, hedefYerlestir()
DURUM_OYUNOyuncu topa çarptıDURUM_BITIS—
DURUM_BITISR basıldıDURUM_MENU—
Her olay durum değiştirmezHedef toplamak skoru artırır ama oyun sürer. Durum, yalnızca tabloda yeni bir durum yazan satırlarda değişir.
Tablo hazırsa kod hazırdırdraw() ve keyPressed(), tablodaki satırların doğrudan çevirisine dönüşür. Tablosuz yazınca genellikle bir geçiş unutulur.

Yapay zekâyla: durum diyagramı

  1. Üç durumu ve en az dört geçişi kâğıda çizin.
  2. Yapay zekâdan aynı diyagramı Mermaid metni olarak isteyin. mermaid.live adresinde açın. Eksik ya da hatalı bir geçiş var mı?
  3. “Duraklat” eklemek isterseniz hangi yeni durum ve geçişler gerekir? Sorun, sonra kendi diyagramınıza ekleyin.

Kod zamanı

  1. İskelet: üç durumlu bir sketch yazın. Her durumda farklı arka plan rengi ve ortada durumun adı. SPACE ile oyuna, R ile menüye. Oyundan bitişe geçiş için şimdilik B tuşu.
  2. Oyun durumundayken bir kare ok tuşlarıyla hareket etsin; menüde ve bitişte hareket etmesin.
  3. DURUM_DURAKLAT ekleyin: oyundayken P ile duraklat, yeniden P ile devam.
  4. Trafik ışığını durum makinesiyle yazın; süreyi deltaTime ile sayın.
  5. Zorlu: fareyi kovalayan bir hayalet. Tıklayınca 4 saniye korksun ve kaçsın.

Oyun bitiş ekranında. Oyuncu SPACE’e bastı. Ne olur?

  1. Oyun yeniden başlar
  2. Menüye dönülür
  3. Hiçbir şey olmaz
  4. Hata verir

İlk if menü durumunu, ikincisi R tuşunu istiyor. İkisi de tutmuyor. Bitişte SPACE tanımlı bir olay değil.

Hangisi bir geçiş değildir?

  1. Menüde SPACE’e basınca oyunun başlaması
  2. Oyun sırasında hedef toplayıp skorun 1 artması
  3. Oyuncunun topa çarpıp bitiş ekranına düşmesi
  4. Bitişte R’ye basınca menüye dönülmesi

Skor arttı ama durum hâlâ “oyun”. Geçiş, durum değişkeninin değer değiştirmesidir.

Menüde W’ye basılı tutunca oyuncu hareket ediyor. Hata en çok nerede aranır?

  1. keyPressed() içinde
  2. draw() içinde: guncelleOyun() durum kontrolünün dışında çağrılıyor
  3. setup() içinde
  4. Sabitlerin yazımında

Sürekli hareket guncelleOyun() içindedir. O fonksiyon yalnızca DURUM_OYUN iken çağrılmalı.

Merak edenler için kaynaklar

Bugün ne öğrendik?

  • Durum makinesi: sistem her an tek bir durumdadır; olaylar geçişleri tetikler.
  • Ayrı boolean’lar yerine tek bir oyunDurumu değişkeni.
  • Durum adları için const sabitleri: yazım hatası sessiz kalmaz.
  • draw duruma göre dallanır; girdi de duruma göre işlenir ya da yok sayılır.
  • Her olay durum değiştirmez; geçiş, durum değişkenine yapılan atamadır.
  • Önce diyagram ve geçiş tablosu, sonra kod.

Sıradaki ders

Kaç-Kaç Top

Menüsü, oyunu ve bitiş ekranı olan ilk tam oyunumuz.