Çubuğu yükseltmek için mavi kutuya tıklayın ve basılı tutun



Stick champ oyunu

İşte şampiyonumuzun taşların üzerinden atlamak için bir sopa kullandığı küçük oyunumuzun kodu (ayrıntılı açıklama aşağıda):

<html>
<body>
<canvas id="myCanvaswidth="600height="500style='position:absoluteleft:0;'></canvas>
<script>
let canvas = document.getElementById("myCanvas");
let context = canvas.getContext("2d");
context.font = 'bold 30px sans-serif';
context.lineWidth = 4;
let image = new Image();
image.src = "sprite.png";
const maxStones = 6size = 40;
let angle = -Math.PI / 2;
let xyframecurrentStonemoderunoffsetstickLengthstones;
 
function reset() {
    currentStone = 0;
    x = 100;
    y = 360;
    frame = 0;
    stones = [];
    stickLength = 0;
    offset = 0;
    run = 0;
    for (let i = 0i < maxStonesi++) {
        stones[i] = {
            xi * 300 + Math.floor(Math.random() * 80),
            width50 + Math.floor(Math.random() * 50)
        };
    }
    stones[0].x = 80;
    mode = 'wait';
}
 
function animate() {
    context.clearRect(00canvas.widthcanvas.height);
    context.fillText('Kalan mesafe: ' + (maxStones - currentStone - 1), 250100);
    stones.forEach((stone)=>{
        context.fillRect(stone.x - offset398stone.width600);
    }
    );
 
    context.drawImage(imageMath.floor(frame) * size0sizesizex + size / 2ysizesize);
    switch (mode) {
    case 'pointerdown':
        stickLength++;
        break;
    case 'stickFall':
        angle = angle + Math.PI / 64;
        if (angle >= 0)
            mode = 'run';
        break;
    case 'run':
        offset++;
        run++;
        frame = frame + .5;
        if (frame == 20)
            frame = 0;
        if (stickLength == run) {
            mode = 'wait';
            angle = -Math.PI / 2;
            stickLength = 0;
            run = 0;
            let gameOver = true;
            stones.forEach((stone,index)=>{
                if (offset + x + size > stone.x && offset + x < stone.x + stone.width - size) {
                    gameOver = false;
                    currentStone = Math.max(currentStoneindex);
                    if (currentStone == maxStones - 1) {
                        mode = 'gameOver';
                        frame = 21;
                    }
                }
            }
            );
            if (gameOver) {
                mode = 'gameOver';
                frame = 20;
            }
        }
        break;
    case 'gameOver':
        if (currentStone < maxStones - 1) {
            y++;
            context.fillText('Oyun bittiYeniden başlatmak için tıklayın', 2060);
        } else
            context.fillText('KazandınYeniden başlatmak için tıklayın', 2060);
    }
    let x2 = x + (stickLength - run) * Math.cos(angle);
    let y2 = y + (stickLength - run) * Math.sin(angle);
    context.beginPath();
    context.moveTo(x + size - runy + size);
    context.lineTo(x2 + size, y2 + size);
    context.stroke();
    window.requestAnimationFrame(animate);
}
 
window.onpointerdown = function() {
    switch (mode) {
    case 'wait':
        mode = 'pointerdown';
        break;
    case 'gameOver':
        mode = 'wait';
        reset();
    }
};
 
window.onpointerup = function() {
    if (mode == 'pointerdown')
        mode = 'stickFall';
};
reset();
animate();
</script>
</body>
</html>



Satır [1-8] HTML5 Canvas ve 2d bağlamını ayarlar
[9-10] sprite sayfasını tutan görünmez resim (20 kare koşu sekansı, 1 düşüş, 1 kutlama):



[11-13] Oyun değişkenlerini ve sabitlerini tanımla:
[11] maksimum taş sayısı (=katedilecek mesafe), sprite boyutu (40x40 piksel)
[12] çubuğun başlangıç açısı - düz yukarı gider
[13] x - şampiyonun x koordinatı
y - çubuğun tepesinin y koordinatı
frame - mevcut animasyon karesi
currentStone - kaç taşa ulaşıldı
mode - oyun modu (bekle/tıklandı/çubukDüşüşü/oyunBitti)
run - mevcut koşunun uzunluğu
offset - ekranın yatay kaydırma ofseti
stickLength - çubuğun mevcut uzantısı
stones - taş nesneleri dizisi

[15-32] tüm değişkenleri başlangıç değerlerine sıfırla
[24-29] taş pozisyonlarını ve genişliklerini rastgele belirle

[34-96] ana oyun döngüsü:
[35] kareyi temizle
[36] kalan mesafeyi ekranda göster
[37-40] taşları çiz (ekrana sığmasalar bile - işleri basit tutmak için)
[42] sprite'ın mevcut animasyon karesini çiz
drawImage'ın nasıl çalıştığı hakkında ayrıntılara ihtiyacınız varsa, buraya tıklayın
[44-46] işaretçiye (fare/dokunmatik) basılırsa, çubuk uzunluğunu artır
[47-51] çubuk düşüyorsa, açıyı artır.
[49-50] tamamen aşağı düştüyse, oyun modunu "run" (koş) olarak değiştir
[52-80] eğer 'run' modundaysak:
[53-54] ofseti ve koşu uzunluğunu artır
[55] sprite karesi her 2 animasyon karesinde bir değişir
[56-57] spritesheet'teki animasyon sekansının sonuna ulaşırsak, başa dön
[58-62] koşu uzunluğu çubuğun ucuna eşitse; çubuk uzunluğunu, açıyı, koşuyu sıfırla ve 'wait' (bekle) moduna geç
[63-74] taşın üzerine inip inmediğimizi kontrol et:
[63] boş bir alana indiğimizi varsay
[64-65] şampiyon koordinatlarını her taşla karşılaştır
[66] şampiyon bir taşa indiyse, [63]'teki kötümser varsayımı düzelt
[67] currentStone'u (mevcut taşı) hesapla
[68-71] son taşa ulaşıldıysa, kazandın!
[75-78] şampiyon boş bir alana indiyse, modu gameOver (oyun bitti) yap ve düşme pozunu göster
[81-87] 'gameOver' modunda:
[82-84] kaybettiysen, düşersin
[85-86] kazandıysan, kazandın.
[88-89] çubuğun ucunun koordinatlarını hesapla
[90-93] çubuğu çiz
[94] bir sonraki animasyon karesini tetikle

[97-107] ekrana tıklanırsa/dokunulursa:
[98-101] bekliyorsak, 'pointerdown' moduna geçeriz
[102-105] 'gameOver' modundaysak, oyun yeniden başlatılır
[108-111] işaretçi bırakılırsa ve 'pointerdown' modundaysak, 'stickFall' moduna geçeriz
[112] oyunu başlat
[113] animasyonu başlat

Oyunun tadını çıkarın!



GitHub deposu
Tüm kodlar MIT lisansı altında sunulmaktadır