Ana Başlık 4. Klavye Girdisi

Amaç: Klavye olaylarını (keyIsDown, key, keyPressed()) öğreterek oyuncu kontrollü hareket sağlamak.

Öğrenme Çıktıları:

Anahtar Sözcükler: klavye girdisi, keyIsDown, keyPressed, key, keyCode, oyuncu kontrolü, ASCII, Unicode

Giriş

Önceki ana başlıkta top deltaTime ile kendi kendine hareket ediyordu; oyuncu yalnızca izliyordu. Oyunlarda karakter, araç veya imleç çoğu zaman klavye (ve fare) ile yönlendirilir. Klavyenin en tanıdık kullanımı tek seferlik olaydır: bir tuşa basıldığı anda tek bir iş yapılır, örneğin R ile tur yeniden başlatılır. Gerçek zamanlı kontrolde ise tuş basılı tutulduğu sürece hareket devam etmelidir: WASD veya ok tuşlarıyla kareyi gezdirmek buna tipik örnektir.

p5.js, fare girdisinde olduğu gibi klavye için de iki katman sunar: draw() içinde her frame okunan durum (keyIsDown) ve tuşa basıldığı anda bir kez çalışan olay fonksiyonu (keyPressed). Bu ana başlıkta her iki yöntem sistematik biçimde ele alınacak; hareket deltaTime ile birleştirilerek önceki ana başlıktaki frame bağımsız hız korunacaktır.

Bu iki katmanlı yaklaşım, klavyenin fiziksel doğasından kaynaklanır: bir tuş, oyuncu parmağını kaldırana kadar "basılı" kalır ve bu süre boyunca aynı tuşa ait sayısız draw() çağrısı gerçekleşebilir. Programın bu süreklilikten haberdar olması için her frame'de tuşun anlık durumunu sorgulaması gerekir; bu da keyIsDown() fonksiyonunun görevidir. Buna karşılık "tuşa basıldı" bilgisinin yalnızca bir kez işlenmesi istenen durumlar da vardır — bir menüde seçim yapmak, bir mermi ateşlemek gibi; bu tür senaryolarda p5.js'in tuş basışını olay olarak bildirdiği keyPressed() daha uygundur. İki katmanı doğru yerde kullanmak, klavye kontrollü bir oyunun hem tepkisel hem öngörülebilir olmasını sağlar.

Türkiye'de okul laboratuvarlarında QWERTY klavye yaygındır; WASD ve ok tuşları birlikte desteklenirse farklı alışkanlıklara sahip oyuncular aynı sketch'i kullanabilir. Tuval odaklıyken tuşlar sketch'e gider — önizleme paneline bir kez tıklamak gerekir; aksi halde girdi tarayıcıya veya editöre yönlenebilir.

4.1. Klavye Olayları ve p5.js Örüntüsü

Tanım: Klavye girdisi — Oyuncunun tuş basmasıyla programa ilettiği kontrol bilgisidir.

p5.js'te yerleşik olay fonksiyonları (önceki bölümlerde setup, draw, mousePressed ile tanıtılan örüntü):

Tablo 1.

Fonksiyon Ne zaman çalışır Tipik kullanım
keyPressed() Tuşa basıldığı frame'de bir kez Zıplama, ateş, menü seçimi, tur yenileme
keyReleased() Tuş bırakıldığı frame'de bir kez Tuş bırakılınca eylem tetikleme (ör. şarj biriktirip bırakınca ateş etme)
draw() + keyIsDown() Tuş basılı olduğu sürece her frame Sürekli yürüme, hızlanma

Bilgi: keyPressed adını taşıyan fonksiyon, p5.js'in otomatik çağırdığı yerleşik olay adıdır; setup ve draw gibi tam yazım gerekir. Kendi fonksiyon adınız farklı olursa p5.js o kodu tuş olayı için çalıştırmaz.

Fare ile karşılaştırma (önceki bölümler):

Tablo 2.

Girdi Sürekli (basılı tutma) Tek seferlik olay
Fare mouseIsPressed, mouseX / mouseY mousePressed()
Klavye keyIsDown(...) keyPressed()

4.2. keyIsDown ile Sürekli Hareket

Tanım: keyIsDown(key) — p5.js fonksiyonu; verilen tuş o frame'de basılıysa true, değilse false döndürür. draw() içinde çağrılır.

Ok tuşları için p5.js sabitleri kullanılabilir: LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW. Harf tuşlarında keyIsDown sayı ister: 65 (A), 68 (D).

Kod bloğu: Ok tuşlarıyla yatay hareket — deltaTime ile hız.

Kod 1.

javascript
let kareX = 200;let kareY = 150;const KARE_BOYUT = 40;const HIZ = 180; // piksel / saniye function setup() {  createCanvas(500, 300);  noStroke();} function draw() {  background(35, 40, 55);   let dt = deltaTime / 1000;   if (keyIsDown(RIGHT_ARROW)) {    kareX = kareX + HIZ * dt;  }  if (keyIsDown(LEFT_ARROW)) {    kareX = kareX - HIZ * dt;  }   fill(100, 200, 255);  rect(kareX, kareY, KARE_BOYUT, KARE_BOYUT);}

Birden fazla if kullanıldığında koşullar bağımsızdır; çapraz hareket (ör. sağ + yukarı) aynı frame'de birleşebilir. else if yalnızca tek yön seçilecekse uygundur.

Çapraz hareket ve hız: Sağ ve yukarı aynı anda basılıyken kare hem X hem Y değişir; frame başına kat edilen mesafe HIZ * dt ile her eksende ayrı uygulanır. Köşegen hareket biraz daha hızlı görünebilir (Pisagor bağıntısı); rekabetçi oyunlarda hız normalize edilir. Örneklerde basit bağımsız if blokları kullanılır; çapraz hızı eşitlemek istenirse X ve Y bileşenleri birim vektöre göre ölçeklenip (normalize edilip) tekrar HIZ ile çarpılır.

Tablo 3.

Tuş kombinasyonu X değişimi Y değişimi Görsel etki
Yalnızca RIGHT + 0 Yatay
Yalnızca UP 0 − Dikey
RIGHT + UP + − Çapraz sağ-üst

Dikkat: Tuş kodunu yalnızca keyPressed() içinde okursanız basılı tutma ile sürekli hareket üretilemez; draw() döngüsünde keyIsDown gerekir.

Bu hata sık görülür çünkü keyPressed() sezgisel olarak "tuşla ilgili her şeyin buraya yazılacağı" fonksiyon gibi algılanabilir. Ancak keyPressed() yalnızca tuşa basılma anında bir kez tetiklenir; oyuncu tuşu birkaç saniye basılı tutsa da fonksiyon gövdesi tek seferlik çalışır. Bu nedenle keyPressed() içine kareX = kareX + HIZ * dt gibi bir satır yazmak, karenin yalnızca her basışta bir kez ve sabit miktarda ilerlemesine yol açar — akıcı hareket değil, adım adım sıçrama görünür. Sürekli hareket her zaman draw() içindeki bir koşulla, yani keyIsDown() ile sağlanmalıdır.

Dikey hareket için UP_ARROW ve DOWN_ARROW aynı örüntüyle eklenir:

Kod 2.

javascript
  if (keyIsDown(DOWN_ARROW)) {    kareY = kareY + HIZ * dt;  }  if (keyIsDown(UP_ARROW)) {    kareY = kareY - HIZ * dt;  }

4.3. keyPressed ve Tek Seferlik Eylemler

Turu yeniden başlatan R tuşu, keyPressed() ile şu biçimde yazılır:

Kod 3.

javascript
function keyPressed() {  if (key === "r" || key === "R") {    // turu sıfırla  }}

Tanım: key — Basılan tuşun karakter değerini tutan p5.js değişkeni ( 'a', 'R', ' ' boşluk vb.). Yalnızca olay fonksiyonu çalıştığı frame'de anlamlıdır.

keyPressed() ile mousePressed() aynı mantığı izler: olay bir kez tetiklenir. Zıplama, tek atış veya menüde seçim gibi "her basışta bir eylem" senaryolarına uygundur.

Kod bloğu: Boşluk tuşuna basınca karenin rengini değiştirme (toggle).

Kod 4.

javascript
let kareRengi; function setup() {  createCanvas(400, 300);  kareRengi = color(100, 200, 255);} function draw() {  background(30);  fill(kareRengi);  rect(width / 2 - 30, height / 2 - 30, 60, 60);} function keyPressed() {  if (key === " ") {    if (red(kareRengi) > 200) {      kareRengi = color(100, 200, 255);    } else {      kareRengi = color(255, 120, 80);    }  }}

red() p5.js renk bileşenini okur; renk kavramı önceki bölümlerdeki fill(r, g, b) ile uyumludur.

Bilgi: Tek seferlik eylem için draw() içinde keyIsDown + bayrak değişkeni kullanmak yerine doğrudan keyPressed() tercih edilir; kod niyeti daha net iletilir.

Alternatif olarak draw() içinde keyIsDown ile birlikte bir "önceki durum" bayrağı tutulup tek seferlik eylem simüle edilebilir (tuş bu frame basılı, önceki frame basılı değildi ise eylemi çalıştır). Bu teknik bazı ileri senaryolarda (örneğin aynı frame'de birden çok girdi kaynağını birleştirirken) gerekebilir; ancak ek bir değişken ve karşılaştırma gerektirdiği için kodu karmaşıklaştırır. p5.js'in kendisi bu karşılaştırmayı keyPressed() aracılığıyla otomatik yaptığından, basit ve orta düzey oyunlarda doğrudan keyPressed() tercih edilmelidir.

keyReleased(): Tuş bırakıldığı anda bir kez çalışır. keyPressed() basma anını, keyIsDown() basılı tutmayı, keyReleased() ise bırakma anını yakalar. Örneğin SPACE basılıyken şarj dolup bırakılınca ateş etmek için keyIsDown ile şarj, keyReleased ile ateş ayrılabilir.

Kontrol şeması örneği (uzay gemisi):

Tablo 4.

Tuş Yöntem Eylem
Ok / WASD keyIsDown + draw() Sürekli hareket
SPACE keyPressed() Tek mermi
R keyPressed() Tur sıfırlama
ESC keyPressed() Menüye dön (önceki bölümlerin 4. ana başlığı)

4.4. key ve keyCode

Bazı tuşların tek karakterle temsil edilmesi zordur veya ok tuşları farklı klavyelerde farklı karakter üretebilir. Bu durumda keyCode kullanılır.

Tanım: keyCode — Basılan tuşun sayısal kodu. Ok tuşları için p5.js sabitleri keyCode ile eşleşir.

key ve keyCode arasındaki fark, "hangi karakter" ile "hangi fiziksel tuş" sorularının ayrımına dayanır. Harf ve rakam tuşlarında key doğrudan okunabilir bir karakter döndürür ('a', '5'); bu, ekrana metin yazdırma veya karakter karşılaştırma için pratiktir. Ok tuşları, SHIFT, CTRL gibi tuşlarda ise yazdırılabilir bir karakter yoktur — bu tuşlar keyCode üzerinden sayısal bir kimlikle temsil edilir. p5.js, sık kullanılan ok tuşları için LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW adlı sabitleri önceden tanımlayarak bu sayısal kodları ezberlemeyi gereksiz kılar; geliştirici keyCode === 37 yazmak yerine keyCode === LEFT_ARROW yazabilir, kod hem okunur hem hataya daha az açık olur.

37 nereden geliyor? ASCII, Unicode ve tuş kodları

keyCode === 37 yazıldığında 37 «rastgele bir sabit» değildir; bilgisayarların karakter ve tuşları sayılarla temsil etme geleneğinden gelir. «Bu sayı tablonun neresinde?» sorusu için üç katmanı ayırmak yeterlidir.

1. ASCII (American Standard Code for Information Interchange)
Erken bilgisayarlarda harf, rakam ve bazı denetim karakterleri 0–127 aralığında numaralandırıldı. 0–31 denetim kodlarıdır (görünmez); 32–126 yazdırılabilir karakterlerdir. Görsel 1 bu yazdırılabilir aralığı gösterir; renkler rakam, büyük harf ve küçük harf bloklarını ayırır.

Görsel 1. ASCII tablosu — yazdırılabilir karakterler (32–126)
Görsel 1. ASCII tablosu — yazdırılabilir karakterler (32–126)

Tablo 5.

Aralık ASCII / Unicode Anlam
48 … 57 '0' … '9' Rakamlar
65 … 90 'A' … 'Z' Büyük harfler
97 … 122 'a' … 'z' Küçük harfler
32 boşluk Space

Harf ve rakam gibi yazdırılabilir tuşlarda key değişkeni doğrudan bu karakteri verir ('A', 'w'). JavaScript’te bir karakterin numarasını görmek için charCodeAt kullanılabilir: 'A'.charCodeAt(0) → 65.

Bilgi: Tam ASCII listesi ve tarihçesi için ASCII (Wikipedia) veya ASCII Table kaynaklarına bakılabilir. Bu kitaptaki Görsel 1, oyun kodunda en çok kullanılan yazdırılabilir dilimi özetler.

Yazdırılamayan (denetim) karakterler: \n, \t

Görsel 1’de görünmeyen 0–31 aralığı denetim kodlarıdır; ekranda bir «harf» gibi basılmaz, ama programda kaçış dizisi (escape sequence) ile yazılır. Oyun ve arayüz metinlerinde en sık kullanılan ikisi:

Tablo 6.

Yazım (string içinde) ASCII Adı Ne yapar?
\n 10 LF (line feed) Yeni satır (satır sonu)
\t 9 TAB (sekme) Yatay sekme; genelde birkaç boşluk kadar ilerler
(boşluk tuşu) 32 Space Görünür boşluk (yazdırılabilir)

JavaScript string’inde backslash (\) «sonraki karakter özel anlam taşır» demektir: "Merhaba\nDunya" içinde \n iki karakter (\ ve n) gibi yazılır ama bellekte tek satır-sonu karakterine dönüşür.

p5.js text() bu kaçışları işler; HUD (skor / can) gibi çok satırlı yazılar için \n pratiktir:

Kod 5.

javascript
function draw() {  background(30);  fill(255);  textSize(18);  textAlign(LEFT, TOP);  text("Skor: 3\nCan: 5", 24, 40);   // iki satır  text("A\tB\tC", 24, 100);            // sekme ile aralık}

Görsel 2. `\n` ve `\t` — text() kaynak kodu ve tuval çıktısı
Görsel 2. `\n` ve `\t` — text() kaynak kodu ve tuval çıktısı

Görsel 2 solda string içindeki kaçışları, sağda tuvalde oluşan satır kırılmasını ve sekme boşluğunu gösterir.

Bilgi: console.log("skor\t" + skor) konsolda sütun gibi hizalama için de \t kullanır. Tuvalde sütunlar kritikse \t yazı tipine göre farklı genişlik verebilir; o zaman ayrı text(..., x, y) çağrıları veya sabit x ofsetleri daha öngörülebilirdir.

Dikkat: Kaynak kodda girinti için kullanılan boşluk ve Tab da aynı ASCII karakterleridir (32 ve 9). Bunlar string içindeki \n / \t ile karıştırılmamalıdır: biri editörde satırı içeri almak, diğeri metin içeriğinde satır kırmak / sekme koymaktır. Girintinin okunabilirlikteki rolü önceki bölümlerde if ve for bloklarıyla birlikte vurgulanır.

2. Unicode
ASCII yalnızca Latin alfabesinin dar bir dilimini kapsar. Unicode, dünyadaki yazı sistemlerini (Türkçe ğ, ş, emoji, vb.) tek bir numara uzayında toplayan daha geniş standarttır. Unicode’un ilk 128 kodu ASCII ile aynıdır; yani 'A' hem ASCII’de hem Unicode’da 65’tir. Bu kitapta oyun girdileri çoğunlukla Latin harf ve ok tuşlarıyla sınırlıdır; yine de metinleri bilgisayarın «harf = sayı» diye sakladığını bilmek, ileride dosya, ağ veya farklı dillerle çalışırken işe yarar.

Bilgi: Unicode’un resmi özeti: The Unicode Standard. Karakter arama için Unicode Character Table kullanışlıdır. JavaScript kaynak dosyaları UTF-8 ile saklandığında Unicode karakterler metin içinde kullanılabilir.

Dikkat: JavaScript (ve dolayısıyla p5.js sketch’leri) Unicode destekler; teknik olarak let skorŞuAn = 0; veya function çizTop() { … } gibi Türkçe karakterli tanımlayıcılar çoğu modern tarayıcıda çalışır. Yine de bu kitaptaki örneklerde ve önerilen alıştırmalarda değişken / fonksiyon adlarında ASCII harfler (skorSuAn, cizTop) tercih edilir: (1) farklı editör ve yazı tipi kombinasyonlarında karakter bozulması riski azalır; (2) İngilizce kaynaklar ve hata mesajlarıyla eşleşmek kolaylaşır; (3) takım çalışmasında klavye düzeni farkları az sorun çıkarır. Oyuncuya gösterilen metinlerde (text("Skor: " + skor), "Kazandınız!") Türkçe karakter kullanmak ise doğaldır ve teşvik edilir — kısıt tanımlayıcı adlarındadır, ekran yazılarında değil.

3. keyCode ve ok tuşları (37, 38, 39, 40)

Dikkat: Ok tuşlarının ASCII kodu yoktur. ASCII (ve Görsel 1) yazdırılabilir / denetim karakterleri içindir (A, %, satır sonu…). Sol oka basınca metin kutusuna % yazılmaz; key de genelde tek bir yazdırılabilir harf vermez. Oklar «karakter» değil, özel tuştur.

O zaman 37 nereden geliyor? Tarayıcıların eski klavye API’sinin (p5.js’in keyCode ile yansıttığı) ayrı bir tuş-numara listesinden. Bu liste ASCII tablosu değildir; tesadüfen sol oka 37 denmiştir. Aynı şekilde yukarı 38, sağ 39, aşağı 40’tır:

Tablo 7.

Tuş keyCode (sayı) p5.js sabiti ASCII’de karşılığı?
Sol ok 37 LEFT_ARROW Yok (← diye bir ASCII karakteri yok)
Yukarı ok 38 UP_ARROW Yok
Sağ ok 39 RIGHT_ARROW Yok
Aşağı ok 40 DOWN_ARROW Yok

«Ama ASCII 37 = % değil mi?» Evet — ama o başka bir sözlükteki 37’dir. İki farklı numaralandırma aynı rakamı kullanabilir; bu bir çakışma veya çelişki değil, tesadüftür. (İki farklı apartmanda «daire 37» olması gibi: aynı numara, farklı binalar.) Sol ok ≠ %. % tuşuna basınca key === "%" olur; sol oka basınca keyCode === LEFT_ARROW (yani 37) bakılır — farklı olaylar.

Bu yüzden keyCode === 37 ile keyCode === LEFT_ARROW aynı karşılaştırmadır; LEFT_ARROW yalnızca o tuş kimliğinin okunabilir adıdır. Harf tuşlarında keyCode çoğu ortamda büyük harfin ASCII/Unicode numarasına yakındır (ör. A → 65); yine de harf kontrolünde key === "w" / key === "W" daha doğrudan ve güvenilirdir. Ok, SHIFT, ENTER gibi özel tuşlarda keyCode (veya LEFT_ARROW sabiti) kullanılır — ASCII tablosundan ok aramayın; orada yoktur.

Dikkat: Ok / SHIFT sayılarını ezberlemeyin; ASCII’den «okun kodu» diye satır aramayın. Kodda her zaman LEFT_ARROW / RIGHT_ARROW / UP_ARROW / DOWN_ARROW yazın. console.log(keyCode) yalnızca merak veya hata ayıklama içindir.

Dikkat: LEFT / RIGHT / UP / DOWN sabitleri hizalama içindir (textAlign(LEFT) …) ve değerleri string’dir ('left'). keyIsDown(LEFT) bu yüzden «Number bekleniyor, string geldi» uyarısı üretir ve ok tuşunu yakalamaz. Oklar için LEFT_ARROW kullanın. keyIsDown harf için de sayı ister: keyIsDown(65) (A), 68 (D), 87 (W), 83 (S).

Tablo 8.

Tuş p5.js sabiti Tipik kullanım
Sol ok LEFT_ARROW keyIsDown(LEFT_ARROW) veya keyCode === LEFT_ARROW
Sağ ok RIGHT_ARROW keyIsDown(RIGHT_ARROW)
Yukarı UP_ARROW keyIsDown(UP_ARROW)
Aşağı DOWN_ARROW keyIsDown(DOWN_ARROW)
Harf keyCode sayısı keyIsDown(65) (A); olaylarda key === "w"

Kod bloğu: keyPressed() içinde ok tuşu ile mesaj — önceki bölümlerde tanıtılan console.log() ile tuşa basıldığı alt konsolda görülür (tuvalde değil).

Kod 6.

javascript
function keyPressed() {  if (keyCode === UP_ARROW) {    console.log("Yukari ok");  }  if (key === "w" || key === "W") {    console.log("W tusu");  }}

WASD ve ok tuşlarını aynı hareket için birleştirmek yaygındır:

Kod 7.

javascript
  if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) {    kareX = kareX - HIZ * dt;  }  if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) {    kareX = kareX + HIZ * dt;  }

4.5. Klavye ile Kontrol Edilen Kare

Aşağıdaki sketch, ok tuşları ve WASD ile hareket eden bir kareyi tuval sınırları içinde tutar. Hareket deltaTime ile hesaplanır; ekranda basılı tuş bilgisi gösterilir.

Kontrol özeti:

Kod 8.

javascript
let oyuncuX;let oyuncuY;const BOYUT = 44;const HIZ = 200; function setup() {  createCanvas(560, 360);  noStroke();  oyuncuX = width / 2 - BOYUT / 2;  oyuncuY = height / 2 - BOYUT / 2;} function draw() {  background(28, 32, 48);  let dt = deltaTime / 1000;   if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) {    oyuncuX = oyuncuX - HIZ * dt;  }  if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) {    oyuncuX = oyuncuX + HIZ * dt;  }  if (keyIsDown(UP_ARROW) || keyIsDown(87)) {    oyuncuY = oyuncuY - HIZ * dt;  }  if (keyIsDown(DOWN_ARROW) || keyIsDown(83)) {    oyuncuY = oyuncuY + HIZ * dt;  }   oyuncuX = constrain(oyuncuX, 0, width - BOYUT);  oyuncuY = constrain(oyuncuY, 0, height - BOYUT);   fill(90, 180, 255);  rect(oyuncuX, oyuncuY, BOYUT, BOYUT);   fill(220);  textSize(14);  textAlign(LEFT, TOP);  text("Ok / WASD: hareket  |  R: merkeze sifirla", 12, 12);  text("Fare: " + floor(mouseX) + ", " + floor(mouseY), 12, 32);} function keyPressed() {  if (key === "r" || key === "R") {    oyuncuX = width / 2 - BOYUT / 2;    oyuncuY = height / 2 - BOYUT / 2;  }}

Tanım: constrain(deger, min, max) — p5.js fonksiyonu; değeri verilen alt ve üst sınır arasında tutar. Kare tuval dışına taşmaz. Bu, tuval sınır çarpışmasının pratik kısayoludur; bir sonraki ana başlıkta sınır testinin if ile açık yazımı ve sekme tepkisi ayrıca ele alınır.

Tanım: color(r, g, b) — p5.js fonksiyonu; Önceki bölümlerdeki RGB modeliyle (0–255 bileşenler) renk değeri üretir ve değişkende saklanabilir. red(), green(), blue() bu değerden ilgili bileşeni okur. Doğrudan fill(r, g, b) ile aynı sayı aralığı kullanılır; fark, rengin bir kez üretilip yeniden kullanılabilmesidir.

Tanım: floor(n) — Ondalıklı sayıyı aşağı yuvarlayarak tam sayıya indirger; ekranda koordinat göstermek için kullanılmıştır (önceki bölümler, diziler ana başlığındaki floor(random(...)) örneğiyle aynı işlev).

Tuval odaklıyken tuşlar sketch'e gider; tarayıcı sekmesinin odak dışı kalması durumunda girdi alınmayabilir — önizleme paneline tıklamak gerekir.

Hata ayıklama ipuçları:

Tablo 9.

Sorun Olası neden Denenecek
Tuşlar hiç çalışmıyor Tuval odak dışı Önizlemeye tıkla
Hareket çok yavaş/hızlı HIZ veya deltaTime HIZ * dt formülünü kontrol et
R tuşu yanıt vermiyor keyPressed tanımsız Fonksiyon adının doğru yazıldığını doğrula
Kare ekrandan çıkıyor constrain eksik Sınır satırını ekle
Çapraz hareket beklenenden hızlı X ve Y aynı anda değişiyor Basit oyunlarda sorun oluşturmaz; hız normalize edilerek düzeltilebilir
Bir tuş bazen çalışıyor bazen çalışmıyor Klavye düzeni (harf/sembol) farkı keyCode veya büyük/küçük harf kontrolünü gözden geçir

Bu tablo, klavye kontrollü bir sketch'te karşılaşılan sorunların çoğunun ya odak (tuvalin girdi almaması) ya da hangi p5.js aracının (durum mu, olay mı) kullanıldığıyla ilgili olduğunu gösterir. Hata ayıklarken ilk soru her zaman "bu davranış sürekli mi yoksa tek seferlik mi olmalı?" olmalıdır; yanıt keyIsDown ile keyPressed arasındaki seçimi belirler.

Yapay Zekâ Etkileşimi: Kontrol Şeması Tasarlama Tahmini etkinliği tamamlama süresi: 25–30 dakika.

Amaç: Klavye girdisini oyun eylemleriyle eşleştirmek.

Adım 1: Basit bir oyun fikri seç (ör. uzay gemisi, top, kare). Adım 2: Hangi tuşların sürekli (keyIsDown), hangilerinin tek seferlik (keyPressed) olacağını tabloya yaz. Adım 3: Yapay zekâ sohbet robotuna şu istemi gir: "p5.js için [oyun] kontrol tablom: [tablo]. Her tuş için keyIsDown mu keyPressed mi kullanmalıyım? Kısa gerekçe ver." Adım 4: Öneriyi yukarıdaki kare örneğiyle karşılaştır.

Yapay Zekâ Etkileşimi: Klavye Girdisi Tahmini etkinliği tamamlama süresi: 20–25 dakika.

Adım 1: keyIsDown (sürekli) ile keyPressed (tek sefer) farkını tabloya yazın. Adım 2: Ok tuşları için LEFT_ARROW kullanımını not edin. Adım 3: Yapay zekâ sohbet robotuna sorun: «p5.js keyIsDown keyPressed keyCode ne zaman kullanılır?» Adım 4: Yanıtı bu ana başlıktaki kontrol tablosu ile karşılaştırın.

Sıra Sizde: Bir oyunda sürekli basılı tutulan hareket (WASD) ile tek seferlik eylem (SPACE ile ateş / zıplama) için hangi klavye API’sini seçerdiniz? İkisini tablo gibi iki satırda yazın.

Özet

Klavye girdisi, oyuncunun gerçek zamanlı kontrolünü sağlar. p5.js'te iki temel katman ayırt edilir: keyIsDown() tuş basılıyken her frame true döndüğü için draw() içinde sürekli hareket üretir; keyPressed() ise basış anında bir kez çalışır. Sürekli harekette hız deltaTime ile çarpılarak Bölüm 2 Ana Başlık 4'teki frame bağımsız tempo korunur; çapraz hareket için bağımsız if blokları birleşir. WASD ve ok tuşları birlikte desteklenebilir; böylece farklı alışkanlıklara sahip oyuncular aynı sketch'i kullanır. Ok tuşları için LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW sabitleri; keyIsDown ile harf tuşları için 65 / 68 gibi keyCode sayıları kullanılır. keyPressed() zıplama, ateş, tur yenileme ve renk değiştirme gibi tek seferlik eylemler için uygundur. key harf ve sembol tuşlarını, keyCode ok tuşları gibi özel tuşları tanımlamada kullanılır; key === "r" veya keyCode === LEFT_ARROW gibi koşullar olay gövdesinde yazılır. Yazdırılabilir karakterler ASCII (ve onu kapsayan Unicode) numaralarıyla saklanır ('A' → 65); ok tuşları ise ASCII’de yoktur — keyCode 37/38/39/40 gibi özel sayılardır ve p5.js bunları LEFT_ARROW / UP_ARROW / RIGHT_ARROW / DOWN_ARROW sabitleriyle adlandırır. Ham sayı yerine sabiti kullanmak okunabilirliği artırır. Denetim karakterleri \n (satır sonu) ve \t (sekme) string içinde kaçış dizisi olarak yazılır; text() ile çok satırlı HUD üretilebilir. constrain() ile nesne tuval sınırları içinde tutulur — bu, konumu sınırda kilitleyen bir engellemedir; duvara çarpınca yön değiştiren sekme tepkisi sonraki ana başlıkta açık if ve hız tersine çevirme ile ele alınır. Fare ile karşılaştırıldığında sürekli basılı tutma mouseIsPressed / keyIsDown, tek seferlik olay ise mousePressed() / keyPressed() eşleşmesine karşılık gelir.

Neler Öğrendik?

Soru 1 Sürekli yürüme hareketi için en uygun yapı hangisidir?

A) Yalnızca keyPressed() içinde konum artırmak

B) draw() içinde keyIsDown() ile konum güncellemek

C) Yalnızca setup() içinde keyIsDown() kullanmak

D) background() ile tuş okumak

E) createCanvas() her frame çağırmak

Soru 2 key === "r" ifadesi ne zaman anlamlıdır?

A) Her frame otomatik true olur

B) keyPressed() veya keyReleased() çalıştığında basılan tuşu kontrol eder

C) Yalnızca fare tıklanınca

D) Tuval genişliğini verir

E) Dizi uzunluğunu döndürür

Soru 3 [Kod okuma] HIZ = 200, deltaTime ≈ 16.7 ms iken aşağıdaki blok bir frame'de kareX değerini yaklaşık ne kadar artırır? Kod 9.

javascript
if (keyIsDown(RIGHT_ARROW)) {  kareX = kareX + HIZ * deltaTime / 1000;}

A) 200 piksel

B) Yaklaşık 3.3 piksel

C) 16.7 piksel

D) 0 piksel

E) 1000 piksel

Soru 4 constrain(oyuncuX, 0, width - BOYUT) satırının amacı nedir?

A) FPS artırmak

B) Oyuncu konumunu tuval sınırları içinde tutmak

C) Klavye olayını silmek

D) Diziye eleman eklemek

E) R tuşunu devre dışı bırakmak

Neler Öğrendik Yanıt Anahtarı

Soru 1: Doğru Cevap: B

Soru 2: Doğru Cevap: B

Soru 3: Doğru Cevap: B

Soru 4: Doğru Cevap: B

Yararlanılan Kaynaklar

Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır: