Ana Başlık 4. Klavye Girdisi
Amaç: Klavye olaylarını (keyIsDown, key, keyPressed()) öğreterek oyuncu kontrollü hareket sağlamak.
Öğrenme Çıktıları:
- Klavye girdisinin oyun döngüsündeki yerini açıklar.
keyIsDown()ile sürekli basılı tuş kontrolü yapar.keyPressed()ile tek seferlik tuş olayını yakalar.keyvekeyCodedeğişkenlerini ayırt eder; tuş kodlarının ASCII/Unicode ile ilişkisini açıklar.deltaTimeile klavye kontrollü hareket kodlar.
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.
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.
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.
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.
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.

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.
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 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.
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.
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:
- Ok veya WASD: sürekli hareket
- R: konumu merkeze sıfırla (tek seferlik
keyPressed) - Fare konumu bilgi metninde gösterilir (önceki bölümler girdisi ile birlikte)
Kod 8.
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.
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
- Çözüm: Basılı tutma
draw()döngüsündekeyIsDownile okunur;keyPressedyalnızca bir frame tetiklenir. - İlgili Konu: 4.2. keyIsDown ile Sürekli Hareket
Soru 2: Doğru Cevap: B
- Çözüm:
keyolay anındaki karakter tuşunu verir; sürekli okuma içinkeyIsDownkullanılır. - İlgili Konu: 4.4. key ve keyCode
Soru 3: Doğru Cevap: B
- Çözüm: 200 × 0.0167 ≈ 3.3 piksel; hız saniye başına tanımlıdır.
- İlgili Konu: 4.2. keyIsDown ile Sürekli Hareket
Soru 4: Doğru Cevap: B
- Çözüm:
constraindeğeri min–max aralığına sıkıştırır; kare ekran dışına çıkmaz. - İlgili Konu: 4.5. Klavye ile Kontrol Edilen Kare
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- ASCII. (n.d.). In Wikipedia. https://en.wikipedia.org/wiki/ASCII
- asciitable.com. (n.d.). ASCII Table. https://www.asciitable.com/
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- MDN Web Docs. (n.d.). Identifiers — Lexical grammar. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
- Microsoft. (n.d.). Visual Studio Code. https://code.visualstudio.com/
- Nystrom, R. (2014). Game Programming Patterns. Genever Benning. https://gameprogrammingpatterns.com/
- p5.js Foundation. (n.d.). constrain. p5.js Reference. https://p5js.org/reference/p5/constrain/
- p5.js Foundation. (n.d.). keyCode. p5.js Reference. https://p5js.org/reference/p5/keyCode/
- p5.js Foundation. (n.d.). keyIsDown. p5.js Reference. https://p5js.org/reference/p5/keyIsDown/
- p5.js Foundation. (n.d.). keyPressed. p5.js Reference. https://p5js.org/reference/p5/keyPressed/
- p5.js Foundation. (n.d.). p5.js Web Editor. https://editor.p5js.org/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
- Unicode Consortium. (n.d.). The Unicode Standard. https://www.unicode.org/standard/standard.html
- unicode-table.com. (n.d.). Unicode Character Table. https://unicode-table.com/