Bölüm 4 · Sunum 2
Menü, oyun ve bitiş ekranlarını birbirine karıştırmadan yönetmek.
Ö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 | Ekranda ne görünür? | Girdi ne işe yarar? |
|---|---|---|
| Menü | Başlık, “Başla” talimatı | SPACE → oyunu başlat |
| Oyun | Oyuncu, hedef, top, skor | WASD 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.
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.
Bir hata sonucu ikisi de true olursa ekranda ne görürsünüz?
true olursa draw aynı frame’de hem menüyü hem sahneyi çizer. Girdinin hangi bloğa gideceği belirsizleşir.oyunDurumuHer an yalnızca bir değer taşır. Geçiş tek bir atama satırıdır.| Yaklaşım | Örnek | Ne zaman yeterli? |
|---|---|---|
| Tek boolean | oyunBitti | Yalnızca devam / bitti |
| Metin durum | "menu", "oyun", "bitis" | Birkaç aşamalı akış |
| Ayrı boolean’lar | menuAcik, oyunAcik | Önerilmez: çakışma riski |
Daire Tıklama’daki oyunBitti aslında iki durumlu küçük bir makineydi: oynuyor / bitti.
Kırmızı → Sarı → Yeşil → Sarı → Kırmızı. Burada olay bir tuş değil; sürenin dolması.

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.
Durduruldu ↔ Çalıyor ↔ Duraklatıldı. Oyuna “duraklat” eklemek istediğinizde de kalıp aynıdır: yeni bir durum, birkaç yeni geçiş.
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.
Ortak nokta: nesne bir anda tek durumdadır ve neye izin verildiği o duruma bağlıdır.
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.
Kâğıt yeterlidir. Dijital için ücretsiz araçlar da var:
| Araç | Adres | Not |
|---|---|---|
| Mermaid Live | mermaid.live | Metinden otomatik şekil |
| diagrams.net | app.diagrams.net | Sürükle bırak |
| Excalidraw | excalidraw.com | El çizimi hissi, hızlı taslak |
keyPressed() ve draw() dallarının kontrol listesi olur.| Satır | Anlamı |
|---|---|
stateDiagram-v2 | Bu bir durum diyagramıdır |
[*] --> menu | Siyah nokta başlangıç; ilk durum menu |
menu --> oyun : SPACE | menu iken SPACE → oyun |
oyun --> bitis : carpisma | oyun iken çarpışma → bitis |
bitis --> menu : R | bitis 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.

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


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

Bir ok kendi kutusuna dönüyor: parça yere oturdu, dolu satır yok, yeni parça geliyor. Durum aynı kalır.
DURUM_OYUN içinde, sira = "X" / "O" değişkeniyle tutulacak. Menü / oyun / bitiş omurgası aynı kalacak.oyunDurumu.keyPressed) duruma göre geçiş uygula.| Sabit | Anlamı |
|---|---|
DURUM_MENU | Başlangıç, ana menü |
DURUM_OYUN | Aktif oyun |
DURUM_BITIS | Oyun bitti ekranı |
Durum değerleri metin olarak tutulur. Karşılaştırmalarda === kullanılır.
"menü" ile "menu" farklı metinlerdirfalse döner. Sonuç: nedeni belirsiz bir “hiçbir şey olmuyor”.DURUM_MENU yerine DURUM_MENÜ yazarsanız JavaScript tanımsız ad için hata verir ve sorunu doğrudan gösterir.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.
random sayesinde her tur biraz farklı başlar.draw()| Fonksiyon | Gö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.
| Durum | draw() içinde | keyPressed() | Sürekli girdi (keyIsDown) |
|---|---|---|---|
DURUM_MENU | cizMenu() | SPACE → oyuna geç | Yok sayılır |
DURUM_OYUN | guncelleOyun() + cizOyun() | — | WASD / ok tuşları |
DURUM_BITIS | cizBitis() | R → menüye dön | Yok 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.
keyPressed() içindeif iki şeye birden bakıyor: hangi durumdayız ve hangi tuş.keyPressed.keyIsDown ile guncelleOyun() içinde kalır.mousePressed() içinde de duruma bakın. Yoksa bitiş ekranındaki bir tıklama oyun mantığını tetikleyebilir.| Mevcut durum | Olay / koşul | Yeni durum | Ek işlem |
|---|---|---|---|
DURUM_MENU | SPACE basıldı | DURUM_OYUN | oyunuSifirla() |
DURUM_OYUN | Oyuncu hedefe değdi | DURUM_OYUN (değişmez) | Skor artar, hedefYerlestir() |
DURUM_OYUN | Oyuncu topa çarptı | DURUM_BITIS | — |
DURUM_BITIS | R basıldı | DURUM_MENU | — |
draw() ve keyPressed(), tablodaki satırların doğrudan çevirisine dönüşür. Tablosuz yazınca genellikle bir geçiş unutulur.mermaid.live adresinde açın. Eksik ya da hatalı bir geçiş var mı?DURUM_DURAKLAT ekleyin: oyundayken P ile duraklat, yeniden P ile devam.deltaTime ile sayın.İlk if menü durumunu, ikincisi R tuşunu istiyor. İkisi de tutmuyor. Bitişte SPACE tanımlı bir olay değil.
Skor arttı ama durum hâlâ “oyun”. Geçiş, durum değişkeninin değer değiştirmesidir.
keyPressed() içindedraw() içinde: guncelleOyun() durum kontrolünün dışında çağrılıyorsetup() içindeSürekli hareket guncelleOyun() içindedir. O fonksiyon yalnızca DURUM_OYUN iken çağrılmalı.
oyunDurumu değişkeni.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.Sıradaki ders
Menüsü, oyunu ve bitiş ekranı olan ilk tam oyunumuz.