{"id":31141,"date":"2025-10-06T08:31:59","date_gmt":"2025-10-06T05:31:59","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/"},"modified":"2025-10-06T08:31:59","modified_gmt":"2025-10-06T05:31:59","slug":"typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/","title":{"rendered":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi"},"content":{"rendered":"<p><body><\/p>\n<p>Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.<\/p>\n<p>Modern web taray\u0131c\u0131lar\u0131, g\u00fc\u00e7l\u00fc ve etkile\u015fimli deneyimler sunma kapasitesine sahip geli\u015fmi\u015f platformlar haline geldi. Eskiden yaln\u0131zca masa\u00fcst\u00fc uygulamalarla s\u0131n\u0131rl\u0131 olan oyun geli\u015ftirme s\u00fcre\u00e7leri, g\u00fcn\u00fcm\u00fczde HTML5, CSS3 ve JavaScript gibi web teknolojileri sayesinde do\u011frudan taray\u0131c\u0131lar \u00fczerinden eri\u015filebilir hale geldi. Peki, neden taray\u0131c\u0131 tabanl\u0131 bir oyun geli\u015ftirmeyi d\u00fc\u015f\u00fcnmelisiniz? Bu sorunun cevab\u0131 asl\u0131nda olduk\u00e7a basit: eri\u015filebilirlik ve da\u011f\u0131t\u0131m kolayl\u0131\u011f\u0131. Bir taray\u0131c\u0131 tabanl\u0131 oyun, herhangi bir indirme veya kurulum gerektirmeden, sadece bir ba\u011flant\u0131ya t\u0131klayarak an\u0131nda oynanabilir. Bu, oyununuzu geni\u015f kitlelere ula\u015ft\u0131rmak i\u00e7in benzersiz bir avantaj sunar. Ayr\u0131ca, mobil cihazlardan masa\u00fcst\u00fc bilgisayarlara kadar geni\u015f bir cihaz yelpazesinde \u00e7al\u0131\u015fabilme potansiyeli de cabas\u0131.<\/p>\n<p>Endless runner (sonsuz ko\u015fu) oyunlar\u0131, basit ama ba\u011f\u0131ml\u0131l\u0131k yap\u0131c\u0131 mekanikleriyle \u00f6zellikle mobil platformlarda b\u00fcy\u00fck pop\u00fclarite kazanm\u0131\u015ft\u0131r. Temple Run, Subway Surfers gibi \u00f6rnekler, bu t\u00fcr oyunlar\u0131n ne kadar geni\u015f bir oyuncu kitlesine ula\u015fabilece\u011fini kan\u0131tlam\u0131\u015ft\u0131r. Bu t\u00fcr oyunlar, genellikle tek dokunu\u015f veya basit klavye kontrolleriyle oynanabilir ve s\u00fcrekli artan bir zorluk seviyesi sunarak oyuncular\u0131 me\u015fgul tutar. Bu basitlik, onlar\u0131 hem geli\u015ftirmesi nispeten kolay hem de olduk\u00e7a e\u011flenceli hale getirir. Geli\u015ftirme s\u00fcrecine yeni ba\u015flayanlar i\u00e7in harika bir \u00f6\u011frenme projesi sunarlar \u00e7\u00fcnk\u00fc temel oyun mekaniklerini, animasyonlar\u0131, \u00e7arp\u0131\u015fma tespitini ve skor sistemlerini uygulaman\u0131z\u0131 gerektirirler.<\/p>\n<p>Bu makalede, TypeScript kullanarak s\u0131f\u0131rdan bir taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirece\u011fiz. Neden TypeScript mi? JavaScript&#8217;in tip tan\u0131ml\u0131 bir \u00fcst k\u00fcmesi olan TypeScript, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli ve karma\u015f\u0131k projelerde kod kalitesini, okunabilirli\u011fini ve bak\u0131m\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131r\u0131r. Hata ay\u0131klamay\u0131 kolayla\u015ft\u0131r\u0131r, derleme zaman\u0131nda potansiyel hatalar\u0131 yakalar ve nesne y\u00f6nelimli programlama (OOP) prensiplerini daha sa\u011flam bir \u015fekilde uygulaman\u0131za olanak tan\u0131r. Ayr\u0131ca, modern geli\u015ftirme ara\u00e7lar\u0131yla harika bir uyum i\u00e7indedir ve giderek artan bir toplulu\u011fa sahiptir. Oyun geli\u015ftirme s\u0131ras\u0131nda kar\u015f\u0131la\u015f\u0131lan karma\u015f\u0131kl\u0131klar\u0131 y\u00f6netmek i\u00e7in TypeScript&#8217;in sundu\u011fu yap\u0131sal avantajlar paha bi\u00e7ilmezdir. Dolay\u0131s\u0131yla, sadece bir oyun de\u011fil, ayn\u0131 zamanda sa\u011flam ve \u00f6l\u00e7eklenebilir bir kod taban\u0131 olu\u015fturmay\u0131 da \u00f6\u011freneceksiniz.<\/p>\n<p>Haz\u0131rsan\u0131z, web&#8217;in g\u00fc\u00e7l\u00fc potansiyelini ke\u015ffetmeye ve kendi dijital ko\u015fu maceran\u0131z\u0131 yaratmaya ba\u015flayal\u0131m! Bu rehberin sonunda, sadece \u00e7al\u0131\u015fan bir oyun de\u011fil, ayn\u0131 zamanda modern web teknolojileri ve oyun geli\u015ftirme prensipleri hakk\u0131nda derinlemesine bilgi sahibi olacaks\u0131n\u0131z.<\/p>\n<h2 id=\"temel-konseptler-bir-endless-runner-nasil-calisir\">Temel Konseptler: Bir Endless Runner Nas\u0131l \u00c7al\u0131\u015f\u0131r?<\/h2>\n<p>Bir sonsuz ko\u015fu oyununun ard\u0131ndaki temel mekanikler olduk\u00e7a basittir, ancak bu basitlik etkili bir \u015fekilde uyguland\u0131\u011f\u0131nda ba\u011f\u0131ml\u0131l\u0131k yarat\u0131c\u0131 bir deneyim sunabilir. \u00d6ncelikle, her oyunun kalbinde bir &#8220;oyun d\u00f6ng\u00fcs\u00fc&#8221; yatar. Bu d\u00f6ng\u00fc, oyunun s\u00fcrekli olarak g\u00fcncellenmesini ve \u00e7izilmesini sa\u011flayan merkezi bir mekanizmad\u0131r. Tipik bir oyun d\u00f6ng\u00fcs\u00fc iki ana a\u015famadan olu\u015fur: g\u00fcncellemeler (update) ve \u00e7izimler (render). G\u00fcncelleme a\u015famas\u0131nda, oyuncunun konumu, engellerin h\u0131z\u0131, skor gibi oyunun t\u00fcm dinamik elemanlar\u0131 hesaplan\u0131r ve de\u011fi\u015ftirilir. \u00c7izim a\u015famas\u0131nda ise, bu g\u00fcncellenmi\u015f durum ekranda g\u00f6rsel olarak sunulur. Taray\u0131c\u0131 tabanl\u0131 oyunlarda, bu d\u00f6ng\u00fc genellikle <code>requestAnimationFrame<\/code> API&#8217;\u0131 kullan\u0131larak optimize edilir, bu da taray\u0131c\u0131n\u0131n ekran yenileme h\u0131z\u0131yla senkronize olarak p\u00fcr\u00fczs\u00fcz animasyonlar elde etmemizi sa\u011flar.<\/p>\n<p>Oyunun temel yap\u0131 ta\u015flar\u0131 &#8220;oyun nesneleri&#8221;dir. Bunlar genellikle oyuncu karakteri, engeller, arkaplan elemanlar\u0131 ve bazen toplanabilir \u00f6\u011feler (power-ups) gibi g\u00f6rsel ve mant\u0131ksal varl\u0131klard\u0131r. Her oyun nesnesinin kendine ait bir konumu, boyutu, h\u0131z\u0131 ve durumu bulunur. TypeScript kullan\u0131rken, bu nesneleri temsil etmek i\u00e7in s\u0131n\u0131flar (classes) olu\u015fturmak m\u00fckemmel bir yakla\u015f\u0131md\u0131r. \u00d6rne\u011fin, bir <code>Player<\/code> s\u0131n\u0131f\u0131, karakterin z\u0131plama mekaniklerini ve animasyonunu y\u00f6netirken, bir <code>Obstacle<\/code> s\u0131n\u0131f\u0131 engellerin hareketini ve \u00e7arp\u0131\u015fma \u00f6zelliklerini kontrol edebilir. Bu nesneler, oyun d\u00f6ng\u00fcs\u00fc i\u00e7inde s\u00fcrekli olarak g\u00fcncellenir ve \u00e7izilir.<\/p>\n<p>Sonsuz ko\u015fu oyunlar\u0131nda olmazsa olmaz mekaniklerden biri &#8220;\u00e7arp\u0131\u015fma tespiti&#8221;dir. Bu, oyuncu karakterinin bir engele \u00e7arp\u0131p \u00e7arpmad\u0131\u011f\u0131n\u0131 veya bir \u00f6\u011feyi toplay\u0131p toplamad\u0131\u011f\u0131n\u0131 anlamak i\u00e7in kullan\u0131l\u0131r. En yayg\u0131n \u00e7arp\u0131\u015fma tespit y\u00f6ntemlerinden biri, iki dikd\u00f6rtgenin (oyuncu ve engel) birbirine de\u011fip de\u011fmedi\u011fini kontrol etmektir (Axis-Aligned Bounding Box &#8211; AABB \u00e7arp\u0131\u015fma tespiti). E\u011fer bir \u00e7arp\u0131\u015fma tespit edilirse, oyunun &#8220;oyun bitti&#8221; (game over) durumuna ge\u00e7mesi, skorun kaydedilmesi veya ba\u015fka bir olay\u0131n tetiklenmesi gerekebilir.<\/p>\n<p>Oyunun &#8220;skor sistemi&#8221; ise oyuncunun ne kadar s\u00fcre hayatta kald\u0131\u011f\u0131n\u0131 veya ne kadar mesafe kat etti\u011fini takip eder. Genellikle zamanla veya ge\u00e7ilen engel say\u0131s\u0131yla orant\u0131l\u0131 olarak artar. Bu, oyuncuyu daha y\u00fcksek bir skor elde etmek i\u00e7in tekrar oynamaya te\u015fvik eden \u00f6nemli bir geri bildirim mekanizmas\u0131d\u0131r. Basit bir skor sayac\u0131, bu t\u00fcr oyunlar i\u00e7in ba\u015flang\u0131\u00e7ta fazlas\u0131yla yeterli olacakt\u0131r.<\/p>\n<p>Son olarak, t\u00fcm bu g\u00f6rsel elemanlar\u0131 ekranda g\u00f6stermek i\u00e7in &#8220;HTML5 Canvas&#8221; \u00f6\u011fesini kullanaca\u011f\u0131z. Canvas, JavaScript ile programatik olarak grafikler \u00e7izmenize olanak tan\u0131yan bir HTML \u00f6\u011fesidir. Dikd\u00f6rtgenler, daireler, \u00e7izgiler \u00e7izebilir, resimler y\u00fckleyebilir ve metinler g\u00f6sterebilirsiniz. Oyunumuzdaki her \u00e7izim i\u015flemi, Canvas&#8217;\u0131n 2D \u00e7izim ba\u011flam\u0131 (<code>CanvasRenderingContext2D<\/code>) arac\u0131l\u0131\u011f\u0131yla ger\u00e7ekle\u015ftirilecektir. TypeScript&#8217;in sundu\u011fu g\u00fc\u00e7l\u00fc tip sistemi, Canvas API&#8217;lar\u0131n\u0131 kullan\u0131rken hatalar\u0131 azaltmam\u0131za ve kodumuzu daha g\u00fcvenilir hale getirmemize yard\u0131mc\u0131 olacakt\u0131r. Bu temel konseptleri anlad\u0131\u011f\u0131m\u0131zda, kendi oyunumuzu in\u015fa etmek i\u00e7in sa\u011flam bir zeminimiz olacak.<\/p>\n<h2 id=\"proje-kurulumu-ve-ilk-adimlar-typescript-ortami-nasil-hazirlanir\">Proje Kurulumu ve \u0130lk Ad\u0131mlar: TypeScript Ortam\u0131 Nas\u0131l Haz\u0131rlan\u0131r?<\/h2>\n<p>Bir taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmeye ba\u015flamadan \u00f6nce, projemizin temelini olu\u015fturan bir geli\u015ftirme ortam\u0131n\u0131 kurmam\u0131z gerekiyor. TypeScript&#8217;in g\u00fcc\u00fcnden yararlanabilmek i\u00e7in \u00f6ncelikle Node.js ve npm (Node Package Manager) veya yarn kurulu olmal\u0131d\u0131r. Bunlar, TypeScript derleyicisini ve di\u011fer ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00f6netmemizi sa\u011flayacak ara\u00e7lard\u0131r. E\u011fer kurulu de\u011fillerse, Node.js&#8217;in resmi web sitesinden kolayca indirebilirsiniz.<\/p>\n<ol>\n<li><strong>Proje Dizini Olu\u015fturma ve Ba\u015flatma:<\/strong><br \/>\n            \u00d6ncelikle projemiz i\u00e7in bir klas\u00f6r olu\u015fturun ve terminal veya komut istemcisini kullanarak bu klas\u00f6re gidin. Ard\u0131ndan, npm&#8217;i kullanarak yeni bir proje ba\u015flat\u0131n:<\/p>\n<pre><code>\n                mkdir endless-runner\n                cd endless-runner\n                npm init -y\n            <\/pre>\n<p><\/code><br \/>\n            Bu komut, projenizin k\u00f6k dizininde temel bir <code>package.json<\/code> dosyas\u0131 olu\u015fturacakt\u0131r.<\/li>\n<li><strong>TypeScript ve Gerekli Paketleri Y\u00fckleme:<\/strong><br \/>\n            \u015eimdi, TypeScript derleyicisini ve gelecekte i\u015fimize yarayabilecek bir canl\u0131 sunucu (live-server) paketini kural\u0131m:<\/p>\n<pre><code>\n                npm install --save-dev typescript live-server\n            <\/pre>\n<p><\/code><br \/>\n            <code>--save-dev<\/code> bayra\u011f\u0131, bu paketlerin sadece geli\u015ftirme ortam\u0131nda kullan\u0131laca\u011f\u0131n\u0131 belirtir.<\/li>\n<li><strong>TypeScript Yap\u0131land\u0131rmas\u0131 (tsconfig.json):<\/strong><br \/>\n            TypeScript'i projenizde nas\u0131l derleyece\u011finizi belirtmek i\u00e7in bir <code>tsconfig.json<\/code> dosyas\u0131 olu\u015fturman\u0131z gerekir. Bu dosya, TypeScript derleyicisine (<code>tsc<\/code>) hangi dosyalar\u0131 derleyece\u011fini, \u00e7\u0131kt\u0131 dizinini ve hangi ECMAScript s\u00fcr\u00fcm\u00fcne d\u00f6n\u00fc\u015ft\u00fcrece\u011fini s\u00f6yler. Projenizin k\u00f6k dizininde a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131rarak varsay\u0131lan bir <code>tsconfig.json<\/code> dosyas\u0131 olu\u015fturabilirsiniz:<\/p>\n<pre><code>\n                npx tsc --init\n            <\/pre>\n<p><\/code><br \/>\n            Ard\u0131ndan, <code>tsconfig.json<\/code> dosyas\u0131n\u0131 a\u00e7\u0131n ve a\u015fa\u011f\u0131daki \u00f6nemli ayarlar\u0131 g\u00fcncelleyin (veya ekleyin):<\/p>\n<pre><code class=\"language-json\">\n{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",                     \/* \u00c7\u0131k\u0131\u015f JavaScript s\u00fcr\u00fcm\u00fcn\u00fc ayarlar *\/\n    \"module\": \"CommonJS\",                   \/* Mod\u00fcl \u00fcretme sistemini ayarlar *\/\n    \"outDir\": \".\/dist\",                     \/* \u00c7\u0131kt\u0131 dizinini ayarlar *\/\n    \"rootDir\": \".\/src\",                     \/* Giri\u015f dosyalar\u0131n\u0131n k\u00f6k dizinini ayarlar *\/\n    \"strict\": true,                         \/* T\u00fcm s\u0131k\u0131 tip kontrol se\u00e7eneklerini etkinle\u015ftirir *\/\n    \"esModuleInterop\": true,                \/* CommonJS\/ES mod\u00fcllerini birlikte \u00e7al\u0131\u015ft\u0131r\u0131r *\/\n    \"skipLibCheck\": true,                   \/* Bildirim dosyalar\u0131nda tip kontrol\u00fcn\u00fc atlar *\/\n    \"forceConsistentCasingInFileNames\": true \/* Ayn\u0131 dosya i\u00e7in b\u00fcy\u00fck\/k\u00fc\u00e7\u00fck harf kullan\u0131m\u0131nda tutarl\u0131l\u0131k sa\u011flar *\/\n  },\n  \"include\": [\"src\/**\/*.ts\"],               \/* Derlenecek dosyalar\u0131 belirler *\/\n  \"exclude\": [\"node_modules\"]               \/* Hari\u00e7 tutulacak dizinleri belirler *\/\n}\n            <\/pre>\n<p><\/code><br \/>\n            Bu ayarlar, TypeScript kaynak kodunuzu (<code>.ts<\/code> dosyalar\u0131) <code>src<\/code> klas\u00f6r\u00fcnden alacak, modern JavaScript'e (<code>ESNext<\/code>) derleyecek ve derlenmi\u015f JavaScript \u00e7\u0131kt\u0131lar\u0131n\u0131 <code>dist<\/code> klas\u00f6r\u00fcne yerle\u015ftirecektir.<\/li>\n<li><strong>HTML Yap\u0131s\u0131n\u0131 Olu\u015fturma (index.html):<\/strong><br \/>\n            Oyunumuzun \u00e7al\u0131\u015faca\u011f\u0131 temel HTML dosyas\u0131n\u0131, yani <code>index.html<\/code>'i projenizin k\u00f6k dizinine olu\u015ftural\u0131m. Bu dosya, oyunumuz i\u00e7in bir HTML5 Canvas elementi i\u00e7erecek ve derlenmi\u015f JavaScript kodumuzu y\u00fckleyecektir:<\/p>\n<pre><code class=\"language-html\">\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>TypeScript Endless Runner<\/title>\n    <style>\n        body {\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            min-height: 100vh;\n            margin: 0;\n            background-color: #222;\n            overflow: hidden; \/* Kayd\u0131rma \u00e7ubuklar\u0131n\u0131 gizle *\/\n        }\n        canvas {\n            border: 2px solid #fff;\n            background-color: #87CEEB; \/* G\u00f6ky\u00fcz\u00fc rengi *\/\n            display: block;\n        }\n\n        \/* Mobil uyumluluk i\u00e7in temel media query \u00f6rne\u011fi *\/\n        @media (max-width: 768px) {\n            canvas {\n                width: 95vw;\n                height: auto; \/* Oran\u0131 koru *\/\n            }\n        }\n        @media (max-width: 480px) {\n            canvas {\n                width: 100vw;\n                height: auto;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <canvas id=\"gameCanvas\" width=\"800\" height=\"400\">\n        Taray\u0131c\u0131n\u0131z Canvas'\u0131 desteklemiyor.\n    <\/canvas>\n    <script src=\".\/dist\/main.js\"><\/script>\n<\/body>\n<\/html>\n            <\/pre>\n<p><\/code><br \/>\n            Burada <code><canvas><\/code> elementi oyunumuzun g\u00f6rsel \u00e7\u0131kt\u0131s\u0131n\u0131 alaca\u011f\u0131 aland\u0131r. <code><script src=\".\/dist\/main.js\"><\/script><\/code> sat\u0131r\u0131 ise derlenmi\u015f TypeScript kodumuzu (ki bu <code>dist\/main.js<\/code> olacak) taray\u0131c\u0131ya y\u00fckler. CSS k\u0131sm\u0131, oyunun taray\u0131c\u0131da ortalanmas\u0131n\u0131 ve mobil cihazlarda ekran boyutuna uyum sa\u011flamas\u0131n\u0131 hedefleyen basit bir stil sa\u011flar. \u00d6zellikle <code>@media<\/code> sorgular\u0131, k\u00fc\u00e7\u00fck ekranlarda Canvas'\u0131n geni\u015fli\u011fini ayarlayarak oyunun responsive olmas\u0131n\u0131 sa\u011flar.<\/li>\n<li><strong>\u0130lk TypeScript Dosyas\u0131n\u0131 Olu\u015fturma (src\/main.ts):<\/strong><br \/>\n            \u015eimdi, <code>src<\/code> ad\u0131nda bir klas\u00f6r olu\u015fturun ve i\u00e7ine <code>main.ts<\/code> ad\u0131nda bir dosya ekleyin. Bu, oyunumuzun ana giri\u015f noktas\u0131 olacakt\u0131r:<\/p>\n<pre><code>\n                mkdir src\n                touch src\/main.ts\n            <\/pre>\n<p><\/code><br \/>\n            <code>src\/main.ts<\/code> dosyas\u0131na \u015fimdilik basit bir \"Merhaba D\u00fcnya\" kodu ekleyelim:<\/p>\n<pre><code class=\"language-typescript\">\nconsole.log(\"TypeScript Endless Runner'a Ho\u015f Geldiniz!\");\n\n\/\/ Canvas elementini alal\u0131m\nconst canvas = document.getElementById('gameCanvas') as HTMLCanvasElement;\nconst ctx = canvas.getContext('2d');\n\nif (ctx) {\n    ctx.fillStyle = 'red';\n    ctx.fillRect(50, 50, 100, 100); \/\/ K\u0131rm\u0131z\u0131 bir kare \u00e7iz\n    console.log(\"Canvas ba\u015far\u0131yla al\u0131nd\u0131 ve \u00e7izim yap\u0131ld\u0131.\");\n} else {\n    console.error(\"Canvas 2D ba\u011flam\u0131 al\u0131namad\u0131.\");\n}\n            <\/pre>\n<p><\/code><\/li>\n<li><strong>Derleme ve \u00c7al\u0131\u015ft\u0131rma:<\/strong><br \/>\n            <code>package.json<\/code> dosyan\u0131za, TypeScript kodunu derlemek ve oyunu bir canl\u0131 sunucuyla ba\u015flatmak i\u00e7in baz\u0131 scriptler ekleyelim:<\/p>\n<pre><code class=\"language-json\">\n{\n  \/\/ ... di\u011fer ayarlar ...\n  \"scripts\": {\n    \"build\": \"npx tsc\",\n    \"start\": \"npm run build && live-server\"\n  },\n  \/\/ ... di\u011fer ayarlar ...\n}\n            <\/pre>\n<p><\/code><br \/>\n            \u015eimdi terminalde a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code>\n                npm start\n            <\/pre>\n<p><\/code><br \/>\n            Bu komut \u00f6nce TypeScript kodunuzu derleyecek (<code>src\/main.ts<\/code> -> <code>dist\/main.js<\/code>), ard\u0131ndan <code>live-server<\/code> ile projenizi bir web sunucusunda yay\u0131nlayacakt\u0131r. Taray\u0131c\u0131n\u0131zda a\u00e7\u0131lan sayfada, Canvas \u00fczerinde k\u0131rm\u0131z\u0131 bir kare g\u00f6rmelisiniz. Konsolda ise \"TypeScript Endless Runner'a Ho\u015f Geldiniz!\" ve \"Canvas ba\u015far\u0131yla al\u0131nd\u0131 ve \u00e7izim yap\u0131ld\u0131.\" mesajlar\u0131n\u0131 g\u00f6receksiniz. Tebrikler! TypeScript oyun geli\u015ftirme ortam\u0131n\u0131z\u0131 ba\u015far\u0131yla kurdunuz ve ilk \u00e7iziminizi yapt\u0131n\u0131z.<\/p>\n<div class=\"expert-tip\">\n                Uzman \u0130pucu: Projenizin boyutu b\u00fcy\u00fcd\u00fck\u00e7e Webpack veya Rollup gibi mod\u00fcl paketleyicileri kullanmay\u0131 d\u00fc\u015f\u00fcnebilirsiniz. Bu ara\u00e7lar, birden fazla TypeScript dosyas\u0131n\u0131 tek bir JavaScript dosyas\u0131na derleme, ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00f6netme ve hatta kod s\u0131k\u0131\u015ft\u0131rma gibi geli\u015fmi\u015f \u00f6zellikler sunar, bu da oyununuzun y\u00fckleme s\u00fcresini ve performans\u0131n\u0131 iyile\u015ftirebilir. \u015eimdilik <code>npx tsc<\/code> yeterli olsa da, gelecekteki projelerinizde bu ara\u00e7lar\u0131 ara\u015ft\u0131rmak ufkunuzu geni\u015fletecektir.\n            <\/div>\n<\/li>\n<\/ol>\n<h2 id=\"oyun-nesneleri-ve-animasyon-karakterinizi-ve-engellerinizi-hayata-gecirin\">Oyun Nesneleri ve Animasyon: Karakterinizi ve Engellerinizi Hayata Ge\u00e7irin<\/h2>\n<p>Oyunumuzun temel yap\u0131 ta\u015flar\u0131n\u0131 ve ortam\u0131n\u0131 kurduktan sonra, s\u0131ra oyuna can verecek karakter ve engelleri tasarlamaya geliyor. TypeScript'in nesne y\u00f6nelimli programlama yetenekleri sayesinde, bu unsurlar\u0131 ayr\u0131 ayr\u0131 y\u00f6netilebilir s\u0131n\u0131flar olarak tan\u0131mlayabiliriz. Bu yakla\u015f\u0131m, kodumuzu daha d\u00fczenli, okunabilir ve bak\u0131m\u0131 kolay hale getirecektir. Her oyun nesnesinin kendi konumu, boyutu, h\u0131z\u0131 ve g\u00f6r\u00fcn\u00fcm\u00fc olacakt\u0131r. \u00d6zellikle bir sonsuz ko\u015fu oyununda, oyuncu s\u00fcrekli hareket ederken engeller ona do\u011fru ilerleyecek, bu da dinamik bir etkile\u015fim alan\u0131 yaratacakt\u0131r.<\/p>\n<h3 id=\"oyuncu-karakterini-tasarlama\">Oyuncu Karakterini Tasarlama<\/h3>\n<p>\u00d6ncelikle oyuncu karakterimiz i\u00e7in bir <code>Player<\/code> s\u0131n\u0131f\u0131 olu\u015ftural\u0131m. Bu s\u0131n\u0131f, karakterin konumunu (x, y koordinatlar\u0131), boyutunu (geni\u015flik, y\u00fckseklik), yer\u00e7ekimi etkisini, z\u0131plama g\u00fcc\u00fcn\u00fc ve mevcut h\u0131z\u0131n\u0131 tutacakt\u0131r. Ayr\u0131ca, karakteri Canvas \u00fczerine \u00e7izecek bir <code>draw<\/code> metodu ve her oyun d\u00f6ng\u00fcs\u00fcnde durumunu g\u00fcncelleyecek bir <code>update<\/code> metodu i\u00e7erecektir. Z\u0131plama mekani\u011fi, oyuncunun y eksenindeki konumunu ve dikey h\u0131z\u0131n\u0131 de\u011fi\u015ftirerek sim\u00fcle edilir. Yer\u00e7ekimi, karakterin z\u0131plad\u0131ktan sonra tekrar yere inmesini sa\u011flar.<\/p>\n<p><code>src\/Player.ts<\/code> dosyas\u0131n\u0131 olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ src\/Player.ts\nexport class Player {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    velocityY: number;\n    gravity: number;\n    isJumping: boolean;\n    onGround: boolean;\n\n    constructor(x: number, y: number, width: number, height: number) {\n        this.x = x;\n        this.y = y;\n        this.width = width;\n        this.height = height;\n        this.velocityY = 0;\n        this.gravity = 0.5; \/\/ Yer\u00e7ekimi kuvveti\n        this.isJumping = false;\n        this.onGround = true;\n    }\n\n    jump() {\n        if (this.onGround) {\n            this.velocityY = -10; \/\/ Z\u0131plama g\u00fcc\u00fc\n            this.isJumping = true;\n            this.onGround = false;\n        }\n    }\n\n    update(canvasHeight: number) {\n        \/\/ Yer\u00e7ekimi etkisi\n        this.velocityY += this.gravity;\n        this.y += this.velocityY;\n\n        \/\/ Zemine \u00e7arpma kontrol\u00fc\n        if (this.y + this.height > canvasHeight) {\n            this.y = canvasHeight - this.height;\n            this.velocityY = 0;\n            this.isJumping = false;\n            this.onGround = true;\n        }\n    }\n\n    draw(ctx: CanvasRenderingContext2D) {\n        ctx.fillStyle = 'blue'; \/\/ Oyuncuyu mavi bir dikd\u00f6rtgen olarak \u00e7izelim\n        ctx.fillRect(this.x, this.y, this.width, this.height);\n    }\n}\n    <\/pre>\n<p><\/code><\/p>\n<p>Bu <code>Player<\/code> s\u0131n\u0131f\u0131, bir oyuncunun temel \u00f6zelliklerini ve hareketlerini kapsar. <code>update<\/code> metodu, her karede karakterin pozisyonunu yer\u00e7ekimi ve z\u0131plama durumuna g\u00f6re ayarlar. <code>draw<\/code> metodu ise karakteri Canvas \u00fczerine basit bir dikd\u00f6rtgen olarak \u00e7izer. Daha geli\u015fmi\u015f animasyonlar i\u00e7in, bu metodda sprite sheet'ler kullanarak kare kare animasyonlar g\u00f6sterebiliriz. \u00d6rne\u011fin, ko\u015fu animasyonu i\u00e7in ard\u0131\u015f\u0131k resimler y\u00fckleyebilir ve her update d\u00f6ng\u00fcs\u00fcnde bir sonraki kareye ge\u00e7ebiliriz.<\/p>\n<h3 id=\"engelleri-olusturma\">Engelleri Olu\u015fturma<\/h3>\n<p>S\u0131ra geldi oyuncumuzun a\u015fmas\u0131 gereken engellere. Engeller de t\u0131pk\u0131 oyuncu gibi kendi konum, boyut ve hareket \u00f6zelliklerine sahip olacakt\u0131r. Ancak engeller, oyuncuya do\u011fru (ekran\u0131n sa\u011f\u0131ndan soluna) hareket eder ve ekrandan \u00e7\u0131kt\u0131klar\u0131nda geri d\u00f6n\u00fc\u015ft\u00fcr\u00fclmeleri veya yeni engellerin olu\u015fturulmas\u0131 gerekir. Bu, oyunun sonsuzlu\u011funu sa\u011flayan \u00f6nemli bir mekaniktir.<\/p>\n<p><code>src\/Obstacle.ts<\/code> dosyas\u0131n\u0131 olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ src\/Obstacle.ts\nexport class Obstacle {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    speed: number;\n\n    constructor(x: number, y: number, width: number, height: number, speed: number) {\n        this.x = x;\n        this.y = y;\n        this.width = width;\n        this.height = height;\n        this.speed = speed;\n    }\n\n    update() {\n        this.x -= this.speed; \/\/ Engeli sola do\u011fru hareket ettir\n    }\n\n    draw(ctx: CanvasRenderingContext2D) {\n        ctx.fillStyle = 'green'; \/\/ Engeli ye\u015fil bir dikd\u00f6rtgen olarak \u00e7izelim\n        ctx.fillRect(this.x, this.y, this.width, this.height);\n    }\n\n    \/\/ Engelin ekran d\u0131\u015f\u0131na \u00e7\u0131k\u0131p \u00e7\u0131kmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in\n    isOffscreen(): boolean {\n        return this.x + this.width < 0;\n    }\n}\n    <\/pre>\n<p><\/code><\/p>\n<p>Bu <code>Obstacle<\/code> s\u0131n\u0131f\u0131, engelin ba\u015flang\u0131\u00e7 konumunu, boyutunu ve h\u0131z\u0131n\u0131 tan\u0131mlar. <code>update<\/code> metodu, engeli her karede sola do\u011fru hareket ettirir. <code>isOffscreen<\/code> metodu ise, engelin ekran\u0131n sol taraf\u0131ndan tamamen \u00e7\u0131k\u0131p \u00e7\u0131kmad\u0131\u011f\u0131n\u0131 kontrol ederek, bu engeli yeniden kullanma veya yok etme karar\u0131 almam\u0131za yard\u0131mc\u0131 olur. Bu engeller, oyunun zorlu\u011funu ve \u00e7e\u015fitlili\u011fini art\u0131ran ana unsurlard\u0131r.<\/p>\n<h3 id=\"paralaks-arkaplan-ile-derinlik-katma\">Paralaks Arkaplan ile Derinlik Katma<\/h3>\n<p>Bir sonsuz ko\u015fu oyununa derinlik ve hareket hissi katman\u0131n etkili yollar\u0131ndan biri \"paralaks arkaplan\" kullanmakt\u0131r. Bu teknik, farkl\u0131 h\u0131zlarda hareket eden birden fazla arkaplan katman\u0131 olu\u015fturarak, oyuncunun etraf\u0131ndaki d\u00fcnyan\u0131n hareketli oldu\u011fu izlenimini verir. Uzaktaki nesneler yava\u015f hareket ederken, yak\u0131n plan nesneler daha h\u0131zl\u0131 hareket eder. Bu, g\u00f6rsel olarak olduk\u00e7a \u00e7ekici bir etki yarat\u0131r ve oyunun daha dinamik hissetmesini sa\u011flar. Arkaplan g\u00f6rsellerini <code>Image<\/code> objeleri olarak y\u00fckleyebilir ve her katman i\u00e7in farkl\u0131 bir kayd\u0131rma h\u0131z\u0131 uygulayarak bu efekti Canvas \u00fczerinde olu\u015fturabiliriz.<\/p>\n<p>\u00d6rne\u011fin, <code>src\/Background.ts<\/code> ad\u0131nda bir dosya olu\u015fturup a\u015fa\u011f\u0131daki gibi bir yap\u0131 kurabiliriz:<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ src\/Background.ts\nexport class Background {\n    image: HTMLImageElement;\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    speed: number;\n\n    constructor(imageSrc: string, y: number, width: number, height: number, speed: number) {\n        this.image = new Image();\n        this.image.src = imageSrc;\n        this.x = 0;\n        this.y = y;\n        this.width = width;\n        this.height = height;\n        this.speed = speed;\n    }\n\n    update() {\n        this.x -= this.speed;\n        if (this.x < -this.width) {\n            this.x = 0; \/\/ Arkaplan\u0131 ba\u015fa sar\n        }\n    }\n\n    draw(ctx: CanvasRenderingContext2D) {\n        \/\/ \u0130ki kere \u00e7izerek s\u00fcrekli kayd\u0131rma efekti veriyoruz\n        ctx.drawImage(this.image, this.x, this.y, this.width, this.height);\n        ctx.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);\n    }\n}\n    <\/pre>\n<p><\/code><\/p>\n<p>Bu <code>Background<\/code> s\u0131n\u0131f\u0131, bir resim dosyas\u0131 al\u0131r, onu Canvas \u00fczerine \u00e7izer ve belirli bir h\u0131zda kayd\u0131r\u0131r. <code>update<\/code> metodunda, resmin sol kenar\u0131 ekran\u0131n d\u0131\u015f\u0131na \u00e7\u0131kt\u0131\u011f\u0131nda resmi tekrar ba\u015fa sararak sonsuz bir kayd\u0131rma ill\u00fczyonu yarat\u0131r\u0131z. <code>draw<\/code> metodunda ise, resmin iki kopyas\u0131n\u0131 yan yana \u00e7izerek bu s\u00fcreklili\u011fi sa\u011flar\u0131z. Farkl\u0131 h\u0131zlarda birden fazla <code>Background<\/code> objesi olu\u015fturarak paralaks etkisini elde edebiliriz. \u00d6rne\u011fin, bulutlar i\u00e7in yava\u015f, a\u011fa\u00e7lar i\u00e7in orta, zemin i\u00e7in h\u0131zl\u0131 bir h\u0131z ayarlayarak daha ger\u00e7ek\u00e7i bir derinlik hissiyat\u0131 yaratabiliriz.<\/p>\n<p>Bu s\u0131n\u0131flar\u0131 olu\u015fturduktan sonra, <code>src\/main.ts<\/code> dosyam\u0131zda bunlar\u0131 import edip oyunumuzun ana d\u00f6ng\u00fcs\u00fcnde kullanmaya ba\u015flayabiliriz. Bu nesneler, oyunun g\u00f6rsel ve etkile\u015fimli deneyimini olu\u015fturan temel bile\u015fenlerdir. Gelecek b\u00f6l\u00fcmde, bu nesneleri bir araya getirerek oyunun ana mant\u0131\u011f\u0131n\u0131 ve etkile\u015fimlerini nas\u0131l y\u00f6netece\u011fimizi inceleyece\u011fiz.<\/p>\n<h2 id=\"oyun-mantigi-ve-etkilesim-carpisma-skor-ve-sonsuz-kosu-mekanikleri\">Oyun Mant\u0131\u011f\u0131 ve Etkile\u015fim: \u00c7arp\u0131\u015fma, Skor ve Sonsuz Ko\u015fu Mekanikleri<\/h2>\n<p>Oyuncu ve engel nesnelerimizi tan\u0131mlad\u0131ktan sonra, bu nesneleri bir araya getirip onlara hayat verecek olan oyun mant\u0131\u011f\u0131n\u0131 in\u015fa etme zaman\u0131 geldi. Bu a\u015fama, oyunumuzun \"sonsuz\" ve \"ko\u015fu\" k\u0131sm\u0131n\u0131 tan\u0131mlayacak mekanikleri i\u00e7erir: oyun d\u00f6ng\u00fcs\u00fc, engellerin \u00fcretimi ve geri d\u00f6n\u00fc\u015ft\u00fcr\u00fclmesi, \u00e7arp\u0131\u015fma tespiti, skor takibi ve tabii ki kullan\u0131c\u0131 giri\u015fi. T\u00fcm bu elementler, birbiriyle uyumlu bir \u015fekilde \u00e7al\u0131\u015farak ak\u0131c\u0131 ve ba\u011f\u0131ml\u0131l\u0131k yap\u0131c\u0131 bir deneyim sunar.<\/p>\n<h3 id=\"ana-oyun-dongusunu-kurma\">Ana Oyun D\u00f6ng\u00fcs\u00fcn\u00fc Kurma<\/h3>\n<p>Daha \u00f6nce bahsetti\u011fimiz gibi, oyun d\u00f6ng\u00fcs\u00fc her oyunun kalbidir. Taray\u0131c\u0131 tabanl\u0131 oyunlarda, bu d\u00f6ng\u00fc genellikle <code>requestAnimationFrame<\/code> API'\u0131 ile olu\u015fturulur. Bu fonksiyon, taray\u0131c\u0131n\u0131n bir sonraki ekran yenilemesinden \u00f6nce belirli bir fonksiyonu \u00e7a\u011f\u0131rmas\u0131n\u0131 ister, bu da animasyonlar\u0131n daha p\u00fcr\u00fczs\u00fcz olmas\u0131n\u0131 sa\u011flar ve CPU kullan\u0131m\u0131n\u0131 optimize eder. Oyunumuzun t\u00fcm durum g\u00fcncellemeleri ve \u00e7izim i\u015flemleri bu d\u00f6ng\u00fc i\u00e7inde ger\u00e7ekle\u015fecektir.<\/p>\n<p><code>src\/Game.ts<\/code> ad\u0131nda bir dosya olu\u015ftural\u0131m ve ana oyun mant\u0131\u011f\u0131n\u0131 buraya ta\u015f\u0131yal\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ src\/Game.ts\nimport { Player } from '.\/Player';\nimport { Obstacle } from '.\/Obstacle';\nimport { Background } from '.\/Background'; \/\/ Paralaks arkaplan i\u00e7in\n\nexport class Game {\n    canvas: HTMLCanvasElement;\n    ctx: CanvasRenderingContext2D;\n    player: Player;\n    obstacles: Obstacle[];\n    backgrounds: Background[]; \/\/ Birden fazla arkaplan katman\u0131 i\u00e7in\n    score: number;\n    gameOver: boolean;\n    gameSpeed: number;\n    lastObstacleTime: number;\n    obstacleInterval: number; \/\/ Engel \u00fcretim aral\u0131\u011f\u0131\n\n    constructor(canvas: HTMLCanvasElement) {\n        this.canvas = canvas;\n        this.ctx = canvas.getContext('2d')!; \/\/ <code>!<\/code> ile null kontrol\u00fcn\u00fc ge\u00e7ebiliriz, \u00e7\u00fcnk\u00fc main.ts'de kontrol ettik\n        this.player = new Player(50, this.canvas.height - 70, 50, 50); \/\/ Oyuncuyu zemine yak\u0131n konumland\u0131r\n        this.obstacles = [];\n        this.backgrounds = [];\n        this.score = 0;\n        this.gameOver = false;\n        this.gameSpeed = 5;\n        this.lastObstacleTime = 0;\n        this.obstacleInterval = 1500; \/\/ Her 1.5 saniyede bir engel \u00fcret\n\n        \/\/ Arkaplan katmanlar\u0131n\u0131 ekle (\u00f6rnek g\u00f6rseller kulland\u0131m)\n        this.backgrounds.push(new Background('https:\/\/via.placeholder.com\/800x400\/87CEEB\/ffffff?text=Sky', 0, this.canvas.width, this.canvas.height, 0.5)); \/\/ G\u00f6ky\u00fcz\u00fc (en yava\u015f)\n        this.backgrounds.push(new Background('https:\/\/via.placeholder.com\/800x400\/6B8E23\/ffffff?text=Hills', this.canvas.height - 200, this.canvas.width, 200, 1.5)); \/\/ Tepeler (orta)\n        this.backgrounds.push(new Background('https:\/\/via.placeholder.com\/800x400\/556B2F\/ffffff?text=Ground', this.canvas.height - 50, this.canvas.width, 50, this.gameSpeed)); \/\/ Zemin (en h\u0131zl\u0131, oyun h\u0131z\u0131yla ayn\u0131)\n\n        this.setupEventListeners();\n    }\n\n    setupEventListeners() {\n        document.addEventListener('keydown', e => {\n            if (e.code === 'Space' && !this.gameOver) {\n                this.player.jump();\n            }\n            if (e.code === 'KeyR' && this.gameOver) {\n                this.restartGame();\n            }\n        });\n        this.canvas.addEventListener('touchstart', (e) => {\n            if (!this.gameOver) {\n                this.player.jump();\n            }\n            e.preventDefault(); \/\/ Mobil taray\u0131c\u0131lar\u0131n varsay\u0131lan kayd\u0131rma davran\u0131\u015f\u0131n\u0131 engeller\n        });\n        \/\/ Dokunmatik cihazlar i\u00e7in oyun bitiminde yeniden ba\u015flatma\n        this.canvas.addEventListener('click', () => {\n            if (this.gameOver) {\n                this.restartGame();\n            }\n        });\n    }\n\n    generateObstacle(currentTime: number) {\n        if (currentTime - this.lastObstacleTime > this.obstacleInterval) {\n            const obstacleWidth = Math.random() * 30 + 30; \/\/ 30-60 aras\u0131 geni\u015flik\n            const obstacleHeight = Math.random() * 40 + 40; \/\/ 40-80 aras\u0131 y\u00fckseklik\n            const obstacleX = this.canvas.width;\n            const obstacleY = this.canvas.height - obstacleHeight; \/\/ Zemine oturmas\u0131n\u0131 sa\u011fla\n\n            this.obstacles.push(new Obstacle(obstacleX, obstacleY, obstacleWidth, obstacleHeight, this.gameSpeed));\n            this.lastObstacleTime = currentTime;\n\n            \/\/ Zamanla engel \u00fcretim aral\u0131\u011f\u0131n\u0131 k\u0131saltarak zorlu\u011fu art\u0131r\n            this.obstacleInterval = Math.max(800, this.obstacleInterval - 50);\n            \/\/ Oyun h\u0131z\u0131n\u0131 art\u0131r\n            this.gameSpeed += 0.1;\n            this.backgrounds.forEach(bg => {\n                \/\/ Sadece zemin katman\u0131n\u0131n h\u0131z\u0131n\u0131 oyun h\u0131z\u0131yla senkronize et\n                if (bg.image.src.includes('Ground')) { \/\/ veya ba\u015fka bir tan\u0131mlay\u0131c\u0131 kullan\n                    bg.speed = this.gameSpeed;\n                }\n            });\n        }\n    }\n\n    checkCollision(player: Player, obstacle: Obstacle): boolean {\n        \/\/ AABB (Axis-Aligned Bounding Box) \u00e7arp\u0131\u015fma tespiti\n        return player.x < obstacle.x + obstacle.width &#038;&#038;\n               player.x + player.width > obstacle.x &&\n               player.y < obstacle.y + obstacle.height &#038;&#038;\n               player.y + player.height > obstacle.y;\n    }\n\n    update(deltaTime: number) {\n        if (this.gameOver) return;\n\n        this.player.update(this.canvas.height);\n\n        \/\/ Arkaplanlar\u0131 g\u00fcncelle\n        this.backgrounds.forEach(bg => bg.update());\n\n        \/\/ Engelleri g\u00fcncelle ve \u00e7arp\u0131\u015fma kontrol\u00fc yap\n        this.obstacles.forEach((obstacle, index) => {\n            obstacle.speed = this.gameSpeed; \/\/ Engellerin h\u0131z\u0131 oyun h\u0131z\u0131yla senkronize olsun\n            obstacle.update();\n            if (this.checkCollision(this.player, obstacle)) {\n                this.gameOver = true;\n                console.log(\"Game Over! Skor: \" + this.score);\n            }\n            \/\/ Engelleri ekran d\u0131\u015f\u0131na \u00e7\u0131kt\u0131\u011f\u0131nda temizle\n            if (obstacle.isOffscreen()) {\n                this.obstacles.splice(index, 1);\n                this.score++; \/\/ Engel ge\u00e7ildi\u011finde skoru art\u0131r\n            }\n        });\n\n        this.generateObstacle(performance.now());\n    }\n\n    draw() {\n        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); \/\/ Her karede Canvas'\u0131 temizle\n\n        \/\/ Arkaplanlar\u0131 \u00e7iz\n        this.backgrounds.forEach(bg => bg.draw(this.ctx));\n\n        this.player.draw(this.ctx);\n        this.obstacles.forEach(obstacle => obstacle.draw(this.ctx));\n\n        \/\/ Skoru \u00e7iz\n        this.ctx.fillStyle = 'black';\n        this.ctx.font = '24px Arial';\n        this.ctx.fillText(<code>Skor: ${this.score}<\/code>, 10, 30);\n\n        \/\/ Game Over ekran\u0131\n        if (this.gameOver) {\n            this.ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);\n            this.ctx.fillStyle = 'white';\n            this.ctx.font = '48px Arial';\n            this.ctx.textAlign = 'center';\n            this.ctx.fillText('OYUN B\u0130TT\u0130!', this.canvas.width \/ 2, this.canvas.height \/ 2 - 30);\n            this.ctx.font = '24px Arial';\n            this.ctx.fillText(<code>Son Skor: ${this.score}<\/code>, this.canvas.width \/ 2, this.canvas.height \/ 2 + 10);\n            this.ctx.fillText('Yeniden Ba\u015flamak \u0130\u00e7in \"R\" Tu\u015funa Bas\u0131n veya T\u0131klay\u0131n', this.canvas.width \/ 2, this.canvas.height \/ 2 + 50);\n        }\n    }\n\n    restartGame() {\n        this.player = new Player(50, this.canvas.height - 70, 50, 50);\n        this.obstacles = [];\n        this.score = 0;\n        this.gameOver = false;\n        this.gameSpeed = 5;\n        this.lastObstacleTime = 0;\n        this.obstacleInterval = 1500;\n        this.backgrounds.forEach(bg => {\n            if (bg.image.src.includes('Ground')) {\n                bg.speed = this.gameSpeed;\n            }\n            bg.x = 0; \/\/ Arkaplan\u0131 da s\u0131f\u0131rla\n        });\n    }\n}\n    <\/pre>\n<p><\/code><\/p>\n<h3 id=\"ana-main-ts-dosyasini-guncelleme\">Ana main.ts Dosyas\u0131n\u0131 G\u00fcncelleme<\/h3>\n<p>\u015eimdi <code>src\/main.ts<\/code> dosyas\u0131n\u0131, <code>Game<\/code> s\u0131n\u0131f\u0131m\u0131z\u0131 kullanarak oyun d\u00f6ng\u00fcs\u00fcn\u00fc ba\u015flatacak \u015fekilde g\u00fcncelleyelim:<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ src\/main.ts\nimport { Game } from '.\/Game';\n\nconsole.log(\"TypeScript Endless Runner ba\u015flat\u0131l\u0131yor...\");\n\nconst canvas = document.getElementById('gameCanvas') as HTMLCanvasElement;\nconst ctx = canvas.getContext('2d');\n\nif (ctx) {\n    const game = new Game(canvas);\n\n    let lastTime = 0;\n    function gameLoop(timestamp: number) {\n        const deltaTime = timestamp - lastTime;\n        lastTime = timestamp;\n\n        game.update(deltaTime);\n        game.draw();\n\n        requestAnimationFrame(gameLoop);\n    }\n\n    requestAnimationFrame(gameLoop); \/\/ Oyun d\u00f6ng\u00fcs\u00fcn\u00fc ba\u015flat\n    console.log(\"Oyun d\u00f6ng\u00fcs\u00fc ba\u015flat\u0131ld\u0131.\");\n} else {\n    console.error(\"Canvas 2D ba\u011flam\u0131 al\u0131namad\u0131. Oyun ba\u015flat\u0131lam\u0131yor.\");\n}\n    <\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki kodda, <code>gameLoop<\/code> fonksiyonu, <code>requestAnimationFrame<\/code> taraf\u0131ndan s\u00fcrekli olarak \u00e7a\u011fr\u0131l\u0131r. Her \u00e7a\u011fr\u0131da <code>game.update()<\/code> metodu oyunun mant\u0131\u011f\u0131n\u0131 g\u00fcncellerken (oyuncu hareketi, engel ilerlemesi, \u00e7arp\u0131\u015fma kontrol\u00fc vb.), <code>game.draw()<\/code> metodu ise t\u00fcm nesneleri Canvas \u00fczerine \u00e7izer. Bu yap\u0131, oyunumuzun ak\u0131c\u0131 bir \u015fekilde \u00e7al\u0131\u015fmas\u0131n\u0131 ve s\u00fcrekli g\u00fcncellenmesini sa\u011flar. \u00d6zellikle mobil cihazlarda dokunmatik kontroller i\u00e7in <code>touchstart<\/code> olay dinleyicisini eklemeyi unutmad\u0131k. Bu sayede oyun hem klavye hem de dokunmatik ekranlar \u00fczerinden kontrol edilebilir hale gelir.<\/p>\n<h3 id=\"nesne-havuzu-object-pooling-ile-performans-iyilestirmesi\">Nesne Havuzu (Object Pooling) ile Performans \u0130yile\u015ftirmesi<\/h3>\n<p>Oyun ilerledik\u00e7e, s\u00fcrekli olarak yeni engeller olu\u015fturup eski engelleri bellekten atmak (garbage collection) performans\u0131 olumsuz etkileyebilir. \u00d6zellikle taray\u0131c\u0131 ortamlar\u0131nda bu durum daha belirgin olabilir. Bu sorunu a\u015fmak i\u00e7in \"nesne havuzu\" (object pooling) tekni\u011fini kullanabiliriz. Bu yakla\u015f\u0131mda, belirli say\u0131da engeli (veya di\u011fer oyun nesnelerini) \u00f6nceden olu\u015fturur ve bir havuzda tutar\u0131z. Bir engele ihtiya\u00e7 duyuldu\u011funda, havuzdan mevcut bir engeli al\u0131p konumunu ve \u00f6zelliklerini s\u0131f\u0131rlayarak kullan\u0131r\u0131z. Engel ekran d\u0131\u015f\u0131na \u00e7\u0131kt\u0131\u011f\u0131nda ise onu bellekten atmak yerine havuza geri g\u00f6ndeririz. Bu, bellek ay\u0131rma ve serbest b\u0131rakma i\u015flemlerinin maliyetini ortadan kald\u0131rarak performans\u0131 art\u0131r\u0131r.<\/p>\n<p><code>generateObstacle<\/code> metodunu nesne havuzu kullanacak \u015fekilde optimize edebiliriz. \u00d6rne\u011fin, bir <code>availableObstacles<\/code> dizisi olu\u015fturup, engel d\u0131\u015far\u0131 \u00e7\u0131kt\u0131\u011f\u0131nda buraya ekleyebilir, yeni engel gerekti\u011finde ise \u00f6nce bu diziden almay\u0131 deneyebiliriz. Bu, \u00f6zellikle kaynaklar\u0131 k\u0131s\u0131tl\u0131 cihazlarda veya \u00e7ok say\u0131da nesnenin oldu\u011fu oyunlarda b\u00fcy\u00fck bir performans kazanc\u0131 sa\u011flayacakt\u0131r. Ancak bu rehberin kapsam\u0131 gere\u011fi, mevcut basit <code>obstacles.push<\/code> ve <code>splice<\/code> kullan\u0131m\u0131 ba\u015flang\u0131\u00e7 i\u00e7in yeterlidir ve konuyu karma\u015f\u0131kla\u015ft\u0131rmayacakt\u0131r.<\/p>\n<div class=\"expert-tip\">\n        Uzman \u0130pucu: Oyun h\u0131z\u0131n\u0131n zamanla art\u0131r\u0131lmas\u0131, oyuncuya s\u00fcrekli bir meydan okuma sunar ve oyunun \"sonsuz\" hissini peki\u015ftirir. <code>gameSpeed<\/code> de\u011fi\u015fkenini d\u00fczenli aral\u0131klarla art\u0131rarak veya skorla orant\u0131l\u0131 olarak de\u011fi\u015ftirerek oyunun zorluk seviyesini dinamik olarak ayarlayabilirsiniz. Unutmay\u0131n, iyi bir zorluk e\u011frisi, oyuncular\u0131n oyunu b\u0131rakmamas\u0131n\u0131 sa\u011flar. Ayr\u0131ca, mobil uyumluluk i\u00e7in <code>touchstart<\/code> ve <code>click<\/code> event'lerini kullanmak, oyununuzun daha geni\u015f bir kitleye ula\u015fmas\u0131na yard\u0131mc\u0131 olur.\n    <\/div>\n<h2 id=\"ileri-duzey-ipuclari-ve-performans-optimizasyonu-oyununuzu-bir-sonraki-seviyeye-tasiyin\">\u0130leri D\u00fczey \u0130pu\u00e7lar\u0131 ve Performans Optimizasyonu: Oyununuzu Bir Sonraki Seviyeye Ta\u015f\u0131y\u0131n<\/h2>\n<p>Temel bir sonsuz ko\u015fu oyununu ba\u015far\u0131l\u0131 bir \u015fekilde olu\u015fturduktan sonra, s\u0131ra onu daha cilal\u0131, performansl\u0131 ve kullan\u0131c\u0131 dostu hale getirmeye geliyor. Bu b\u00f6l\u00fcmde, oyununuzu bir sonraki seviyeye ta\u015f\u0131yacak ileri d\u00fczey ipu\u00e7lar\u0131 ve performans optimizasyon tekniklerinden bahsedece\u011fiz. Bu teknikler, sadece deneyimli geli\u015ftiriciler i\u00e7in de\u011fil, ayn\u0131 zamanda projesini daha profesyonel hale getirmek isteyen her seviyeden geli\u015ftirici i\u00e7in de\u011ferlidir.<\/p>\n<h3 id=\"asset-yukleme-ve-yonetimi\">Asset Y\u00fckleme ve Y\u00f6netimi<\/h3>\n<p>Oyununuzdaki g\u00f6rselleri (sprite sheet'ler, arkaplan resimleri), ses efektlerini ve m\u00fczikleri \u00f6nceden y\u00fcklemek, oyunun ba\u015flang\u0131c\u0131nda olu\u015fabilecek tak\u0131lmalar\u0131 \u00f6nler ve daha p\u00fcr\u00fczs\u00fcz bir kullan\u0131c\u0131 deneyimi sunar. Bir \"Asset Y\u00f6neticisi\" veya basit bir y\u00fckleyici fonksiyonu olu\u015fturarak t\u00fcm g\u00f6rsel ve ses dosyalar\u0131n\u0131 oyun ba\u015flamadan \u00f6nce haf\u0131zaya alabilirsiniz. Bu i\u015flem tamamland\u0131\u011f\u0131nda, oyunu ba\u015flatan bir geri arama (callback) fonksiyonu \u00e7a\u011f\u0131rabilirsiniz. Bu, \u00f6zellikle oyununuzun a\u00e7\u0131l\u0131\u015f\u0131nda bir y\u00fckleme ekran\u0131 (loading screen) g\u00f6stermek istedi\u011finizde kritik \u00f6neme sahiptir.<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ Basit bir asset y\u00fckleyici \u00f6rne\u011fi\nclass AssetLoader {\n    images: { [key: string]: HTMLImageElement } = {};\n    totalAssets: number = 0;\n    loadedAssets: number = 0;\n    onComplete: (() => void) | null = null;\n\n    load(assets: { name: string; src: string }[], onComplete: () => void) {\n        this.totalAssets = assets.length;\n        this.onComplete = onComplete;\n\n        if (this.totalAssets === 0) {\n            this.onComplete?.();\n            return;\n        }\n\n        assets.forEach(asset => {\n            const img = new Image();\n            img.onload = () => {\n                this.loadedAssets++;\n                if (this.loadedAssets === this.totalAssets) {\n                    this.onComplete?.();\n                }\n            };\n            img.onerror = () => {\n                console.error(<code>Resim y\u00fcklenemedi: ${asset.src}<\/code>);\n                this.loadedAssets++; \/\/ Hata olsa bile sayac\u0131 art\u0131r\n                if (this.loadedAssets === this.totalAssets) {\n                    this.onComplete?.();\n                }\n            };\n            img.src = asset.src;\n            this.images[asset.name] = img;\n        });\n    }\n\n    getImage(name: string): HTMLImageElement | undefined {\n        return this.images[name];\n    }\n}\n\n\/\/ Kullan\u0131m \u00f6rne\u011fi:\n\/\/ const loader = new AssetLoader();\n\/\/ loader.load([\n\/\/     { name: 'playerSprite', src: 'assets\/player.png' },\n\/\/     { name: 'obstacleSprite', src: 'assets\/obstacle.png' }\n\/\/ ], () => {\n\/\/     console.log('T\u00fcm assetler y\u00fcklendi, oyunu ba\u015flatabiliriz!');\n\/\/     \/\/ Oyun ba\u015flatma mant\u0131\u011f\u0131 buraya\n\/\/ });\n    <\/pre>\n<p><\/code><\/p>\n<h3 id=\"canvas-optimizasyonlari\">Canvas Optimizasyonlar\u0131<\/h3>\n<p>Canvas \u00fczerinde \u00e7izim yapmak pahal\u0131 bir i\u015flemdir, \u00f6zellikle her karede \u00e7ok say\u0131da nesne \u00e7iziyorsan\u0131z. Performans\u0131 art\u0131rmak i\u00e7in baz\u0131 teknikler kullanabiliriz:<\/p>\n<ul>\n<li><strong><code>clearRect<\/code> Kullan\u0131m\u0131:<\/strong> Her karede t\u00fcm Canvas'\u0131 temizlemek yerine, sadece de\u011fi\u015fen b\u00f6lgeleri temizlemeyi d\u00fc\u015f\u00fcnebilirsiniz. Ancak \u00e7o\u011fu durumda <code>clearRect(0, 0, width, height)<\/code> performansa \u00e7ok b\u00fcy\u00fck bir etki yapmaz ve kodun daha basit kalmas\u0131n\u0131 sa\u011flar.<\/li>\n<li><strong>Offscreen Canvas (\u00c7ift Tamponlama):<\/strong> Karma\u015f\u0131k sahneleri arka plandaki g\u00f6r\u00fcnmez bir Canvas'a \u00e7izip, sonra tek bir i\u015flemle bu Canvas'\u0131 ana Canvas'a kopyalamak, ekran y\u0131rt\u0131lmas\u0131n\u0131 (tearing) azaltabilir ve daha p\u00fcr\u00fczs\u00fcz animasyonlar sa\u011flayabilir. \u00d6zellikle y\u00fcksek \u00e7\u00f6z\u00fcn\u00fcrl\u00fckl\u00fc veya \u00e7ok say\u0131da eleman\u0131 olan oyunlarda faydal\u0131d\u0131r.<\/li>\n<li><strong>Pixel Snapping:<\/strong> Nesneleri tam piksel koordinatlar\u0131na hizalamak (<code>Math.floor(x)<\/code> veya <code>Math.round(x)<\/code> kullanarak), taray\u0131c\u0131n\u0131n anti-aliasing (kenar yumu\u015fatma) i\u015flemlerinden ka\u00e7\u0131nmas\u0131n\u0131 sa\u011flayarak \u00e7izim performans\u0131n\u0131 art\u0131rabilir.<\/li>\n<li><strong><code>save()<\/code> ve <code>restore()<\/code> Yeri:<\/strong> Canvas ba\u011flam\u0131n\u0131n durumunu (d\u00f6n\u00fc\u015f\u00fcmler, stiller vb.) s\u0131k s\u0131k kaydetmek ve geri y\u00fcklemek performans maliyeti yaratabilir. Yaln\u0131zca ger\u00e7ekten gerekti\u011finde kullanmaya \u00f6zen g\u00f6sterin.<\/li>\n<\/ul>\n<h3 id=\"mobil-uyumluluk-ve-dokunmatik-kontroller\">Mobil Uyumluluk ve Dokunmatik Kontroller<\/h3>\n<p>Oyununuzun mobil cihazlarda da sorunsuz \u00e7al\u0131\u015fmas\u0131 i\u00e7in <code>meta viewport<\/code> etiketini kullanmak zorunludur:<\/p>\n<pre><code class=\"language-html\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n    <\/pre>\n<p><\/code><\/p>\n<p><code>user-scalable=no<\/code> ile kullan\u0131c\u0131lar\u0131n yak\u0131nla\u015ft\u0131rmas\u0131n\u0131 engelleyebiliriz. Dokunmatik kontroller i\u00e7in ise <code>touchstart<\/code>, <code>touchmove<\/code> ve <code>touchend<\/code> olaylar\u0131n\u0131 kullanmal\u0131s\u0131n\u0131z. Ayr\u0131ca, mobil taray\u0131c\u0131lar\u0131n varsay\u0131lan kayd\u0131rma davran\u0131\u015flar\u0131n\u0131 engellemek i\u00e7in olay dinleyicilerinizde <code>e.preventDefault()<\/code> \u00e7a\u011f\u0131rmay\u0131 unutmay\u0131n. Makalenin \u00f6nceki b\u00f6l\u00fcmlerinde verdi\u011fimiz CSS media query \u00f6rnekleri, Canvas'\u0131n farkl\u0131 ekran boyutlar\u0131na uyum sa\u011flamas\u0131na yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<h3 id=\"oyun-durum-yonetimi\">Oyun Durum Y\u00f6netimi<\/h3>\n<p>Oyununuz b\u00fcy\u00fcd\u00fck\u00e7e, farkl\u0131 durumlar\u0131 (ana men\u00fc, oyun i\u00e7i, oyun bitti, duraklat\u0131ld\u0131) y\u00f6netmek karma\u015f\u0131k hale gelebilir. Bir \"durum makinesi\" (state machine) deseni kullanarak bu durumlar aras\u0131ndaki ge\u00e7i\u015fleri daha d\u00fczenli bir \u015fekilde y\u00f6netebilirsiniz. Her durum, kendi update ve draw mant\u0131\u011f\u0131n\u0131 i\u00e7erebilir.<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ Basit bir durum makinesi aray\u00fcz\u00fc\ninterface GameState {\n    enter(): void;\n    update(deltaTime: number): void;\n    draw(ctx: CanvasRenderingContext2D): void;\n    exit(): void;\n}\n\n\/\/ \u00d6rne\u011fin, bir men\u00fc durumu\nclass MainMenuState implements GameState {\n    enter() { console.log('Ana Men\u00fcye Giri\u015f'); }\n    update(deltaTime: number) { \/* Men\u00fc mant\u0131\u011f\u0131 *\/ }\n    draw(ctx: CanvasRenderingContext2D) {\n        ctx.fillStyle = 'black';\n        ctx.font = '30px Arial';\n        ctx.fillText('BA\u015eLAMAK \u0130\u00c7\u0130N TIKLA', 400, 200);\n    }\n    exit() { console.log('Ana Men\u00fcden \u00c7\u0131k\u0131\u015f'); }\n}\n\n\/\/ Game s\u0131n\u0131f\u0131 i\u00e7inde durumlar\u0131 y\u00f6netebiliriz\n\/\/ let currentState: GameState;\n\/\/ currentState = new MainMenuState();\n\/\/ ...\n\/\/ currentState.update(deltaTime);\n\/\/ currentState.draw(ctx);\n    <\/pre>\n<p><\/code><\/p>\n<h3 id=\"ses-efektleri-ve-muzik\">Ses Efektleri ve M\u00fczik<\/h3>\n<p>Ses efektleri ve fon m\u00fczi\u011fi, oyun deneyimini zenginle\u015ftiren kritik unsurlard\u0131r. HTML5 Audio API'si veya Web Audio API'si (daha geli\u015fmi\u015f kontrol i\u00e7in) kullan\u0131larak sesler kolayca eklenebilir. Z\u0131plama, \u00e7arp\u0131\u015fma veya puan kazanma gibi olaylar i\u00e7in k\u0131sa ses efektleri, oyunun daha etkile\u015fimli hissetmesini sa\u011flar. Fon m\u00fczi\u011fi ise oyunun atmosferini g\u00fc\u00e7lendirir.<\/p>\n<pre><code class=\"language-typescript\">\n\/\/ Basit bir ses efekti \u00e7alma \u00f6rne\u011fi\nfunction playSound(src: string) {\n    const audio = new Audio(src);\n    audio.play().catch(e => console.error(\"Ses \u00e7al\u0131namad\u0131:\", e));\n}\n\n\/\/ \u00d6rne\u011fin, z\u0131plama sesi\n\/\/ playSound('assets\/jump.mp3');\n    <\/pre>\n<p><\/code><\/p>\n<p>Bu ileri d\u00fczey ipu\u00e7lar\u0131 ve optimizasyon stratejileri, oyununuzu sadece i\u015flevsel olmaktan \u00e7\u0131kar\u0131p, ger\u00e7ekten keyifli ve ak\u0131lda kal\u0131c\u0131 bir deneyim haline getirecektir. Her birini denemek, web tabanl\u0131 oyun geli\u015ftirme becerilerinizi daha da keskinle\u015ftirecektir.<\/p>\n<h3 id=\"vaka-calismasi-populer-endless-runner-oyunlarindan-ilham\">Vaka \u00c7al\u0131\u015fmas\u0131: Pop\u00fcler Endless Runner Oyunlar\u0131ndan \u0130lham<\/h3>\n<p>Endless runner t\u00fcr\u00fcn\u00fcn pop\u00fcler \u00f6rnekleri olan Subway Surfers ve Temple Run, basit bir ko\u015fu mekani\u011fini \u00e7e\u015fitli \u00f6zelliklerle nas\u0131l zenginle\u015ftirebilece\u011fimizi g\u00f6steriyor. Bu oyunlar, temel d\u00f6ng\u00fcy\u00fc s\u00fcrd\u00fcr\u00fcrken, oyuncunun ilgisini canl\u0131 tutacak unsurlar ekleyerek uzun s\u00fcreli bir oynanabilirlik sunar.<\/p>\n<ul>\n<li><strong>Subway Surfers:<\/strong> Bu oyunda karakter, tren raylar\u0131 \u00fczerinde s\u00fcrekli ko\u015far ve engellerin \u00fczerinden atlar, alt\u0131ndan ge\u00e7er veya yana do\u011fru hareket eder. Bizim basit oyunumuzda sadece z\u0131plama mekani\u011fi varken, Subway Surfers'\u0131n yanal hareket ve engellerden ka\u00e7\u0131nma \u00e7e\u015fitlili\u011fi, oyuncuya daha fazla kontrol ve stratejik d\u00fc\u015f\u00fcnme alan\u0131 sunar. \u00d6rne\u011fin, bizim oyunumuza farkl\u0131 \"\u015feritler\" ekleyebilir ve oyuncunun bu \u015feritler aras\u0131nda ge\u00e7i\u015f yapmas\u0131n\u0131 sa\u011flayabiliriz. Power-up'lar (\u00f6rne\u011fin, jetpack veya m\u0131knat\u0131s) ve g\u00f6revler (belirli say\u0131da para toplama, belirli bir mesafeyi kat etme) oyuncuyu oyunda tutar. Ayr\u0131ca, farkl\u0131 karakterler ve \u00f6zelle\u015ftirme se\u00e7enekleri de oyuncunun oyuna ba\u011fl\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131r.<\/li>\n<li><strong>Temple Run:<\/strong> Bu oyun ise 3D bir ortamda ge\u00e7en bir sonsuz ko\u015fu oyunudur ve kamera perspektifi karakterin arkas\u0131ndan takip eder. Engellerden ka\u00e7\u0131nman\u0131n yan\u0131 s\u0131ra, virajlara girmeyi ve u\u00e7urumlardan atlamay\u0131 da gerektirir. Bizim 2D Canvas tabanl\u0131 oyunumuzda do\u011frudan 3D perspektifi taklit etmek zor olsa da, Temple Run'\u0131n dinamik kamera hareketleri ve h\u0131zl\u0131 karar verme mekanikleri bize ilham verebilir. \u00d6rne\u011fin, oyun h\u0131z\u0131n\u0131 zamanla art\u0131rmak, farkl\u0131 engel t\u00fcrleri (yerdeki engeller, havadan gelen engeller) eklemek veya belirli aral\u0131klarla g\u00f6rsel temay\u0131 de\u011fi\u015ftirmek (g\u00fcnd\u00fcz\/gece d\u00f6ng\u00fcs\u00fc gibi) oyunun monotonlu\u011funu k\u0131rabilir.<\/li>\n<\/ul>\n<p>Bu oyunlardan ilham alarak, kendi oyunumuza ekleyebilece\u011fimiz \u00f6zellikler \u015funlar olabilir:<\/p>\n<ul>\n<li><strong>Zorluk E\u011frisi:<\/strong> Oyun h\u0131z\u0131 ve engel \u00fcretim aral\u0131\u011f\u0131n\u0131n zamanla kademeli olarak art\u0131r\u0131lmas\u0131. Bizim \u00f6rne\u011fimizde bu mekani\u011fi basit\u00e7e uygulad\u0131k, ancak daha karma\u015f\u0131k algoritmalarla (\u00f6rne\u011fin skorla orant\u0131l\u0131 art\u0131\u015f) daha dinamik bir zorluk sa\u011flayabiliriz.<\/li>\n<li><strong>Engel \u00c7e\u015fitlili\u011fi:<\/strong> Sadece dikd\u00f6rtgen engeller yerine, farkl\u0131 boyutlarda, y\u00fcksekliklerde veya hareket paternlerine sahip engeller eklemek. \u00d6rne\u011fin, havadan d\u00fc\u015fen engeller veya daha geni\u015f atlama gerektiren \u00e7ift engeller.<\/li>\n<li><strong>Toplanabilir \u00d6\u011feler (Collectibles):<\/strong> Puan\u0131 art\u0131ran veya ge\u00e7ici yetenekler (daha h\u0131zl\u0131 ko\u015fma, yenilmezlik) veren paralar veya g\u00fc\u00e7lendirmeler eklemek. Bu, oyuncuya ka\u00e7\u0131nman\u0131n \u00f6tesinde bir hedef verir.<\/li>\n<li><strong>Paralaks Arkaplan Geli\u015ftirmesi:<\/strong> Daha fazla katman ve daha detayl\u0131 g\u00f6rseller kullanarak daha zengin bir g\u00f6rsel deneyim sunmak.<\/li>\n<li><strong>G\u00f6rsel Geri Bildirim:<\/strong> Oyuncu z\u0131plad\u0131\u011f\u0131nda, \u00e7arpt\u0131\u011f\u0131nda veya puan ald\u0131\u011f\u0131nda g\u00f6rsel efektler (par\u00e7ac\u0131klar, fla\u015f efektleri) eklemek.<\/li>\n<\/ul>\n<p>Bu vaka analizleri, temel bir oyun motorunun \u00fczerine nas\u0131l katmanlar in\u015fa ederek daha zengin ve ilgi \u00e7ekici bir deneyim olu\u015fturabilece\u011fimizi g\u00f6sterir. Basit bir sonsuz ko\u015fucu, bu eklemelerle birlikte saatlerce oynanabilir bir hal alabilir.<\/p>\n<h2 id=\"sonuc-kendi-sonsuz-kosu-oyununuzu-gelistirme-yolculugunuz\">Sonu\u00e7: Kendi Sonsuz Ko\u015fu Oyununuzu Geli\u015ftirme Yolculu\u011funuz<\/h2>\n<p>Bu kapsaml\u0131 rehber boyunca, TypeScript'in g\u00fcc\u00fcn\u00fc kullanarak taray\u0131c\u0131 tabanl\u0131 bir sonsuz ko\u015fu oyunu geli\u015ftirmenin ad\u0131mlar\u0131n\u0131 detayl\u0131 bir \u015fekilde inceledik. Ba\u015flang\u0131\u00e7ta basit bir proje kurulumuyla temel altyap\u0131y\u0131 olu\u015fturduk, ard\u0131ndan oyuncu ve engel gibi ana oyun nesnelerini tan\u0131mlad\u0131k. HTML5 Canvas \u00fczerinde \u00e7izim yapmay\u0131, oyun d\u00f6ng\u00fcs\u00fcn\u00fc y\u00f6netmeyi, \u00e7arp\u0131\u015fma tespiti ve skor takibi gibi temel oyun mekaniklerini uygulamay\u0131 \u00f6\u011frendik. Ayr\u0131ca, paralaks arkaplan gibi g\u00f6rsel zenginlik katan \u00f6zelliklere ve mobil uyumluluk, performans optimizasyonu ve asset y\u00f6netimi gibi ileri d\u00fczey konulara da de\u011findik. Subway Surfers ve Temple Run gibi pop\u00fcler \u00f6rneklerden ilham alarak kendi oyunumuzu daha da geli\u015ftirmenin yollar\u0131n\u0131 ke\u015ffettik.<\/p>\n<p>Bu s\u00fcre\u00e7, sadece bir oyun geli\u015ftirmeyi de\u011fil, ayn\u0131 zamanda modern web geli\u015ftirme prensiplerini, nesne y\u00f6nelimli programlama yakla\u015f\u0131mlar\u0131n\u0131 ve taray\u0131c\u0131n\u0131n g\u00fc\u00e7l\u00fc grafik yeteneklerini anlama f\u0131rsat\u0131 sundu. TypeScript'in sa\u011flad\u0131\u011f\u0131 tip g\u00fcvenli\u011fi ve kod d\u00fczeni, b\u00fcy\u00fck projelerde karma\u015f\u0131kl\u0131\u011f\u0131 y\u00f6netme konusunda paha bi\u00e7ilmez bir yard\u0131mc\u0131 oldu\u011funu bir kez daha g\u00f6sterdi. Art\u0131k kendi yarat\u0131c\u0131 fikirlerinizi hayata ge\u00e7irebilecek sa\u011flam bir temel bilgi birikimine sahipsiniz.<\/p>\n<p>Bu noktadan sonra, oyununuzu ki\u015fiselle\u015ftirmek ve yeni \u00f6zellikler eklemek tamamen sizin elinizde. Belki farkl\u0131 engel t\u00fcrleri, toplanabilir e\u015fyalar, g\u00fc\u00e7lendirmeler, lider tablolar\u0131 veya daha karma\u015f\u0131k bir g\u00f6rsel tema eklemek isteyebilirsiniz. Unutmay\u0131n, oyun geli\u015ftirme s\u00fcrekli bir \u00f6\u011frenme ve deneme s\u00fcrecidir. Bu rehber, ba\u015flang\u0131\u00e7 noktan\u0131z oldu; \u015fimdi s\u0131ra sizde, bu bilgiyi kullanarak kendi benzersiz dijital maceralar\u0131n\u0131z\u0131 yarat\u0131n. Ba\u015far\u0131lar dileriz!<\/p>\n<h3 id=\"sikca-sorulan-sorular-sss\">S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<dl>\n<dt>TypeScript'i JavaScript'e tercih etmemin nedenleri nelerdir?<\/dt>\n<dd>TypeScript, JavaScript'in tip tan\u0131ml\u0131 bir \u00fcst k\u00fcmesidir. Yani, JavaScript kodunuz TypeScript kodu olarak ge\u00e7erlidir. Ancak TypeScript, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli projelerde tip g\u00fcvenli\u011fi, geli\u015ftirme zaman\u0131nda hata tespiti, kodun okunabilirli\u011fi ve bak\u0131m\u0131 kolayl\u0131\u011f\u0131 gibi avantajlar sunar. Bu, \u00f6zellikle karma\u015f\u0131k oyun mant\u0131\u011f\u0131 geli\u015ftirirken hatalar\u0131 azalt\u0131r ve daha sa\u011flam bir kod taban\u0131 olu\u015fturman\u0131za yard\u0131mc\u0131 olur.<\/dd>\n<dt>Taray\u0131c\u0131 tabanl\u0131 oyunlar i\u00e7in ba\u015fka framework'ler veya k\u00fct\u00fcphaneler var m\u0131?<\/dt>\n<dd>Evet, bir\u00e7ok pop\u00fcler oyun motoru ve k\u00fct\u00fcphane bulunmaktad\u0131r. \u00d6rne\u011fin, Phaser, PixiJS ve Babylon.js gibi k\u00fct\u00fcphaneler, sprite animasyonlar\u0131, fizik motorlar\u0131, sahne y\u00f6netimi ve daha fazlas\u0131 gibi haz\u0131r \u00e7\u00f6z\u00fcmler sunarak oyun geli\u015ftirme s\u00fcrecini b\u00fcy\u00fck \u00f6l\u00e7\u00fcde h\u0131zland\u0131rabilir. Bu rehberde Canvas API'\u0131n\u0131 do\u011frudan kullanarak temel prensipleri \u00f6\u011frenmenizi sa\u011flad\u0131k, ancak daha karma\u015f\u0131k oyunlar i\u00e7in bu k\u00fct\u00fcphaneleri ara\u015ft\u0131rman\u0131z\u0131 \u015fiddetle tavsiye ederiz.<\/dd>\n<dt>Oyunumu farkl\u0131 ekran boyutlar\u0131na ve cihazlara nas\u0131l uyumlu hale getirebilirim?<\/dt>\n<dd>Oyununuzun responsive (duyarl\u0131) olmas\u0131n\u0131 sa\u011flamak i\u00e7in CSS media query'lerini kullanarak Canvas elementinin boyutunu ayarlayabilirsiniz. Ayr\u0131ca, oyun i\u00e7indeki nesnelerin boyutlar\u0131n\u0131 ve konumlar\u0131n\u0131, Canvas'\u0131n mevcut boyutlar\u0131na g\u00f6re dinamik olarak \u00f6l\u00e7eklendiren bir oranlama stratejisi (\u00f6rne\u011fin, t\u00fcm koordinatlar\u0131 ve boyutlar\u0131 Canvas'\u0131n mevcut geni\u015fli\u011fine\/y\u00fcksekli\u011fine g\u00f6re oranlamak) kullanmak en etkili y\u00f6ntemdir. Dokunmatik cihazlar i\u00e7in ise fare olaylar\u0131 yerine <code>touchstart<\/code>, <code>touchmove<\/code>, <code>touchend<\/code> gibi dokunmatik olaylar\u0131 dinlemelisiniz.<\/dd>\n<dt>Oyunuma ses efektleri ve fon m\u00fczi\u011fi nas\u0131l ekleyebilirim?<\/dt>\n<dd>Oyununuza ses efektleri ve fon m\u00fczi\u011fi eklemek i\u00e7in HTML5 Audio API'sini kullanabilirsiniz. Basit ses dosyalar\u0131 i\u00e7in <code>new Audio('path\/to\/sound.mp3').play()<\/code> yeterlidir. Daha geli\u015fmi\u015f ses kontrol\u00fc (\u00f6rne\u011fin, ses seviyesi ayar\u0131, efektler, mekansal ses) i\u00e7in Web Audio API'si daha g\u00fc\u00e7l\u00fc bir se\u00e7enek sunar. Ses dosyalar\u0131n\u0131 oyun ba\u015flamadan \u00f6nce y\u00fcklemeyi ve mobil cihazlarda otomatik oynatma k\u0131s\u0131tlamalar\u0131n\u0131 dikkate almay\u0131 unutmay\u0131n (genellikle ilk kullan\u0131c\u0131 etkile\u015fimi sonras\u0131 ses \u00e7al\u0131nabilir).<\/dd>\n<dt>Geli\u015ftirdi\u011fim bu oyunu nas\u0131l yay\u0131nlayabilirim?<\/dt>\n<dd>Taray\u0131c\u0131 tabanl\u0131 bir oyunu yay\u0131nlamak olduk\u00e7a basittir. Projenizin t\u00fcm derlenmi\u015f JavaScript dosyalar\u0131n\u0131 (<code>.js<\/code>), HTML dosyas\u0131n\u0131 (<code>index.html<\/code>) ve t\u00fcm assetleri (resimler, sesler) bir web sunucusuna y\u00fcklemeniz yeterlidir. GitHub Pages, Netlify, Vercel veya basit bir hosting sa\u011flay\u0131c\u0131s\u0131 gibi \u00fccretsiz veya uygun fiyatl\u0131 platformlar \u00fczerinden kolayca yay\u0131nlayabilirsiniz. Oyununuzu bir klas\u00f6re toplay\u0131p bu klas\u00f6r\u00fc sunucuya y\u00fckledi\u011finizde, oyununuz internet \u00fczerinden eri\u015filebilir olacakt\u0131r.<\/dd>\n<\/dl>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-31141","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi<\/title>\n<meta name=\"description\" content=\"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi\" \/>\n<meta property=\"og:description\" content=\"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-06T05:31:59+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"33 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi\",\"datePublished\":\"2025-10-06T05:31:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\"},\"wordCount\":4821,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\",\"name\":\"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-10-06T05:31:59+00:00\",\"description\":\"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi","description":"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/","og_locale":"tr_TR","og_type":"article","og_title":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi","og_description":"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.","og_url":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-10-06T05:31:59+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"33 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi","datePublished":"2025-10-06T05:31:59+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/"},"wordCount":4821,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/","url":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/","name":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-10-06T05:31:59+00:00","description":"Taray\u0131c\u0131 tabanl\u0131 sonsuz ko\u015fu oyunu geli\u015ftirmek mi istiyorsunuz? Bu ad\u0131m ad\u0131m TypeScript rehberiyle HTML5 Canvas, oyun d\u00f6ng\u00fcs\u00fc, \u00e7arp\u0131\u015fma tespiti ve performans ipu\u00e7lar\u0131n\u0131 \u00f6\u011frenerek kendi oyununuzu s\u0131f\u0131rdan in\u015fa edin.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/typescript-ile-tarayicida-sonsuz-kosu-oyunu-gelistirme-rehberi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"TypeScript ile Taray\u0131c\u0131da Sonsuz Ko\u015fu Oyunu Geli\u015ftirme Rehberi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=31141"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31141\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=31141"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=31141"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=31141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}