Bölüm 1 · Sunum 6

Fare ve ilk oyunumuz: Daire Tıklama

Değişkenleri, koşulları ve fareyi birleştirip oynanabilir bir oyun yazacağız.

mouseX, mouseYtext ve hizalamadist ile isabetmousePressedAdım adım oyun

Oyun, oyuncunun ne yaptığını nereden bilir?

Şimdiye kadar sketch’lerimiz kendi kendine çalıştı. Bir oyunda ise kararlar oyuncuya bağlı: fare nerede, tıkladı mı?

p5.js fareyi bizim yerimize izler

AdTürNe verir?Örnek
mouseXnumberİmlecin x konumu (0 … width − 1)500 genişlikte tuvalin ortasında ≈ 250
mouseYnumberİmlecin y konumu (0 … height − 1)Üst kenarda 0
mouseIsPressedbooleanFare tuşu şu an basılı mı?Basılıyken true
mousePressed()fonksiyonTuşa basıldığı an çalışırHer basışta bir kez
mouseReleased()fonksiyonTuş bırakıldığı an çalışırHer bırakışta bir kez
Olay fonksiyonumousePressed() ve mouseReleased(), tıpkı setup() ve draw() gibi özeldir: olay gerçekleşince p5.js bu addaki fonksiyonu kendisi çağırır.

Yalnızca fareyle oynanan oyunlar

Fruit Ninja 2010Parmağın ekranda bıraktığı iz meyveye değiyor mu? Oyun her frame parmağın konumunu okur.
osu! 2007Müzikle beliren dairelere doğru anda tıklanır. Bugün yazacağımız oyunun ritimli akrabası.
Nişan antrenmanıE-spor oyuncuları maçtan önce ısınır: beliren hedefe en hızlı tıklayan kazanır.
Üçünün de sorduğu iki soruİmleç şu an nerede? Tıklama, hedefin içine mi düştü? Bu derste ikisini de yanıtlayacağız.

Daire fareyi takip etsin

Fareyi tuvalde gezdirin, sonra tuşu basılı tutun. mouseX ve mouseY her frame güncellenir.

mouseX ve mouseY ile: gözler sineği izler

Fareyi tuvalde gezdirin. Dört yaratık da aynı iki sayıyı okuyor: mouseX ve mouseY. Göz bebeğinin hesabını şimdi anlamanız gerekmiyor.

Ekrana yazı yazmak

KomutNe yapar?
text(metin, x, y)(x, y) noktasını referans alarak metni yazar.
textSize(boyut)Yazı boyutunu piksel olarak ayarlar.
textAlign(hizaX, hizaY)(x, y) noktasının, metnin hangi köşesine ya da kenarına denk geleceğini seçer.
YatayLEFT sol kenar, CENTER orta, RIGHT sağ kenar.
DikeyTOP üst, CENTER orta, BOTTOM alt.

textAlign koordinatı değiştirmez; o noktanın metne nereden bağlanacağını değiştirir.

Aynı araçlar, iki farklı hizalama

Köşe yazıları için textAlign(LEFT, TOP); ekran ortası mesajı için textAlign(CENTER, CENTER) ve width / 2, height / 2.

Fare dairenin içinde mi? Bunu program nasıl anlar?

Elimizde dört sayı var: farenin x ve y’si, dairenin merkezi ve yarıçapı. Hangi soruyu sormalıyız?

Mesafe yarıçaptan küçükse içeridedir

Fareyi dairenin içine ve dışına götürün. Renkli çizgi merkezle fare arasındaki mesafe, mavi çizgi yarıçaptır; soru yalnızca hangisinin daha uzun olduğudur.

dist(): iki nokta arasındaki mesafe

dist(x1, y1, x2, y2)p5.js’in yerleşik fonksiyonu. İki nokta arasındaki düz mesafeyi (Öklid mesafesi) sayı olarak verir.
  • Matematikteki karşılığı: sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)). sqrt de yerleşiktir; isterseniz kendiniz yazabilirsiniz.
  • İleride iki dairenin birbirine değip değmediğini de böyle anlayacağız: mesafe ile yarıçapların toplamını karşılaştırarak.

Fare daireye girince renk değişsin

Aynı test, başka oyun: el feneri

Bir nesne yalnızca dist(fare, nesne) < 110 ise çiziliyor. Korku oyunlarındaki el feneri, strateji oyunlarındaki “savaş sisi” aynı sorunun cevabına bakar.

Tıklayınca skor 1 artsın. Bunu draw içine yazarsak?

Bir kez tıkladınız. Skor kaç olur?

Tek tıklama, onlarca puan

Tuvale birkaç kez tıklayın. Sonra tuşu basılı tutun: hangi sayaç fırlıyor?

Dünyanın en cömert oyunu

🤑Bir tık, kırk puanFare düğmesi bir saniyenin üçte ikisi kadar basılı kaldı.
Neden?draw saniyede 60 kez çalışır. Parmağınız düğmedeyken her frame “basılı mı?” sorusunun cevabı evettir.

Gerçek oyunlarda da görülür: bir düğmeye bir kez bastığınızda menüde üç satır birden atlanıyorsa sebep büyük ihtimalle budur.

Basılı tutmak ile basma anı aynı şey değil

YöntemNe zaman?Skor için
mouseIsPressedTuş basılı tutulduğu her frame (saniyede ~60)Tek tıklama birçok kez sayılır
mousePressed()Tuşa basıldığı tek anSkor bir kez artar
KuralBir kez sayılması gereken olaylar mousePressed() içine yazılır.

mousePressed() ile tek tıklamayı yakalamak

tiklandi bir bayrak: tıklama olunca true oluyor, draw ona bakıp yazıyı gösteriyor.

İkisi bir arada: boya programı

Çizmek süren bir iş: basılı olduğu her frame çizgi uzar. Renk seçmek tek seferlik bir olay: tıklama anında bir kez olur. Bu sketch’te background yalnızca setup’ta ve “Temizle”de çağrılıyor; çizgiler o yüzden kalıyor.

Daire Tıklama: kurallar

  1. Ekranda rastgele bir konumda hedef daire görünür.
  2. Oyuncu daireye tıklarsa skor 1 artar; daire yeni bir rastgele konuma taşınır.
  3. Daireye isabet etmezse skor değişmez.
  4. Skor 10’a ulaşınca oyun kazanılır.
  5. Yeni tur için sketch yeniden çalıştırılır; ayrı bir menü yok.
Neye ihtiyacımız var?Yalnızca değişkenler ve if / else. Döngü ya da dizi gerekmiyor.

Tıklama anında kararlar

  1. mousePressed() tetiklenir.
  2. Oyun bittiyse hiçbir şey yapma; çık.
  3. Fare ile hedef arasındaki mesafeyi hesapla.
  4. Mesafe yarıçaptan küçük değilse: ıskaladı, skor değişmez.
  5. Küçükse: skoru 1 artır.
  6. Skor hedefe ulaştıysa oyunu bitir; ulaşmadıysa hedefi yeni bir konuma taşı.

Kutuları hazırla

  • Hepsi en üstte, setup ve draw’ın dışında: oyun boyunca yaşayacaklar.
  • hedefX ve hedefY henüz boş; değerlerini setup verecek.
  • HEDEF_SKOR değişmeyecek: const.
  • oyunBitti bir bayrak: başta false.

setup(): tuval ve ilk hedef

random(min, max)min ile max arasında rastgele, ondalıklı bir sayı verir; max dahil değildir. random(10, 50) yaklaşık 10 ile 50 arasında bir değer üretir.
Tek parametreli random(max) 0 ile max arasında, parametresiz random() 0 ile 1 arasında değer verir.

Neden random(0, width) yazmadık?

Daha basit görünüyor. Hedefin merkezi tam 0’a ya da tam width’e denk gelirse ne olur?

Daire tuvalden taşar

merkez x = 0 merkez burada seçilir

ellipse merkezden çizer. Merkez kenara çok yaklaşırsa dairenin bir kısmı dışarıda kalır; oyuncu yarım bir hedefe tıklamaya çalışır.

Çözüm: bir yarıçap içeride kalx için alt sınır hedefYaricap, üst sınır width - hedefYaricap. y için aynısı height ile.

draw(): çizim ve oyun durumu

  • !oyunBitti: “oyun bitmediyse”. Hedef daire yalnızca o zaman çizilir.
  • Oyun bittiyse dairenin yerine kazanma yazısı gelir.
  • Skor göstergesi if’in dışında: her durumda çizilir.
  • İki yazı için iki ayrı textAlign: ortada ve sol üstte.

mousePressed(): tıklama kontrolü

returnBulunulan fonksiyonun geri kalanını çalıştırmadan çıkmasını sağlar.
  • Oyun bittiyse tıklamalar yok sayılır.
  • İsabet varsa skor 1 artar.
  • Hedef skora ulaşıldıysa oyun biter; ulaşılmadıysa hedef yeni konuma taşınır.

Tam kod

Turuncu daireye tıklayın: 10 isabet

Bu oyunda olmayanlar

KlavyekeyIsDown ve keyPressed() kullanmadık. Klavye girdisini ilerleyen bölümlerde ele alacağız.
Birden fazla hedefAynı anda birçok daire için dizilere ihtiyaç var. O da sonraki bölümlerin konusu.

Bu oyun, bir oyunun en temel döngüsünü gösteriyor: girdi → karar → geri bildirim.

Bir adım ötesi: süre, küçülen hedef, ıska

Çekirdek aynı: dist ile isabet testi ve mousePressed. Üstüne üç küçük fikir eklendi. Bunları “Oyunu zorlaştırın” etkinliğinde kendiniz yazmayı deneyeceksiniz.

Kendi cümlelerinizle açıklayın

  1. Skorun bir basışta birden fazla artmaması için mousePressed ile draw içindeki mouseIsPressed arasındaki farkı anlatın. Yanlış tasarımda ne olurdu?
  2. Hedef konumunda neden random(hedefYaricap, width) ya da random(0, width) yazmadık? Bu ikisinden birini kullansaydık görünüm ve tıklanabilirlik nasıl değişirdi? Editörde deneyip gözleyin.

Oyunu zorlaştırın

  1. Dairenin dışına tıklanınca skor 3 puan azalsın.
  2. Skor sıfırın altına düşerse oyun bitsin ve ekranda “Üzgünüm, oyunu kaybettiniz” yazsın.
  3. Kazanma ve kaybetme mesajlarını skora bakarak ayırt edin.
İpucumousePressed içindeki mesafe < hedefYaricap dalına bir else ekleyin. draw içinde iki mesajı skor ile ayırın.

Zorlu görevler

Küçülen hedefHer isabette yarıçap 3 piksel küçülsün ama 15’in altına inmesin.
İsabet oranıHer tıklamayı sayın. Sol üstte “7 / 12” gibi isabet / deneme gösterin. Oyun bitince tıklamalar sayılmasın.
SüreOyuncunun 15 saniyesi olsun. Kalan süreyi ekrana yazın; süre bitince oyun bitsin. İpucu: frameCount / 60.

Yapay zekâyla: nokta elipsin içinde mi?

  1. Yapay zekâdan, (mouseX, mouseY) noktasının bir dairenin içinde olup olmadığını denetleyen kısa bir kod ve formülün terim terim açıklamasını isteyin.
  2. İlk yanıt çoğu zaman yüzeysel kalır. Soruyu ilerletin: “Aynısını dist kullanmadan sqrt ile yaz; Pisagor bağıntısıyla ilişkisini göster.”
  3. Kendi fonksiyonunu tanımlarsa geri çevirin: henüz fonksiyon yazmayı görmedik.
  4. Aldığınız kodu dist(mouseX, mouseY, hedefX, hedefY) < hedefYaricap ifadesiyle karşılaştırın.

Yapay zekâyla: dokunmatik ekran

  1. Sorun: “p5.js sketch’imi dokunmatik ekranda kullanacağım. mousePressed / mouseX yerine dokunmayı nasıl algılarım?”
  2. Yanıttaki adları (örneğin touches, touchStarted) p5.js referansından doğrulayın.
  3. Sketch’inizi telefonda ya da tablette nasıl açacağınızı sorun ve önerilen yollardan birini deneyin.

dist(0, 0, 3, 4) kaç döndürür?

  1. 7
  2. 5
  3. 12
  4. 25

Pisagor: 3² + 4² = 25, karekökü 5. dist yatay ve dikey farkları toplamaz.

Oyuncu tam dairenin kenarına tıkladı: mesafe = 40, yarıçap = 40.

  1. İsabet sayılır
  2. Iska sayılır

40 < 40 yanlıştır. Kenarı da isabet saymak isteseydik <= yazardık. Hangisini istediğinize siz karar verirsiniz.

mousePressed’in başındaki return’lü if’i silersek?

  1. Hiçbir şey değişmez.
  2. Oyun hiç bitmez.
  3. Oyun bittikten sonra da, eski hedefin olduğu yere tıklanınca skor artmaya devam eder.
  4. Program hata verir.

Daire artık çizilmiyor ama hedefX ve hedefY hâlâ duruyor. İsabet testi çalışır; skor 11, 12… olur.

Merak edenler için kaynaklar

Bölüm 1’i bitirdik

  • mouseX, mouseY imlecin konumunu verir; her frame güncellenir.
  • mouseIsPressed basılı tutulduğu her frame doğrudur; mousePressed() basma anında bir kez çalışır.
  • text, textSize, textAlign ile ekrana yazı yazılır.
  • dist < yarıçap: nokta dairenin içinde.
  • random(min, max) ile hedef, kenardan bir yarıçap içeride seçilir.
  • return fonksiyondan erken çıkar; oyunBitti bayrağı oyunu durdurur.

Sıradaki bölüm

Bölüm 2: Döngüler ve fonksiyonlar

Aynı satırı yüz kez yazmadan yüz şekil çizmek.