Skip to content

Latest commit

 

History

History
339 lines (216 loc) · 13.1 KB

File metadata and controls

339 lines (216 loc) · 13.1 KB

Soru : animation(frameCount){

this.frameCount = frameCount;

this.currentFrame = 0;

this.frameTimer = 0.0;

}

update(deltaTime){

this.animation(4);

this.frameTimer += deltaTime;

if(this.frameTimer>= this.animationSpeed)

{

this.currentFrame++;

this.frameTimer = 0.0;

}

if(this.currentFrame>=this.frameCount)

this.currentFrame = 0;

}bu kodda neden frameler değişmiyor?

Sorunun sebebi, update(deltaTime) döngüsünün içinde this.animation(4) metodunu sürekli çağırıyor olman. Oyun veya animasyon motorlarında update fonksiyonu saniyede defalarca (genellikle 60 kez) çalışır. update her çalıştığında this.animation(4) fonksiyonunu tetikliyorsun ve o fonksiyonun içine bakarsak şu iki satırı görüyoruz: JavaScript

this.currentFrame = 0; this.frameTimer = 0.0;

Yani update her döndüğünde senin frame sayacını ve zamanlayıcını sürekli sıfırlıyor. Bu yüzden frameTimer değerin hiçbir zaman this.animationSpeed değerine ulaşıp bir sonraki kareye geçemiyor.

update(playerX,playerY){

            this.angle =(90.0-Math.atan2(this.x+this.width-cross.x,this.y+this.height/2-cross.y));//silah ile crosshair arasındaki açıyı buluyoruz

            

            if(this.isClicked && Date.now()-this.clickTime >= 400){

                this.currentFrame = 0;

                this.isClicked = false;

            }

            

            if(this.angle>90.00&&this.angle<93.0){

              

                this.x = playerX+player.width-35;

                this.y = playerY+45;

                

            }   

            else{

                this.x = playerX-25;

                this.y = playerY+45;

            }

               

            

    }

Açıda bir hata mı var? Cevap: şte kodundaki o 3 matematiksel hata:

Math.atan2 Parametre Sırası: JavaScript'te bu fonksiyon (y, x) sırasıyla çalışır. Ancak sen önce x değerini, sonra y değerini vermişsin.

Hedef - Kaynak Mantığı: İki nokta arasındaki açıyı bulurken her zaman "Hedef eksi Kaynak" yapılmalıdır. Sen tüfeğin pozisyonundan farenin pozisyonunu çıkarmışsın (this.x - cross.x). Bunun tam tersi olmalıydı.

Radyan ve Derece Karışıklığı (En kritiği): Math.atan2 fonksiyonu sana derece (0-360) değil, Radyan (yaklaşık -3.14 ile +3.14 arası bir değer) döndürür. Sen bu değeri 90.0 (derece) sayısından çıkarmaya çalışmışsın. Elmalarla armutları toplamaya çalıştığın için ortaya çıkan sayı, Math.cos ve Math.sin içine girdiğinde sistemi tamamen bozmuş.update(playerX, playerY) {
// 1. Silahın merkez (pivot) noktasını bul (Ateş etme kodundakiyle aynı olmalı)
let pivotX = this.x + this.width / 2;
let pivotY = this.y + this.height / 2;

// 2. DOĞRU AÇI HESAPLAMASI (Önce Y, sonra X ve Hedef - Kaynak)
let dy = cross.y - pivotY;
let dx = cross.x - pivotX;

// Tertemiz, doğrudan trigonometrik radyan açısı. Hiçbir sayıdan çıkarma!
this.angle = Math.atan2(dy, dx); 

// 3. Tıklama animasyonu kontrolü
if (this.isClicked && Date.now() - this.clickTime >= 400) {
    this.currentFrame = 0;
    this.isClicked = false;
}

// 4. SİLAHIN SAĞA/SOLA GEÇME MANTIĞI
// Artık o garip (90-93) açı hesaplarına ihtiyacımız yok. 
// Fare (cross), karakterin solunda mı sağında mı? Buna bakmak çok daha güvenilir!
let playerCenter = playerX + (player.width / 2); // Karakterin tam ortası

if (cross.x > playerCenter) {
    // Fare karakterin SAĞINDA ise tüfek sağda dursun
    this.x = playerX + player.width - 35; 
    this.y = playerY + 45;
} else {
    // Fare karakterin SOLUNDA ise tüfek solda dursun
    this.x = playerX - 25; 
    this.y = playerY + 45;
}

}

Soru: if(bullet.x <= enemy.x + enemy.width &&

bullet.x + bullet.width >= enemy.x&&

bullet.y + bullet.height>= enemy.y &&

bullet.y <= enemy.y + enemy.height)

{

enemy.death = true;

setTimeout(enemy.x = -700, 5000);

player.bullets+=2;

}

Cevap: It looks like you're working on the collision detection between a bullet and an enemy for your 2D game! Your Axis-Aligned Bounding Box (AABB) collision logic is perfectly correct.

However, there is a bug in how you are using setTimeout that will cause the enemy to teleport instantly instead of waiting 5 seconds.

Here is the issue: JavaScript

setTimeout(enemy.x = -700, 5000);

Because you wrote enemy.x = -700 directly inside the parentheses, JavaScript executes that assignment immediately. It then takes the result (-700) and tries to use it as the function for setTimeout, which won't work.

To fix this, you need to wrap the code you want to delay inside a callback function (like an arrow function). The Fix: JavaScript

if (bullet.x <= enemy.x + enemy.width && bullet.x + bullet.width >= enemy.x && bullet.y + bullet.height >= enemy.y && bullet.y <= enemy.y + enemy.height)
{ enemy.death = true;

// Wrap the assignment in an arrow function
setTimeout(() => {
    enemy.x = -700;
}, 5000);

player.bullets += 2;

} Soru: html canvasta yüklediğim terrain asseti stretchlenince bulanıklaşıyor. Çevap: HTML Canvas'ta bir görseli (özellikle piksel art veya harita/terrain assetlerini) büyüttüğünüzde bulanıklaşmasının sebebi, tarayıcıların varsayılan olarak görselleri yumuşatma (anti-aliasing/smoothing) işlemi uygulamasıdır. Bu özellik fotoğraflar için harikadır ama oyun assetlerinde piksellerin birbirine karışmasına ve çamur gibi bir görüntü oluşmasına yol açar.

Bunu çözmek için uygulayabileceğiniz iki temel adım var:

  1. Canvas Context Üzerinde Yumuşatmayı Kapatmak (En Önemlisi)

Görseli ekrana çizdirmeden (yani drawImage fonksiyonunu kullanmadan) hemen önce 2D context üzerinden imageSmoothingEnabled özelliğini kapatmanız gerekir. Bu, tarayıcıya resmi "nearest-neighbor" algoritmasıyla (pikselleri bozmadan, blok blok) büyütmesini söyler. JavaScript

const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d');

// Yumuşatmayı (anti-aliasing) devre dışı bırak ctx.imageSmoothingEnabled = false;

// Eğer çok eski tarayıcıları da desteklemeniz gerekiyorsa şunları da ekleyebilirsiniz: ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false;

// Sonrasında asset'inizi çizebilirsiniz // ctx.drawImage(terrainImage, x, y, stretchedWidth, stretchedHeight);

Önemli Not: canvas.width veya canvas.height değerlerini kod içinde her değiştirdiğinizde (örneğin pencere yeniden boyutlandırıldığında), bu ayar varsayılan olarak tekrar true değerine sıfırlanır. Eğer canvas boyutunu dinamik değiştiriyorsanız, imageSmoothingEnabled = false; kodunu boyut değişiminden hemen sonra tekrar çağırdığınızdan emin olun.
  1. CSS Üzerinden Pikselleştirme (Eğer Canvas'ı CSS ile Büyütüyorsanız)

Eğer canvas'ın iç çözünürlüğü (width/height özellikleri) küçükse ama CSS ile ekranda büyük görünmesi için esnetiyorsanız (örneğin width: 100% veya width: 800px gibi), CSS tarafında da tarayıcıya pikselleri keskin tutmasını söylemeniz gerekir.

Canvas elementinize şu CSS kurallarını ekleyin: CSS

canvas { /* Piksellerin keskin (pixelated) kalmasını sağlar / image-rendering: -moz-crisp-edges; / Firefox / image-rendering: -webkit-optimize-contrast;/ Safari / image-rendering: crisp-edges; image-rendering: pixelated; / Chrome ve Edge */ }

Soru: Bu spritesheeti javascriptte nasıl implement edeceğim?

Temel mantık şudur: Bu büyük resmi (spritesheet) hafızaya yüklersin, ancak ekrana tamamını çizmezsin. Bunun yerine, resmi bir "ızgara" (grid) gibi düşünürsün. Ekrana her saniye, bu ızgaranın sadece bir hücresini (tek bir kareyi) kesip çizersin. Hangi hücreyi çizeceğini de zamanlayıcılara ve karakterin o anki durumuna (koşuyor mu, duruyor mu?) göre belirlersin.

İşte bunu projende nasıl uygulayabileceğini gösteren, anlaşılır bir Pseudo Code (Sözde Kod):

  1. Başlangıç Değişkenleri

Öncelikle oyun motoruna resmin boyutlarını ve karakterin durumunu tanıtmalısın.

  1. Güncelleme Döngüsü (Update Loop)

Oyunun her karesinde (örneğin saniyede 60 kez) çalışacak mantık. Burada hangi animasyonun oynayacağına ve karenin ne zaman ilerleyeceğine karar veririz. / --- OYUN DÖNGÜSÜ (MANTIK) ---

Fonksiyon Guncelle(gecenZaman):

// 1. Kullanıcı girdisine göre animasyon satırını seç
Eğer (TusaBasildi("SAG_OK") veya TusaBasildi("SOL_OK")) ise:
    gecerliSatir = YURUME_ANIMASYONU
    aktifAnimasyonKareSayisi = 6 // Yürüme satırında 6 kare var
    
Değilse Eğer (TusaBasildi("BOSLUK")) ise:
    gecerliSatir = ZIPLAMA_ANIMASYONU
    aktifAnimasyonKareSayisi = 5 // Zıplama satırında 5 kare var
    
Değilse:
    // Hiçbir tuşa basılmıyorsa durma animasyonuna dön
    gecerliSatir = DURMA_ANIMASYONU
    aktifAnimasyonKareSayisi = 4 


// 2. Zamanlayıcıyı kullanarak kareyi (frame) ilerlet
zamanlayici = zamanlayici + gecenZaman

Eğer (zamanlayici >= animasyonHizi) ise:
    gecerliKare = gecerliKare + 1 // Bir sonraki resme geç
    zamanlayici = 0.0             // Zamanlayıcıyı sıfırla
    
    // Eğer o animasyonun son karesini geçtiysek, başa sar (Döngü)
    Eğer (gecerliKare >= aktifAnimasyonKareSayisi) ise:
        gecerliKare = 0
  1. Çizim Döngüsü (Draw Loop) Hesaplanan karenin X,Y değerlerini kullanarak büyük resimden kesip ekrana yazarız. ParcaCiz(tavsanSprite, kesmeNoktasiX, kesmeNoktasiY, KARE_GENISLIGI, KARE_YUKSEKLIGI, karakterX_Pozisyonu, karakterY_Pozisyonu)

draw(){         context.save();         context.translate(this.x+this.width,this.y);         if(this.death){             context.scale(-1,1);             context.drawImage(this.deathImage,this.currentFramethis.frameWidth,0,0,0,                 this.width,this.height             )         }         else{         context.scale(-1,1);         context.drawImage(this.image,this.currentFramethis.frameWidth,0,             this.frameWidth,this.frameHeight,             0,0,this.width,this.height // translate yaptığımız için x ve y değerlerini 0 giriyoruz.         );         context.restore();         }                     } bu koddaki sıkıntı nedir

Merhaba! Kodunuzu inceledim. Canvas ile sprite animasyonları yaparken bu tarz ufak gözden kaçmalar çok normaldir. Kodunuzda uygulamanın düzgün çalışmasını engelleyen iki kritik hata ve düzeltilebilecek bir yapısal durum bulunuyor.

Koddaki Temel Sorunlar

  1. context.restore() Fonksiyonunun Yanlış Yerde Olması: context.restore() komutunu sadece else bloğunun içine yazmışsınız. Eğer karakteriniz ölürse (this.death durumu true olursa), kod if bloğuna girecek ve en başta çağrılan context.save() işlemi asla restore() edilmeyecektir. Bu durum, her "ölüm" karesinde translate ve scale işlemlerinin sürekli üst üste binmesine (stacking) neden olur. Sonucunda çizimleriniz ekrandan kaybolur veya tamamen bozulur.

  2. drawImage Komutunun Hatalı Parametreleri: if(this.death) bloğunun içindeki drawImage fonksiyonuna 7 adet parametre göndermişsiniz. Canvas API'sinde drawImage fonksiyonu yalnızca 3, 5 veya 9 parametre ile çalışır; aksi takdirde tarayıcı konsolunda TypeError hatası alırsınız. Ayrıca kaynak genişlik ve yüksekliğini 0, 0 olarak girmişsiniz, bu yüzden hata vermese bile ekrana hiçbir şey çizilmez. else bloğunda yaptığınız gibi 9 parametreli doğru yapıyı kurmalısınız.

  3. Gereksiz Kod Tekrarı: context.scale(-1,1); komutu her iki koşulun içinde de yer alıyor. Bunu if/else koşulundan hemen önceye alarak kodunuzu sadeleştirebiliriz.

Düzeltilmiş ve Optimize Edilmiş Kod Hataların giderilmiş ve daha temiz hale getirilmiş versiyonunu aşağıda bulabilirsiniz:

JavaScript draw() { context.save(); context.translate(this.x + this.width, this.y);

// Her iki durumda da yansıtma (scale) yapılacağı için dışarı alıyoruz.
context.scale(-1, 1); 

if (this.death) {
    // Eksik ve hatalı parametreler 9 parametreli versiyona göre düzeltildi.
    context.drawImage(
        this.deathImage, 
        this.currentFrame * this.frameWidth, 0, 
        this.frameWidth, this.frameHeight, // 0, 0 olan sWidth ve sHeight düzeltildi
        0, 0, this.width, this.height
    );
} else {
    context.drawImage(
        this.image, 
        this.currentFrame * this.frameWidth, 0,
        this.frameWidth, this.frameHeight,
        0, 0, this.width, this.height // translate yaptığımız için x ve y değerlerini 0 giriyoruz.
    );
}

// restore() komutunu if/else bloğunun tamamen dışına, en sona alıyoruz.
context.restore(); 

} Bu değişikliklerle birlikte animasyonunuz hem ölüm durumunda hem de normal durumda canvas ayarlarını bozmadan sorunsuz bir şekilde çizilecektir.