Bu yazıda, javascript ve <canvas> öğesini kullanarak tarayıcınızda oynayabileceğiniz bir oyun oluşturacağız.
Bu yazıdaki örnekleri kullanmak için <canvas> öğesini destekleyen bir tarayıcıya ihtiyacınız olacak.
Daha fazla okumadan önce, oyunu oynamak için “kodu çalıştır” düğmesini tıklayın.
Her bölümde, şu ana kadar geliştirdiğimiz kodu çalıştırmak için “kod çalıştır” düğmesini tıklayabilirsiniz. Bunun dışında her bölümde, butona basar basmaz oyunla aynı kutuda çalıştırılacak olan javascript kodunu içeren bir editör vardır. Kodda değişiklikler yapabilir ve “kod çalıştır” düğmesini tıklatarak sonuçları anında görebilirsiniz.
Bölüm 1: Bir Daire Çizin
Yapmamız gereken ilk şey, <canvas> öğesinin bir örneğini oluşturmaktır, böylece üzerinde çizmeye başlayabiliriz. Örnekte kullandığımız sayfanın kaynağına bakarsanız, şuna benzeyen bir bildirim görürsünüz:
1 2 3 | <canvas id="canvas" width="300" height="300"></canvas> |
Bu bildirim, uygulamanın geri kalanında çizeceğimiz tuvali oluşturur. Şimdi çizmemiz gereken bir tuvalimiz var, hadi başlayalım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <style> #canvas{ border:1px solid red; } </style> <canvas id="canvas" width="400" height="250"></canvas> <script> //tuvalimizi çağırıyoruz. const ctx =document.querySelector('#canvas').getContext("2d"); //daire çiziyoruz. ctx.beginPath(); ctx.arc(75, 75, 15, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); </script> |
Çizimi beginPath()
veclosePath()
arasında yapın. Ekrana bir yay çizmek için arc(…) yada bir kare çizmek için rect() fonksiyonlarını kullanabilirsiniz. Kare çizmek için try ctx.rect(xKord, yKord, Genişlik, Yükseklik)
yazabilirsiniz.
1 2 3 | ctx.arc(x,y,r,sAngle,eAngle,counterclockwise); |
Parametreler
x Dairenin merkezinin x koordinatı
y Dairenin merkezinin y koordinatı
r Dairenin yarıçapı
sAngle Başlama açısı, radyan olarak (0, ark dairenin saat 3 konumunda)
eAngle Radyan olarak bitiş açısı
counterclockwise; Çizimin saat yönünün tersine mi yoksa saat yönünde mi olacağını belirtir. false, varsayılandır ve saat yönünde, true ise saat yönünün tersine gösterir.
Yayı çizdiğinizde beginPath()
ve closePath()
fonksiyonları arasında olduğundan emin olun. koruduğunuzdan ve yukarıdaki örnek çağrıdaki gibi tıpkı çağrıları beginPath () ve closePath () fonksiyonlarına yaptığınızdan emin olun. Ayrıca ctx.fill()
yerine ctx.stroke()
deneyerek değişimi inceleyebilirsiniz.
Bölüm 2: Biraz Renk Ekleyin
Ekrandaki topu farklı renklerde de çevirebiliriz. ctx.fillStyle
öğesinin değerini değiştirmek tuvalin geçerli rengini değiştirir; değerini ‘#rrggbb‘ biçimindeki yada ‘rgba (r, g, b, a)‘ oalrak ayarlayabiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <canvas id="canvas" width="400" height="250"></canvas> <script> //tuvalimizi çağırıyoruz. const ctx =document.querySelector('#canvas').getContext("2d"); //daireyi rengi ile birlikte çiziyoruz. ctx.fillStyle = "#2d3436"; ctx.beginPath(); ctx.arc(75, 75, 15, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); //ikinci daireyi rengi ile birlikte çiziyoruz. ctx.fillStyle = "#d63031"; ctx.beginPath(); ctx.arc(150, 200, 50, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); //kareyi rengi ile birlikte çiziyoruz. Son renk kodu(.5) alfa kanalını göstermektedir. ctx.fillStyle = "rgba(255, 255, 0, .5)" ctx.beginPath(); ctx.rect(15, 150, 120, 120); ctx.closePath(); ctx.fill(); </script> |
Renkler ve dikdörtgenin alfa değeriyle biraz oynayın ve nesnelerin nasıl tepki verdiğini görün.
Bölüm 3: Hareket
Zaten bir top yaptık, şimdi onu hareket ettirelim. Bunu yapmak için, ekranı silen, topu çeken, sonra mevcut konumunu güncelleyen bir ciz() işlevi oluşturacağız. Tarayıcıya, her 10 milisaniyede bir ciz() işlevini çalıştırmasını ve hareket yanılsamasını yaratmasını sağlamak için baslat() işlevinde setInterval (function, timeout) işlevini kullanırız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <canvas id="canvas" width="400" height="250"></canvas> <script> //tuvalimizi çağırıyoruz. const ctx=document.querySelector('#canvas').getContext("2d"); let x = 150,y = 150,dx = 2,dy = 4; function baslat() { return setInterval(ciz, 10); } function ciz() { ctx.clearRect(0,0,300,300); ctx.beginPath(); ctx.arc(x, y, 10, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); x += dx; y += dy; } baslat(); </script> |
Topun yönünü değiştirmek için dx ve dy değerlerini değiştirmeyi deneyin veya topun başlayacağı yeri değiştirmek için x ve y değişkenlerini değiştirin. dx ve dy için negatif değerler denediğinizden emin olun.
Bölüm 4: Kütüphane haline getirelim (oyun-kutuphane.js)
Şimdi bir yerlere geldiğimize göre, kodumuz tek bir ekran için biraz fazla büyüyor, bu yüzden hayatımızı kolaylaştırmak için bazılarını bir işlev kütüphanesine yapıştırmaya başlayacağız. Gelecekteki sayfalarda, ciz() fonksiyonumuza odaklanabilmemiz için kütüphane kodunu oyun-kutuphane.js olarak kaydedeceğiz. Kütüphane dosyasını istediğimiz zaman açıp gerekli düzenlemeleri yapabilir.
oyun-kutuphane.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /*Oyun Kütüphane Başlangıç */ let x = 150, y = 150; let dx = 2; let dy = 4; let WIDTH; let HEIGHT; let intervalId = 0; let ctx; function baslat() { WIDTH = ctx.canvas.width; HEIGHT = ctx.canvas.height; intervalId = setInterval(ciz, 30); } function daire(x,y,r) { ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } function dikdortgen(x,y,w,h) { ctx.beginPath(); ctx.rect(x,y,w,h); ctx.closePath(); ctx.fill(); } function temizle() { ctx.clearRect(0, 0, WIDTH, HEIGHT); } /*Oyun Kütüphane Bitiş */ |
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); function ciz() { temizle(); daire(x, y, 10); x += dx; y += dy; } baslat(); </script> |
Buradaki amaç yapılacak çizime odaklanmak içindi. Şimdi yazdığımız kodları sadeleşti. Yazdığımız koda odaklanabiliriz. ciz() fonksiyonu ekranı temizleyip istediğimiz nesneyi çizmektedir. her 10ms bir yenilendiği için çizilen nesne ekrandan hareket etmektedir.
Bölüm 5: Sıçrama
Topumuz ekranda hareket ediyor, fakat ekran küçük odluğu için ekrandan çok çabuk kaçıyor; Duvarları dikkate alarak topu ekrana tekrar yerleştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); function ciz() { temizle(); daire(x, y, 10); if (x + dx > WIDTH || x + dx < 0) dx = -dx; if (y + dy > HEIGHT || y + dy < 0) dy = -dy; x += dx; y += dy; } baslat(); </script> |
Bölüm 6: Bir tane raket ekleyelim
Artık oyunumuzu gerçek bir oyun gibi yapmayı düşünmeye başlayabiliriz. Bir raket ekleyelim ve sadece topa vurduğunda topun sıçramasına izin verelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); var raketx; var raketH; var raketW; function raket_baslat() { raketx = WIDTH / 2; raketH = 10; //raket yükseklik raketW = 75;//raket genişlik } function ciz() { temizle(); daire(x, y, 10); dikdortgen(raketx, HEIGHT-raketH, raketW, raketH); if (x + dx > WIDTH || x + dx < 0) dx = -dx; if (y + dy < 0) dy = -dy; else if (y + dy > HEIGHT) { if (x > raketx && x < raketx + raketW) dy = -dy; else //kesişme olmazsa oyun biter clearInterval(intervalId); } x += dx; y += dy; } baslat(); raket_baslat(); </script> |
Bölüm 7: Klavye Kontrolü
Raketimize klavye kontrolü eklemek için iki şeye ihtiyacımız var. Sağ ve sol oklara ne zaman basıldığını tespit etmek ve raketi hareket ettirmek. İstediğimiz olayları almak için onkeyup ve onkeydown olaylarını kullanacağız. Bu olaylar gerçekleştiğinde çalıştırmak için bir fonksiyon yazacağız. Daha sonra çizme işlemini bu klavye kontrolüne göre yapıp, raketi hareket ettirmiş olacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); var raketx; var raketH; var raketW; var sagTus = false; var solTus = false; //sag veya sol tuşa basıldığında çalışır. function onKeyDown(evt) { if (evt.keyCode == 39) sagTus = true; else if (evt.keyCode == 37) solTus = true; } //sağ veye sol tuştan el çekildiğinde çalışır. function onKeyUp(evt) { if (evt.keyCode == 39) sagTus = false; else if (evt.keyCode == 37) solTus = false; } document.onkeyup=onKeyUp; document.onkeydown=onKeyDown; function raket_baslat() { raketx = WIDTH / 2; raketH = 10; //raket yükseklik raketW = 75;//raket genişlik } function ciz() { temizle(); daire(x, y, 10); //raketi hareket ettir. if (sagTus) raketx += 5; else if (solTus) raketx -= 5; dikdortgen(raketx, HEIGHT-raketH, raketW, raketH); if (x + dx > WIDTH || x + dx < 0) dx = -dx; if (y + dy < 0) dy = -dy; else if (y + dy > HEIGHT) { if (x > raketx && x < raketx + raketW) dy = -dy; else //game over, so stop the animation clearInterval(intervalId); } x += dx; y += dy; } baslat(); raket_baslat(); </script> |
Bölüm 8: Fare Kullanımı
Oyunumuza fare desteği eklemek klavye eklemekten daha da kolaydır; tek yapmamız gereken onmousemove olayını bir onMouseMove işlevine göndermek, farenin oyunun sınırları dahilinde olup olmadığını görmek ve eğer varsa raketi hareket ettirmek.
Bir önceki bölümde bulunan koda aşağıdaki gibi ekleme yapıyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | *************** var canMinX; var canMaxX; function fare_baslat() { canMinX = document.querySelector('#canvas').offsetLeft; canMaxX = canMinX + WIDTH; } //fare hereketini kontrol edecek mousemove fonksiyonu function onMouseMove(evt) { if (evt.pageX > canMinX && evt.pageX < canMaxX) { raketx = evt.pageX - canMinX; } } //dom document üzerine onMouseMove olayını bağlıypruz. document.onmousemove=onMouseMove; *************** fare_baslat(); |
Kodun eklenmiş hali şu şekilde oluşacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); var raketx; var raketH; var raketW; var sagTus; var solTus; var canMinX; var canMaxX; function fare_baslat() { canMinX = document.querySelector('#canvas').offsetLeft; canMaxX = canMinX + WIDTH; } //fare hereketini kontrol edecek mousemove fonksiyonu function onMouseMove(evt) { if (evt.pageX > canMinX && evt.pageX < canMaxX) { raketx = evt.pageX - canMinX; } } //dom document üzerine onMouseMove olayını bağlıypruz. document.onmousemove=onMouseMove; //sag veya sol tuşa basıldığında çalışır. function onKeyDown(evt) { if (evt.keyCode == 39) sagTus = true; else if (evt.keyCode == 37) solTus = true; } //sağ veye sol tuştan el çekildiğinde çalışır. function onKeyUp(evt) { if (evt.keyCode == 39) sagTus = false; else if (evt.keyCode == 37) solTus = false; } document.onkeyup=onKeyUp; document.onkeydown=onKeyDown; function raket_baslat() { raketx = WIDTH / 2; raketH = 10; //raket yükseklik raketW = 75;//raket genişlik } function ciz() { temizle(); daire(x, y, 10); //raketi hareket ettir. if (sagTus) raketx += 5; else if (solTus) raketx -= 5; dikdortgen(raketx, HEIGHT-raketH, raketW, raketH); if (x + dx > WIDTH || x + dx < 0) dx = -dx; if (y + dy < 0) dy = -dy; else if (y + dy > HEIGHT) { if (x > raketx && x < raketx + raketW) dy = -dy; else //game over, so stop the animation clearInterval(intervalId); } x += dx; y += dy; } baslat(); raket_baslat(); fare_baslat(); </script> |
Bölüm 9: Tuğlaların Yapımı
Şimdi tuğlaları tutmak için 2 boyutlu bir dizi oluşturacağız, kırılmayanları çizmek için birkaç halka kullanacağız ve vurulduklarında tuğlaları kaldırdığınızdan emin olun.
Önceki bölümde bulunan kodları kütüphane içine ekeyip tuğlaların yapımına geçiyorum. Kütüphane dosyasına eklerken ciz() fonksiyonu eklenmediğini belirtmek isterim(üzerinde düzenleme yapacağız.) Değişen kütüphane dosyası şu şekilde oluşacaktır.
kutuphane.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | /*Oyun Kütüphane Başlangıç */ let x = 150, y = 150; let dx = 2; let dy = 4; let WIDTH; let HEIGHT; let intervalId = 0; let ctx; var raketx; var raketH; var raketW; var sagTus; var solTus; var canMinX; var canMaxX; //Unutmayın!!! ctx kutuphane dosyasında tanımlanmıştır. ctx=document.querySelector('#canvas').getContext("2d"); function baslat() { WIDTH = ctx.canvas.width; HEIGHT = ctx.canvas.height; intervalId = setInterval(ciz, 30); } function daire(x,y,r) { ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } function dikdortgen(x,y,w,h) { ctx.beginPath(); ctx.rect(x,y,w,h); ctx.closePath(); ctx.fill(); } function temizle() { ctx.clearRect(0, 0, WIDTH, HEIGHT); } function fare_baslat() { canMinX = document.querySelector('#canvas').offsetLeft; canMaxX = canMinX + WIDTH; } //fare hereketini kontrol edecek mousemove fonksiyonu function onMouseMove(evt) { if (evt.pageX > canMinX && evt.pageX < canMaxX) { raketx = evt.pageX - canMinX; } } //dom document üzerine onMouseMove olayını bağlıypruz. document.onmousemove=onMouseMove; //sag veya sol tuşa basıldığında çalışır. function onKeyDown(evt) { if (evt.keyCode == 39) sagTus = true; else if (evt.keyCode == 37) solTus = true; } //sağ veye sol tuştan el çekildiğinde çalışır. function onKeyUp(evt) { if (evt.keyCode == 39) sagTus = false; else if (evt.keyCode == 37) solTus = false; } document.onkeyup=onKeyUp; document.onkeydown=onKeyDown; function raket_baslat() { raketx = WIDTH / 2; raketH = 10; //raket yükseklik raketW = 75;//raket genişlik } /*Oyun Kütüphane Bitiş */ |
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | <canvas id="canvas" width="400" height="250"></canvas> <script src="oyun-kutuphane.js"></script> <script> var tuglalar; var satirSayisi; var sutunSayisi; var tuglaGenislik; var tuglaYukseklik; var bosluk; function tugla_baslat() { satirSayisi = 5; sutunSayisi = 5; tuglaGenislik = (WIDTH/sutunSayisi) - 1; tuglaYukseklik = 15; bosluk = 1; tuglalar = new Array(satirSayisi); for (i=0; i < satirSayisi; i++) { tuglalar[i] = new Array(sutunSayisi); for (j=0; j < sutunSayisi; j++) { tuglalar[i][j] = 1; } } console.log(tuglalar) } function ciz() { temizle(); daire(x, y, 10); //raketi hareket ettir. if (sagTus) raketx += 5; else if (solTus) raketx -= 5; dikdortgen(raketx, HEIGHT-raketH, raketW, raketH); //tuğlaları çizdirme for (i=0; i < satirSayisi; i++) { for (j=0; j < sutunSayisi; j++) { if (tuglalar[i][j] == 1) { dikdortgen((j * (tuglaGenislik + bosluk)) + bosluk, (i * (tuglaYukseklik + bosluk)) + bosluk, tuglaGenislik, tuglaYukseklik); } } } //Tuğlar vuruldu mu? rowheight = tuglaYukseklik + bosluk; colwidth = tuglaGenislik + bosluk; row = Math.floor(y/rowheight); col = Math.floor(x/colwidth); //top ile eşleşen tuğlaların bulunduğu dizideki 1 değerlerini 0 olarak değiştir if (y < sutunSayisi * rowheight && row >= 0 && col >= 0 && tuglalar[row][col] == 1) { dy = -dy; tuglalar[row][col] = 0; } if (x + dx > WIDTH || x + dx < 0) dx = -dx; if (y + dy < 0) dy = -dy; else if (y + dy > HEIGHT) { if (x > raketx && x < raketx + raketW) dy = -dy; else clearInterval(intervalId); } x += dx; y += dy; } baslat(); raket_baslat(); fare_baslat(); tugla_baslat(); </script> |
Sonuç olarak canvas ile yapacaklarınız size kalmış. Oyun yada benzer uygulamaların tamamında ekrandaki bilgiyi tekrar tekrar çizip temizleme söz konusun. Bu uygulama ile anlatacaklarım bu kadar. Site içinde diğer canvas örneklerine bakabilirsiniz.
Yorum Yap