T: tema · Z: kodu büyüt · S: konuşmacı notları · F: tam ekran · Esc: genel bakış · ⌂ ders haritası
OYUN GEOMETRİSİ VE FİZİĞİ · G9
Kamera Algoritmaları
Dünya–ekran dönüşümü, 2B takip kuralları, ekran sarsıntısı, çok hedefi kadraja sığdırma, üçüncü şahıs kamera kolu — “oyuncu neyi görmeli?”
PRESS ▶ TO START

Bu derste oyunun haritası 🗺️

  1. Kamera bir dönüşümdür — dünya ↔ ekran; fare dünyada nereyi gösteriyor; görünmeyeni çizmemek
  2. 2B takip: beş kural — kamera penceresi, ileri bakma, platforma oturma, yumuşatma, seviye sınırları
  3. Ekran sarsıntısı — travma modeli: neden kare, neden yumuşak gürültü
  4. Çok hedef — herkesi kadraja sığdırmak: sınır kutusu, merkez, ölçek
  5. Üçüncü şahıs kamera kolu — yörünge ve duvara çarpınca kısalan kol
  6. Her adımda — elle hesap → canlı demo → kod (JavaScript / Python / C#) → motor kaynak kodu
🎮 Bu dersin sonunda…

bir 2B oyun için sakin ve bilgilendirici bir takip kamerası, his veren ama baş döndürmeyen bir sarsıntı, çok oyunculu bir kadraj ve duvarlardan geçmeyen bir 3B kamera kolu yazabilecek; motorların kamera bileşenlerindeki ayarların ne yaptığını bilerek seçebileceksiniz.

🤔 ISINMA: EN İYİ KAMERA, FARK EDİLMEYEN KAMERADIR

Bir platform oyununda kamerayı en basit hâliyle yazdınız: karakter nerede, kamera orada. Oyunu denettiğiniz arkadaşınız beş dakika sonra “başım döndü” deyip bıraktı. Kamera görevini yapıyordu: karakter hep tam ortadaydı. Sorun ne?

  • Karakter saniyede iki kez zıplıyor; her zıplamada bütün dünya 130 piksel aşağı inip çıkıyor. Göz karakteri değil, sallanan arka planı izlemek zorunda kalıyor.
  • Karakter ortada olduğu için gittiği yönün yalnızca yarım ekranını görüyor; düşmanı son anda fark ediyor.
  • Kamera, karakterin her titremesini büyütüp ekrana yayıyor.
  • İyi bir kamera karakteri değil, oyuncunun görmesi gerekeni izler ve mümkün olduğunca az kıpırdar. Bunu sağlayan birkaç basit kural var; her biri iki-üç satır.

🎯 Bu konu için bilmeniz gerekenler

Yeşil = gerekli · kesikli = faydalı ama şart değil. Tıklayınca ilgili sunuma gider.

Neden?G6’da kamerayı “hedefe yumuşakça yaklaşan bir nokta” olarak yazdık. O tek satır bu sunumun yapı taşı; burada soru değişiyor: yaklaşılacak hedef neresi olmalı?
🧰 Kodlamadan korkuyorsanızBu sunumun tamamı toplama, çıkarma, min / max ve G6’daki yaklas fonksiyonundan ibaret. 3B kısmında tek yeni şey iki açıdan bir yön vektörü üretmek (cos ve sin); onu da hazır formül olarak kullanacağız.

Mini sözlük

world / screen spacedünya / ekran koordinatıOyun dünyasındaki konum / pencerede piksel konumu
viewport · cullinggörüş alanı · ayıklamaKameranın dünyada gördüğü dikdörtgen · dışında kalanı çizmeme
camera window · dead zonekamera penceresi · ölü bölgeKarakterin kamerayı kıpırdatmadan dolaşabildiği kutu
look-aheadileri bakmaKameranın karakterin gidiş (ya da bakış) yönüne doğru kayması
platform snappingplatforma oturmaDikeyde yalnızca karakter yere bastığında kamerayı hizalama
confiner · limitssınırlayıcı · sınırlarKameranın seviye dışını göstermesini engelleme
screen shake · traumaekran sarsıntısı · travmaDarbe hissi için kamerayı titretme · darbelerin biriktiği, zamanla sönen sayaç
framing · target groupkadrajlama · hedef grubuBirden çok hedefi ekrana sığdırma
orbit camera · spring armyörünge kamerası · kamera koluHedefin çevresinde dönen kamera · engele çarpınca kısalan görünmez kol
LEVEL 0
Kamera bir dönüşümdür
dünya ↔ ekran

Çizimle: kamera dünyanın bir parçasını ekrana taşır

DÜNYA (seviye; burada yalnızca 0 … 1.000 kısmı)01002003004005006007008009001.000kamera x = 500ölçek 1: 100 … 900ölçek 2: 300 … 700⭐🚪EKRAN (800 piksel), ölçek 10400800⭐🚪⭐ dünya 600 → (600 − 500) · 1 + 400 = 500🚪 dünya 100 → (100 − 500) · 1 + 400 = 0EKRAN (800 piksel), ölçek 20400800⭐⭐ dünya 600 → (600 − 500) · 2 + 400 = 600🚪 dünya 100 → ekranın dışında (görünen 300 … 700)

Dünya hiç kıpırdamaz; kamera yalnızca “nereye bakıyorum, ne kadar yakından” bilgisidir. Mavi çerçeve ölçek 1’de görünen dünya (500 ± 400), mor kesikli çerçeve ölçek 2’de (500 ± 200). Aynı yıldız (dünya 600) iki ekranda farklı yerde ve boyda görünür; kapı (dünya 100) ölçek 2’de kadraj dışında kalır. Sayılar sonraki slaytlardaki elle hesap tablosunun aynısı.

Problem: dünya ekrandan büyük

🎮 İki koordinat sistemi
  • Seviye 2.600 piksel genişliğinde; ekran 720. Karakter “x = 1.900”de: ekranın neresine çizilecek?
  • Dünya koordinatı: nesnelerin oyun dünyasındaki yeri. Fizik, çarpışma, YZ hep bununla çalışır.
  • Ekran koordinatı: pencerede piksel. Yalnızca çizim ve fare / dokunma bununla çalışır.
  • Kamera ikisi arasındaki çeviridir: “dünyanın şu noktası ekranın ortasında, şu ölçekte görünsün.”
  • Çeviri iki yönde gerekir: çizerken dünya → ekran; fareyle tıklarken ekran → dünya.
İlk akla gelen: her şeyi kaydır

Karakter sağa gidince bütün nesnelerin x’inden 5 çıkar.

  • Dünya koordinatları artık anlamsız: kapı “x = 800”de mi, yoksa şu an 312’de mi? Kayıt dosyası, ağ (G7), YZ: hepsi bozulur.
  • Her nesne için her kare çıkarma: binlerce nesnede israf.
  • Yakınlaştırma, döndürme, ikinci bir kamera (mini harita, bölünmüş ekran) eklemek imkânsızlaşır.
  • Küçük kayan nokta hataları birikir; nesneler birbirine göre kayar.

Doğrusu: dünya hiç kıpırdamaz. Kamera yalnızca iki-üç sayıdır (x, y, ölçek); çizim sırasında herkes aynı dönüşümden geçer.

Fikir: çıkar, çarp, ortala

$$\begin{aligned}\text{ekran} = {} &(\text{dünya} - \text{kamera}) \cdot \text{ölçek} \\ &+ \tfrac{1}{2}\,\text{ekran genişliği}\end{aligned}$$

  • Çıkar: nesnenin kameraya göre yeri.
  • Çarp: ölçek 2 ise her şey iki kat büyük.
  • Ortala: kameranın baktığı nokta ekranın ortasına gelsin.
  • Tersi (fare → dünya): aynı adımlar ters sırayla geri alınır: ortayı çıkar, ölçeğe böl, kamerayı ekle.
  • Görünen alan: kamera ± (ekran / 2) / ölçek. Dışındaki nesneyi çizmeye gerek yok (G2’deki ızgarayla: yalnızca o hücreleri sor).
  • y ekseni için aynısı; döndürme de eklenebilir (sarsıntıda kullanacağız).

Arayüz (can, puan, mini harita çerçevesi) bu dönüşümden geçmez: doğrudan ekran koordinatıyla çizilir.

Elle hesap: ekran 800 piksel; kamera x = 500’e bakıyor
soruhesapsonuç
dünya 600, ölçek 1 → ekran?(600 − 500) · 1 + 400500
dünya 600, ölçek 2 → ekran?(600 − 500) · 2 + 400600
dünya 100, ölçek 1 → ekran?(100 − 500) · 1 + 4000 (sol kenar)
fare ekranda 600, ölçek 2 → dünya?(600 − 400) / 2 + 500600 ✓
ölçek 1’de görünen aralık?500 ± 400100 … 900
ölçek 2’de görünen aralık?500 ± 200300 … 700

Paralaks: uzak arka planı kameranın yalnızca bir kesriyle kaydırın: (dünya − kamera · 0,3). Dağlar yavaş, ağaçlar hızlı kayar: derinlik hissi, tek çarpma.

Mini harita: aynı dünyayı ikinci bir kamerayla (küçük ölçek, sabit merkez) bir daha çizmek.

Kod: dünya ↔ ekran (1/2)

Kod: dünya ↔ ekran (2/2)

🎒 Kodu okuyalım

ifadene demekneden böyle
(dx - kamera.x) * kamera.zoom + width / 2çıkar, çarp, ortalaSıra önemli: önce ölçekleyip sonra çıkarırsanız kamera ölçekle birlikte “kayar”.
translate → scale → translatep5.js’te aynı üç adımDönüşümler sondan başa uygulanır: en son yazılan translate(-kamera…) noktaya ilk uygulanır.
push() / pop()dönüşümü sakla / geri alBir yığın (Yığınlar ve Kuyruklar). pop()’tan sonra çizilenler kameradan etkilenmez: arayüz.
ekrandanDunyaya(mouseX, mouseY)fare dünyada nereyi gösteriyorKameralı her oyunda tıklama, nişan alma, sürükleme bundan geçer. Unutulursa “kamera kayınca tıklamalar tutmuyor” hatası.
gorunenAlan()kameranın dünyadaki dikdörtgeniÇizimde ayıklama; ayrıca “ekran dışındaki düşmanlar uyusun”, “ekrana girince müzik başlasın” gibi kurallar.
Unity: LateUpdatekamerayı en son güncelleKarakter Update’te hareket eder; kamera ondan önce çalışırsa bir kare geriden gelir ve titrer.
ÖnermeDünya → ekran ve ekran → dünya dönüşümleri birbirinin tersidir: art arda uygulanınca başlanan noktaya dönülür. Ölçek z iken ekrandaki 1 piksel dünyada 1/z birimdir; görünen alan z² ile küçülür (ölçek 2: dörtte bir alan, dörtte bir nesne).

🌱 Isınma kodu: dünya → ekran

Tek satır: return (wx - camX) * zoom + screenW / 2;. Örnekler: (600, 500, 1, 800) → 500; (600, 500, 2, 800) → 600; (500, 500, herhangi, 800) → 400 (kameranın baktığı nokta hep ortada).

🌱 Isınma kodu: ekran → dünya

Adımları ters sırayla geri alın: return (sx - screenW / 2) / zoom + camX;. Kontrol: screenToWorld(worldToScreen(600, 500, 2, 800), 500, 2, 800) yine 600 vermeli.
LEVEL 1
2B takip: beş kural
kamera neyi izlemeli?

Çizimle: zıplayan karakter, sallanan dünya

kamera = karakter: her zıplamada bütün dünya sallanır🌳🏃yerde🌳🏃zıplamanın tepesi🌳🏃yerdekarakter hep ortada; zemin ve ağaç 135 piksel inip çıkıyorkamera penceresi: karakter pencerede kaldıkça kamera kıpırdamazpencere🌳🏃🏃🏃zıplama pencerenin içinde: zemin ve ağaç yerinden oynamazkenara değersekamera kayar

Solda kamera karakterin tam üstünde: karakter zıpladıkça bütün dünya aşağı-yukarı oynar; oyuncunun gözü yorulur. Sağda kameranın ortasında bir pencere var: karakter pencerenin içinde kaldıkça kamera kıpırdamaz, kenara değince kayar. Bu, birazdan kuracağımız beş kuraldan biri.

Problem: karaktere yapışık kamera

“Kamera = karakter”in dört kusuru
  • Zıplama: karakter zıpladıkça bütün dünya aşağı-yukarı sallanır. Demodaki zıplama yaklaşık 135 piksel: saniyede iki kez, ekranın yarısına yakın.
  • Önünü görememe: karakter ortada; gittiği yönde yalnızca yarım ekran var. Hızlı oyunda tepki süresi yetmez.
  • Titreme: karakterin her küçük hareketi (yön değiştirme, merdiven, düşman çarpması) ekranın tamamına yayılır.
  • Seviye dışı: karakter sol kenardayken ekranın sol yarısı boşluktur: israf edilen ekran ve bozulan büyü.
🎮 Otuz yıllık çözümler

Itay Keren 2015’teki GDC konuşmasında (“Scroll Back”, Kaynaklar) 1980’lerden bugüne yandan görünümlü oyunların kameralarını tek tek inceleyip ortak teknikleri adlandırdı. Bugün motorlardaki ayarların adları büyük ölçüde o sınıflandırmadan gelir.

  • Kamera karakteri değil, karakterden türetilen bir odak noktasını izler.
  • Odak, oyuncunun ihtiyacına göre kaydırılır: gittiği yön, bastığı zemin, yaklaşan tehlike.
  • Kamera gereksiz yere kıpırdamaz.
  • Her kural bağımsızdır; üst üste eklenir.

Beş temel kuralı sırayla kuracağız; her biri iki-üç satır.

Fikir: beş kural

kuralne yaparnasıl (yatay örnek)hangi kusuru giderir
1 · İleri bakmaodak, karakterin gidiş yönünde önündedirodak = karakter + yön · 170 (yön değişince yumuşakça geçer)önünü görememe
2 · Kamera penceresiodak, kameranın çevresindeki kutunun içindeyse kamera dururodak > kamera + 60 ise kamera = odak − 60 (solda tersi)titreme
3 · Platforma oturmadikeyde yalnızca karakter yere basınca hizalanıryerdeyse zemin = karakter.y; kamera zemine bakarzıplamada sallanma
4 · Yumuşatmahedefe ışınlanmaz, yaklaşırkamera = yaklas(kamera, hedef, yarı ömür, dt) (G6)ani sıçramalar
5 · Sınırlarseviyenin dışını göstermezkamera, [ekran/2, seviye − ekran/2] aralığına sıkıştırılırboş ekran
Elle hesap: pencere (yarı genişlik 60), kamera 100’de
odakpencere 40…160yeni kamera
150içinde100 (kıpırdamaz)
170sağ kenarı 10 aştı170 − 60 = 110
30sol kenarı 10 aştı30 + 60 = 90
Elle hesap: sınırlar (ekran 800, seviye 3.000)
istenenizinli aralık 400…2.600sonuç
100sol kenar taşar400
1.000içinde1.000
2.900sağ kenar taşar2.600

Seviye ekrandan darsa: kamerayı seviyenin ortasına sabitleyin.

Canlı: kuralları tek tek açıp kapatın 🎬

  1. Ekranı okuyun: üstte oyun; altta bütün seviye ve kırmızı çerçeveyle kameranın gördüğü kısım. Kırmızı artı = ekranın ortası. Mavi kesikli kutu = kamera penceresi; mor nokta = odak (ileri bakma); sarı kesikli çizgi = kameranın oturduğu zemin. Üst satırda kameranın kat ettiği yol ve dikey yön değiştirme sayısı.
  2. Hepsi açık (başlangıç): A / D ile koşup W ile platformlara çıkın. Zıplarken arka plana bakın: yerinde duruyor. Ancak yeni bir platforma basınca kamera yumuşakça oraya çıkıyor.
  3. “Platforma oturma”yı kapatın ve aynı yerde beş kez zıplayın: bütün dünya zıplıyor; “dikey yön değiştirme” sayacı 9–10 artıyor. Geri açın: hiç artmıyor.
  4. “İleri bakma”yı kapatın ve sağa koşun: karakter ekranın ortasının sağında (kamera geriden geliyor), önünüzde yarım ekrandan az yer var. Açın: karakter ortanın soluna geçer, önünüz açılır (fark ≈ 170 piksel). Yön değiştirin: odak (mor nokta) öbür tarafa yumuşakça geçer.
  5. “Kamera penceresi”ni kapatın, yerinizde A-D-A-D yapın: ekran sizinle birlikte titrer. Açın: mavi kutunun içinde kamera hiç kıpırdamaz.
  6. “Yumuşatma”yı kapatın: platforma basınca kamera bir karede atlar. “Seviye sınırları”nı kapatın ve sol kenara yürüyün: ekranın yarısı siyah.
🔎 DEMODA DENEYİN
  1. Ekranı okuyun: üstte oyun; altta bütün seviye ve kırmızı çerçeveyle kameranın gördüğü kısım. Kırmızı artı = ekranın ortası. Mavi kesikli kutu = kamera penceresi; mor nokta = odak (ileri bakma); sarı kesikli çizgi = kameranın oturduğu zemin. Üst satırda kameranın kat ettiği yol ve dikey yön değiştirme sayısı.
  2. Hepsi açık (başlangıç): A / D ile koşup W ile platformlara çıkın. Zıplarken arka plana bakın: yerinde duruyor. Ancak yeni bir platforma basınca kamera yumuşakça oraya çıkıyor.
  3. “Platforma oturma”yı kapatın ve aynı yerde beş kez zıplayın: bütün dünya zıplıyor; “dikey yön değiştirme” sayacı 9–10 artıyor. Geri açın: hiç artmıyor.
  4. “İleri bakma”yı kapatın ve sağa koşun: karakter ekranın ortasının sağında (kamera geriden geliyor), önünüzde yarım ekrandan az yer var. Açın: karakter ortanın soluna geçer, önünüz açılır (fark ≈ 170 piksel). Yön değiştirin: odak (mor nokta) öbür tarafa yumuşakça geçer.
  5. “Kamera penceresi”ni kapatın, yerinizde A-D-A-D yapın: ekran sizinle birlikte titrer. Açın: mavi kutunun içinde kamera hiç kıpırdamaz.
  6. “Yumuşatma”yı kapatın: platforma basınca kamera bir karede atlar. “Seviye sınırları”nı kapatın ve sol kenara yürüyün: ekranın yarısı siyah.

🔗 Başka gözle: etkileşimli anlatımlar ve yazılar

Aynı konuyu başka bir anlatımla, kendi elinizle oynayarak görmek çok işe yarar. Kartlar yeni sekmede açılır; çoğu İngilizce ama görsel ve etkileşimli.

Kod: beş kurallı takip kamerası (1/2)

Kod: beş kurallı takip kamerası (2/2)

🎒 Kodu okuyalım

ifadene demekneden böyle
ileri = yaklas(ileri, o.yon * 170, 0.25, dt)ileri bakma miktarı yumuşakça değişirYön değişince odak bir anda 340 piksel atlarsa kamera savrulur. Karakter durunca ileri korunur: kamera son bakılan yönde kalır.
odakX > hx + 60 → hx = odakX - 60pencerenin kenarı odağa yapışırİçerideyken hx hiç değişmez. Pencere genişledikçe kamera sakinleşir ama karakter kenara yaklaşır.
if (o.yerde) zemin = o.ydikey hedef = son basılan zeminZıplama boyunca zemin sabit: kamera kıpırdamaz.
o.y > zemin + 90emniyet: uzun düşüşte aşağıyı gösterPlatformdan atlayan karakter ekranın altından çıkmasın; oyuncu nereye düştüğünü görsün.
zemin - 50karakter ekranın ortasının biraz altındaPlatform oyununda tehlike ve hedef çoğunlukla yukarıdadır.
yarı ömür: yatay 0,06 · dikey 0,14eksen başına ayrı yumuşatmaYatay hareket hızlı ve sürekli: sıkı. Dikey geçişler seyrek ve büyük: yavaş ve yumuşak.
constrain(...) en sondasınırlar son sözü söylerYumuşatmadan önce yapılırsa kamera sınıra yaklaşırken yavaşlar; sonra yapılırsa sınırda temiz durur. İkisi de kullanılır.
ÖnermeKamera penceresi yarı genişliği h ise, karakterin ±h içindeki hareketi kamerayı hiç oynatmaz; pencere dışına taşan hareketin tamamı kameraya geçer. Platforma oturmayla, yüksekliği emniyet eşiğinden küçük her zıplamada kameranın dikey hareketi sıfırdır (demoda: 135 piksellik zıplama, 170 piksellik eşik).

Oyunlarda: Godot’nun Camera2D’si ve Mario’nun kameraları

Kaynak: Godot Engine 4.3, camera_2d.cpp (MIT lisansı). “FIXME” yorumu özgün koddan.

🎮 Satır satır ve oyun oyun
  • Drag margin: bizim kamera penceremiz; ekranın yarısının kesri olarak verilir (varsayılan 0,2). MIN / MAX çifti, iki if’imizin tek satırlık yazımı.
  • Limit: “görüş dikdörtgeni sınırı ne kadar aştıysa o kadar geri it”: bizim constrain.
  • Yumuşatma: c = hız · delta. G6’da “yarım düzeltme” dediğimiz doğrusal yaklaşım: küçük adımda iyi çalışır, büyük adımda oran 1’i aşabilir. Üstündeki yorum, motor geliştiricilerinin de bu satırla dertli olduğunu gösteriyor.
  • Super Mario Bros. (1985): kamera yalnızca ileri kayar; geri dönüş yok. Mario ekranın ortasını geçince kamera onunla hızlanır.
  • Super Mario World (1990): dikeyde platforma oturma; yatayda Mario’nun baktığı yöne göre iki ayrı odak çizgisi (ileri bakma); oyuncu omuz tuşlarıyla kamerayı elle kaydırabilir.
  • Bugün: Celeste oda oda kilitli kamera + oda içinde yumuşak takip kullanır; Hollow Knight bölgelere göre kamera kilitleri; hepsi bu beş kuralın karışımı.

🧪 Canlı laboratuvar: kamera penceresi

Başlangıç kodunda üstteki görüntü karakterin her titremesiyle sallanır ve “kat ettiği yol” alttakinin katları olur. Üç satır: if (targetX > camX + half) return targetX - half; · if (targetX < camX - half) return targetX + half; · return camX;. Örnek: (100, 170, 60) → 110; (100, 150, 60) → 100.

🌱 Isınma kodu: seviye sınırları

Kameranın sol kenarı camX - viewW / 2 en az 0, sağ kenarı camX + viewW / 2 en çok levelW olmalı: if (levelW <= viewW) return levelW / 2; sonra return Math.max(viewW / 2, Math.min(levelW - viewW / 2, camX));. Örnek: (100, 800, 3000) → 400; (2900, 800, 3000) → 2600.
Quiz 1 · 2B kamera
Platform oyununuzda oyuncular “zıplarken midem bulanıyor, platformları tutturamıyorum” diyor. Kamera her kare karakterin konumuna yumuşakça yaklaşıyor. En etkili düzeltme?
Sorun kameranın zıplamanın kendisini izlemesi: dünya her zıplamada inip çıkıyor ve platformlar ekranda hareket ettiği için mesafe kestirmek zorlaşıyor. Platforma oturmayla zıplama sırasında kamera yerinde kalır; platformlar ekranda sabit durur. Yumuşatmayı artırmak sallantıyı azaltır ama geciktirir ve karakter ekrandan taşabilir.

🎬 Ara: iyi bir 2B kamera nasıl yapılır?

How to Make a Good 2D Camera
Game Maker’s Toolkit (Mark Brown) · 11 dk 38 sn · YouTube’da aç

Beş kuralın oyunlardan örneklerle anlatımı: kamera penceresi, ileri bakma, platforma oturma, yumuşatma ve kamera bölgeleri. Itay Keren’in konuşmasının (Kaynaklar) özetini de içeriyor.

🤔 İzlerkenVideodaki oyunlardan hangisi bizim beş kuralımızdan hangisini kullanıyor? Kamera hangi durumlarda bilerek karakteri merkezden uzaklaştırıyor? Videoda bizim demoda olmayan bir teknik var mı?
LEVEL 2
Ekran sarsıntısı
travma modeli

Çizimle: travma ve sarsıntı zaman içinde

zaman (sn) →00,250,50,75100,511,52💥🔫🔫travma (doğrusal söner, 0,9/sn)sarsıntı = travma²

💥 = patlama (+0,5), 🔫 = mermi (+0,25). Mavi çizgi travma: her darbe ekler, saniyede 0,9 söner. Kırmızı çizgi kameranın gerçekten sarsılma miktarı: travmanın karesi. Tek patlamada travma 0,5 ama sarsıntı yalnızca 0,25; 0,1 ve 0,2 saniyede iki mermi daha gelince travma 0,82’ye, sarsıntı 0,67’ye çıkar (tek patlamanın 2,7 katı): ekran “kızışır”, sonra uzun ve hafif bir kuyrukla susar.

Problem: darbe hissi

🎮 Neden sarsıyoruz?
  • Patlama, sert iniş, ağır silah, alınan hasar: ekran bir an titrer ve oyuncu darbeyi hisseder. G6’daki “juice”un en güçlü baharatı.
  • Jan Willem Nijman (Vlambeer: Nuclear Throne, Luftrausers) 2013’teki “The art of screenshake” konuşmasında sıradan bir nişancıyı adım adım “iyi hissettiren” bir oyuna çevirdi; adımların çoğu kamerayla ilgiliydi.
  • İyi yapılırsa: güç, ağırlık, tehlike. Kötü yapılırsa: baş ağrısı, okunmayan ekran, kapatılan oyun.
İlk akla gelen: her kare rastgele kaydır

kamera.x += random(-8, 8); yarım saniye boyunca.

  • Kamera kayıp gider: rastgele adımlar birbirini götürmez; sarsıntı bitince kamera başka yerdedir. (Kaymayı kameraya eklememeli, çizimde üstüne koymalı.)
  • Sinek gibi titrer: her kare bağımsız rastgele sayı; kamera bir karede sağda, sonrakinde solda. Sallanma değil, parazit.
  • Birikmez: art arda beş patlama tek patlamayla aynı; ya da süreler çakışınca bir anda kesilir.
  • Aç / kapa: sarsıntı bir anda başlar, bir anda biter.
  • Kare hızına bağlı (G5, G6).

Squirrel Eiserloh’un 2016’daki GDC konuşmasında önerdiği model bunların hepsini üç satırla çözer: travma.

Fikir: travma biriktir, karesini kullan, gürültüyle yönlendir

  • Travma: 0 ile 1 arası tek bir sayı. Her darbe ekler (mermi +0,15, patlama +0,5); üst sınırı 1.
  • Sönme: travma her saniye sabit miktarda azalır (örneğin 0,9): kendi kendine biter.
  • Sarsıntı = travma² (ya da küpü). Kameranın kayması bununla orantılı.
  • Yön: her kare rastgele değil; zamanla yumuşakça değişen bir gürültüden (Perlin, Y15) okunur. x, y ve dönme için gürültünün farklı yerlerinden.
  • Üstüne koy: kayma kameranın konumuna eklenmez; çizim dönüşümüne eklenir. Travma 0 olunca kamera tam yerindedir.
  • Dönme: birkaç derecelik eğilme, kaymadan daha güçlü hissettirir.
Elle hesap: en büyük kayma 26 piksel
travmasarsıntı = travma²kayma (en çok)
0,25 (tek mermi)0,06251,6 piksel
0,5 (patlama)0,256,5
0,750,5614,6
1,0126
  • Neden kare? Küçük darbeler neredeyse görünmez (1,6 piksel), ama birikince katlanır: üç mermi art arda 0,75 → 14,6 piksel; tek merminin 9 katı. Aksiyon yoğunlaştıkça ekran “kendiliğinden” kızışır.
  • Sönüş de yumuşar: travma doğrusal iner (1 → 0,5 → 0), sarsıntı karesiyle (1 → 0,25 → 0): hızlı düşer, uzun ve hafif bir kuyrukla biter.
  • Sönme 0,9 / sn ise tam travma 1,1 saniyede söner.

Gürültü −1 ile +1 arasında gezdiği için gerçek kayma çoğu an tablodaki değerin altındadır; tablo üst sınırı verir.

Canlı: patlatın 💥

  1. Ekranı okuyun: üstte sahne; altında kırmızı travma çubuğu ve o anki sarsıntı; en altta son 4 saniyenin grafiği: kırmızı = travma, sarı = sarsıntı (travmanın kuvveti), mavi = kameranın yatay kayması.
  2. 1’e bir kez basın: travma 0,25; ekran belli belirsiz kıpırdar. Şimdi 1’e hızlıca dört kez basın: travma 1’e yaklaşır, sarsıntı çok daha fazla. Aynı darbe, biriken etki.
  3. 3’e basın ve grafiği izleyin: kırmızı çizgi düz iner; sarı eğri hızlı düşüp uzun bir kuyrukla söner.
  4. Kuvveti 1 yapın: küçük darbeler de belirgin sarsar; birikmenin etkisi azalır. 3 yapın: küçük darbeler kaybolur, yalnızca büyükler hissedilir.
  5. Kayma yönünü “her kare rastgele” yapıp 3’e basın: mavi eğri diken diken; ekran titriyor. “Yumuşak gürültü”ye dönün: mavi eğri dalga; ekran sallanıyor.
  6. “Dönme de ekle”yi kapatın: sarsıntı düzleşir. Açın: birkaç derecelik eğilme darbeyi “ağır” hissettirir.
🔎 DEMODA DENEYİN
  1. Ekranı okuyun: üstte sahne; altında kırmızı travma çubuğu ve o anki sarsıntı; en altta son 4 saniyenin grafiği: kırmızı = travma, sarı = sarsıntı (travmanın kuvveti), mavi = kameranın yatay kayması.
  2. 1’e bir kez basın: travma 0,25; ekran belli belirsiz kıpırdar. Şimdi 1’e hızlıca dört kez basın: travma 1’e yaklaşır, sarsıntı çok daha fazla. Aynı darbe, biriken etki.
  3. 3’e basın ve grafiği izleyin: kırmızı çizgi düz iner; sarı eğri hızlı düşüp uzun bir kuyrukla söner.
  4. Kuvveti 1 yapın: küçük darbeler de belirgin sarsar; birikmenin etkisi azalır. 3 yapın: küçük darbeler kaybolur, yalnızca büyükler hissedilir.
  5. Kayma yönünü “her kare rastgele” yapıp 3’e basın: mavi eğri diken diken; ekran titriyor. “Yumuşak gürültü”ye dönün: mavi eğri dalga; ekran sallanıyor.
  6. “Dönme de ekle”yi kapatın: sarsıntı düzleşir. Açın: birkaç derecelik eğilme darbeyi “ağır” hissettirir.

Kod: travma tabanlı sarsıntı (1/2)

Kod: travma tabanlı sarsıntı (2/2)

🎒 Kodu okuyalım

ifadene demekneden böyle
min(1, travma + miktar)darbeler toplanır, 1’de doyarÜst sınır olmazsa yüz patlama ekranı kullanılmaz yapar.
travma - SONME * dtzamanla doğrusal sönmedt ile: kare hızından bağımsız (G5).
travma * travmasarsıntı = travmanın karesiKüçük darbeleri bastırır, birikeni ödüllendirir. Küp daha da keskin.
noise(t), noise(t + 100)aynı gürültünün uzak iki yerix ve y aynı değeri okursa kamera yalnızca çaprazda sallanır. 100’lük ofset onları bağımsız yapar.
t = millis() / 1000 * 22gürültüde gezme hızıKüçük sayı: gemi gibi yalpalama. Büyük sayı: titreme. 15–30 arası “patlama” gibi durur.
translate(width/2 + kx, …)kayma çizime eklenirkamera.x değişmedi: takip mantığı sarsıntıdan habersiz. Sarsıntı bitince kamera tam yerinde.
arayüz pop()’tan sonracan çubuğu sarsılmazOkunabilirlik. (Bazı oyunlar arayüzü bilerek çok hafif sarsar.)
ÖnermeTravma modelinde sarsıntı her zaman sınırlıdır (en çok “en büyük kayma”), süreklidir (ani başlangıç ve bitiş yok; gürültü ve sönme sürekli) ve kameranın gerçek konumunu değiştirmez. Darbeler toplanarak birleşir: aynı anda kaç kaynak olursa olsun tek bir sayı yönetilir.

Oyunlarda: ne kadar, ne zaman ve kimin için?

🎮 Ustaların kuralları
  • Eiserloh (GDC 2016, “Juicing Your Cameras With Math”): travma modeli bu konuşmadan. Önerileri: 2B’de kayma ve dönme; 3B’de yalnızca dönme (kayma kamerayı duvarın içine sokabilir); gürültü olarak Perlin.
  • Nijman / Vlambeer: sarsıntıyı darbenin yönüne verin: silah ateşlenince kamera geriye teper; patlama kamerayı kendinden uzağa iter. Rastgele sarsıntıdan daha “fiziksel”.
  • Darbe duraklaması (hitstop): güçlü vuruşta oyunu 2–5 kare dondurmak; sarsıntıyla birlikte kullanılır (dövüş oyunları, Zelda, Hollow Knight).
  • Uzaklık: patlama uzaktaysa travmayı azaltın (Cinemachine Impulse bunu kendisi yapar).
  • Kumanda titreşimi aynı travma değerinden beslenebilir: tek sayı, iki çıktı.
Erişilebilirlik: kapatma düğmesi şart

Ekran sarsıntısı bazı oyuncularda mide bulantısı ve baş ağrısı yapar (hareket hassasiyeti); epilepsi ve denge bozukluklarında daha da ciddidir.

  • Ayarlara “ekran sarsıntısı: %0–100” sürgüsü koyun. Travma modelinde bu tek çarpmadır.
  • Celeste, Hades, Dead Cells, God of War, The Last of Us Part II: hepsinde sarsıntı ayarı var. Microsoft’un ve “Game Accessibility Guidelines”ın erişilebilirlik listelerinde temel madde.
  • Sarsıntı bilgi taşıyorsa (hasar aldım!) kapatıldığında yerine başka bir işaret koyun: kenar parlaması, ses, titreşim.
  • Ekran büyüdükçe (TV, VR) aynı piksel kayması daha rahatsız edicidir: kaymayı ekranın yüzdesi olarak tanımlayın. VR’da kamerayı oyuncunun iradesi dışında oynatmak neredeyse yasaktır.

Genel kural: sarsıntı tuz gibidir. Azı yemeği güzelleştirir; çoğu yenmez yapar.

🐍 Laboratuvar: sarsıntının bir karesi

Üç satır: travma = max(0, travma - sonme * dt) · sarsinti = travma * travma · return [travma, en_buyuk_kayma * sarsinti * gurultu]. Örnek: (1, 1, 0,1, 30, 1) → travma 0,9; sarsıntı 0,81; kayma 24,3. Başlangıç kodu travmayı hiç söndürmez ve karesini almaz: sarsıntı hiç bitmez.
Quiz 2 · ekran sarsıntısı
Oyununuzda makineli tüfek her mermide ekranı sabit 6 piksel sarsıyor; oyuncular “sürekli titreme yorucu, ama tek patlama da zayıf kalıyor” diyor. Travma modeline geçince ne değişir?
Travmanın karesi küçük darbeleri bastırır (0,15² = 0,02) ama darbeler toplandıkça sarsıntı hızla büyür; büyük tek darbe (0,6² = 0,36) hemen hissedilir. Doğrusal sönme sürekli ateşte bile travmayı dengede tutar. Böylece ekran, sahnedeki şiddetin toplamını yansıtır; her olayın sabit bir sarsıntısı olmaz.
LEVEL 3
Çok hedef
herkesi kadraja sığdırmak

Çizimle: ortalamaya değil kutunun ortasına bak

02004006008001.0001.200kutu + 2 · 100 pay = 1.200 → ölçek 800 / 1.200 = 0,67sınır kutusu 100 … 1.100🔴🟢🟡🔵ortalama 387,5kutunun ortası 600

Dört oyuncu x = 100, 150, 200 ve 1.100’de. Ortalamaları 387,5: kamera oraya bakarsa sağdaki 🔵 kadrajdan çıkar. Hepsini içine alan kutunun ortası 600: kalabalığa değil uçlara bakar. Kutu 1.000 genişliğinde; iki yandan 100 pay ile 1.200 → ekran 800 olduğuna göre ölçek 800 / 1.200 ≈ 0,67.

Problem ve fikir: sınır kutusu → merkez → ölçek

🎮 Tek karakter yoksa?
  • Dövüş / parti oyunları: Super Smash Bros., Brawlhalla, Towerfall: dört oyuncu aynı ekranda; hepsi görünmeli.
  • Aynı ekranda eşli oyun: iki oyuncu ayrılınca ne olacak?
  • Spor oyunları: top ve en yakın oyuncular.
  • Tek oyunculu: karakter + patron; karakter + hedef gösterilen kapı; ara sahnede konuşan iki kişi.

İlk akla gelen: konumların ortalamasına bak. Hedefler birbirinden uzaklaşınca uçtakiler kadrajdan çıkar; ayrıca üç oyuncu bir köşede toplanınca ortalama oraya kayar ve dördüncü kaybolur.

Üç adım
  • 1 · Sınır kutusu: hedeflerin en küçük ve en büyük x, y değerleri (G2’deki AABB).
  • 2 · Merkez: kutunun ortası (ortalama değil!): (min + max) / 2. Kalabalık bir köşe merkezi çekmez.
  • 3 · Ölçek: kutu + kenar payı ekrana sığsın: ölçek = ekran / (kutu + 2 · pay). İki eksen için ayrı hesapla; küçüğünü al (ikisi de sığsın).
  • Ölçeği [en uzak, en yakın] aralığına sıkıştır; kamerayı ve ölçeği yumuşakça yaklaştır (G6).
hedeflerin x’lerikutu + 2 · 100 payölçek (ekran 800)merkez
300, 700400 + 200 = 600800 / 600 = 1,33500
0, 1.6001.600 + 200 = 1.800800 / 1.800 = 0,44800
0, 5.0005.2000,15 → sınır 0,252.500

Son satır: ölçek alt sınıra takıldı; görünen genişlik 800 / 0,25 = 3.200: uçtakiler kadraj dışında. Oyunun buna bir cevabı olmalı (bir sonraki slayt).

Canlı: herkesi kadraja sığdır 🥊

  1. Ekranı okuyun: beyaz çerçeveli yeşil daire sizsiniz (W / A / S / D). Sarı kesikli kutu dövüşçülerin sınır kutusu. Sol altta arenanın tamamı ve kırmızı çerçeveyle kameranın gördüğü alan; yanında ölçek ve kadraj dışında kalanların sayısı.
  2. Öbürlerinin yanına gidin: kamera yakınlaşır (ölçek 1’in üstüne çıkar). Arenanın köşesine kaçın: uzaklaşır; herkes küçülür ama görünür.
  3. Uzaklaşma hızlı, yakınlaşma yavaş: köşeye kaçıp hemen dönün. Kamera sizi kaçırmadan açılır, sonra acele etmeden kapanır. İkisi aynı hızda olsaydı kamera sürekli “pompalardı”.
  4. “Sığdırmak için yakınlaştır”ı kapatın ve köşeye gidin: kamera ortalamaya bakıyor, siz kadraj dışındasınız (kırmızı sayaç).
  5. Kenar payını 0 yapın: dövüşçüler ekranın kenarına yapışır. 200 yapın: herkes ortada, küçük.
  6. “En uzak”ı 0,8 yapıp köşeye gidin: kamera daha fazla açılamıyor; biri dışarıda kalıyor. Gerçek oyunlar burada ne yapıyor?
🔎 DEMODA DENEYİN
  1. Ekranı okuyun: beyaz çerçeveli yeşil daire sizsiniz (W / A / S / D). Sarı kesikli kutu dövüşçülerin sınır kutusu. Sol altta arenanın tamamı ve kırmızı çerçeveyle kameranın gördüğü alan; yanında ölçek ve kadraj dışında kalanların sayısı.
  2. Öbürlerinin yanına gidin: kamera yakınlaşır (ölçek 1’in üstüne çıkar). Arenanın köşesine kaçın: uzaklaşır; herkes küçülür ama görünür.
  3. Uzaklaşma hızlı, yakınlaşma yavaş: köşeye kaçıp hemen dönün. Kamera sizi kaçırmadan açılır, sonra acele etmeden kapanır. İkisi aynı hızda olsaydı kamera sürekli “pompalardı”.
  4. “Sığdırmak için yakınlaştır”ı kapatın ve köşeye gidin: kamera ortalamaya bakıyor, siz kadraj dışındasınız (kırmızı sayaç).
  5. Kenar payını 0 yapın: dövüşçüler ekranın kenarına yapışır. 200 yapın: herkes ortada, küçük.
  6. “En uzak”ı 0,8 yapıp köşeye gidin: kamera daha fazla açılamıyor; biri dışarıda kalıyor. Gerçek oyunlar burada ne yapıyor?

Kod: kadraja sığdırma

🎒 Kodu okuyalım ve oyunlar

ifadene demekneden böyle
min / max döngüsüsınır kutusun hedef için n adım. Ortalama yerine kutu: aykırı tek hedef de hesaba girer.
+ 2 * PAYiki yandan boşlukHedefin merkezi değil gövdesi sığmalı; ayrıca oyuncu kenarın ötesini biraz görmeli.
min(width / w, height / h)iki eksenden dar olanGeniş ekranda yatay yayılım ucuz, dikey yayılım pahalıdır.
constrain(…, EN_UZAK, EN_YAKIN)ölçek sınırlarıÇok yakın: bulanık dev karakterler. Çok uzak: karınca.
iki farklı yarı ömürhızlı aç, yavaş kapatBilgi kaybı (kadraj dışı) estetikten önemli.
🎮 Sınıra takılınca
  • Super Smash Bros.: kamera belli bir ölçekten fazla açılmaz; kadraj dışına çıkan oyuncu bir büyüteç balonu içinde gösterilir; arenadan çok uzaklaşan elenir. Kamera sınırı, oyun kuralının parçasıdır.
  • Eşli macera oyunları (LEGO serisi): oyuncular ayrılınca ekran ikiye bölünür; yaklaşınca birleşir. Bölme çizgisi iki oyuncuyu birleştiren doğruya diktir.
  • Görünmez duvar: en eski çözüm: kadrajın kenarı oyuncuları durdurur (Contra, eski beat ’em up’lar).
  • Ağırlıklar: her hedefe önem verin: top 2, oyuncular 1, nakavt olan 0’a doğru sönsün. Kutu, ağırlığı düşen hedefi yavaşça bırakır.
  • Patron dövüşü: hedef grubu = oyuncu + patron. Patron ölünce ağırlığı sıfırlanır; kamera oyuncuya döner.

🐍 Laboratuvar: merkez ve ölçek

sol, sag = min(xs), max(xs) · merkez = (sol + sag) / 2 · olcek = ekran_w / ((sag - sol) + 2 * pay) · olcek = max(en_uzak, min(en_yakin, olcek)) · return [merkez, olcek]. Örnek: ([300, 700], 800, 100, 0,25, 1,5) → [500, 1,333…]. Tek hedef varsa kutu sıfır genişliktedir: ölçek = ekran / (2 · pay), sonra sınır.
Quiz 3 · çok hedef
Dört oyunculu parti oyununuzda kamera oyuncuların konumlarının ortalamasına bakıyor. Üç oyuncu sol alt köşede dövüşürken sağ üstteki dördüncü oyuncu ekrandan çıkıyor. Neden ve çözüm?
Ortalama, üç oyuncunun bulunduğu köşeye 3’e 1 ağırlıkla çekilir; tek kalan oyuncu merkezden uzak düşer. Sınır kutusunun ortası herkese eşit uzaklıktadır (uçlar belirler, kalabalık değil) ve ölçek kutudan hesaplandığı için kutu tanım gereği ekrana sığar.
LEVEL 4
Üçüncü şahıs kamera kolu
yörünge ve duvara çarpınca kısalan kol

Çizimle: duvara çarpan kamera kolu (üstten)

🧍🎥istenen yer: kol 120duvar (70’te)🎥kamera: 70 − 8 = 62pay 8hedef

Kamera karakterin 120 birim arkasında olmak istiyor ama 70’te duvar var. Hedeften istenen yere ışın atılır, duvar bulunur, kamera duvarın 8 birim önüne (62’ye) konur. Kol hızlı kısalır (duvarın içi bir kare bile görünmesin), engel kalkınca yavaşça uzar.

Problem ve fikir: kamera bir karakterdir

🎮 3B’de yeni dert: araya giren dünya
  • Üçüncü şahıs oyununda kamera karakterin arkasında ve yukarısında, sabit bir uzaklıkta durur; oyuncu fareyle / sağ çubukla çevresinde döndürür (yörünge).
  • Karakter sırtını duvara verince kameranın “olması gereken yer” duvarın içinde ya da öbür tarafındadır.
  • Sonuç: ekranı kaplayan bir duvar, modelin içinden görülen boşluk, kaybolan karakter. 3B oyunlardaki en bilinen kamera hatası.
  • 1996’da Super Mario 64 bu yüzden kamerayı oyunun içinde bir karakter yaptı: bulutun üstünde kamera tutan Lakitu. Kameranın da bir yeri, bir gövdesi, bir yolu vardır.
Fikir: görünmez bir kol
  • İstenen yer: hedef + yön · kol boyu. Yön iki açıdan gelir: sapma (sağ-sol) ve eğim (yukarı-aşağı).
  • Işın at (G3): hedeften istenen yere doğru. Arada engel var mı?
  • Varsa: kamerayı çarpma noktasının biraz önüne koy: kol kısalır.
  • Yoksa: kol tam boyunda.
  • Hızlı kısal, yavaş uza: duvarın içi tek kare bile görünmemeli; ama engel kalkınca kamera geriye süzülmeli, zıplamamalı.
  • Işın yerine küçük bir küre süpürmek daha sağlamdır: kameranın da “gövdesi” olur, ince direklere takılmaz, duvara yapışınca içini göstermez.
kolışınpaykamera uzaklığı
120engel yok8120
12070’te duvar870 − 8 = 62
12015’te duvar8en az 12 (alt sınır)

Alt sınırın da altında kalınıyorsa: karakteri saydamlaştır ya da birinci şahsa geç.

Canlı: sırtınızı duvara verin 🎥

  1. Ekranı okuyun: odaya yukarıdan bakıyoruz. Yeşil daire karakter (W / S ileri-geri, A / D dön); mavi kutu kamera; açık mavi alan kameranın gördüğü. Kesikli gri çizgi kolun istenen boyu; kalın mavi çizgi şu anki kol; sarı nokta ışının duvara çarptığı yer. Sol üstte sayılar.
  2. Açık alanda dönün: kol tam boyunda (120). Bir duvara geri geri yaklaşın (S): sarı nokta belirir; kamera hemen öne çekilir.
  3. Duvardan uzaklaşın (W): kol yavaşça uzar. Hızlı kısalıp yavaş uzamayı sayılardan izleyin.
  4. “Kamera çarpışması”nı kapatın ve sırtınızı duvara verin: kamera duvarın öbür tarafına geçer (kırmızı); gördüğü alan karakteri içermez. Sayaç, karakterin görünmediği süreyi tutar.
  5. Çarpışma açıkken dar koridora girin (ortadaki L biçimli duvarın içi) ve dönün: kol sürekli uzayıp kısalır. Gerçek oyunlar dar yerlerde kolu bilerek kısa tutar ya da kamerayı omuz üstüne alır.
  6. Kol boyunu 220 yapın: kamera daha çok şeye takılır. 40 yapın: neredeyse hiç takılmaz ama karakter ekranı kaplar. Kol boyu = görüş ile sorun arasındaki pazarlık.
🔎 DEMODA DENEYİN
  1. Ekranı okuyun: odaya yukarıdan bakıyoruz. Yeşil daire karakter (W / S ileri-geri, A / D dön); mavi kutu kamera; açık mavi alan kameranın gördüğü. Kesikli gri çizgi kolun istenen boyu; kalın mavi çizgi şu anki kol; sarı nokta ışının duvara çarptığı yer. Sol üstte sayılar.
  2. Açık alanda dönün: kol tam boyunda (120). Bir duvara geri geri yaklaşın (S): sarı nokta belirir; kamera hemen öne çekilir.
  3. Duvardan uzaklaşın (W): kol yavaşça uzar. Hızlı kısalıp yavaş uzamayı sayılardan izleyin.
  4. “Kamera çarpışması”nı kapatın ve sırtınızı duvara verin: kamera duvarın öbür tarafına geçer (kırmızı); gördüğü alan karakteri içermez. Sayaç, karakterin görünmediği süreyi tutar.
  5. Çarpışma açıkken dar koridora girin (ortadaki L biçimli duvarın içi) ve dönün: kol sürekli uzayıp kısalır. Gerçek oyunlar dar yerlerde kolu bilerek kısa tutar ya da kamerayı omuz üstüne alır.
  6. Kol boyunu 220 yapın: kamera daha çok şeye takılır. 40 yapın: neredeyse hiç takılmaz ama karakter ekranı kaplar. Kol boyu = görüş ile sorun arasındaki pazarlık.

Kod: kamera kolu ve yörünge

🎒 Kodu okuyalım

ifadene demekneden böyle
geri = { -cos(aci), -sin(aci) }karakterin baktığı yönün tersiKamera arkada. 3B’de bu, iki açıdan hesaplanan yön vektörüdür.
isinAt(karakter, geri, KOL)ışın karakterden kameraya doğruTersi (kameradan karaktere) yanlış sonuç verir: kamera zaten duvarın içindeyse ışın duvarın içinden başlar.
serbest - PAYçarpma noktasının biraz önüTam çarpma noktasında kameranın yakın kırpma düzlemi duvarı keser: duvarın içi görünür.
max(12, …)kolun alt sınırıKamera karakterin kafasının içine girmesin.
yarı ömür 0,02 / 0,25hızlı kısal, yavaş uzaAsimetrik yumuşatma: çok hedefli kameradaki “hızlı aç, yavaş kapat”ın aynısı.
min(kolBoyu, serbest)emniyet kemeriYumuşatma ne derse desin kamera engelin ötesine geçemez.
Python: eğim sınırı−30° … +70°Eğim ±90°’ye varırsa kamera tepetaklak olur ve “yukarı” yönü belirsizleşir.
ÖnermeKol kuralıyla kamera ile hedef arasındaki doğru üzerinde (pay kadar tolerans dışında) engel bulunmaz: hedef her zaman görünür. Maliyet kare başına bir ışın (ya da küre süpürme); sahne bir BVH ya da ızgarada tutuluyorsa (G2) logaritmik.

Oyunlarda: Godot’nun SpringArm3D’si ve 50 kamera hatası

Kaynak: Godot Engine 4.3, spring_arm_3d.cpp (MIT lisansı). Unreal’ın Spring Arm bileşeni ve Unity Cinemachine’in Deoccluder’ı aynı fikrin başka yazımlarıdır.

🎮 Satır satır ve ötesi
  • cast_direction * spring_length: bizim “geri yön × kol”. Godot’da kol düğümün yerel +Z ekseni boyunca uzanır.
  • Kamera çocuğu varsa ışın yerine kameranın görüş piramidi biçiminde bir şekil süpürülür (cast_motion): yalnızca merkezin değil, ekranın köşelerinin de duvara girmemesi için.
  • Kamera yoksa düz intersect_ray: bizim yazdığımız sürüm.
  • Super Mario 64 (1996): kamera bir karakter (Lakitu); oyuncu C tuşlarıyla kontrol eder. 3B kamera sorunlarının çoğu ilk kez burada görüldü ve adlandırıldı.
  • John Nesky (Journey), GDC 2014, “50 Game Camera Mistakes”: duvardan geçmek, karakteri kapatmak, oyuncunun elinden kontrolü almak, ani kesmeler… Kamera programlayan herkesin izlemesi gereken liste (Videolar).
  • Engeli yok etmek de bir çözümdür: kamerayla karakter arasına giren duvarı saydamlaştır (izometrik oyunlar, Baldur’s Gate 3) ya da karakterin siluetini duvarın üstüne çiz.
Quiz 4 · kamera kolu
Üçüncü şahıs oyununuzda kamera duvara çarpınca öne çekiliyor; ama karakter ince bir sokak lambasının yanından geçerken kamera her seferinde bir an için karakterin ensesine fırlayıp geri dönüyor. En uygun düzeltme?
Işın (ya da süpürülen küre) bir an için lambaya değiyor ve kol kısalıyor. İnce, görüşü gerçekte kapatmayan nesneler kamera için “engel” sayılmamalı: motorların hepsinde kamera çarpışması için ayrı bir katman / maske vardır (Godot’daki collision_mask, Unity’deki engelKatmani). Çarpışmayı kapatmak duvar sorununu geri getirir; kolu uzatmak sorunu artırır.
LEVEL 5
Hepsi bir arada
tam kod, araçlar, kapanış

📦 Tam kod: p5.js ile iyi bir 2B kamera

İskelet. kamerayiGuncelle “Kod: beş kurallı takip kamerası” slaytındaki fonksiyon.

🎮 Çalıştırın, kopyalayın, bozun

▶ Eksiksiz örneği aç — yaklaşık 75 satır: A / D yürü, W zıpla, X yere vur (sarsıntı); 1–5 beş kuralı açıp kapatır.

Deneyin:

  • İleri bakmayı hıza değil fareye bağlayın: kamera nişan alınan yöne kaysın (yukarıdan bakışlı nişancılar).
  • Fare tekerleğiyle yakınlaştırma ekleyin; tıklanan dünya noktasını yazdırın (ekran → dünya).
  • Arka plana iki paralaks katmanı ekleyin (0,3 ve 0,6 çarpanlarıyla).
  • Seviyeye “kamera bölgeleri” ekleyin: bir dikdörtgene girince kamera oraya kilitlensin (patron odası).
  • Ayarlara “sarsıntı %” sürgüsü ekleyin.

🧰 Motorlarda ve kütüphanelerde

Unity · CinemachinePosition Composer (Dead Zone, Damping, Lookahead) · Confiner 2D · Target Group + Group Framing · Impulse · Orbital Follow · DeoccluderBu sunumun bütün başlıkları birer bileşen. Kod yazmadan denenir; ayarların anlamı bu sunumda.
GodotCamera2D (drag margins, limits, position smoothing) · SpringArm3D + Camera3D · Phantom Camera eklentisiCamera2D’de pencere, sınır ve yumuşatma hazır; ileri bakma ve platforma oturma için odağı kendiniz taşıyın.
UnrealSpring Arm Component (Camera Lag, Do Collision Test) · Camera Shake (Perlin / dalga desenleri) · Player Camera ManagerKarakter şablonları kamera koluyla gelir.
p5.js / tuvalpush / translate / scale / rotate / pop · noise()Kamera üç satır dönüşüm; gerisi bu sunumdaki fonksiyonlar.
Okuyun / izleyinItay Keren: Scroll Back · Squirrel Eiserloh: Juicing Your Cameras · John Nesky: 50 Game Camera MistakesÜç konuşma, kamera tasarımının üç ana kaynağı (Kaynaklar).

Pratik kural: önce kamerayı hata ayıklama çizgileriyle yazın (pencere, odak, zemin çizgisi, görünen alan). Kamerayı ancak ne düşündüğünü görerek ayarlayabilirsiniz; bu sunumdaki demoların hepsi o çizgilerle başladı.

🤖 Bu konuyu bir YZ kod asistanıyla yazarken

Sık yapılan hatalar — kontrol edin
  • Kamerayı karakterden önce güncellemek (bir kare gecikme, titreme)
  • lerp(kamera, hedef, 0.1): kare hızına bağlı yumuşatma (G6)
  • Fare konumunu dünyaya çevirmeden kullanmak
  • Arayüzü kamera dönüşümünün içinde çizmek
  • Sarsıntıyı kameranın konumuna eklemek (kamera kayar gider)
  • Sarsıntıda her kare random(); sönme yok; üst sınır yok; ayar yok
  • Çok hedefte ortalama kullanmak; ölçeği sınırlamamak
  • 3B’de ışını kameradan karaktere atmak; kolu yavaş kısaltmak
İyi bir istek (prompt) örneği

“p5.js, kütüphane yok. 2B platform oyunu için kamera modülü: (1) kamera = { x, y, zoom }; dünya→ekran ve ekran→dünya fonksiyonları. (2) Takip, şu sırayla ve her biri ayrı bir bayrakla açılıp kapanacak şekilde: ileri bakma (170 piksel, yarı ömür 0,25 sn), kamera penceresi (±60), dikeyde platforma oturma (yere basınca hizala; 90 piksel düşüş / 170 piksel yükseliş emniyeti), kare hızından bağımsız yumuşatma (1 − 2^(−dt/h)), seviye sınırları. (3) Travma tabanlı sarsıntı: darbe(miktar), doğrusal sönme, sarsıntı = travma², p5 noise() ile kayma ve dönme; kameranın konumunu değiştirmesin. (4) Hata ayıklama: bir tuşla pencereyi, odağı ve zemin çizgisini çiz. (5) Test: yerinde 5 kez zıplayınca kamera.y değişmemeli; sarsıntı bitince kamera sarsıntıdan önceki konumunda olmalı.”

  • Kuralların sırasını ve sayılarını verin.
  • Hata ayıklama çizgilerini isteyin.
  • Ölçülebilir test verin: “zıplarken kamera.y sabit”.

💬 Tartışma soruları

Yanınızdakiyle 2 dakika konuşun, sonra sınıfça tartışalım
  1. Kamerasını sevmediğiniz bir oyun düşünün. Bu sunumdaki hangi kural eksikti ya da yanlış ayarlanmıştı? Kamerasını hiç fark etmediğiniz bir oyun? (Hangisi daha iyi?)
  2. Ekran sarsıntısı “his” katar ama bazı oyuncuları rahatsız eder. Varsayılan olarak açık mı kapalı mı olmalı? Rekabetçi oyuncular neden çoğu efekti kapatır?
  3. Kamerayı oyuncu mu kontrol etmeli, oyun mu? Sabit kameralı (ilk Resident Evil), tamamen serbest (çoğu üçüncü şahıs oyunu) ve yönlendirilen (God of War, Journey) kameraların oyuna etkisini karşılaştırın.
  4. Aynı ekranda dört oyuncu: kamerayı uzaklaştırmak mı, ekranı bölmek mi, oyuncuları kadraja hapsetmek mi? Her birinin hangi oyun türüne uyduğunu tartışın.
  5. Sinemada kamera hareketi anlam taşır (yakın çekim, sallanan el kamerası). Oyunlarda kameranın “anlam” için kullanıldığı örnekler sayın (patron ortaya çıkarken uzaklaşma, kovalamacada yakınlaşma, korku oyunlarında dar açı).

🚀 Proje ve araştırma önerileri

  1. [kolay] Kamera oyun alanı — Örnek kodu genişletin: her kural için sürgü (pencere genişliği, ileri bakma mesafesi, yarı ömürler). Üç hazır ayar: “Mario”, “Celeste”, “kötü kamera”. Arkadaşlarınıza hangisini sevdiklerini sorun.
  2. [kolay] Sarsıntı kataloğu — Aynı patlamayı altı farklı sarsıntıyla gösterin: rastgele / gürültü, doğrusal / kare / küp, yönlü tepme, dönmeli. Erişilebilirlik sürgüsü ekleyin.
  3. [orta] Kamera bölgeleri — Seviye editörüne dikdörtgen “kamera odaları” ekleyin: oda içinde yumuşak takip, odalar arasında yarım saniyelik geçiş (G6: smoothstep). Patron odasında kamera kilitlensin ve uzaklaşsın.
  4. [orta] Dört kişilik arena — Dört daire (ikisi klavyeden, ikisi bot): kadraja sığdırma + sınıra takılınca kadraj dışındaki oyuncuyu ekran kenarında okla gösterme.
  5. [zor] Dinamik bölünmüş ekran — İki oyuncu yakınken tek kamera; uzaklaşınca ekran, aralarındaki doğruya dik bir çizgiyle ikiye bölünsün (LEGO oyunları). Her yarıda ayrı kamera dönüşümü ve kırpma.
  6. [araştırma] Kamera çözümlemesi — Sevdiğiniz bir 2B oyundan 2 dakikalık video kaydedin; kare kare kameranın konumunu çıkarın (karakter–kamera farkının grafiği). Hangi kuralları kullanıyor? Keren’in sınıflandırmasıyla adlandırın.

Neler öğrendik? 🎒

  • Kamera bir dönüşümdür: ekran = (dünya − kamera) · ölçek + ekran / 2. Dünya kıpırdamaz; fare için tersini uygula; arayüz dönüşümün dışında.
  • 2B takip: karakteri değil, türetilmiş bir odağı izle. İleri bakma, kamera penceresi, platforma oturma, yumuşatma, sınırlar. Amaç: gereken bilgiyi göster, en az kıpırda.
  • Sarsıntı: travma biriktir, doğrusal söndür, karesiyle sars, yumuşak gürültüyle yönlendir, kameranın üstüne koy. Kapatma ayarı şart.
  • Çok hedef: sınır kutusu → ortası → sığdıran ölçek (iki eksenden dar olan). Hızlı aç, yavaş kapat. Sınıra takılınca oyunun bir cevabı olsun.
  • Kamera kolu: hedeften geriye ışın (ya da küre); çarparsa kolu kısalt; hızlı kısal, yavaş uza.
  • Ortak araç: G6’daki kare hızından bağımsız yaklaşma; ve hata ayıklama çizgileri.
  • Sonraki: G10 Üçgenleme ve Voronoi: noktaları birbirine bağlamak, haritayı bölgelere ayırmak ve zindan koridorları. Sonra Bölüm 7: oyunlarda yapay zekâ.

🎮 Bu sunumdaki oyunlar (1/2)

Adı geçen oyunu tanımıyorsanız: oyuncuların kullandığı wiki sayfası ve oyunu kısaca gösteren bir video. ▶ video slaydın üstünde açılır (Esc ile kapanır); 🎯 işaretli bağlantılar doğrudan bu sunumdaki konuya gider.

Super Mario Bros. 1985 · platform
Nintendo’nun yan kaydırmalı platform klasiği; zıplama hissi bugün hâlâ ölçüt.
Celeste 2018 · platform
Bir dağa tırmanış; zor ama cömert kontrol noktalı hassas platform oyunu.
Hollow Knight 2017 · metroidvania
El çizimi, böceklerin dünyasında geçen zorlu 2B keşif oyunu; çok küçük bir ekip yaptı.
The Legend of Zelda 1986– · aksiyon-macera
Nintendo’nun zindan ve bulmaca serisi; anahtar–kapı düzenleri seviye tasarımının klasiği.
Hades 2020 · aksiyon roguelike
Yeraltı dünyasından kaçmaya çalışan Zagreus; her denemede oda sırası değişir.

🎮 Bu sunumdaki oyunlar (2/2)

Adı geçen oyunu tanımıyorsanız: oyuncuların kullandığı wiki sayfası ve oyunu kısaca gösteren bir video. ▶ video slaydın üstünde açılır (Esc ile kapanır); 🎯 işaretli bağlantılar doğrudan bu sunumdaki konuya gider.

Dead Cells 2018 · aksiyon roguelike
Her ölümde yeniden dizilen bir şatoda geçen hızlı platform-dövüş oyunu.
God of War 2018 · aksiyon-macera
Kratos ve oğlu Atreus’un İskandinav yolculuğu; oyun baştan sona tek kesintisiz kamera çekimiyle akar.
The Last of Us 2013 · aksiyon-macera
Salgın sonrası Amerika’da Joel ve Ellie’nin yolculuğu; yoldaş YZ’si çok övüldü.
Resident Evil 4 2005 · korku / aksiyon
Omuz üstü kamerayı popülerleştiren korku-aksiyon oyunu.

Kaynaklar: videolar 🎬

Kaynaklar: kaynak kodu, yazılar ve belgeler 📚

NEXT LEVEL ▶
G10 · Üçgenleme ve Voronoi
çokgeni üçgenlere bölmek, Delaunay, Voronoi ve zindan koridorları
SONRAKİ SUNUM ▶