Bölüm 2 — Amaç ve Kapsam
Genel Amaç
Bu bölümün temel amacı, tekrarlayan işlemleri for ve while döngüleriyle ölçeklemek; fonksiyonlarla modüler sketch yapısı kurmak; oyun döngüsü ve FPS ile animasyon zamanlamasının temelini atmaktır. Bölüm boyunca her ana başlık kendi içinde amaç, öğrenme çıktıları, örnek kod ve değerlendirme sorularıyla tamamlanır; böylece bir sonraki bölüme geçmeden önce ölçülebilir kazanımlar elde edilir.
Kapsam
Bu bölüm şu ana başlıklar altında ele alınmaktadır:
Ana Başlık 1: for, while ve Döngü Kontrolü
Ana Başlık 2: İç İçe Döngüler, Izgara ve Animasyon
Ana Başlık 3: Fonksiyonlar ve Modüler Kod Yazımı
Ana Başlık 4: Oyun Döngüsü, FPS ve frameRate
Ana Başlık 1. for, while ve Döngü Kontrolü
Amaç: for ve while döngülerini, break/continue ve seçim ölçütlerini öğreterek tekrarlayan işlemleri güvenli yazmak.
Öğrenme Çıktıları:
- for döngüsünün üç parçasını açıklar ve uygular.
- while ile koşula bağlı tekrar yazar.
- for ve while arasında seçim gerekçesi verir.
- break ve continue ile döngü akışını denetler.
Anahtar Sözcükler: for, while, break, continue, sonsuz döngü, sayaç
Giriş
Önceki bölümlerde tekil şekiller ve koşullu kararlar işlendi. Oyun dünyaları ise çoğu zaman onlarca tekrarlayan öğe içerir: ızgara çizgileri, engeller, parçacıklar. Aynı kodu elle kopyalamak bakımı zorlaştırır; döngüler bu tekrarı tek bir kalıpta toplar.
for sayaç tabanlı, while koşul tabanlı tekrardır. Yanlış koşul sonsuz döngüye yol açabilir; break erken çıkış, continue tur atlama sağlar. Bu ana başlık döngünün nedenini, sözdizimini ve güvenli kontrolünü kurar. İç içe ızgara ve animasyon bir sonraki ana başlıkta gelir. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur. Bu ana başlığın çıktısı, sonraki oyunda yeniden kullanılabilecek bir iskelet oluşturur.
1.1. Neden Döngü? Tekrarlayan İşlemler
Tanım: Döngü (loop) — Aynı veya benzer işlemleri, döngü değişkeni ve koşul yardımıyla otomatik olarak tekrarlayan programlama yapısıdır.
Döngü olmadan beş adet dikdörtgen çizmek için rect() beş kez yazılmalıdır:
Kod 1.
rect(0, 0, 40, 40);rect(50, 0, 40, 40);rect(100, 0, 40, 40);rect(150, 0, 40, 40);rect(200, 0, 40, 40);Burada yalnızca X konumu 50'şer piksel artmaktadır. On veya yüz dikdörtgen gerektiğinde bu yöntem sürdürülebilir değildir. Döngü ile örüntü tek bir değişkene bağlanır; değişken her turda güncellenir.
Dikkat: Döngü, draw() içinde her frame'de çalışırsa gövdedeki kod da her frame'de tekrarlanır. Örneğin 10 tur dönen bir for döngüsü, saniyede 60 frame ile saniyede 600 kez gövdeyi çalıştırır. Performans sorunlarında döngü tur sayısı ve draw() içindeki iş yükü birlikte düşünülmelidir.
1.2. for Döngüsü
Tanım: for döngüsü — Başlangıç değeri, devam koşulu ve artış adımının başta, noktalı virgülle ayrılmış üç parçada tanımlandığı; tekrar sayısı genellikle önceden bilinen döngü türüdür.
Sözdizimi:
Kod 2.
for (başlangıç; koşul; artış) { // döngü gövdesi — koşul true olduğu sürece tekrarlanır}Dikkat — girinti (indentation): for / while gövdesi de if gibi süslü parantez içindedir. Gövde satırlarını içeri almak (çoğunlukla 2 veya 4 boşluk), özellikle iç içe döngülerde hangi rect veya if satırının hangi döngüye ait olduğunu ayırt etmeyi kolaylaştırır. JavaScript girintiyi zorunlu kılmaz (Python’da yanlış indentation programı durdurur); okunabilirlik ve hata ayıklama için bu kitaptaki örneklerde her zaman kullanılır. Tab ile boşluğu karıştırmayın (Bölüm 1 Ana Başlık 3, if sözdizimi notu).
Tanım: Döngü değişkeni — for veya while içinde tur sayısını veya konumu izleyen değişkendir. Örneklerde sayaç için çoğu zaman i, j veya anlamlı adlar (satir, sutun) kullanılır.
for başlığının üç parçası — ne işe yarar?
Üç parça zorunlu isimler değil; her biri farklı anda çalışır. Noktalı virgüller parçaları ayırır:
Tablo 1.
| Sıra | Parça | Ne zaman çalışır? | Görevi | Örnek |
|---|---|---|---|---|
| 1 | Başlangıç | Döngü bir kez, en başta | Değişkene ilk değer | let i = 0 |
| 2 | Koşul | Her tur öncesi | true ise gövde çalışır; false ise döngü biter |
i < 5 |
| 3 | Güncelleme (çoğu zaman “artış”) | Her gövde bitince (tur sonu) | Değişkeni günceller | i++, i--, i += 5 |
Çalışma sırası her zaman şöyledir: başlangıç → (koşul? → gövde → güncelleme → koşul? → …). Üçüncü parça gövdeden sonra gelir; bu yüzden gövde içinde i hâlâ o turun değeridir.
Bilgi: Bu parçaya alışkanlıkla artış denir; ancak buraya illa i++ yazmak zorunda değilsiniz. Azaltma (i--), ikişer/beşer adım (i += 2, i += 5) veya başka bir atama da geçerlidir — önemli olan tur sonunda değişkenin bir sonraki tura uygun hale gelmesidir. Parça boş bırakılırsa güncelleme gövdeye (veya hiç) yazılır; bu durum bir sonraki alt bölümde örneklenir.
Kod bloğu: Üç parçanın rolünü konsolda izleme.
Kod 3.
function setup() { createCanvas(200, 100); console.log("başlangıç çalışacak"); for (let i = 0; i < 3; i++) { console.log("gövde, i =", i); } console.log("döngü bitti");} function draw() { background(240);}Konsol çıktısı:
Kod 4.
başlangıç çalışacakgövde, i = 0gövde, i = 1gövde, i = 2döngü bitti(i++ her gövdeden sonra sessizce çalışır; ayrı bir console.log satırı yoktur.)
Üç parçadan bazılarını boş bırakmak
Noktalı virgüller durur; aradaki ifade yazılmazsa o parça atlanmış sayılır:
Tablo 2.
| Yazım | Anlam |
|---|---|
for (let i = 0; i < 5; ) |
Artış yok — gövdede i++ yazılmazsa sonsuz döngü riski |
for (; i < 5; i++) |
Başlangıç yok — i döngüden önce tanımlanmış olmalı |
for (let i = 0; ; i++) |
Koşul yok — koşul hep true kabul edilir; çıkış için break gerekir |
for (;;) |
Üçü de boş — while (true) ile aynı mantık; bilinçli break şart |
Aşağıda her durum için kısa, çalışır örnekler vardır (setup içinde; konsol çıktısı).
Kod bloğu: Artış boş — güncelleme gövdede.
Kod 5.
function setup() { createCanvas(200, 100); for (let i = 0; i < 3; ) { console.log("artış gövdede, i =", i); i++; // üçüncü parça boş olduğu için burada }} function draw() { background(240);}Kod 6.
artış gövdede, i = 0artış gövdede, i = 1artış gövdede, i = 2Kod bloğu: Başlangıç boş — i önce tanımlanır.
Kod 7.
function setup() { createCanvas(200, 100); let i = 0; // başlangıç döngü dışında for (; i < 3; i++) { console.log("başlangıç dışarıda, i =", i); }} function draw() { background(240);}Kod 8.
başlangıç dışarıda, i = 0başlangıç dışarıda, i = 1başlangıç dışarıda, i = 2Kod bloğu: Koşul boş — break ile çıkış.
Kod 9.
function setup() { createCanvas(200, 100); for (let i = 0; ; i++) { console.log("koşul yok, i =", i); if (i >= 2) { break; // yoksa sonsuz döner } } console.log("break ile çıktık");} function draw() { background(240);}Kod 10.
koşul yok, i = 0koşul yok, i = 1koşul yok, i = 2break ile çıktıkKod bloğu: for (;;) — üçü de boş (while (true) eşdeğeri).
Kod 11.
function setup() { createCanvas(200, 100); let n = 0; for (;;) { console.log("for(;;), n =", n); n++; if (n >= 3) { break; } }} function draw() { background(240);}Kod 12.
for(;;), n = 0for(;;), n = 1for(;;), n = 2Dikkat: Boş parça “yazmayı unuttum” ile karıştırılmamalıdır. Bilinçli boş bırakma nadirdir; başlangıç düzeyinde üç parçayı da doldurmak okunabilirliği artırır. for (;;) veya koşulsuz for yalnızca break ile birlikte ve draw() dışında kullanılmalıdır.
Kısayol operatörleri (++, --, +=, -=)
Sayısal değişkeni bir artırmak veya azaltmak döngülerde sık tekrarlanır. JavaScript bunun için kısayol operatörleri sunar; bunlar yeni bir dil kuralı değil, uzun yazımın kısa eşdeğeridir:
Tablo 3.
| Uzun yazım | Kısayol | Anlam |
|---|---|---|
i = i + 1 |
i++ |
i bir artar |
i = i - 1 |
i-- |
i bir azalır |
x = x + 10 |
x += 10 |
x on artar |
skor = skor - 1 |
skor -= 1 |
skor bir azalır |
for döngüsünün üçüncü bölümünde her iki biçim de geçerlidir:
Kod 13.
for (let i = 0; i < 5; i = i + 1) { /* … */ }for (let i = 0; i < 5; i++) { /* … */ } // aynı anlamfor (let satir = 5; satir >= 0; satir--) { /* … */ } // alttan üsteDikkat: ++ ve -- tek birimlik adımdır. Beşer beşer ilerlemek için i = i + 5 veya i += 5 yazılır; i++++ diye bir yazım yoktur.
Kod bloğu: Yatay dizide beş kare çizen for döngüsü.
Kod 14.
function setup() { createCanvas(400, 200); noStroke();} function draw() { background(30, 30, 50); for (let i = 0; i < 5; i = i + 1) { fill(100 + i * 30, 150, 200); rect(i * 50, 80, 40, 40); }}i sırasıyla 0, 1, 2, 3, 4 değerlerini alır; her değerde rect(i * 50, 80, 40, 40) farklı X konumunda bir kare çizer.
for döngüsü izleme tablosu
for (let i = 0; i < 5; i = i + 1) ifadesinin turları:
Tablo 4.
| Tur | Koşul i < 5 |
i değeri | Gövdede çizilen X | Tur sonu: artış |
|---|---|---|---|---|
| 1 | true (0 < 5) |
0 | 0 | i → 1 |
| 2 | true (1 < 5) |
1 | 50 | i → 2 |
| 3 | true (2 < 5) |
2 | 100 | i → 3 |
| 4 | true (3 < 5) |
3 | 150 | i → 4 |
| 5 | true (4 < 5) |
4 | 200 | i → 5 |
| 6 | false (5 < 5) |
— | döngü biter | — |
Koşul false olduğunda gövde bir kez daha çalışmaz; akış döngüden sonraki satıra geçer.

Görsel 1 for döngüsünün çalışma sırasını özetler: başlangıç (i = 0), koşul kontrolü (i < 5), gövde, artış (i = i + 1) ve koşula geri dönüş. Koşul false olduğunda döngü biter.
Dikkat: Koşul ifadesinde yaygın hata sınır kullanımıdır. i < 5 ifadesi i'nin 0, 1, 2, 3, 4 olduğu beş tur üretir; i <= 5 yazılırsa altı tur olur. Izgara ve dizi indekslerinde bu fark sık kaynaklıdır.
1.3. while Döngüsü
Tanım: while döngüsü — Koşul başta kontrol edilir; koşul true olduğu sürece gövde tekrarlanır. Başlangıç ve artış for başlığında değil, döngü öncesinde ve gövdesinde yazılır.
Sözdizimi:
Kod 15.
while (koşul) { // gövde}Kod bloğu: while ile sayaç — setup() içinde mantık gösterimi. Konsola yazdırmak için 1.3'teki console.log() kullanılır.
Kod 16.
function setup() { createCanvas(400, 400); let sayac = 0; while (sayac < 5) { console.log("sayac:", sayac); sayac = sayac + 1; } console.log("while bitti");} function draw() { background(220);}Konsol çıktısı (sırayla):
Kod 17.
sayac: 0sayac: 1sayac: 2sayac: 3sayac: 4while bittiwhile döngüsü izleme tablosu
sayac = 0 sonrası while (sayac < 5) { …; sayac = sayac + 1; } için:
Tablo 5.
| Tur | Koşul sayac < 5 |
sayac (gövde başı) | Konsola yazılan | Tur sonu: sayac |
|---|---|---|---|---|
| 1 | true (0 < 5) |
0 | sayac: 0 |
1 |
| 2 | true (1 < 5) |
1 | sayac: 1 |
2 |
| 3 | true (2 < 5) |
2 | sayac: 2 |
3 |
| 4 | true (3 < 5) |
3 | sayac: 3 |
4 |
| 5 | true (4 < 5) |
4 | sayac: 4 |
5 |
| 6 | false (5 < 5) |
— | döngü biter | — |
Tablo, for izleme tablosuyla aynı mantıktadır; fark yalnızca başlangıç/artışın nerede yazıldığıdır.

Görsel 2 while akışını özetler: döngü öncesi sayac = 0, koşul, gövde, artış, koşula dönüş.
Sonsuz döngü
Gövdede koşulu false yapacak güncelleme yoksa döngü sonsuz döner ve program donabilir.
Yanlış örnek (çalıştırmayın — tarayıcı kilitlenebilir):
Kod 18.
let n = 0;while (n < 5) { console.log(n); // n artırılmadı → koşul hep true kalır}Dikkat: draw() içinde while (true) veya çok uzun süren bir while yazmak animasyonu hızlandırmaz; tam tersine yavaşlatır ve çoğu zaman tarayıcıyı kilitler. Çünkü draw bir frame’i bitirmeden bir sonraki frame’e geçilemez — uzun while o frame’i bitirmez, ekran güncellenmez, fare/tuş olayları da işlenmeyebilir. Sonsuz veya sürekli tekrar için p5.js zaten her frame draw() çağırır; ekstra “sonsuz while” gerekmez.
1.4. Aynı İş: for ve while — Hangisi Ne Zaman?
Aynı görev çoğu zaman her iki döngüyle de yazılabilir. Aşağıda “0’dan 4’e kadar konsola yaz” işi yan yana gösterilir.
Kod bloğu: Aynı mantık — for sürümü.
Kod 19.
function setup() { createCanvas(200, 100); for (let i = 0; i < 5; i++) { console.log("for:", i); }} function draw() { background(240);}Kod bloğu: Aynı mantık — while sürümü.
Kod 20.
function setup() { createCanvas(200, 100); let i = 0; while (i < 5) { console.log("while:", i); i++; }} function draw() { background(240);}Her iki konsol da 0 1 2 3 4 üretir. Eşleme şöyle okunur:
Tablo 6.
for parçası |
while karşılığı |
|---|---|
let i = 0 (başlangıç) |
Döngüden önceki let i = 0 |
i < 5 (koşul) |
while (i < 5) |
i++ (artış) |
Gövde sonundaki i++ |
Çizim örneği de aynıdır: Beş kare için for (let i = 0; i < 5; i++) { rect(i * 50, 80, 40, 40); } yerine let i = 0; while (i < 5) { rect(…); i++; } yazılabilir; tuval aynı görünür.
Basit desenler: yatay / dikey çizgi ve eşmerkezli daire
Aşağıdaki üç desen döngü değişkenini konuma bağlamanın en sade örnekleridir. Her biri önce for, sonra while ile yazılır; tuval çıktısı aynıdır.

Görsel 3 üç deseninin beklenen çıktısını özetler.
Kod bloğu: Yatay paralel çizgiler — for.
Kod 21.
function setup() { createCanvas(280, 200);} function draw() { background(236); stroke(40); for (let i = 0; i < 8; i++) { let y = 20 + i * 20; line(20, y, 260, y); }}Kod bloğu: Aynı yatay çizgiler — while.
Kod 22.
function setup() { createCanvas(280, 200);} function draw() { background(236); stroke(40); let i = 0; while (i < 8) { let y = 20 + i * 20; line(20, y, 260, y); i++; }}i her turda Y konumunu kaydırır; X uçları sabittir → yatay paralel çizgiler.
Kod bloğu: Dikey paralel çizgiler — for / while.
Kod 23.
// forfor (let i = 0; i < 8; i++) { let x = 20 + i * 30; line(x, 20, x, 180);} // while (eşdeğer)let i = 0;while (i < 8) { let x = 20 + i * 30; line(x, 20, x, 180); i++;}Burada değişen X’tir; çizgiler dikeydir.
Kod bloğu: Eşmerkezli daireler — for / while.
Kod 24.
function setup() { createCanvas(280, 200);} function draw() { background(236); noFill(); stroke(40); for (let i = 1; i <= 6; i++) { let çap = i * 28; circle(140, 100, çap); }} // while eşdeğeri:// let i = 1;// while (i <= 6) {// circle(140, 100, i * 28);// i++;// }Merkez sabit, çap i ile büyür → eşmerkezli daireler. (circle(x, y, çap) p5.js’te çap parametresi alır.)
Sıra Sizde: Tek bir for ile renk tayfı çizin (p5.js). Hedef görünümler:


İstenenler:
- Görsel 4 (dikey / mavi): Yatay şeritler; mavi bileşen 0’dan 255’e artsın (
fill(0, 0, mavi)—mavidöngü değişkenine bağlı). - Görsel 5 (yatay / kırmızı): Dikey şeritler; kırmızı 0’dan 255’e artsın (
fill(kirmizi, 0, 0)). - İç içe döngü gerekmez — yukarıdaki yatay/dikey çizgi örnekleri gibi tek
foryeter. Tek tek renk yazmayın.
İpucu: N şerit için renk = i * (255 / (N - 1)) (veya map(i, 0, N - 1, 0, 255)). Şerit yüksekliği / genişliği: height / N, width / N.
draw() ile dolaylı döngü (background silmeden)
for / while tek frame içinde birçok çizgi üretir. Benzer sonucu bazen draw()’ın kendisine bırakmak da mümkündür: background() çağrılmazsa önceki çizimler silinmez; her frame’de bir yeni çizgi eklenir. Bu, p5.js’in sürekli draw çağrısını dolaylı bir döngü gibi kullanmaktır.
Kod bloğu: Her frame bir yatay çizgi — background yok.
Kod 25.
let satir = 0; function setup() { createCanvas(280, 200); background(236); // yalnızca bir kez stroke(40);} function draw() { if (satir < 8) { let y = 20 + satir * 20; line(20, y, 260, y); satir++; } // satir 8 olunca yeni çizgi eklenmez; tuval dolu kalır}İlk 8 frame’de ekran Görsel 3’teki yatay desene yaklaşır; fark, çizgilerin zamanla birikmesidir (animasyon gibi görünür). for ile tek frame’de biten sürüm anında tamamlanır.
Tablo 7.
| Yaklaşım | Ne zaman? |
|---|---|
for / while + background her frame |
Desen her frame yeniden çizilir (oyun / animasyon iskeleti) |
draw + biriktirme (background yok) |
Adım adım biriktirme; eğitim / basit “çizim makinesi” |
draw içinde while (true) |
Kullanma — frame bitmez; animasyon yavaşlar / tarayıcı kilitlenebilir |
Dikkat: Biriktirme örneğinde background’ı draw içine koyarsanız her frame tuval silinir ve yalnızca son çizgi kalır. Bilinçli seçim gerekir.
Hangisi hangi durumda daha iyi?
Kesin bir kural yoktur; okunabilirlik ve niyet önemlidir. Başlangıç düzeyinde şu tercihler yaygındır:
Tablo 8.
| Durum | Önerilen | Gerekçe |
|---|---|---|
| Tur sayısı baştan belli (5 kare, 8×8 ızgara, dizi boyutu) | for |
Üç parça tek satırda; artış unutulması zor |
| “Koşul doğru olduğu sürece devam” (hedef bulunana kadar, dışarıdan gelen bayrak) | while |
Koşul vurgulanır; tur sayısı başta net olmayabilir |
draw() içinde sınırlı sayıda nesne çizmek |
for |
Frame başına sabit / bilinen tur |
draw() içinde while (true) |
Kullanma | Frame bitmez → yavaşlama / kilitlenme; animasyon draw tekrarından gelir |
Tartışma: “Beş kare çiz” için while de çalışır; ama for niyeti (“sayarak tekrarla”) daha net gösterir. “Kullanıcı doğru cevabı girene kadar sor” gibi tur sayısı belirsiz işlerde while daha doğal okunur. İkisi de aynı makineye derlenebilir; seçim çoğu zaman okuyan insanın işi anlaması içindir.
Bilgi: for (;;) ile while (true) eşdeğerdir; ikisinde de çıkış break ile yapılır (bir sonraki alt bölüm).
Döngüler oyunlarda neden bu kadar sık?
Beş rect örneğindeki tekrar, oyunlarda da aynıdır: listedeki her düşmanı, her mermiyi veya her tahta satırını tek tek işlemek. Aşağıdakiler örnek senaryolardır (oyun motorunun içini birebir iddia etmez); amaç, döngünün neyi tekrarladığını somutlaştırmaktır.
Tablo 9.
| Oyun | Döngünün tekrarladığı iş (kabaca) | Çoğu zaman |
|---|---|---|
| Super Mario Bros. | Ekrandaki her düşman ve jetonu güncellemek / çizmek | for |
| Pac-Man | Her hayaleti (Blinky, Pinky, …) sırayla hareket ettirmek | for |
| Tetris | Dolu satırları tarayıp silmek; parçanın bloklarını çizmek | for |
| Space Invaders | Formasyondaki her gemiyi ve her mermiyi ilerletmek | for |
while daha çok “koşul doğru olduğu sürece” işlerde öne çıkar: can bitene kadar, doğru cevap gelene kadar, liste boşalana kadar. Bu kitaptaki mini oyunlarda çoğu tekrar for ile başlar; while seçtiğinizde gerekçenizi bir cümleyle söyleyebilmeniz yeterlidir.
Sıra Sizde: Tablodan veya bildiğiniz bir oyundan iki örnek seçin. Her biri için (1) döngünün neyi tekrarladığını, (2) for mu while mu daha doğal olur — birer cümleyle yazın.
1.5. break, continue ve Erken Çıkış
Tanım: break — Döngüyü hemen sonlandırır; akış döngüden sonraki satıra geçer. Kalan turlar çalışmaz.
Tanım: continue — Yalnızca o turdaki gövdenin geri kalanını atlar; döngü bir sonraki tura (koşul / artış) geçer.
Bu iki komut for ve while içinde kullanılabilir. Amaç çoğu zaman “hedef bulundu, yeter” (break) veya “bu turu atla, sonrakine bak” (continue) demektir.
Kod bloğu: break — konsolda izleme.
Kod 26.
function setup() { createCanvas(200, 100); for (let i = 0; i < 10; i++) { if (i === 3) { console.log("break: i =", i, "→ döngü biter"); break; } console.log("i =", i); } console.log("for sonrası");} function draw() { background(240);}Konsol çıktısı:
Kod 27.
i = 0i = 1i = 2break: i = 3 → döngü biterfor sonrasıi 3 olduğunda gövde console.log("i =", i) satırına gelmeden break çalışır; 4…9 turları hiç yapılmaz.
Kod bloğu: continue — tek bir turu atlama.
Kod 28.
function setup() { createCanvas(200, 100); for (let i = 0; i < 5; i++) { if (i === 2) { console.log("continue: i =", i, "→ bu tur atlandı"); continue; } console.log("i =", i); }} function draw() { background(240);}Konsol çıktısı:
Kod 29.
i = 0i = 1continue: i = 2 → bu tur atlandıi = 3i = 4Tablo 10.
| Komut | Ne yapar? | Sonraki adım |
|---|---|---|
break |
Döngüyü tamamen bitirir | Döngünün dışındaki kod |
continue |
Yalnızca o turu yarıda keser | Aynı döngünün sonraki turu |
Bilgi: İç içe döngülerde break yalnızca içinde bulunduğu döngüyü kırar; dış döngü devam eder. Hem dış hem iç döngüyü birden kesmek için genelde bir boolean bayrak (bulundu) veya fonksiyon içinde return kullanılır (fonksiyonlar Ana Başlık 3).
Kod bloğu: İç döngüde break — dış döngü sürer (konsol).
Kod 30.
function setup() { createCanvas(200, 100); for (let satir = 0; satir < 3; satir++) { for (let sutun = 0; sutun < 3; sutun++) { console.log("bak:", satir, sutun); if (satir === 1 && sutun === 1) { console.log("break — yalnızca iç döngü biter"); break; } } console.log("dış tur bitti, satir =", satir); }} function draw() { background(240);}Konsol çıktısı (özet): satir = 1 iken sutun 0 ve 1 yazılır, sonra iç break; ardından satir = 2 yine 0, 1, 2 ile gezer. Dış döngü durmaz.
Kontrollü sonsuz döngü (setup / mantık kodunda; draw içinde değil):
Kod 31.
let deneme = 0;while (true) { deneme++; console.log("deneme", deneme); if (deneme >= 3) { break; // bilinçli çıkış }}Aynı desen for (;;) ile de yazılabilir; yine break şarttır.
Sıra Sizde: for (let i = 0; i < 10; i++) içinde console.log(i) var. i === 3 iken continue, i === 7 iken break ekleyin. Konsolda hangi sayılar görünür? Önce kâğıda yazın, sonra Web Editor’de doğrulayın.
Yapay Zekâ Etkileşimi: for ve while Karşılaştırma
Amaç: Aynı çıktıyı üreten for/while çiftini yapay zekâya yazdırıp farkı tartışmak.
Adım 1: 0’dan 9’a sayıları konsola yazdıran for isteyin. Adım 2: Eşdeğer while isteyin; artış satırını bilinçli silip ne olduğunu gözleyin (gerekirse sayfayı yenileyin). Adım 3: Hangisinin okunabilir olduğunu bir cümleyle not edin.
Özet
Döngü, aynı işlem ailesini bir sayaca veya bir koşula bağlı olarak yineleyen yapıdır; beş rect çağrısını tek tek yazmak yerine örüntüyü tek bir değişkene bağlar. for (başlangıç; koşul; artış) üçlüsünde başlangıç yalnızca bir kez, koşul her tur öncesinde, güncelleme ise her gövde bitiminde çalışır. Bu parçalar bilinçli olarak boş bırakılabilir; ancak boş bırakma nadir bir tercihtir ve for (;;) gibi biçimler yalnızca break ile birlikte anlam taşır. i++, i-- ve i += 5 kısayolları uzun yazımın eşdeğeridir. while ise “koşul doğru kaldıkça” modelidir; başlangıç döngüden önce, güncelleme gövde içinde yazılır ve güncelleme unutulduğunda koşul hiç bozulmadığı için tarayıcı kilitlenebilir.
Aynı iş çoğu zaman her iki yapıyla da yazılabildiğinden seçim okunabilirliğe dayanır: tur sayısı baştan belliyse for, tur sayısı belirsiz ve vurgu koşuldaysa while daha doğal okunur. break içinde bulunduğu döngüyü hemen sonlandırır, continue yalnızca o turun kalan gövdesini atlar; iç içe döngülerde break en içteki döngüyü kırar, dış döngü sürer. Oyunlarda aynı tekrar Tetris’te dolu satırların taranmasında, Pac-Man’de hayaletlerin sırayla güncellenmesinde veya mermi listesinin işlenmesinde görülür. draw içinde while (true) animasyonu hızlandırmaz; frame’i bitirmediği için görüntüyü ve girdiyi dondurur. Bu temel, sonraki ana başlıktaki iç içe ızgara ve frameCount animasyonuna zemin hazırlar.
Neler Öğrendik?
Soru 1
for başlığındaki üç parça sırasıyla neyi kontrol eder?
A) Dosya, ağ, bellek
B) Başlangıç, devam koşulu, artış/adım
C) Renk, stroke, fill
D) HTML, CSS, JS
E) Yalnızca fare olayları
Soru 2
draw() içinde while (true) yazmak genelde neye yol açar?
A) Animasyonu güvenle hızlandırır
B) Frame bitmez; animasyon yavaşlar veya tarayıcı kilitlenebilir
C) Yalnızca rengi değiştirir
D) for döngüsünü zorunlu kılar
E) Hiçbir etkisi olmaz
Soru 3
break ne yapar?
A) Programı yeniden başlatır
B) En içteki döngüyü hemen sonlandırır
C) Tuvali siler
D) FPS’i 60 yapar
E) String birleştirir
Soru 4
continue ne yapar?
A) Döngüyü başa sarıp tüm programı bitirir
B) Bu turdaki kalan gövdeyi atlayıp sonraki tura geçer
C) setup’ı siler
D) mousePressed zorunlu kılar
E) Diziyi sıralar
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: B
- Çözüm: Klasik for üçlüsü başlangıç–koşul–adım biçimindedir.
- İlgili Konu: 1.2. for Döngüsü
Soru 2: Doğru Cevap: B
- Çözüm: draw bir frame’i bitirmeden sonraki frame gelmez; uzun while ekranı ve girdiyi dondurabilir.
- İlgili Konu: 1.3. while Döngüsü
Soru 3: Doğru Cevap: B
- Çözüm: break en yakın döngüden çıkar.
- İlgili Konu: 1.5. break, continue ve Erken Çıkış
Soru 4: Doğru Cevap: B
- Çözüm: continue yalnızca o iterasyonun kalanını atlar.
- İlgili Konu: 1.5. break, continue ve Erken Çıkış
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- MDN Web Docs. (n.d.). JavaScript Guide. Mozilla. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide
- Mozilla Developer Network. (n.d.). break. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
- Mozilla Developer Network. (n.d.). continue. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
- Mozilla Developer Network. (n.d.). for. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
- Mozilla Developer Network. (n.d.). while. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while
- Nystrom, R. (2014). Game loop. In Game Programming Patterns. https://gameprogrammingpatterns.com/game-loop.html
- p5.js Foundation. (n.d.). angleMode. p5.js Reference. https://p5js.org/reference/p5/angleMode/
- p5.js Foundation. (n.d.). radians. p5.js Reference. https://p5js.org/reference/p5/radians/
- p5.js Foundation. (n.d.). sin. p5.js Reference. https://p5js.org/reference/p5/sin/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Ana Başlık 2. İç İçe Döngüler, Izgara ve Animasyon
Amaç: İç içe for ile ızgara üretmek; frameCount ve sin/cos ile döngüsel animasyon kurmak.
Öğrenme Çıktıları:
- İç içe for ile satır–sütun ızgarası çizer.
- frameCount ile çoklu nesne animasyonu kurar.
- sin/cos ile salınım ve düzenli çokgen üretir.
- Döngü değişkenini konum, renk ve faz için kullanır.
- Tarayıcıda breakpoint / adım adım izleme ile iç içe döngüyü veya basit bir hatayı gözlemler.
Anahtar Sözcükler: iç içe for, ızgara, frameCount, sin, cos, animasyon, debug, breakpoint
Giriş
Tek boyutlu döngü bir çizgi veya liste üretir; ızgara ise satır ve sütun boyunca iki sayaç ister. İç içe for bu iki ekseni tarar. Aynı kalıp dama deseni, taş dizilimi veya engel haritası için temeldir. Anlamayı kolaylaştırmak için kâğıtta koordinat karalamak veya tarayıcıda adım adım debug etmek de bu ana başlığın parçasıdır.
Animasyonda döngü draw içinde her frame yeniden çalışır; frameCount zaman benzeri bir sayaçtır. sin ile yumuşak salınım, cos/sin çifti ile düzenli çokgen köşeleri hesaplanır. Bu ana başlık ızgara çizimi ile döngüsel hareketi birleştirir. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur.
2.1. İç İçe for Döngüleri ve Izgara Çizimi
Tanım: Izgara (grid) — Satır ve sütunlardan oluşan, hücrelere bölünmüş düzlem; oyun tahtaları ve seviye tasarımında temel yapıdır.
İki boyutlu düzen (satır × sütun) için bir for döngüsü başka bir for döngüsünün içine yazılır. Dış döngü satırları, iç döngü sütunları gezer.

Görsel 1 iç içe döngüde hücrelerin nasıl numaralandığını gösterir: satir satırı, sutun sütunu belirler; rect(sutun * boyut, satir * boyut, …) ile konum hesaplanır. Vurgulu hücre (satir=1, sutun=1) örneğidir.
Bilgi — Takıldığınızda kâğıt kalem de bir yol olabilir: Her zaman döngüyle başlamak zorunda değilsiniz; for başlığını doğrudan yazabiliyorsanız yazın. Ama “burada bir döngü gerekiyor” dediğiniz hâlde döngü başlığını ya da satir / sutun hesabını bir türlü oturtamıyorsanız, koda geçmeden önce bir süre elle, kâğıt üzerinde ilerlemek işi açar. Amaç kodu kâğıtta bitirmek değil, örüntüyü görünür kılmaktır.
Örneğin 4×4 bir ızgarada, hücre boyutu 40 iken yalnızca birkaç hücrenin sol üst köşesini yazın:
- Üst satırı soldan sağa gezin:
(0,0),(40,0),(80,0),(120,0)— X her sütunda 40 artıyor, Y sabit kalıyor. - Bir alt satıra inin:
(0,40),(0,80),(0,120)— satır değiştikçe Y 40 artıyor, X ise yeniden0’dan başlıyor.
Bu iki gözlem birleşince kural çoğu zaman kendiliğinden çıkar: X = sütun × 40, Y = satır × 40. Kural netleştiği an, tek tek yazdığınız köşeleri iki iç içe for ile sadeleştirmek kolaylaşır (aşağıdaki kod). Bu bir zorunluluk değil, yalnızca takıldığınızda başvurabileceğiniz bir keşif yoludur; kâğıt üzerinde “satır bitti, sütun başa döndü” diye iz sürmek de bir tür zihinsel çalıştırmadır.

Kod 1.
// Takılınca: birkaç hücreyi tek tek yazıp örüntüyü görmekrect(0, 0, 40, 40);rect(40, 0, 40, 40);rect(80, 0, 40, 40);// ... satırda X +40; alt satırda Y +40, X yeniden 0'dan // Örüntü oturunca aynı kural for ile:for (let satir = 0; satir < 4; satir++) { for (let sutun = 0; sutun < 4; sutun++) { rect(sutun * 40, satir * 40, 40, 40); }}Sektörde de benzer alışkanlıklar vurgulanır. Brian Kernighan’ın sık hatırlanan uyarısı özetle şudur: hata ayıklama, kodu yazmaktan çoğu zaman daha zordur — bu yüzden baştan karmaşık yazmak yerine adım adım ilerlemek akıllıdır. Stüdyolarda ve oyun jam’lerinde sıkça kâğıt / tahta karalaması, gri kutu prototip veya “ördeğe anlat” (rubber duck debugging: kodu yüksek sesle, hatta sessiz bir nesneye adım adım anlatarak tutarsızlığı yakalama) kullanılır. Kâğıt üzerinde “satır 1 bitti, sütun başa döndü” diye iz sürmek de bir tür debug’dır; makineye geçmeden önce beyninizde çalıştırmaktır.
Tarayıcıda adım adım çalıştırma (breakpoint, Step over, değişken paneli) ise aynı fikrin dijital karşılığıdır — özellikle iç içe for karışıksa. Bunu nasıl yapacağınızı bu ana başlığın sonundaki Yapay Zekâ Etkileşimi: Tarayıcıda Debug etkinliğinde kendi tarayıcınıza göre sorup uygulayacaksınız.
Kod bloğu: 3×3 hücre ziyaret sırası — önce konsolda izleme, çizim yok.
Kod 2.
function setup() { createCanvas(200, 100); for (let satir = 0; satir < 3; satir++) { for (let sutun = 0; sutun < 3; sutun++) { console.log("hücre (", satir + "," + sutun + ")"); } }} function draw() { background(240);}Konsol çıktısı (dış satır, iç sütun — satır satır):
Kod 3.
hücre (0,0)hücre (0,1)hücre (0,2)hücre (1,0)hücre (1,1)hücre (1,2)hücre (2,0)hücre (2,1)hücre (2,2)İç döngü her dış turda baştan (sutun = 0) başlar; bu yüzden sıra önce bir satırın tüm sütunları, sonra sonraki satırdır.
Bilgi — Neden 0’dan başlıyoruz? Yukarıdaki konsolda ilk hücre (0,0) — günlük hayatta “1. satır, 1. sütun” desek de programlamada saymaya çoğu zaman 0’dan başlanır. Satır ve sütunu 1’den de başlatabilirsiniz:
Kod 4.
for (let satir = 1; satir <= 3; satir++) { for (let sutun = 1; sutun <= 3; sutun++) { rect((sutun - 1) * 40, (satir - 1) * 40, 40, 40); }}Görüldüğü gibi formül karmaşıklaşır: konum için her yerde − 1 gerekir (X = (sütun - 1) × 40). 0’dan başlayınca rect(sutun * 40, satir * 40, …) sade kalır; satir < 3 / sutun < 3 koşulu da doğal okunur. Bu alışkanlığın başka bir örneğini ileride diziler konusunda göreceksiniz (Bölüm 3 Ana Başlık 2): ilk eleman dizi[0]dır, dizi[1] değildir.
Kod bloğu: 8×8 kareli dama/tahta benzeri ızgara.
Kod 5.
const HUCRE_BOYUTU = 50;const SUTUN_SAYISI = 8;const SATIR_SAYISI = 8; function setup() { createCanvas(SUTUN_SAYISI * HUCRE_BOYUTU, SATIR_SAYISI * HUCRE_BOYUTU); noStroke();} function draw() { background(40, 44, 52); for (let satir = 0; satir < SATIR_SAYISI; satir = satir + 1) { for (let sutun = 0; sutun < SUTUN_SAYISI; sutun = sutun + 1) { // Satır + sütun toplamı tek sayıysa açık, çift sayıysa koyu kare (dama deseni) if ((satir + sutun) % 2 === 0) { fill(220, 210, 180); } else { fill(80, 70, 60); } rect(sutun * HUCRE_BOYUTU, satir * HUCRE_BOYUTU, HUCRE_BOYUTU, HUCRE_BOYUTU); } }}Bu örnekte % operatörü (1.5) ve if/else (2.3) döngüyle birleştirilmiştir. (satir + sutun) % 2 === 0 ifadesi hücre rengini satır ve sütuna göre değiştirir.
İç içe döngü tur sayısı
Tablo 1.
Dış satir |
İç sutun döngüsü |
Bu satırda çizilen kare |
|---|---|---|
| 0 | 0 → 7 (8 tur) | 8 |
| 1 | 0 → 7 (8 tur) | 8 |
| … | … | … |
| 7 | 0 → 7 (8 tur) | 8 |
Toplam çizim: 8 × 8 = 64 kare. İç içe döngüde toplam tur, dış tur sayısı ile iç tur sayısının çarpımına eşittir.
Dikkat: İç ve dış döngüde aynı döngü değişkeni adı (i) kullanılırsa iç döngü dış değişkeni gölgeler. JavaScript bu durumda hata vermez; kod çalışır, fakat iç döngü kendi i değerini saydığı için sonuç sessizce bozulur ve hatanın kaynağı zor bulunur. Satır/sütun için satir ve sutun, genel sayaç için i ve j ayrımı okunabilirliği artırır.
Sıra Sizde: Tuvali hücre ızgarasına bölün; üzerine yalnızca yeşillik + gövde olan bir çam çizin. Hedef görünüm:

Görsel 3 ulaşmanız gereken çıktıdır: ağaçta başka süs yok — yeşil taç ve kahverengi gövde. Yeşil kısım hücre hücre boyanır ve üçgen gibi durur çünkü her alt satırda sola ve sağa bir hücre büyür. Gövde tek bir dikdörtgen (rect) olabilir.
İstenenler:
- Izgara: Yatay/dikey çizgiler (
line+for). - Yeşil (taç): Üstte ortada 1 hücre; alt satırda
1 → 3 → 5 → …(sol+sağ +1).trianglekullanmayın — hücrerectboyayın. Tüm ağacı tuvalde / ızgarada ortala (yatay + dikey). - Gövde: Yeşilin altında kahverengi bir
rect; genişliği 3 hücre (tek sayı) olsun ki taç ortasına doğal hizalansın. - Kritik: Izgarayı bozmayın —
backgroundbir kez; sıra: ızgara → yeşil → gövde.
İpucu: Orta sütun mid = floor(SUTUN / 2). Yeşil satır r için aralık mid - r … mid + r. Gövde genişliği 3: rect((mid - 1) * BOYUT, …, 3 * BOYUT, …). Ağacı tuvalde ortalamak için başlangıç satırını da kaydırın: startRow = floor((SATIR - yesilSatir - govdeSatir) / 2).
Kod bloğu: İç içe döngü + continue — diyagonal dışı hücreleri atlayarak yalnızca satir === sutun olanları yazdırma.
Kod 6.
function setup() { createCanvas(200, 100); for (let satir = 0; satir < 4; satir++) { for (let sutun = 0; sutun < 4; sutun++) { if (satir !== sutun) { continue; // diyagonal değilse bu hücreyi atla } console.log("diyagonal:", satir, sutun); } }} function draw() { background(240);}Konsol çıktısı: (0,0), (1,1), (2,2), (3,3).
Sıra Sizde: Aşağıdaki hedef görünüme uygun 9×9 Go tahtasını çizin (p5.js Web Editor). Tek tek çizgi veya taş yazmak yok — hem ızgara hem taşlar döngüyle üretilsin.

Görsel 4 ulaşmanız gereken çıktıdır: ahşap zeminde 9×9 ızgara; ana köşegende beyaz, diğer köşegende siyah taşlar; iki köşegenin kesişimi (4,4) boş.
İstenenler:
- Izgara: 9 yatay + 9 dikey çizgi (
line). Her yön için birforyeterli. - Taşlar: Kesişim noktalarına daire (
ellipse/circle) koyun:- Ana köşegen (
satir === sutun) → beyaz taş - Diğer köşegen (
satir + sutun === 8) → siyah taş - Ortak nokta
(4,4)→ taş koyma (continueveyaifile atlayın)
- Ana köşegen (
- Taş merkezleri çizgi kesişiminde dursun; çapı hücreden biraz küçük seçin.
İpucu: const N = 9;, const BOYUT = 40; gibi sabitler kullanın. Önce boş tahtayı çizin, sonra taş döngüsünü ekleyin. Go’da komşuluk yalnızca dik yönlerdedir (çapraz komşu sayılmaz); bu köşegen yerleşimi öğretim diyagramı olarak geçerlidir — taşlar birbirini dik komşu olarak sıkıştırmaz.
Sıra Sizde: Arkadaşınızın sketch’inde beyaz taşların altında ızgara çizgileri görünüyor; çizgiler taşları kesiyor. Sizce kodda ne yanlış gitmiş olabilir?
2.2. Döngülerle Animasyon
1.5'te frameCount ile tek bir dairenin konumu güncellenmişti. Döngülerle aynı frame'de birden fazla nesne çizilebilir; her nesnenin konumu döngü değişkenine bağlanır. Önce yalnızca toplama ve % kullanan bir örnek; ardından yumuşak salınım için sin() tanıtılır.
Trigonometrisiz örnek: kayan dikdörtgenler
Her frame'de frameCount artar. for ile birkaç dikdörtgen çizilir; i yalnızca başlangıç ofsetini değiştirir. Yatay kayma (frameCount * 2 + i * 70) % width ile sağa akar ve tuval sonuna gelince başa döner — sinüs gerekmez. Formülde * 2 kayma hızıdır (frame başına 2 piksel), i * 70 her şeridi 70 piksel farklı yerden başlatan ofsettir; % width (modulo, 1.5) sonucu 0 … width-1 aralığında tutar, böylece kenara gelen şerit soldan yeniden girer.
Kod bloğu: for + frameCount — yatay kayan şeritler.
Kod 7.
const SERIT_SAYISI = 5; function setup() { createCanvas(400, 280); noStroke();} function draw() { background(30, 34, 48); for (let i = 0; i < SERIT_SAYISI; i++) { // Her şerit farklı yatay ofsetle başlar; hepsi aynı hızda kayar let x = (frameCount * 2 + i * 70) % width; let y = 40 + i * 45; fill(80 + i * 30, 140, 220); rect(x, y, 60, 30); }}i = 0 iken şerit daha solda başlar; i büyüdükçe ofset artar. Renk de i ile değişir. Anlaşılması gereken çekirdek: döngü = aynı frame'de birden fazla nesne, frameCount = zaman.
sin() ile yumuşak salınım
Bazen nesnenin Y konumunun yumuşakça yukarı–aşağı gitmesi istenir. Bunun için p5.js'teki sin() kullanılır.
Tanım: sin(açı) — Verilen açının sinüs değerini döndürür. Sonuç her zaman −1 ile +1 arasındadır; açı arttıkça değer dalga gibi yükselir ve alçalır. Animasyonda sin, “zamanla −1…+1 arasında salınan bir sayı üreteci” gibi düşünülür.
Bilgi — açı birimi (radyan / derece): p5.js’te varsayılan açı birimi radyandır (angleMode(RADIANS)). sin, cos, rotate ve benzeri fonksiyonlar aksi belirtilmedikçe girdiyi radyan kabul eder. Tam tur: TWO_PI radyan ≈ 360°; çeyrek tur: HALF_PI ≈ 90°; PI ≈ 180°. Derece düşünüyorsanız dönüşüm gerekir:
Tablo 2.
| Dönüşüm | p5.js | İlişki (yaklaşık) |
|---|---|---|
| Derece → radyan | radians(90) |
90° → PI/2 |
| Radyan → derece | degrees(HALF_PI) |
PI/2 → 90 |
İsterseniz angleMode(DEGREES) ile tüm sketch’i dereceye çevirebilirsiniz; bu durumda sin(90) yazılır, sin(HALF_PI) değil. Bu kitapta örnekler varsayılan radyan ile kalır; PI, HALF_PI, TWO_PI sabitleri bu yüzden sık kullanılır.

Görsel 5 bir dönemlik sin eğrisini gösterir (ör. sin(PI / 2) değeri 1, sin(3 * PI / 2) değeri -1). Kesik çizgiler dalganın sola ve sağa aynı biçimde sürdüğünü hatırlatır; grafik tek bir tekrarla sınırlı değildir.
Tuvalde piksel konumuna çevirmek için sin çıktısı bir ölçekle çarpılır ve bir merkeze eklenir:
Tablo 3.
| Parça | Örnek | Anlam |
|---|---|---|
sin(...) |
−1 … +1 | Ham salınım |
* 40 |
−40 … +40 | Piksel cinsinden genlik |
150 + … |
110 … 190 | Dikey merkez 150 |
Bu yüzden y = 150 + sin(frameCount * 0.05 + i) * 40 yazılır: daire 150 civarında ±40 piksel salınır. + i her daireye farklı faz verir; hepsi aynı anda aynı yükseklikte olmaz.
Kod bloğu: Yatay kayma + sin ile dikey salınım (önceki kayma örneğinin gelişmiş hâli).
Kod 8.
const DAIRE_SAYISI = 6;const DAIRE_YARICAP = 20; function setup() { createCanvas(400, 300); noStroke();} function draw() { background(20, 25, 40); for (let i = 0; i < DAIRE_SAYISI; i = i + 1) { // Yatay: şerit örneğindeki gibi — yalnızca % ve toplama let x = (frameCount * 2 + i * 60) % width; // Dikey: sin ile yumuşak salınım let y = 150 + sin(frameCount * 0.05 + i) * 40; fill(100 + i * 25, 180, 255); ellipse(x, y, DAIRE_YARICAP * 2, DAIRE_YARICAP * 2); }}Bilgi: sin satırını kaldırıp let y = 150; yazarsanız daireler yalnızca yatay kayar — ilk örnekle aynı mantık. Salınım dikey hareketi ekler; döngü ve frameCount iskeleti paylaşılır.
Döngü değişkeni i burada konum ofseti, renk ve faz farkı yaratır.
Döngü ile düzenli 20gen
Düzenli bir çokgende köşeler, ortak bir çember üzerinde eşit açıyla dizilir. Tam tur TWO_PI radyandır (≈ 360°). 20 köşe için komşu köşeler arası açı:
açıAdımı = TWO_PI / 20
(Derece ile düşünülürse adım 360° / 20 = 18° olur; p5.js varsayılanında yine radians(18) veya doğrudan TWO_PI / 20 yazılır.)
i. köşenin kutupsal açısı i * açıAdımı (örnekte üstten başlamak için -HALF_PI kaydırılır). Dik koordinata çeviri, birim çemberdeki gibi yapılır:
x = merkezX + r * cos(açı)y = merkezY + r * sin(açı)

Görsel 6 hatırlatıcıdır: merkez orijin O (0, 0)dır; O ile P arasındaki doğru parçası yarıçaptır (r). Çember üzerindeki P noktasında yatay izdüşüm cos θ, dikey izdüşüm sin θ değeridir. Birim çemberde r = 1; çokgende aynı formül r ile ölçeklenir (merkezX, merkezY orijini kaydırır). cos ve sin birlikte (−1…+1) aralığında salınır.
Döngü her i için bir köşe hesaplar; vertex ile çokgen kapatılır. açı formülünde TWO_PI / KOSE, tam turu köşe sayısına bölerek komşu iki köşe arasındaki eşit açı adımını verir; -HALF_PI (≈ −90°) ise ilk köşeyi tepeye (saat 12 yönü) kaydırır. R * cos(açı) ve R * sin(açı) bu açıyı yarıçapı R olan çember üzerindeki (x, y) konumuna çevirir.
Kod bloğu: for ile düzenli 20gen.
Kod 9.
const KOSE = 20;const R = 120; function setup() { createCanvas(400, 400);} function draw() { background(255); translate(width / 2, height / 2); noFill(); stroke(40); beginShape(); for (let i = 0; i < KOSE; i++) { let açı = -HALF_PI + i * TWO_PI / KOSE; let x = R * cos(açı); let y = R * sin(açı); vertex(x, y); } endShape(CLOSE);}
Görsel 7 yukarıdaki sketch’in tuval çıktısıdır: 20 eşit kenarlı düzenli çokgen. KOSE 3 → üçgen, 6 → altıgen, 20 → yirmigen olur; yalnızca sabit değişir.
Aynı döngü while ile de yazılabilir:
Kod 10.
let i = 0;while (i < KOSE) { let açı = -HALF_PI + i * TWO_PI / KOSE; let x = R * cos(açı); let y = R * sin(açı); vertex(x, y); i++;}Örnek Olay: Izgara Tasarımı Tahmini etkinliği tamamlama süresi: 35–40 dakika.
Senaryo: Gelecek bölümde kodlanacak bir tic-tac-toe (XOX) oyunu için 3×3 tahta çizilecektir. Tahta, döngülerle üretilen ızgara hücrelerine dayanacaktır.
Durum Tespiti:
- Hücre boyutu ve sütun/satır sayısı sabitlenebilir.
fordöngüsü ile 3×3 yerine elle dokuzrect()yazmaya gerek kalmaz.- Tahta boyutu değişirse yalnızca
SUTUN_SAYISI,SATIR_SAYISIveHUCRE_BOYUTUgüncellenir.
Problem Durumu: Elle yazılmış tekrarlar, tahta boyutu büyüdüğünde bakımı zorlaştırır.
Tartışma Soruları:
- 3×3 tahta için iç içe döngü kaç kez
rect()çağırır? HUCRE_BOYUTUdeğeri iki katına çıkarılırsacreateCanvasboyutu nasıl etkilenir?- Animasyon örneğinde
frameCountolmadan döngü yalnızca konum çeşitliliği mi sağlar, hareket mi? sinkullanmadan kayan şerit örneği ilesin’li daire örneğinin ortak yanı nedir?- Düzenli 20gende
TWO_PI / 20neyi temsil eder;KOSE6 yapılırsa şekil ne olur?
Yapay Zekâ Etkileşimi: Döngüden Izgara Üretme Tahmini etkinliği tamamlama süresi: 30–35 dakika.
Amaç: for ve iç içe for ile farklı ızgara desenleri tasarlayıp döngü mantığını pekiştirmek.
Adım 1: 4×4, 6×6 veya 10×10 boyutunda bir ızgara hedefi belirleyin. Adım 2: Tercih edilen bir yapay zekâ sohbet robotunu açın. Adım 3: Aşağıdaki istemi satır ve sütun sayınızla doldurarak girin.
Örnek İstem:
"Bir p5.js draw() fonksiyonu içinde iç içe for döngüsüyle [satır]×[sütun] ızgara çizen kod yaz. Hücre boyutu [piksel] olsun. Dama tahtası deseni için (satir + sutun) % 2 kullan. Her satırı yorumla açıkla; yalnızca iç içe for döngüsü ve çizim komutları kullan."
Adım 4: Üretilen kodu Web Editor'de çalıştırın; hücre sayısının satır×sütun olduğunu konsolda console.log ile doğrulayın.
Yapay Zekâ Etkileşimi: Tarayıcıda Debug (p5.js) Tahmini etkinliği tamamlama süresi: 25–35 dakika.
Amaç: Hata ayıklamanın (debugging) ne olduğunu ve neden önemli olduğunu kavramak; p5.js sketch’inizi kullandığınız web tarayıcısında adım adım çalıştırarak (özellikle iç içe for) hem öğrenmek hem hata bulmak.
Kısa çerçeve (okuyun, ezberlemeyin): Debug, programın çalışırken ne yaptığını kontrollü biçimde gözlemektir: nerede durduğu, değişkenlerin o anda hangi değeri taşıdığı, hangi dalın seçildiği. Yalnızca “çalışmıyor” demek yetmez; neden çalışmadığını görmek gerekir. Eğitimde de değerlidir: iç içe for karışıksa kodu satır satır ilerletmek, satir / sutun değerlerinin nasıl değiştiğini izlemek çoğu zaman console.log yağmurundan daha öğreticidir. p5.js kodu tarayıcıda çalıştığı için Chrome, Firefox, Edge, Safari vb. Geliştirici Araçları (DevTools) bu işin doğal yeridir.
Adım 1: Kullandığınız tarayıcıyı not edin (ör. Chrome, Firefox, Safari). p5.js Web Editor’de veya kendi HTML sayfanızda küçük bir ızgara sketch’i açık olsun. Adım 2: Yapay zekâya tarayıcınıza özel sorun:
Örnek İstem A (kurulum): "p5.js sketch’imi [TARAYICI ADI] üzerinde debug etmek istiyorum. Sources/Debugger panelini nasıl açarım? Breakpoint koyma, Step over, Step into, Continue/Resume ve Scope/Watch ile değişken (ör. satir, sutun) izlemeyi kısa adım adım anlat. p5.js Web Editor kullanıyorsam neye dikkat edeyim?"
Adım 3: Yanıttaki adımları kendi makinenizde uygulayın. En az bir breakpoint koyup satir ve sutun değerlerinin tur tur değiştiğini görün. Anlamadığınız bir düğme varsa sorun: "Step over ile Step into farkı nedir? Continue ne yapar?"
Adım 4 — Hatalı kodla av: Yapay zekâdan bilerek hatalı 1–2 kısa p5.js örneği isteyin (iç içe for / ızgara tercih edin). Örnek istem:
Örnek İstem B: "İç içe for ile ızgara çizen, içinde 1–2 mantık hatası olan kısa bir p5.js sketch yaz (ör. yanlış çarpan, sınır dışı indeks, iç/dış döngü karışıklığı). Hatayı spoiler olarak hemen söyleme. Ben tarayıcı debugger ile bulacağım; bitince doğru teşhisi soracağım."
Kodu yapıştırıp Play’e basın; DevTools ile adım adım ilerleyerek hatayı kendi gözünüzle bulun. Sonra yapay zekâya teşhisinizi yazın; doğru mu diye doğrulatın. İkinci hatalı örneği de aynı şekilde deneyin.
Adım 5: Bir cümlelik çıkış notu yazın: “Debug bana …… gösterdi.” (ör. iç döngünün her dış turda sıfırlandığını, veya x hesabındaki ofseti.)
Yapay Zekâ Etkileşimi: Döngü ve Animasyon Tahmini etkinliği tamamlama süresi: 15–20 dakika.
Amaç: Aynı döngü değişkeninin (satir / sutun) hem hücrenin konumunu hem de dairenin hareketini nasıl sürdüğünü görmek; değişken sabit bir sayıyla değiştirildiğinde neyin bozulduğunu deneyerek anlamak.
Adım 1 — Izgarayı üretin. Bir yapay zekâ sohbet robotuna aşağıdaki istemi verip çıktıyı p5.js Web Editor’de çalıştırın:
Örnek İstem:
"p5.js draw() içinde iç içe for ile 6×6 daireden oluşan bir ızgara çiz. Her daireyi ellipse(sutun * 60, satir * 60, 30) ile konumla. Yalnızca iç içe for ve çizim komutu kullan; her satırı kısaca yorumla."
Adım 2 — Hareket ekletin. Aynı koda, dairelerin indekslerine göre salınması için sin() + frameCount eklemesini isteyin (ör. "her dairenin y konumuna sin(frameCount * 0.05 + satir + sutun) * 12 kadar kayma ekle; komşu daireler dalga gibi gecikmeli salınsın"). Çalıştırıp dalganın satır ve sütun boyunca nasıl ilerlediğini izleyin.
Adım 3 — Değişkeni sabitleyip gözleyin. Şimdi sutun (ya da satir) yerine sabit bir sayı yazın; ör. ellipse(sutun * 60, …) yerine ellipse(3 * 60, …). Ne değişti? Beklenen: tüm daireler tek bir sütuna yığılır — çünkü her dairenin yerini taşıyan şey döngü değişkeniydi. Aynısını satir için de deneyin. Takılırsanız, bir önceki Tarayıcıda Debug etkinliğindeki breakpoint ve değişken izleme araçlarıyla satir / sutun değerlerini tur tur takip edin.
Çıkış notu (bir cümle): "Döngü değişkenini sabitleyince …… oldu; demek ki o değişken ……yi taşıyor."
Özet
İç içe döngüde dış sayaç satırları, iç sayaç ise sütunları gezer; iç döngü her dış turda yeniden sıfırdan başladığı için hücreler satır satır ziyaret edilir. Hücrenin konumu x = sütun * boyut ve y = satır * boyut ile bulunur; sayma 0’dan başladığında bu formül sade kalır, 1’den başlayan sayımda her konum hesabına bir çıkarma eklenir. (satır + sütun) % 2 koşulu iki rengi dönüşümlü kullanarak dama desenini üretir; toplam tur sayısı satır ve sütun sayısının çarpımına eşittir. Örüntü oturmadığında birkaç hücreyi tek tek rect ile yazmak veya kâğıt üzerinde iz sürmek isteğe bağlı bir keşif yoludur; zorunluluk değildir.
Animasyonda frameCount her frame bir artar ve zaman benzeri bir sayaç işlevi görür; döngü indeksiyle toplandığında her nesne farklı bir ofset veya faz kazanır, % width ise kenara ulaşan nesneyi soldan yeniden başlatır. sin −1 ile +1 arasında salınan bir değer üretir ve bir genlikle çarpılıp bir merkeze eklenerek piksel konumuna çevrilir. Düzenli çokgende komşu köşeler arasındaki açı adımı TWO_PI / köşeSayısıdır; köşeler cos ve sin ile hesaplanıp vertex çağrılarıyla şekil kapatılır. p5.js tarayıcıda çalıştığı için DevTools üzerinden breakpoint, Step over ve değişken izleme hem hata bulmada hem iç içe döngünün akışını görmede işe yarar.
Neler Öğrendik?
Soru 1 10×10 ızgarada iç içe for kaç hücre ziyaret eder?
A) 10
B) 20
C) 100
D) 1000
E) 2
Soru 2 Dama deseni için tipik ifade hangisidir?
A) satir * sutun
B) (satir + sutun) % 2
C) frameRate()
D) createCanvas
E) keyCode
Soru 3
sin animasyonda genelde ne sağlar?
A) Dosya indirme
B) −1…+1 arası yumuşak salınım
C) HTML bilgisini
D) APA atıfı
E) CSS seçici
Soru 4 Pac-Man’de her hayaletin yönünü sırayla hesaplamak hangi programlama fikrine örnektir?
A) Tek bir if ile tüm hayaletleri aynı anda yönetmek
B) Liste / dizideki her eleman için döngüyle aynı tür işlemi tekrarlamak
C) Yalnızca background çağırmak
D) createCanvas boyutunu değiştirmek
E) APA kaynakça yazmak
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: C
- Çözüm: 10 satır × 10 sütun = 100.
- İlgili Konu: 2.1. İç İçe for Döngüleri ve Izgara Çizimi
Soru 2: Doğru Cevap: B
- Çözüm: Toplamın tek/çiftliği renk seçer.
- İlgili Konu: 2.1. İç İçe for Döngüleri ve Izgara Çizimi
Soru 3: Doğru Cevap: B
- Çözüm: Sinüs dalgası yumuşak ofset üretir.
- İlgili Konu: 2.2. Döngülerle Animasyon
Soru 4: Doğru Cevap: B
- Çözüm: Her hayalet için benzer güncelleme; tipik for/while tekrarıdır.
- İlgili Konu: 2.1. İç İçe for Döngüleri ve Izgara Çizimi
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Mozilla Developer Network. (n.d.). break. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
- Mozilla Developer Network. (n.d.). continue. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
- Mozilla Developer Network. (n.d.). for. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
- Mozilla Developer Network. (n.d.). while. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while
- Nystrom, R. (2014). Game loop. In Game Programming Patterns. https://gameprogrammingpatterns.com/game-loop.html
- p5.js Foundation. (n.d.). angleMode. p5.js Reference. https://p5js.org/reference/p5/angleMode/
- p5.js Foundation. (n.d.). radians. p5.js Reference. https://p5js.org/reference/p5/radians/
- p5.js Foundation. (n.d.). sin. p5.js Reference. https://p5js.org/reference/p5/sin/
- Russell, S., & Norvig, P. (2020). Artificial Intelligence: A Modern Approach (4th ed.). Pearson.
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
- Wikipedia contributors. (n.d.). Minimax. Wikipedia. https://en.wikipedia.org/wiki/Minimax
- Wikipedia contributors. (n.d.). Nim. Wikipedia. https://en.wikipedia.org/wiki/Nim
Ana Başlık 3. Fonksiyonlar ve Modüler Kod Yazımı
Amaç: Fonksiyon tanımlama, parametre ve dönüş değeri kavramlarını öğreterek kodu modüler hale getirmek.
Öğrenme Çıktıları:
- Fonksiyon tanımlar ve çağırır.
- Parametreli fonksiyonlarla tekrar kullanılabilir kod yazar.
- return ifadesiyle değer döndürür.
- p5.js'te yardımcı çizim fonksiyonları oluşturur.
- Modüler kod yapısının oyun geliştirmedeki önemini açıklar.
- Global ve yerel değişken kapsamını ayırt eder; parametre ile argüman ilişkisini açıklar.
Anahtar Sözcükler: fonksiyon, parametre, argüman, dönüş değeri, return, modülerlik, yeniden kullanılabilirlik, kapsam, global değişken, yerel değişken, gölgeleme
Giriş
Döngüler tekrarlayan aynı kodu kısaltır; fonksiyonlar ise anlamlı iş parçalarını isimlendirilmiş bloklara ayırır. draw() içinde onlarca satır büyüdüğünde "tahta çiz", "skor yaz", "hedefi güncelle" gibi görevler birbirine karışır. Fonksiyonlar, her görevi ayrı bir isim altında toplayarak okunabilirliği artırır ve aynı işlemi farklı yerlerden tekrar çağırmayı mümkün kılar. Böylece bir değişiklik tek noktada yapılır; kopyalanmış satırlarda unutulan güncellemeler azalır.
p5.js’te setup() ve draw() zaten özel fonksiyonlardır; p5.js bunları belirli zamanlarda otomatik çağırır. mousePressed() de önceki ana başlıklarda benzer biçimde tanıtılmıştır. Bu ana başlıkta kullanıcı tanımlı fonksiyonlar ele alınacak: geliştiricinin kendi adını verdiği, parametre alabilen ve değer döndürebilen bloklar. Parametreler dış veri taşır; return hem erken çıkış hem de hesaplanmış sonuç için kullanılır. Modüler yapı, ileride XOX tahtası çizimi ve Daire Tıklama oyunundaki hedef konumu güncelleme gibi görevlerin düzenlenmesine zemin hazırlar.
Fonksiyonlar yalnızca kod tekrarını azaltmaz; soyutlama sağlar. draw() içinde tahtaCiz() yazmak, «tahtayı çiz» niyetini kodu inceleyene iletir; hücre renginin nasıl seçildiği hucreCiz içinde kalır. Oyun büyüdükçe hangi fonksiyonun ne yaptığını bilmek, hata ayıklamayı hızlandırır: tahta bozuksa önce tahtaCiz ve hucreCiz incelenir, tüm draw() taranmaz.
Modüler yazım aynı zamanda hata ayıklamayı ve ekip çalışmasını kolaylaştırır. Bir oyunda skor hesaplaması hatalıysa, tüm draw() gövdesini satır satır izlemek yerine doğrudan skorArtir gibi anlamlı adlandırılmış fonksiyona bakmak yeterli olur; fonksiyon adı zaten hangi görevi üstlendiğini belirtir. Birden fazla kişi aynı sketch üzerinde çalıştığında da fonksiyonlara bölünmüş kod, kimin hangi parçayı değiştirdiğini ayırt etmeyi kolaylaştırır: biri tahtaCiz üzerinde çalışırken diğeri skorGuncelle üzerinde çalışabilir, iki değişiklik aynı satırlarda çakışmaz.
3.1. Fonksiyon Kavramı ve Sözdizimi
Tanım: Fonksiyon (function) — Belirli bir görevi yerine getiren, isimlendirilmiş ve gerektiğinde tekrar çağrılabilen kod bloğudur.
Matematik dersindeki f(x) = x * x gibi bir fonksiyonu düşünün: dışarıdan bir girdi verirsiniz, içerideki kural çalışır, bir sonuç çıkar. Programlamada da benzer bir bakış yaygındır: çağıran taraf çoğu zaman fonksiyonun içini satır satır bilmek zorunda değildir — adı, girdi ve çıktı yeter; gövde bir kara kutu gibi kalabilir. dist(x1, y1, x2, y2) tam böyle çalışır: mesafe formülünü ezberlemeseniz de sonucu kullanırsınız. Kendi yazdığınız icindeMi veya topla için de aynı alışkanlık geçerlidir: önce «ne alır, ne verir / ne yapar?» sorusunu netleştirin.

Görsel 1 fonksiyonu girdi → kara kutu → çıktı olarak özetler: topla(3, 5) çağrısında önemli olan argümanlar ve dönen 8’dir; kutunun içindeki satırlar çağıran için gizli kalabilir.
Bilgi — Girdi, çıktı ve yan etki: İyi tasarlanmış bir fonksiyon genelde değer alır (parametre) ve çoğu zaman değer üretir (return) veya tek, net bir işi tamamlar. Dosya okuma, ağ isteği, konsola yazdırma gibi girdi/çıktı (I/O) işleri fonksiyon gövdesinde sık sık biriktirilmez; bunlar programın başka katmanlarına bırakılır. Elbette istisna vardır: p5.js’te arkaPlanCiz veya hedefCiz gibi yardımcılar tuvale çizim yapar — bu bir yan etkidir, yine de görevleri tek ve anlaşılırdır. Pratik kural: bir fonksiyon mümkün olduğunca tek, net tanımlanmış bir işe karşılık gelsin; «hem skor hesapla hem dosyaya yaz hem de menüyü çiz» gibi karışık sorumluluklar bakımı zorlaştırır.
Dikkat — dış değişkeni değiştirmek: Burada global, kabaca setup / draw dışında (dosyanın üstünde) tanımlanan değişkendir — örn. let secili = "gunes";. Bir fonksiyonun böyle bir değişkeni güncellemesi (secili = "agac") yan etkidir; ideal olan çoğu zaman return ile sonuç vermektir. Yine de olay fonksiyonlarında bu kalıp sık görülür ve bazen gerekir. Global / yerel ayrımının ayrıntısı 3.6’da; örnek kullanım ise bu ana başlığın sonundaki YZ etkinliğinde.
Bilgi — Ekip çalışması: Fonksiyonlar, işi kişilere bölmeyi kolaylaştırır. Biri tahtaCiz yazarken diğeri skorYaz üzerinde çalışabilir; arayüz (ad, parametre, dönüş) üzerinde anlaşılırsa gövdeler birbirinden bağımsız ilerler. Kara kutu burada da işe yarar: ekip arkadaşınızın yazdığı fonksiyonun satır satır içini bilmeden, «ne aldığını / ne verdiğini / ne yaptığını» biliyorsanız onu çağırabilirsiniz — tıpkı dist gibi.
Temel sözdizimi:
Kod 1.
function fonksiyonAdi() { // gövde — çağrıldığında çalışan satırlar}Çağrı (call): fonksiyonAdi(); — parantezler fonksiyonun şimdi çalıştırılması gerektiğini belirtir.
Tablo 1.
| Kavram | Biçim | Anlam |
|---|---|---|
| Tanım | function hedefCiz() { … } |
Fonksiyonun adı ve gövdesi |
| Çağrı | hedefCiz(); |
Tanımlanan bloğu çalıştırır |
| p5.js yerleşik | setup(), draw() |
p5.js belirli anlarda otomatik çağırır |
Kod bloğu: Basit yardımcı fonksiyon — arka plan rengini sabitleyen arkaPlanCiz.
Kod 2.
function setup() { createCanvas(400, 400);} function draw() { arkaPlanCiz(); ortaCizgiCiz();} function arkaPlanCiz() { background(35, 40, 55);} function ortaCizgiCiz() { stroke(200); strokeWeight(2); line(width / 2, 0, width / 2, height); noStroke();}draw() artık ne yaptığını okunaklı biçimde listeler; ayrıntılar fonksiyon gövdelerinde saklanır. p5.js draw() her frame'de çalıştığı için içinde çağrılan arkaPlanCiz() ve ortaCizgiCiz() de her frame'de yeniden çalışır.
Bilgi: Kendi yazdığınız fonksiyonlarda camelCase örfi kullanılır: hedefCiz, skorGuncelle. setup, draw ve mousePressed ise farklı bir kategoridedir: p5.js bu adları sabit olarak tanır ve sketch çalışırken bu isimdeki fonksiyonları belirli anlarda otomatik çağırır. Örneğin draw yerine cizimYap yazarsanız p5.js her frame'de o fonksiyonu aramaz; tuval güncellenmez. Yani camelCase burada tercih meselesi değil, p5.js'in tanıdığı yerleşik olay adlarıdır; kütüphane dokümantasyonunda bu isimlerle tanımlanır.
Fonksiyon çağrı izi: Aşağıdaki sketch'te draw() çalıştığında çağrı sırası şöyledir:
Tablo 2.
| Adım | Çalışan fonksiyon | Not |
|---|---|---|
| 1 | draw() |
p5.js tarafından tetiklenir |
| 2 | arkaPlanCiz() |
draw() içinden çağrılır |
| 3 | ortaCizgiCiz() |
draw() içinden çağrılır |
| 4 | (frame biter) | Bir sonraki frame'de 1. adıma dönülür |
Fonksiyon iç içe çağrılabilir: tahtaCiz döngü içinde hucreCiz çağırır; her hucreCiz tamamlanınca kontrol tahtaCiz'e döner. Bu «çağrı yığını» (call stack) kavramının basit hâlidir; derin özyineleme (Mayın Tarlası Flood Fill) ileride aynı mantığı kullanır.
Bilgi: JavaScript'te function fonksiyonAdi() { … } biçiminde yazılan tanımlar, dosyanın neresinde durduğuna bakılmaksızın çalıştırılmadan önce tanınır; bu nedenle draw() içindeki arkaPlanCiz() çağrısı, arkaPlanCiz tanımından önce yazılsa da hatasız çalışır. Yine de okunabilirlik açısından ilgili fonksiyonları çağrıldıkları yere yakın veya dosyanın sonunda düzenli biçimde tutmak tercih edilir.
Sıra Sizde: Uzun bir draw() bloğunu en az iki anlamlı fonksiyona bölecek şekilde isimlendirin (ör. arkaplanCiz, skorYaz). Her fonksiyonun tek sorumluluğunu bir satırla yazın.
3.2. Parametreli Fonksiyonlar
Tanım: Parametre (parameter) — Fonksiyon tanımında parantez içine yazılan, dışarıdan alınan değer yer tutucusudur. Çağrı sırasında verilen somut değere argüman (argument) denir.
Kod 3.
function dikdortgenCiz(x, y, w, h, renkR, renkG, renkB) { fill(renkR, renkG, renkB); noStroke(); rect(x, y, w, h);} function draw() { background(20); dikdortgenCiz(50, 50, 80, 60, 255, 100, 100); // kırmızımsı dikdortgenCiz(200, 120, 100, 40, 100, 200, 255); // mavimsi}Aynı fonksiyon farklı argümanlarla birden çok kez kullanılır; kod tekrarı azalır.
Tablo 3.
| Kavram | Tanım yeri | Örnek |
|---|---|---|
| Parametre | function dikdortgenCiz(x, y, w, h) |
x, y, w, h |
| Argüman | Çağrı satırı | 50, 50, 80, 60 |
Dikkat: Parametre sırası önemlidir. dikdortgenCiz(50, 50, 80, 60, …) ifadesinde ilk 50 x'e, ikinci 50 y'ye gider. Argüman sayısı parametre sayısından azsa karşılık gelmeyen parametreler undefined olur; fazlaysa fazladan değerler yok sayılır.
3.3. return ile Değer Döndürme
mousePressed() içinde return; ifadesi fonksiyondan erken çıkış için kullanılır; oyun bittiğinde geri kalan satırlar çalışmaz. return aynı zamanda bir değer üretip çağıran yere iletebilir.
Kod 4.
function acikKareMi(satirSutunToplami) { return (satirSutunToplami % 2 === 0);} function draw() { background(50); for (let satir = 0; satir < 4; satir = satir + 1) { for (let sutun = 0; sutun < 4; sutun = sutun + 1) { if (acikKareMi(satir + sutun)) { fill(230, 220, 200); } else { fill(60, 55, 50); } rect(sutun * 50, satir * 50, 50, 50); } }}Fonksiyon, dama deseninde satır ve sütun toplamının çift olduğu hücreleri açık renge ayırır: acikKareMi(3) çağrısı false, acikKareMi(6) çağrısı true döndürür. Çağıran satır bu boolean değeri if koşulunda kullanır.
Tablo 4.
| return biçimi | Anlam | Örnek |
|---|---|---|
return; |
Değer yok; fonksiyon hemen biter | mousePressed içinde erken çıkış |
return değer; |
Hesaplanan değeri çağıran yere verir | return (a + b); |
Tanım: Dönüş değeri (return value) — Fonksiyonun return ile geri gönderdiği sonuç; çağrı ifadesinin yerine geçer.
Kod 5.
let sonuc = topla(3, 5); // sonuc değişkeni 8 olur function topla(a, b) { return a + b;}Kod bloğu: Oyun mantığında return — mesafe ve «içinde mi» testi (daire çarpışmasında kullanılan dist() ile uyumlu).
Kod 6.
function mesafeHesapla(x1, y1, x2, y2) { return dist(x1, y1, x2, y2);} function icindeMi(fareX, fareY, merkezX, merkezY, yaricap) { let m = mesafeHesapla(fareX, fareY, merkezX, merkezY); return m < yaricap;}icindeMi(mouseX, mouseY, hedefX, hedefY, 40) ifadesi true veya false üretir; if koşulunda doğrudan kullanılabilir. Daire Tıklama oyunundaki dist(...) < hedefYaricap satırı bu yapının satır içi hâlidir; fonksiyona taşımak okunabilirliği artırır.
Sıra Sizde: Bölüm 1 Ana Başlık 3'teki «nokta daire / elips içinde mi?» kontrollerini (renk örneği ve Daire Tıklama) davranışı değiştirmeden yardımcı fonksiyonlara taşıyın; eski yerlerde bu fonksiyonları çağırın. Daire için yukarıdaki icindeMi yeterli olabilir. İsterseniz genişlik ve yüksekliği farklı bir elips için ayrı bir fonksiyon da yazmayı deneyin.
3.4. p5.js'te Yardımcı Çizim Fonksiyonları
Izgara ve şekil çizimini fonksiyonlara ayırmak, draw() gövdesini sade tutar.
Kod bloğu: Parametreli hücre ve tahta çizimi.
Kod 7.
const HUCRE = 50;const SUTUN = 3;const SATIR = 3; function setup() { createCanvas(SUTUN * HUCRE, SATIR * HUCRE); noStroke();} function draw() { background(30, 35, 45); tahtaCiz(0, 0, SATIR, SUTUN, HUCRE); merkezIsaretiCiz(width / 2, height / 2);} function tahtaCiz(baslangicX, baslangicY, satirSayisi, sutunSayisi, hucreBoyutu) { for (let satir = 0; satir < satirSayisi; satir = satir + 1) { for (let sutun = 0; sutun < sutunSayisi; sutun = sutun + 1) { hucreCiz( baslangicX + sutun * hucreBoyutu, baslangicY + satir * hucreBoyutu, hucreBoyutu, satir, sutun ); } }} function hucreCiz(x, y, boyut, satir, sutun) { if ((satir + sutun) % 2 === 0) { fill(240, 235, 220); } else { fill(70, 65, 60); } rect(x, y, boyut, boyut);} function merkezIsaretiCiz(merkezX, merkezY) { fill(255, 80, 80); ellipse(merkezX, merkezY, 12, 12);}tahtaCiz üç kez farklı boyutta çağrılabilir; yalnızca argümanlar değişir. Bu yapı ilerleyen bölümlerdeki XOX oyununun görsel zeminini oluşturur.
Çağrı sırası izlemesi: SATIR = 2, SUTUN = 2 olan daha küçük bir tahtada tahtaCiz çağrısının ürettiği hucreCiz çağrıları sırasıyla şöyledir:
Tablo 5.
| satir | sutun | hucreCiz çağrısı | Hücre rengi |
|---|---|---|---|
| 0 | 0 | hucreCiz(0, 0, 50, 0, 0) |
açık (satir + sutun çift) |
| 0 | 1 | hucreCiz(50, 0, 50, 0, 1) |
koyu |
| 1 | 0 | hucreCiz(0, 50, 50, 1, 0) |
koyu |
| 1 | 1 | hucreCiz(50, 50, 50, 1, 1) |
açık |
Dış döngü satir değerini, iç döngü sutun değerini değiştirir; her ikili için hucreCiz bir kez çağrılır. Toplam çağrı sayısı satirSayisi * sutunSayisi kadardır.
3.5. Modüler Kod ve Oyun Mimarisi
Tanım: Modülerlik — Programın bağımsız, yeniden kullanılabilir parçalara (fonksiyonlara, ileride sınıflara) ayrılmasıdır.
Oyun kodunda yaygın işlev ayrımı:
Tablo 6.
| Fonksiyon görevi | Örnek ad | Ne zaman çağrılır |
|---|---|---|
| Çizim | tahtaCiz, hedefCiz |
draw() içinde her frame |
| Girdi | mousePressed (p5.js olayı) |
Fare tıklanınca |
| Mantık | skorArtir, oyunBittiMi |
Olay veya draw() içinde |
| Yardımcı hesap | rastgeleKonum, icindeMi |
İhtiyaç duyulduğunda |

Görsel 2 draw() fonksiyonunun çizim, tahta ve skor gibi görevleri ayrı fonksiyonlara devretmesini; tahtaCiz içinde hucreCiz gibi iç içe çağrıları gösterir.
Kod bloğu: Daire Tıklama için hedef konumu güncelleme — artık fonksiyon kullanılabilir (bu ana başlıktan sonra refaktör örneği).
Kod 8.
function yeniHedefKonumu() { hedefX = random(50, width - 50); hedefY = random(50, height - 50);} function mousePressed() { if (oyunBitti) { return; } let mesafe = dist(mouseX, mouseY, hedefX, hedefY); if (mesafe < hedefYaricap) { skor = skor + 1; if (skor >= HEDEF_SKOR) { oyunBitti = true; } else { yeniHedefKonumu(); } }}Bu parça, sayı tahmin oyununda satır satır draw() ve mousePressed() içinde yazılmış mantığın modüler hâlidir; yeniHedefKonumu() yalnızca koordinat atamasından sorumludur.
Kod bloğu: XOX taşı çizimi — parametreli tasCiz (ilerleyen bölümlerin 5. ana başlığına hazırlık).
Kod 9.
function tasCiz(satir, sutun, hucre, oyuncu) { let x = sutun * hucre + hucre / 2; let y = satir * hucre + hucre / 2; textAlign(CENTER, CENTER); textSize(hucre * 0.55); fill(30); text(oyuncu, x, y);} function xoxTahtasiniCiz(tahta, hucre) { for (let satir = 0; satir < 3; satir = satir + 1) { for (let sutun = 0; sutun < 3; sutun = sutun + 1) { if (tahta[satir][sutun] !== "") { tasCiz(satir, sutun, hucre, tahta[satir][sutun]); } } }}Boş hücrelerde tasCiz çağrılmaz; dolu hücrelerde "X" veya "O" metni çizilir. Tahta verisi (tahta dizisi) ile görselleştirme (tasCiz) ayrılmış olur.
3.6. Değişken Kapsamı: Global ve Yerel
Fonksiyonlar büyüdükçe «bu x hangisi?» sorusu sık çıkar. Cevap kapsam (scope) kurallarındadır: bir değişkenin adı, yalnızca tanımlandığı bölgede geçerlidir. Yanlış yerde tanımlanan skor frame sonunda yok olur; yanlış adlandırılmış parametre ise global skoru güncellemezmiş gibi görünür.
Tanım: Kapsam (scope) — Bir değişken adının geçerli olduğu kod bölgesidir. Bu bölgenin dışında aynı ad ya tanımsızdır ya da başka bir değişkeni işaret eder.
Global değişkenler
setup() ve draw() dışında, sketch dosyasının üst düzeyinde let / const ile tanımlanan değişkenler global kabul edilir. Bunlara setup, draw, mousePressed ve kullanıcı tanımlı yardımcılardan erişilebilir; değer frame’ler arasında kalır.
Kod 10.
let skor = 0; // global — setup/draw dışındalet hedefX;let hedefY; function setup() { createCanvas(400, 400); hedefX = width / 2; hedefY = height / 2;} function draw() { background(240); text("Skor: " + skor, 20, 30); // global skor okunur circle(hedefX, hedefY, 40);} function skorArtir(artisMiktari) { skor = skor + artisMiktari; // global skor güncellenir}Oyun durumu (skor, hedefX, oyunBitti) bu yüzden üst düzeyde tutulur: draw her frame yeniden çalışsa da global değer silinmez.
Tablo 7.
| Nerede tanımlanır? | Tür | Örnek kullanım |
|---|---|---|
setup / draw dışında (üst düzey) |
Global | skor, hedefX, oyunBitti |
Fonksiyon gövdesinde let / const |
Yerel | Geçici hesap, döngü değişkeni |
| Fonksiyon parametresi | Yerel | dikdortgenCiz(x, y, w, h) içindeki x |
Yerel değişkenler ve draw()
Fonksiyon içinde let x = 5 yazılırsa x yalnızca o fonksiyon gövdesinde geçerlidir; fonksiyon bittiğinde yerel değişken yok olur. Parametreler de yerel kapsamdadır.
Dikkat: draw() her frame bir kez çağrılır ve biter. draw içinde tanımlanan yerel değişken her frame’in başında yeniden yaratılır, sonunda yok olur. Kalıcı oyun durumu için kullanılamaz:
Kod 11.
let skor = 0; // global — doğru yer function draw() { let geciciX = mouseX; // yerel — yalnızca bu frame’de geçerli // let skor = 0; // YANLIŞ: her frame sıfırdan başlar, skor birikmez background(240); text(skor, 20, 30); circle(geciciX, 200, 20);}geciciX her frame fare konumuna göre yeniden hesaplanır; bunu global tutmaya gerek yoktur. Buna karşılık skor birikmeli olduğu için global (veya ileride nesne/dizi) olmalıdır.
Argüman ile parametre aynı şey değildir
Çağrı satırındaki değer argüman, fonksiyon tanımındaki yer tutucu parametredir. İsimler aynı olsa bile bunlar iki ayrı değişkendir: çağrı anında argümanın değeri parametreye kopyalanır.
Kod 12.
function konumYaz(x) { // buradaki x, çağıranın x'i değil — kopya (yerel parametre) x = x + 50; text(x, 20, 40);} function draw() { background(255); let x = 100; // draw'ın yerel x'i konumYaz(x); // argüman: 100 → parametreye kopyalanır text(x, 20, 80); // hâlâ 100 — konumYaz içindeki atama burayı değiştirmez}Tablo 8.
| Ad | Nerede? | Bu örnekte |
|---|---|---|
| Argüman | Çağrı: konumYaz(x) |
draw içindeki x değeri (100) |
| Parametre | Tanım: function konumYaz(x) |
Fonksiyonun kendi yerel x'i (önce 100, sonra 150) |
Ekranda üst satır 150, alt satır 100 görünür. Parametre adı x olsa da çağıranın x'i ile bağlantılı değildir; sayısal değerler kopyalanır. Bu yüzden dikdortgenCiz(x, y, w, h) içindeki x, çağrı sırasında gelen argümanın kopyasıdır — fonksiyon gövdesinde x'i değiştirmek, çağıran taraftaki değişkeni otomatik güncellemez.
Bilgi: İsimler bilerek farklı seçilebilir: function konumYaz(ekranX) { … } ve konumYaz(x);. Davranış aynıdır; okuyan kişi parametre ile çağıran değişkeni daha kolay ayırır.
Gölgeleme (shadowing)
Parametre veya yerel let adı, üst düzeydeki global ile aynı olursa fonksiyon içinde yerel olan kazanır; global o isimle görünmez. Buna gölgeleme (shadowing) denir.
Kod 13.
let skor = 10; // global function skorArtir(skor) { // parametre adı da skor — gölgeleme skor = skor + 1; // yalnızca yerel parametre artar // global skor hâlâ 10} function draw() { skorArtir(skor); // argüman: 10 → yerel parametreye kopyalanır text(skor, 20, 30); // hâlâ 10 — beklenen artış olmaz}Karışıklığı önlemek için parametre adını globalden ayırmak önerilir:
Kod 14.
let skor = 10; function skorArtir(artisMiktari) { skor = skor + artisMiktari; // global skor bilinçli güncellenir} function draw() { // … skorArtir(1);}Dikkat: Global skoru güncelleyecek yardımcıda parametreye skor demek yaygın bir hatadır. Ya parametreyi artisMiktari gibi adlandırın ya da globali doğrudan (parametresiz) güncelleyin; ikisini aynı isimle karıştırmayın.
Örnek Olay: Fonksiyonlara Ayırma Tahmini etkinliği tamamlama süresi: 35–40 dakika.
Senaryo: 3×3 tahta çizen kod tek bir draw() içinde 40 satıra ulaşmıştır; tahta rengi değiştirilmek istendiğinde ilgili satırlar bulunamamaktadır.
Durum Tespiti:
- Hücre rengi, çizgi kalınlığı ve tahta boyutu birbirine karışmıştır.
tahtaCizvehucreCizayrımı bakımı kolaylaştırır.- XOX oyununda taş çizimi ayrı bir
tasCiz(x, y, tur)fonksiyonuna taşınabilir.
Problem Durumu: Tek blok hâlindeki kod, ekip çalışmasında ve hata ayıklamada yavaşlatıcıdır.
Tartışma Soruları:
returnile erken çıkış ilereturn değerarasındaki fark nedir?- Aynı fonksiyonu farklı argümanlarla çağırmak neden kod tekrarını azaltır?
draw()içinde kaç yardımcı fonksiyon çağrısı makul sayılır?- Skor neden
draw()içindeletile tanımlanmamalıdır? - Parametre adı global değişkenle aynı olursa ne olur?
Yapay Zekâ Etkileşimi: Kara Kutu ile Ekipçe Sketch Tahmini etkinliği tamamlama süresi: 40–50 dakika.
Amaç: (1) YZ’den çizim fonksiyonları ve klavye ile secili seçen bir yardımcı almak; (2) sizin tarafınızda yalnızca bildiğiniz mousePressed ile tuvale çizmek; (3) kara kutu, ekip paylaşımı ve «global değiştiren fonksiyon» eleştirisini yaşayarak görmek.
Önemli — klavyeyi henüz işlemedik. keyPressed / key bu kitapta sistematik olarak Bölüm 2’de gelir. Yine de YZ’den (veya bir ekip arkadaşından) «tuşa göre secili değiştir» kodunu alıp içini satır satır bilmeden kullanabilirsiniz — tıpkı Görsel 1’deki kara kutu gibi. Davranış garantisi netse (G → secili === "gunes"), gövdeyi bilmek zorunda değilsiniz.
Adım 1 — Çizim fonksiyonlarını YZ’ye yazdırın.
Örnek İstem:
"p5.js için şu yardımcı fonksiyonları yaz: gunesCiz(merkezX, merkezY), insanCiz(merkezX, merkezY), agacCiz(merkezX, merkezY), evCiz(merkezX, merkezY), kusCiz(merkezX, merkezY). Her fonksiyon yalnızca ellipse, rect, line, triangle gibi temel şekillerle çizsin. Tüm parçalar merkezX / merkezY’ye göre konumlandırılsın; sabit piksel adresleri kullanma."
Üretilen kodu yapıştırın; bir kez gunesCiz(width/2, height/2) ile deneyin.
Adım 2 — Seçim fonksiyonunu YZ’ye yazdırın (klavye — sizin bilmeniz gerekmez). Global secili değişkeni olacak; tuşa göre değeri değişecek.
Örnek İstem:
"p5.js’te global let secili = 'gunes' var. keyPressed yaz: g/G → secili = 'gunes', i/I → 'insan', a/A → 'agac', e/E → 'ev', k/K → 'kus'. Başka bir şey çizme; yalnızca secili’yi güncelle. Kısa yorum ekle."
Bu parçayı da sketch’e ekleyin. Şimdilik keyPressed’in nasıl çalıştığını ezberlemeniz beklenmiyor — sözleşme şu: doğru tuşa basınca secili doğru string olur.
Adım 3 — Sizin işiniz: tıklayınca çiz. Yalnızca Bölüm 1 Ana Başlık 3'ten bildiğiniz fare ile ilerleyin:
Kod 15.
let secili = "gunes"; function setup() { createCanvas(400, 400); background(230); // bir kez} function draw() { // boş — şekiller tıklamayla birikir} function mousePressed() { if (mouseX < 40 && mouseY < 40) { background(230); // temizle return; } if (secili === "gunes") { gunesCiz(mouseX, mouseY); } else if (secili === "insan") { insanCiz(mouseX, mouseY); } else if (secili === "agac") { agacCiz(mouseX, mouseY); } else if (secili === "ev") { evCiz(mouseX, mouseY); } else if (secili === "kus") { kusCiz(mouseX, mouseY); }} // keyPressed — YZ / ekip arkadaşı yazdı; siz içini bilmeden kullanıyorsunuzİş bölümü (ekip analojisi): Biri (burada YZ) «tuş → secili» kutusunu yazar; siz «secili → tuvalde çiz» kutusunu yazarsınız. Ortak dil: secili string değerleri. Bu, fonksiyonların ekip çalışmasındaki faydasıdır — görevler ayrılır, arayüz üzerinde anlaşılır.
Adım 4 — Sahne kurun. Tuşa basın (seçim), sonra tuvale tıklayın (yerleştirme). Birkaç ağaç, bir ev, güneş… Aynı çizim fonksiyonunu farklı (mouseX, mouseY) ile çağırmanın parametre gücünü not edin.
Adım 5 — Eleştirel bakış (iki katman).
- Kara kutu işe yaradı mı? Klavye konusunu bilmeden seçim yapabildiniz mi? Davranış sözü tutulduysa (
G→ güneş seçilir) gövdeyi bilmek zorunda değildiniz — Görsel 1’i hatırlayın. - Global
seciligüncellemesi: Ideal olan çoğu zaman değer alıp değer döndürmektir; burada ise olay fonksiyonu dışarıdaki bir değişkeni değiştiriyor. Bu «en temiz» tasarım sayılmaz — yine dekeyPressed/mousePressedgibi olaylarda sık görülür ve bazen pratik olarak gerekir. Kara kutu kullanmak ile her kara kutunun mükemmel tasarlandığı aynı şey değildir; yine de işe yarar bir paylaşım biçimidir. - YZ gerçekten düzgün çizebiliyor mu? YZ metin ve kod iskeletinde sık işe yarar; görsel şekil üretiminde ise özellikle karmaşık figürlerde (insan, kuş, detaylı ev) sıklıkla zayıf kalır veya saçmalayabilir. Olası sorunlar:
- Merkez parametresini yok sayıp sabit
(100, 100)gibi konumlar kullanmak - Parçaların orantısız veya birbirinden kopuk durması (gövde ile kafa ayrı yerde)
triangle/lineuçlarının yanlış bağlanması; “kuş”un tanınmaz bir karalama olmasıfill/strokeunutulduğu için şekillerin birbirine karışması
Basit güneş (daire + ışınlar) çoğu zaman idare eder; karmaşık silüetlerde YZ çıktısını körü körüne güvenmeyin. En az bir çizim fonksiyonunu kendiniz düzelterek veya sadeleştirerek (ör. insanı daire + iki rect) tekrar deneyin.
Kısa not (3–5 cümle): (a) kara kutu / ekip, (b) global güncellemenin «ideal değil ama bazen gerekir» yanı, (c) hangi şekil bozuldu, neden.
Özet
Fonksiyonlar, adlandırılmış ve gerektiğinde tekrar çağrılabilen kod bloklarıdır. Tanım function ad() { … } biçimindedir; çağrı ad(); ile yapılır — parantezler bloğun o anda çalıştırılacağını belirtir. p5.js’in setup() ve draw() fonksiyonları kütüphane tarafından otomatik çağrılır; mousePressed gibi olay fonksiyonları da benzerdir. Kullanıcı tanımlı fonksiyonlar ise geliştiricinin açıkça çağırdığı yardımcı bloklardır. Modülerlik, uzun draw() gövdelerini çizim, girdi, mantık ve hesap görevlerine ayırarak okunabilirliği ve bakımı artırır; tahta bozuksa tüm draw() yerine tahtaCiz incelenir. Yeniden kullanılabilirlik, aynı yardımcının farklı argümanlarla tekrar çağrılmasından doğar. Parametreler fonksiyona dış veri taşır; çağrı sırasındaki somut değerler argümandır (dikdortgenCiz(50, 80, 100, 40)). Aynı fonksiyon farklı argümanlarla birçok kez kullanılabilir; böylece kopyala-yapıştır azalır. return hem koşul sağlanmadığında erken çıkış (if (oyunBitti) { return; }) hem de topla, acikKareMi, icindeMi gibi yardımcılarda hesaplanmış değer döndürme için kullanılır. Dönüş değeri atama veya koşul ifadesinde tüketilir. Kapsam (scope), bir değişken adının geçerli olduğu bölgedir. setup/draw dışında tanımlanan skor, hedefX gibi değişkenler globaldir; frame’ler arasında kalır ve yardımcılardan okunup yazılabilir. Fonksiyon içindeki let ve parametreler yereldir; fonksiyon (veya draw frame’i) bitince yok olur. Bu yüzden skor draw içinde let skor = 0 ile tanımlanmaz. Argüman ile parametre aynı isimde olsa bile ayrıdır: çağrıda değer kopyalanır; parametreyi değiştirmek çağıranın değişkenini otomatik güncellemez. Parametre adı global ile örtüşürse gölgeleme olur; skorArtir(artisMiktari) gibi ayırt edici adlar tercih edilir. p5.js’te tahtaCiz, hucreCiz, hedefCiz, arkaPlanCiz gibi görevler ayrı fonksiyonlara bölündüğünde draw() kısa ve niyet odaklı kalır; iç içe çağrılar (tahtaCiz → hucreCiz) görev hiyerarşisini yansıtır.
Neler Öğrendik?
Soru 1 Aşağıdakilerden hangisi fonksiyon çağrısıdır?
A) function hedefCiz() { }
B) let x = 10;
C) hedefCiz();
D) return false;
E) if (skor > 0)
Soru 2
function topla(a, b) { return a + b; } tanımında a ve b ne olarak adlandırılır?
A) Argüman
B) Parametre
C) Boolean
D) Yerleşik değişken
E) Döngü değişkeni
Soru 3
mousePressed() içinde if (oyunBitti) { return; } satırının amacı nedir?
A) Oyunu kazanmış olmak
B) Fonksiyondan değer döndürerek skor artırmak
C) Oyun bittiyse fonksiyonun geri kalanını çalıştırmamak
D) draw() fonksiyonunu durdurmak
E) Tuval boyutunu değiştirmek
Soru 4
I. Parametreli fonksiyonlar kod tekrarını azaltır.
II. return a + b; ifadesi toplamı çağıran yere iletir.
III. Modüler kod, görevleri isimlendirilmiş parçalara ayırır.
Hangileri doğrudur?
A) Yalnız I
B) I ve II
C) Yalnız III
D) II ve III
E) I, II ve III
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: C
- Çözüm:
hedefCiz();fonksiyonu çalıştırır. A seçeneği tanımdır;returnveifayrı yapılardır. - İlgili Konu: 3.1. Fonksiyon Kavramı ve Sözdizimi
Soru 2: Doğru Cevap: B
- Çözüm: Tanımdaki
avebparametredir.topla(3, 5)çağrısındaki 3 ve 5 argümandır. - İlgili Konu: 3.2. Parametreli Fonksiyonlar
Soru 3: Doğru Cevap: C
- Çözüm:
return;değer döndürmeden fonksiyonu sonlandırır; oyun bittiğinde tıklama işlenmez. - İlgili Konu: 3.3. return ile Değer Döndürme
Soru 4: Doğru Cevap: E
- Çözüm: Üç ifade de modüler fonksiyon kullanımını doğru tanımlar.
- İlgili Konu: 3.5. Modüler Kod ve Oyun Mimarisi
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Mozilla Developer Network. (n.d.). Functions. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
- Mozilla Developer Network. (n.d.). return. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
- Mozilla Developer Network. (n.d.). Scope. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Glossary/Scope
- p5.js Foundation. (n.d.). p5.js reference. https://p5js.org/reference/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Ana Başlık 4. Oyun Döngüsü, FPS ve frameRate
Amaç: Oyun döngüsü ile FPS/frameRate ilişkisini öğreterek animasyon zamanlamasının temelini kurmak.
Öğrenme Çıktıları:
- Oyun döngüsünün update–draw ritmini açıklar.
- FPS kavramını tanımlar.
- frameRate ile hedef FPS değerini ayarlar.
- Düşük FPS’in harekete etkisini tartışır.
Anahtar Sözcükler: oyun döngüsü, FPS, frameRate, frame, zamanlama
Giriş
Döngü ve fonksiyonlarla sketch modülerleştikten sonra hareketin “ne kadar hızlı?” sorusu belirir. Oyun döngüsü her frame’de güncelleme ve çizimi yineler; saniyedeki frame sayısı FPS’dir. p5.js frameRate ile hedef hızı ayarlar; cihaz meşgulse gerçek FPS düşebilir.
Bu ana başlık döngü–FPS ilişkisini ve frameRate kullanımını kurar. Frame başına sabit piksel eklemenin farklı makinelerde farklı hız üretmesi sorunu bir sonraki ana başlıkta deltaTime ile çözülür. Bundan sonra gelen alt başlıklarda önce veri modeli, sonra hamle kuralı, en sonda çizim ve etkileşim kurulur. Her yeni fonksiyon mümkün olduğunca küçük bir örnekte çalıştırılır; böylece hatanın kaynağı daha kolay bulunur. Anlatımda önce ilgili yapının ne işe yaradığı açıklanır, ardından kod satır satır okunur. Terimler ilk geçtikleri yerde kısa bir tanımla verilir; gerekirse tablo veya görsel ile desteklenir. Örnek sketch’ler tek bir mekaniğe odaklanır; böylece yan konular okumayı dağıtmaz. Parametreleri değiştirip yeniden çalıştırmak, kuralın sınırını görmenin en hızlı yoludur. Bu ana başlığın çıktısı, sonraki oyunda yeniden kullanılabilecek bir iskelet oluşturur. Kod okumada izlenen sıra, veri modelinden başlayıp güncelleme ve çizime doğru ilerler.
4.1. Oyun Döngüsüne Genel Bakış
Tanım: Oyun döngüsü (game loop) — Oyunun çalışma süresince tekrarlanan güncelleme döngüsüdür; tipik adımlar girdi okuma, mantık güncelleme ve çizimdir.
p5.js sketch'inde döngü şu biçimde özetlenebilir:
setup()— tuval boyutu, başlangıç değişkenleri, bir kerelik ayarlar.draw()— her frame'de: arka plan, nesne konumlarının güncellenmesi, çizim.- p5.js, sketch durdurulana kadar 2. adımı sürekli tekrarlar.
Önceki bölümlerdeki numaralı akış bu yapıyı doğrusal biçimde anlatmıştı; burada vurgu, draw() gövdesinin hem güncelleme hem çizim taşıyabileceğidir. Küçük örneklerde ikisi aynı fonksiyonda yazılır; büyük projelerde guncelle() ve ciz() gibi ayrı fonksiyonlara bölünmesi modülerlik sağlar (önceki bölümlerdeki fonksiyon kavramı).
setup() ile draw() arasındaki ayrım yalnızca sözdizimsel değildir; performans açısından da anlamlıdır. createCanvas(), görsel yükleme veya büyük dizi oluşturma gibi maliyetli işlemler setup() içinde bir kez yapılır; aynı işlemler yanlışlıkla draw() içine yazılırsa her frame'de tekrarlanır ve FPS düşer. Bu nedenle bir sketch yavaş çalıştığında ilk kontrol noktası, draw() gövdesinde her frame gerekmeyen bir işlemin bulunup bulunmadığıdır.
Kod bloğu: Her frame'de konumunu sabit adımla ilerleyen basit top.
Kod 1.
let topX = 50;let topY = 200;const TOP_YARICAP = 25; function setup() { createCanvas(500, 300); noStroke();} function draw() { background(30, 35, 50); topX = topX + 3; // Her frame 3 piksel sağa if (topX > width + TOP_YARICAP) { topX = -TOP_YARICAP; } fill(255, 200, 80); ellipse(topX, topY, TOP_YARICAP * 2, TOP_YARICAP * 2);}Bu kod çalışır; ancak hız, saniyede kaç frame üretildiğine bağlıdır. Bir sonraki alt bölümlerde bu bağımlılık ölçülür ve giderilir.
Güncelleme ve çizim ayrımı: Modüler kod yazımında (Bölüm 2'in 3. ana başlığı) draw() gövdesi inceltilir:
Kod 2.
function draw() { background(30, 35, 50); guncelleTop(); cizTop();} function guncelleTop() { topX = topX + 3; if (topX > width + TOP_YARICAP) { topX = -TOP_YARICAP; }} function cizTop() { fill(255, 200, 80); ellipse(topX, topY, TOP_YARICAP * 2, TOP_YARICAP * 2);}«Konum değiştir» ile «ekrana çiz» ayrıldığında hata ayıklama kolaylaşır: top görünmüyorsa cizTop, yanlış hızda gidiyorsa guncelleTop incelenir. deltaTime eklendiğinde yalnızca guncelleTop içindeki formül değişir; çizim aynı kalır.
4.2. FPS ve frameRate()
Tanım: FPS (frames per second — saniyedeki frame sayısı) — Bir saniyede draw() fonksiyonunun kaç kez çalıştığının ölçüsüdür. p5.js bağlamında frame kelimesi geometrik kare anlamında değil, draw() çağrısının bir tekrarı anlamında kullanılır.
p5.js varsayılan olarak hedef frame hızını 60 FPS civarında tutmaya çalışır; donanım ve sketch yükü buna ulaşmayı engelleyebilir. Hedef hız frameRate(saniyeBasinaFrame) ile ayarlanır:
Tablo 1.
| İfade | Anlam | Örnek sonuç |
|---|---|---|
frameRate(60) |
Hedef 60 FPS | Çoğu monitörde akıcı hareket |
frameRate(30) |
Hedef 30 FPS | Daha düşük yük, daha seyrek güncelleme |
frameRate() (argümansız) |
Ölçülen anlık FPS | Ekranda gösterilebilir (ör. 58.2) |
Kod bloğu: FPS değerini ekranda gösterme.
Kod 3.
function setup() { createCanvas(400, 200); frameRate(60);} function draw() { background(40); fill(255); textSize(18); textAlign(LEFT, TOP); text("Olculen FPS: " + nf(frameRate(), 0, 1), 15, 15);}nf(sayi, solBasamak, sagBasamak) p5.js fonksiyonudur; ondalıklı (veya tam) sayıyı biçimlendirilmiş metne çevirir. Üç parametrenin anlamı:
Tablo 2.
| Parametre | Rol | Bu örnekte |
|---|---|---|
sayi |
Biçimlenecek değer | frameRate() → örn. 58.273… |
solBasamak |
Ondalık noktanın solundaki basamak sayısı (gerekirse başa 0 ekler) |
0 → sola sıfır doldurma yok; 58 olduğu gibi kalır |
sagBasamak |
Ondalık noktanın sağındaki basamak sayısı (yuvarlanır) | 1 → tek ondalık: "58.3" |
nf(frameRate(), 0, 1) bu yüzden ekranda 58.273 yerine 58.3 gibi kısa bir metin üretir. Diğer örnekler:
Tablo 3.
| Çağrı | Sonuç (yaklaşık) | Açıklama |
|---|---|---|
nf(58.273, 0, 1) |
"58.3" |
Sağda 1 basamak |
nf(58.273, 0, 0) |
"58" |
Ondalık yok |
nf(7, 3, 0) |
"007" |
Solda 3 basamak; başa sıfır |
nf(3.14159, 1, 2) |
"3.14" |
Sağda 2 basamak |
Argümansız çağrılan frameRate() o anda ölçülen ortalama frame hızını verir; sketch ağırlaştıkça değer hedefin altına düşebilir. nf yalnızca gösterimi düzenler; FPS hesabını değiştirmez.
Bilgi: frameRate() fonksiyonunun iki kullanımı vardır: bir sayı verilerek çağrıldığında (frameRate(60)) yalnızca hedef FPS'i belirler; argümansız çağrıldığında (frameRate()) ise o anki ölçülen değeri döndürür. Gerçek FPS donanıma ve çizim maliyetine bağlıdır; mobil veya düşük güçlü cihazlarda 60 hedefi her zaman tutturulamayabilir; bu nedenle hareket formülünde deltaTime kullanmak daha güvenilirdir.
Ekran, yenileme hızı (Hz) ve FPS
Oyunun ürettiği FPS ile monitörün yenileme hızı aynı şey değildir. Yenileme hızı hertz (Hz) cinsinden ölçülür: ekranın saniyede kaç kez yeni bir görüntü çizdiğini söyler. FPS ise yazılımın (burada draw()’ın) saniyede kaç frame hesapladığını söyler. İkisi yakın olsa da zincirin iki halkasıdır: oyun frame üretir → monitör o frame’leri (veya aralarından seçtiklerini) gösterir.
Tablo 4.
| Kavram | Birim | Ne ölçer? | Tipik değerler |
|---|---|---|---|
| Yenileme hızı | Hz | Monitörün saniyedeki tarama / yenileme sayısı | 60, 75, 120, 144, 165, 240… |
| FPS | frame/s | Oyunun / sketch’in saniyede ürettiği frame sayısı | Hedef 30–60 (p5); oyunlarda 60–240+ |
Çoğu ofis ve dizüstü ekranı hâlâ 60 Hz’tir. Oyun / spor odaklı monitörlerde 120–144 Hz yaygındır; üst segmentte 240 Hz ve üzeri görülür. Telefon ve tablet ekranlarında da 90 / 120 Hz paneller sıklaşmıştır. Tarayıcılar çizimi çoğu zaman monitörün yenileme döngüsüyle eşlemeye çalışır (vsync benzeri davranış): böylece yırtılma (tearing) azalır, fakat oyun FPS’i paneli aşsa bile ekranda o kadar “fazla” frame görünmeyebilir — fazlası atılır veya birleştirilir.
Bu yüzden frameRate(60) masaüstünde sıkça doğal bir hedeftir. Daha yüksek Hz’li monitörde frameRate() çağrılmazsa p5.js daha yüksek FPS’e çıkmaya çalışabilir; frame başına sabit piksel ekleyen hareket o zaman bile farklı tempo üretir. Hedefi açıkça vermek paneller arası farkı azaltır; asıl güvenilir çözüm yine deltaTime’dır (sonraki alt başlıklar).
Bilgi — sinema ve “saniyede 24 kare”: Hareketli görüntünün kültüründe klasik sinema filmi uzun süre yaklaşık 24 fps ile özdeşleşmiştir (sesli dönem standardı; sessiz dönemde 16–18 fps civarı da yaygındı). Televizyonda bölgeler arası farklar vardı (ör. birçok ülkede ~25 veya ~30 fps’lik yayın aileleri). Oyunlar ise etkileşim istediği için genelde sinemadan daha yüksek FPS hedefler: 30 “oynanabilir”, 60 “akıcı”, rekabetçi / yüksek yenilemeli kurulumlarda 120+ sıkça istenir. Yani “kaç fps iyi?” sorusunun cevabı ortama göre değişir — film izlemek ile nişancı oyunu oynamak aynı ihtiyaç değildir.
Oyunlarda FPS neden önemli?
- Akıcılık: Düşük ve dalgalı FPS, hareketi kesik kesik gösterir; özellikle kamera dönünce veya kalabalık sahnelerde rahatsız eder.
- Tepki hissi: Daha sık çizilen frame, fare / dokunuş sonucunun ekranda daha erken görünmesine yardımcı olabilir (giriş gecikmesi yalnızca FPS’e bağlı değildir; yine de düşük FPS gecikmeyi büyütür).
- Adalet ve tutarlılık: Frame’e bağlı fizik / hareket varsa yüksek FPS’li oyuncu avantaj (veya dezavantaj) yaşayabilir — bu ana başlığın asıl teknik kaygısı budur.
- Okunabilirlik: Hızlı nesnelerde (mermi, top) seyrek frame, “nereye gitti?” hissini bozar.
Bilgi — psikoloji / algı (kısa): İnsan gözü “tam olarak X fps’nin üstünü göremez” diye tek bir sihirli sayı yoktur; algı kişiye, sahneye ve önceki deneyime göre değişir. Birçok oyuncu 30 → 60 geçişini belirgin yumuşama olarak tarif eder; 60 → 144 geçişi özellikle fareyle nişan alma ve hızlı kamera hareketinde “daha yapışkan / daha az bulanık” hissedilebilir. Öte yandan çok yüksek FPS peşinde koşmak her zaman aynı oranda fayda getirmez: kazanç azalır, maliyet artar. Önemli olan çoğu zaman istikrardır — sürekli 55–60, bir anda 90’a çıkıp 40’a düşen bir grafikten daha öngörülebilir oynanış verir.
Yüksek FPS ve donanım
Daha fazla frame üretmek CPU/GPU’ya daha çok iş yükler: güç tüketimi ve ısınma artar, dizüstünde batarya daha çabuk biter, fanlar yükselir. Bu yüzden oyunlar sıklıkla FPS sınırı (ör. 60’a kilitleme), dikey senkron, veya “pil / performans” modları sunar. p5.js sketch’inizde gereksiz çizim veya setup’a ait işleri draw içine koymak da FPS’i düşürür — yani “yüksek FPS iyi” demek, sınırsız hedef demek değildir; yeterli ve stabil tempo + doğru hareket formülü (deltaTime) bu dersteki dengedir.
Yapay Zekâ Etkileşimi: FPS Düşüş Senaryosu Tahmini süre: 10–15 dakika.
Amaç: Sabit adım hareketinin FPS’e bağımlılığını görmek.
Adım 1: x += 3 ile giden bir kare düşünün; FPS 60’tan 30’a inince ne olur yazın.
Adım 2: Yapay zekâya aynı senaryoyu sorun; gerekçeyi karşılaştırın.
Adım 3: Bir sonraki ana başlıkta deltaTime’ın bu sorunu nasıl çözdüğünü tek cümleyle tahmin edin.
Pekiştirme: kavramı mini senaryoya bağlama
- Veri: Hangi değişkenler durumu tutuyor?
- Güncelleme: Her frame veya olayda ne değişiyor?
- Çizim: Görünenler hangi alanlardan geliyor?
- Kural: Oyuncu eylemi hangi koşulla kabul/red?
Eksik adımı (sınır, başlangıç değeri, tek seferlik olay) şimdi tamamlamak, sonra büyük sketch içinde aramaktan kolaydır.
Sıra Sizde: Bu ana başlıkta öğrenilenleri sonraki konuya bağlayan tek cümlelik bir köprü yazın: “Şimdi X biliyorum; bundan sonra Y için buna ihtiyacım var.” Cümle kurulamıyorsa eksik kalan alt başlıktaki örnek bir kez daha çalıştırılır.
Bu noktada kurulan kalıbın tek cümlelik bir oyun kuralına bağlanması, kavramın yerleşip yerleşmediğini gösterir; kural yazılamıyorsa ilgili alt başlığa dönülüp örnek bir kez daha çalıştırılır. Küçük bir parametre değişikliğinin çıktıyı nasıl etkilediğini not etmek, sonraki ana başlıktaki birleşik örneğe geçişi kolaylaştırır.
Özet
Oyun döngüsü, oyunun çalıştığı süre boyunca yinelenen girdi okuma, mantık güncelleme ve çizim adımlarıdır; p5.js’te bu ritmin görünen yüzü setup’tan sonra sürekli çağrılan draw fonksiyonudur. Küçük sketch’lerde güncelleme ile çizim aynı gövdede yazılabilir; ayrı fonksiyonlara bölündüğünde ise hata ayıklama kolaylaşır, çünkü görünmeyen nesne çizim tarafında, yanlış hızda ilerleyen nesne güncelleme tarafında aranır. Ayrım performans açısından da anlamlıdır: tuval oluşturma veya büyük veri hazırlama gibi maliyetli işler setup içinde bir kez yapılmazsa her frame tekrarlanır ve FPS düşer.
FPS, bir saniyede draw fonksiyonunun kaç kez çalıştığını gösterir; burada frame sözcüğü geometrik bir şekli değil, draw çağrısının tek bir tekrarını anlatır. frameRate(60) yalnızca hedefi bildirir; donanım ve çizim yükü bu hedefin tutturulmasını engelleyebilir. Argümansız frameRate() o anda ölçülen değeri döndürür ve nf ile biçimlendirilerek ekranda gösterilebilir. Monitörün hertz cinsinden yenileme hızı ile sketch’in ürettiği FPS ayrı büyüklüklerdir; tarayıcı çizimi yenileme döngüsüne eşlemeye çalıştığı için fazladan üretilen frame’ler ekrana yansımayabilir. Bu belirsizlik, frame başına sabit piksel ekleyen x += 3 gibi bir hareketin farklı cihazlarda farklı tempo üretmesinin nedenidir; hızı geçen gerçek süreye bağlayan deltaTime bir sonraki ana başlıkta ele alınır.
Neler Öğrendik?
Soru 1 FPS neyi ifade eder?
A) Saniyedeki frame sayısı
B) Tuval genişliği
C) Dosya boyutu
D) Renk kanalı
E) Git commit sayısı
Soru 2
frameRate(30) tipik olarak ne yapar?
A) Hedef FPS değerini yaklaşık 30’a çeker
B) Diziyi 30 elemana sabitler
C) HTML’i siler
D) Sesi kapatır
E) DNS’i yeniler
Soru 3
Sabit x += 5 hareketi düşük FPS’te genelde nasıl görünür?
A) Daha yavaş ilerler
B) Her zaman aynı gerçek hızda kalır
C) setup’ı siler
D) Rengi değiştirir
E) Klavyeyi kilitler
Soru 4 Oyun döngüsünün pedagojik özü nedir?
A) Sürekli güncelle–çiz tekrarı
B) Yalnızca bir kez setup
C) Yalnızca CSS
D) Yalnızca sunucu
E) Yalnızca SQL
Neler Öğrendik Yanıt Anahtarı
Soru 1: Doğru Cevap: A
- Çözüm: Frames per second.
- İlgili Konu: 4.2. FPS ve frameRate
Soru 2: Doğru Cevap: A
- Çözüm: Hedef FPS istenen değere çekilir.
- İlgili Konu: 4.2. FPS ve frameRate
Soru 3: Doğru Cevap: A
- Çözüm: Frame seyrelince sabit adım hareketi yavaşlatır.
- İlgili Konu: 4.1. Oyun Döngüsü
Soru 4: Doğru Cevap: A
- Çözüm: Update–draw ritmi süreklidir.
- İlgili Konu: 4.1. Oyun Döngüsü
Yararlanılan Kaynaklar
Bu içerik aşağıdaki kaynaklardan derlenerek hazırlanmıştır:
- McCarthy, L., Reas, C., & Fry, B. (2015). Make: Getting Started with p5.js. Maker Media.
- Nystrom, R. (2014). Game Programming Patterns. gameprogrammingpatterns.com — Game Loop bölümü.
- Nystrom, R. (2014). Game Programming Patterns. Genever Benning. https://gameprogrammingpatterns.com/
- Nystrom, R. (2014). Game loop. In Game Programming Patterns. https://gameprogrammingpatterns.com/game-loop.html
- p5.js Foundation. (n.d.). deltaTime. p5.js Reference. https://p5js.org/reference/p5/deltaTime/
- p5.js Foundation. (n.d.). frameRate. p5.js Reference. https://p5js.org/reference/p5/frameRate/
- Shiffman, D. (n.d.). Code! Programming with p5.js. The Coding Train. https://thecodingtrain.com/tracks/code-programming-with-p5-js
Bölüm 2 — Ek Sorular
Her ana başlık için 10 çoktan seçmeli değerlendirme sorusu. Bölüm sonu sınav veya pekiştirme amaçlıdır.
Ana Başlık 1 için 10 Soru
SORU 1: for başlığındaki üç parça sırasıyla neyi kontrol eder?
A) Dosya, ağ, bellek
B) Başlangıç, devam koşulu, artış/adım
C) Renk, stroke, fill
D) HTML, CSS, JS
E) Yalnızca fare olayları
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 1.1
SORU 2: draw() içinde while (true) yazmak genelde neye yol açar?
A) Animasyonu güvenle hızlandırır
B) Frame bitmez; animasyon yavaşlar veya tarayıcı kilitlenebilir
C) Yalnızca rengi değiştirir
D) for döngüsünü zorunlu kılar
E) Hiçbir etkisi olmaz
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 1.2
SORU 3: break ne yapar?
A) Programı yeniden başlatır
B) En içteki döngüyü hemen sonlandırır
C) Tuvali siler
D) FPS’i 60 yapar
E) String birleştirir
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 1.3
SORU 4: continue ne yapar?
A) Döngüyü başa sarıp tüm programı bitirir
B) Bu turdaki kalan gövdeyi atlayıp sonraki tura geçer
C) setup’ı siler
D) mousePressed zorunlu kılar
E) Diziyi sıralar
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 1.4
SORU 5: «for, while ve Döngü Kontrolü» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 1.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 1.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 1.uygulama
SORU 8: Bu ana başlıkta (for, while ve Döngü Kontrolü) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 1.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 1.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 1.uygulama
Ana Başlık 2 için 10 Soru
SORU 1: 10×10 ızgarada iç içe for kaç hücre ziyaret eder?
A) 10
B) 20
C) 100
D) 1000
E) 2
Doğru cevap: C
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 2.1
SORU 2: Dama deseni için tipik ifade hangisidir?
A) satir * sutun
B) (satir + sutun) % 2
C) frameRate()
D) createCanvas
E) keyCode
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 2.2
SORU 3: sin animasyonda genelde ne sağlar?
A) Dosya indirme
B) −1…+1 arası yumuşak salınım
C) HTML bilgisini
D) APA atıfı
E) CSS seçici
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 2.3
SORU 4: Pac-Man’de her hayaletin yönünü sırayla hesaplamak hangi programlama fikrine örnektir?
A) Tek bir if ile tüm hayaletleri aynı anda yönetmek
B) Liste / dizideki her eleman için döngüyle aynı tür işlemi tekrarlamak
C) Yalnızca background çağırmak
D) createCanvas boyutunu değiştirmek
E) APA kaynakça yazmak
Doğru cevap: B
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 2.4
SORU 5: «İç İçe Döngüler, Izgara ve Animasyon» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 2.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 2.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 2.uygulama
SORU 8: Bu ana başlıkta (İç İçe Döngüler, Izgara ve Animasyon) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 2.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 2.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 2.uygulama
Ana Başlık 3 için 10 Soru
SORU 1: hedefCiz(); satırı ne yapar?
A) Fonksiyon tanımı yazar
B) Tanımlı hedefCiz fonksiyonunu çağırır / çalıştırır
C) Tuvali siler
D) Dizi oluşturur
E) FPS ölçer
Doğru cevap: B
Genel açıklama: Parantezli isim fonksiyon çağrısıdır; tanım değildir. İlgili Konu: 4.1. Fonksiyon Kavramı ve Sözdizimi
SORU 2: [Kod okuma] Aşağıdaki kod çalıştırıldığında ekrana yazdırılan değer nedir? Kod 1.
function topla(a, b) { return a + b;} let sonuc = topla(4, 7);// sonuc değişkeninin değeri soruluyorA) "47"
B) 11
C) true
D) undefined
E) 3
Doğru cevap: B
Genel açıklama: return a + b toplamı döndürür; sonuc 11 olur. İlgili Konu: 4.3. return ile Değer Döndürme
SORU 3: return a + b; ile return; arasındaki fark nedir?
A) İkisi de aynıdır
B) Biri değer döndürür, diğeri yalnızca fonksiyondan çıkar
C) Yalnızca setup() içinde kullanılabilirler
D) İkisi de tuval boyutunu değiştirir
E) İkisi de diziyi siler
Doğru cevap: B
Genel açıklama: return değer sonuç iletir; çıplak return erken çıkıştır. İlgili Konu: 4.3. return ile Değer Döndürme
SORU 4: Sketch'te tuval oluşturmak için createCanvas(400, 400) yazılmıştır; ancak fonksiyon adı yanlışlıkla function kurulum() olarak tanımlanmış ve içinde createCanvas çağrılmıştır. p5.js tuvali oluşturmaz. En olası neden nedir?
A) createCanvas yalnızca draw() içinde çalışır
B) p5.js otomatik olarak setup adlı fonksiyonu arar; farklı isim kullanıldığında başlangıç kodu çalışmaz
C) 400 piksel çok küçüktür
D) Dizi tanımlanmamıştır
E) background eksiktir
Doğru cevap: B
Genel açıklama: setup p5.js'in tanıdığı sabit başlangıç adıdır; isim değişince otomatik çağrılmaz. İlgili Konu: 4.1. Fonksiyon Kavramı ve Sözdizimi
SORU 5: Modüler kodda draw() içinde birçok yardımcı fonksiyon çağırmak neden tercih edilir?
A) FPS düşürmek için
B) Görevleri isimlendirilmiş parçalara ayırarak okunabilirliği artırmak için
C) Diziyi silmek için
D) Klavyeyi kapatmak için
E) Tuvali küçültmek için
Doğru cevap: B
Genel açıklama: Modülerlik bakım ve okumayı kolaylaştırır. İlgili Konu: 4.5. Modüler Kod ve Oyun Mimarisi
SORU 6: [Kod okuma] oyunBitti = true iken aşağıdaki mousePressed() çağrıldığında ne olur?
Kod 2.
function mousePressed() { if (oyunBitti) { return; } skor = skor + 1;}A) skor bir artar
B) skor değişmez; fonksiyon erken biter
C) draw() durur
D) Tuval silinir
E) oyunBitti false olur
Doğru cevap: B
Genel açıklama: return sonrası satırlar çalışmaz; skor güncellenmez. İlgili Konu: 4.3. return ile Değer Döndürme
SORU 7: [Kod okuma] Aşağıdaki draw() gövdesinde kaç kez hucreCiz çağrılır? (SATIR = 2, SUTUN = 2)
Kod 3.
function draw() { background(0); for (let satir = 0; satir < SATIR; satir = satir + 1) { for (let sutun = 0; sutun < SUTUN; sutun = sutun + 1) { hucreCiz(sutun * 40, satir * 40, 40, satir, sutun); } }}A) 1
B) 2
C) 4
D) 8
E) 16
Doğru cevap: C
Genel açıklama: 2×2 = 4 hücre; her biri bir fonksiyon çağrısı. İlgili Konu: 4.4. p5.js'te Yardımcı Çizim Fonksiyonları
SORU 8: yeniHedefKonumu() fonksiyonu Daire Tıklama'da hangi görevi toplar?
A) Skoru ekrana yazmak
B) Hedef koordinatlarını rastgele yeniden atamak
C) Tuvali silmek
D) Diziyi dolaşmak
E) while döngüsü koşulunu test etmek
Doğru cevap: B
Genel açıklama: Koordinat ataması tek fonksiyonda toplanır; tekrar azalır. İlgili Konu: 4.5. Modüler Kod ve Oyun Mimarisi
SORU 9: I. Kullanıcı tanımlı fonksiyonlarda camelCase örfi yaygındır.
II. draw yerine Draw yazmak p5.js davranışını değiştirmez.
III. Parametreli fonksiyon aynı kodu farklı verilerle tekrar kullanmayı kolaylaştırır.
Hangileri doğrudur?
A) Yalnız I
B) I ve III
C) Yalnız II
D) II ve III
E) I, II ve III
Doğru cevap: B
Genel açıklama: I ve III doğru. II yanlış; p5.js küçük harf draw arar. İlgili Konu: 4.1–4.3
SORU 10: hucreCiz(x, y, boyut, satir, sutun) içinde (satir + sutun) % 2 kullanılmasının amacı nedir?
A) FPS ölçmek
B) Hücre rengini satır/sütuna göre alternatif yapmak
C) Diziye push yapmak
D) Klavye okumak
E) Fonksiyonu silmek
Doğru cevap: B
Genel açıklama: Dama deseni parametreli hücre fonksiyonunda uygulanır. İlgili Konu: 4.4
Ana Başlık 4 için 10 Soru
SORU 1: FPS neyi ifade eder?
A) Saniyedeki frame sayısı
B) Tuval genişliği
C) Dosya boyutu
D) Renk kanalı
E) Git commit sayısı
Doğru cevap: A
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 4.1
SORU 2: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 3: Sabit x += 5 hareketi düşük FPS’te genelde nasıl görünür?
A) Daha yavaş ilerler
B) Her zaman aynı gerçek hızda kalır
C) setup’ı siler
D) Rengi değiştirir
E) Klavyeyi kilitler
Doğru cevap: A
Genel açıklama: Bu soru ana başlık kazanımını ölçer. İlgili Konu: 4.3
SORU 4: Aşağıdaki yaklaşımlardan hangisi oyun sketch’inde daha sağlam bir geliştirmedir?
A) Konu dışı teknolojiye (biçim/dil dışı) sapıp temel kuralı atlamak
B) Öğrenilen p5.js API’si ile ölçülebilir bir oyun kuralı eklemek
C) draw içinde createCanvas tekrarlamak
D) Skoru her frame koşulsuz artırmak
E) Hata ayıklamadan uzun kodu olduğu gibi bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme, öğrenilen araçlarla kural eklemeyi hedefler; alandan kopuk şıklar elenir. İlgili Konu: Pekiştirme
SORU 5: «Oyun Döngüsü, FPS ve frameRate» bağlamında hangisi daha iyi bir sonraki adım geliştirmedir?
A) Konu dışı bir CSS animasyonu eklemek
B) Mevcut sketch’e ölçülebilir bir kural (skor, sınır, durum) eklemek
C) Tuvali silip boş bırakmak
D) setup’ı tamamen kaldırmak
E) Rastgele sözdizimi hatası bırakmak
Doğru cevap: B
Genel açıklama: Geliştirme mevcut öğrenilen API ile kural ekler. İlgili Konu: 4.uygulama
SORU 6: Aşağıdaki hangi seçenek tipik bir çeldirici bug senaryosudur?
A) dist ile isabet, ardından skoru bir kez artırmak
B) draw içinde koşulsuz skor artışı
C) createCanvas’ı setup içinde bir kez çağırmak
D) background ile frame temizlemek
E) keyIsDown ile sürekli hareket
Doğru cevap: B
Genel açıklama: Koşulsuz artış her frame şişer — görünür bug. İlgili Konu: 4.uygulama
SORU 7: Kod okuma: if (x > width) { x = 0; } ne yapar?
A) Y’yi sıfırlar
B) X tuval sağını aşınca sola sarar
C) FPS’i sıfırlar
D) Fareyi kilitler
E) Diziyi temizler
Doğru cevap: B
Genel açıklama: Yatay sarma (wrap) kalıbı. İlgili Konu: 4.uygulama
SORU 8: Bu ana başlıkta (Oyun Döngüsü, FPS ve frameRate) hangi uygulama en uygundur?
A) Öğrenilen API’yi bilinçli yok sayıp rastgele hazır kütüphane çağırmak
B) Anlatılan kavramı küçük bir sketch’te görünür çıktıyla denemek
C) Konuyu yalnızca okuyup hiç kod yazmamak
D) Tuval boyutunu her frame rastgele değiştirmek
E) Hata ayıklamadan uzun kod kopyalamak
Doğru cevap: B
Genel açıklama: Seçenek konu başlığıyla örtüşür; diğerleri alandan kopuk. İlgili Konu: 4.uygulama
SORU 9: console.log ayıklamada asıl faydası nedir?
A) Tuval çözünürlüğünü artırır
B) Ara değerleri görüp yanlış varsayımı yakalamayı sağlar
C) Otomatik çarpışma ekler
D) draw’ı durdurur
E) Kaynakça üretir
Doğru cevap: B
Genel açıklama: Gözlemlenebilir ara durum. İlgili Konu: 4.uygulama
SORU 10: Bir fonksiyonu parametreli yazmanın faydası?
A) FPS’i kilitlemek
B) Aynı mantığı farklı argümanlarla yeniden kullanmak
C) setup’ı kaldırmak
D) HTML’i silmek
E) Rengi yasaklamak
Doğru cevap: B
Genel açıklama: Modülerlik ve yeniden kullanım. İlgili Konu: 4.uygulama
Ana Başlık 1 — Açık Uçlu
A1. «for, while ve Döngü Kontrolü» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «for, while ve Döngü Kontrolü» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.
Ana Başlık 2 — Açık Uçlu
A1. «İç İçe Döngüler, Izgara ve Animasyon» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «İç İçe Döngüler, Izgara ve Animasyon» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.
Ana Başlık 3 — Açık Uçlu
A1. draw() içinde 50 satırlık tek blok yerine fonksiyonlara ayırmanın bakım açısından faydalarını açıklayın.
Örnek yanıt unsurları: Okunabilirlik, hata ayıklama, yeniden kullanım, ekip çalışması.
Değerlendirme: En az iki gerekçe somut mu?
A2. setup yerine kurulum adlı bir fonksiyon tanımlansa p5.js sketch'inde ne beklenir? Neden?
Örnek yanıt unsurları: p5.js yalnızca belirli adları otomatik çağırır; tuval oluşmaz.
Değerlendirme: Yerleşik olay adı kavramı doğru mu?
A3. XOX tahtası için tahtaCiz ve tasCiz(x, y, tur) gibi iki fonksiyonun sorumluluklarını nasıl bölerdiniz?
Örnek yanıt unsurları: tahta = ızgara/hücre; taş = X veya O sembolü; parametrelerle konum.
Değerlendirme: Görev ayrımı net mi?
Ana Başlık 4 — Açık Uçlu
A1. «Oyun Döngüsü, FPS ve frameRate» konusundaki merkezi kavramı kendi cümlelerinizle açıklayın ve bunu somut bir mini oyun / sketch örneğine bağlayın.
A2. «Oyun Döngüsü, FPS ve frameRate» için küçük bir varyasyon tasarlayın (yeni kural, sınır durumu veya görsel geri bildirim). Hangi fonksiyonlar değişir? Madde madde yazın.
A3. Bu ana başlıkta sık yapılan bir yanlış varsayımı (yanlış indeks, sıra, durum veya veri modeli) seçin; neden hatalı olduğunu ve doğru yaklaşımı iki–üç cümleyle yazın.