CodeWeek 2025 kapsamında Yeşil Vatan temasıyla Kahramanmaraş TOBB Fen Lisesi kodlama etkinliği başlatıyor. Bu kapsamda HTML tabanlı YEŞİL VATAN temalı bir yılan oyunu geliştiriyoruz. Oyunun bitmiş haline ve kaynak kodlarına aşağıdan erişebilirsiniz.
Oyunu Denemek İçin Tıklayın
- Aşağıdaki kodları kopyalayın.
- Visual Studio Code'da File menüsünden New File alt menüsüne tıklayın.
- index.html adında yeni bir dosya oluşturun ve aşağıdaki kodları sayfaınıza yapıştırıp kaydedin.
- Ardından kodlarınınızı F5 tuşuyla çalıştırın.
- Kodlarda değişiklik yaparak kendi özelleştirilmiş versiyonunuzu geliştirebilirsiniz.
<!DOCTYPE html><html lang="tr"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Yeşil Vatan - Yılan Oyunu</title><style>:root{--bg:#e9f7ee;--panel:#dff1df;--accent:#2b7a3b;--dark:#15421f;--muted:#6b8a6a;}body{margin:0;font-family:Inter, Arial, sans-serif;background: linear-gradient(180deg, #f0fff4 0%, var(--bg) 100%);display:flex;align-items:center;justify-content:center;min-height:100vh;gap:20px;padding:20px;color:var(--dark);}.container{display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap;}.game-card{background:var(--panel);border-radius:12px;padding:16px;box-shadow:0 8px 20px rgba(0,0,0,0.08);}canvas{background:linear-gradient(90deg,#dff7e6,#e8f9ee);border-radius:8px;display:block;}.hud{display:flex;gap:10px;align-items:center;margin-bottom:10px;flex-wrap:wrap;}.stat{background:#fff;padding:8px 12px;border-radius:8px;box-shadow:0 4px 10px rgba(0,0,0,0.05);min-width:88px;text-align:center;}.stat small{display:block;color:var(--muted);font-size:12px}.controls{display:flex;gap:8px;margin-top:8px;}button{background:var(--accent);color:white;border:0;padding:8px 12px;border-radius:8px;cursor:pointer;font-weight:600;}button.ghost{background:transparent;color:var(--dark);border:1px solid rgba(21,66,31,0.12);}.mobile-ctrl{display:none;margin-top:10px;user-select:none;-webkit-user-select:none;}.dpad{width:160px;height:160px;position:relative;display:grid;grid-template-columns:1fr 1fr 1fr;grid-template-rows:1fr 1fr 1fr;gap:8px;}.dpad button{width:48px;height:48px;border-radius:8px;padding:0;}.dpad .center{grid-column:2;grid-row:2;background:transparent;box-shadow:none}@media (max-width:800px){.container{flex-direction:column; align-items:center;}.mobile-ctrl{display:block;}}.foot{margin-top:8px;font-size:13px;color:var(--muted)}</style></head><body><div class="container"><div class="game-card"><div class="hud"><div class="stat"><div id="score">0</div><small>Skor</small></div><div class="stat"><div id="highscore">0</div><small>Yüksek Skor</small></div><div class="stat"><div id="level">1</div><small>Seviye</small></div><div style="margin-left:auto"><button id="pauseBtn" class="ghost">Duraklat</button><button id="restartBtn">Yeniden Başlat</button></div></div><canvas id="game" width="600" height="600"></canvas><div class="foot">Tema: <strong>Yeşil Vatan</strong> — Fidan topla, ağaç dik, toprağı yeşillendir 🌱</div><div class="mobile-ctrl"><div style="display:flex;gap:8px;justify-content:center;margin-top:10px"><div class="dpad" id="dpad"><div></div><button data-dir="up">↑</button><div></div><button data-dir="left">←</button><div class="center"></div><button data-dir="right">→</button><div></div><button data-dir="down">↓</button><div></div></div></div><div style="text-align:center;margin-top:8px;color:var(--muted)">Mobil için dokunmatik yön tuşları</div></div></div><div class="game-card" style="min-width:240px;max-width:360px;"><h3 style="margin:0 0 8px 0;color:var(--dark)">Oyun Bilgileri</h3><p style="margin:0 0 8px 0;color:var(--muted)">Yeşil Vatan Yılan Oyunu'nda fidanları (yeşil yem) toplayarak skor kazanırsın. Her 3 fidan topladığında toprağa yeni bir ağaç engeli eklenir. Engellere veya kendi bedenine çarparsan oyun biter.</p><ul style="margin:8px 0 0 16px;color:var(--muted)"><li>Kontroller: Ok tuşları / WASD / Mobil dokunmatik</li><li>Duraklat: "Duraklat" butonu</li><li>Yüksek skor tarayıcıda saklanır</li></ul><hr style="margin:12px 0"><h4 style="margin:6px 0 4px 0">Seviye ve Hız</h4><p style="margin:0;color:var(--muted)">Seviye arttıkça yılanın hızı artar. Her 5 yemde seviye artar.</p><div style="margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;"><button id="muteBtn" class="ghost">Ses Kapat</button><button id="saveScoreBtn" class="ghost">Skoru Manuel Kaydet</button></div></div></div><script>/*Yeşil Vatan - SnakeTürkçe yorumlar ile tek dosya*/// --- Ayarlar ---const canvas = document.getElementById('game');const ctx = canvas.getContext('2d');const gridSize = 20; // grid kutu boyutu (px)const cols = canvas.width / gridSize;const rows = canvas.height / gridSize;let snake = [{x: Math.floor(cols/2), y: Math.floor(rows/2)}];let dir = {x:1,y:0}; // başlangıç yönü sağlet nextDir = null;let food = null;let obstacles = [];let score = 0;let highScore = parseInt(localStorage.getItem('yesilVatanHighScore') || '0',10);let level = 1;let speed = 8; // hareket/saniyelet running = true;let eatenSinceLastObstacle = 0;let foodCountTotal = 0;let muted = false;// HUD elemanlarıconst scoreEl = document.getElementById('score');const highEl = document.getElementById('highscore');const levelEl = document.getElementById('level');const pauseBtn = document.getElementById('pauseBtn');const restartBtn = document.getElementById('restartBtn');const muteBtn = document.getElementById('muteBtn');const saveScoreBtn = document.getElementById('saveScoreBtn');highEl.textContent = highScore;// Ses: basit WebAudio efektlericonst AudioCtx = window.AudioContext || window.webkitAudioContext;let audioCtx = null;function ensureAudio(){if(!audioCtx) audioCtx = new AudioCtx();}function beep(freq=440, duration=0.08, gain=0.08){if(muted) return;ensureAudio();const o = audioCtx.createOscillator();const g = audioCtx.createGain();o.type='sine';o.frequency.value = freq;g.gain.value = gain;o.connect(g); g.connect(audioCtx.destination);o.start();o.stop(audioCtx.currentTime + duration);}// Yardımcı: rastgele grid pozisyonu çakışma kontrolüfunction randomGridPosition(){return {x: Math.floor(Math.random()*cols),y: Math.floor(Math.random()*rows)};}function positionCollides(pos, list){return list.some(p => p.x===pos.x && p.y===pos.y);}// Yeni fidan oluşturfunction spawnFood(){let tries = 0;while(tries < 200){const p = randomGridPosition();if(positionCollides(p, snake)) { tries++; continue; }if(positionCollides(p, obstacles)) { tries++; continue; }food = p;return;}// Eğer yer kalmadıysa oyunu bitirfood = null;}// Yeni engel (ağaç) eklefunction addObstacle(){let tries=0;while(tries<300){const p = randomGridPosition();if(positionCollides(p, snake) || (food && p.x===food.x && p.y===food.y) || positionCollides(p, obstacles)){tries++; continue;}obstacles.push(p);return;}}// Oyun sıfırlamafunction resetGame(){snake = [{x: Math.floor(cols/2), y: Math.floor(rows/2)}];dir = {x:1,y:0};nextDir = null;obstacles = [];score = 0;level = 1;speed = 8;eatenSinceLastObstacle = 0;foodCountTotal = 0;running = true;spawnFood();updateHUD();}// HUD güncellefunction updateHUD(){scoreEl.textContent = score;highEl.textContent = highScore;levelEl.textContent = level;}// Çarpışma kontrolüfunction checkGameOver(head){// kendi vücuduna çarpmafor(let i=1;i<snake.length;i++){if(snake[i].x===head.x && snake[i].y===head.y) return true;}// engel çarpmasıif(positionCollides(head, obstacles)) return true;// duvar yerine sarmalı davranış: dışarı çıkarsa karşı taraftan girreturn false;}// Hızı güncelle (seviye ile)function updateSpeed(){// temel hız + level faktörüspeed = 8 + Math.floor((level-1)*1.5);}// Oyun döngüsü (zaman tabanlı)let lastTime = 0;let moveInterval = 1000 / speed;function loop(timestamp){if(!running){lastTime = timestamp;requestAnimationFrame(loop);return;}if(!lastTime) lastTime = timestamp;const elapsed = timestamp - lastTime;moveInterval = 1000 / speed;if(elapsed > moveInterval){update(); // oyun mantığılastTime = timestamp;}draw();requestAnimationFrame(loop);}// Mantık güncellefunction update(){if(nextDir){// dikey/horizontal tersine gitmeyi engelleif(!(nextDir.x === -dir.x && nextDir.y === -dir.y)){dir = nextDir;}nextDir = null;}const head = {x: snake[0].x + dir.x, y: snake[0].y + dir.y};// sınırları sarmal: ekranın diğer tarafından geri gelsinif(head.x < 0) head.x = cols-1;if(head.x >= cols) head.x = 0;if(head.y < 0) head.y = rows-1;if(head.y >= rows) head.y = 0;if(checkGameOver(head)){// oyun biterbeep(120,0.25,0.15);running = false;pauseBtn.textContent = "Devam Et";// yüksek skor kaydetif(score > highScore){highScore = score;localStorage.setItem('yesilVatanHighScore', String(highScore));}updateHUD();return;}snake.unshift(head);// yemi yediyseif(food && head.x===food.x && head.y===food.y){score += 10;foodCountTotal++;eatenSinceLastObstacle++;beep(880,0.06,0.08); // yeme sesi// her 3 yemde yeni engelif(eatenSinceLastObstacle >= 3){addObstacle();eatenSinceLastObstacle = 0;beep(220,0.1,0.08);}// seviye artışı her 5 yemif(foodCountTotal % 5 === 0){level++;updateSpeed();}spawnFood();} else {// normal hareket: kuyruğu kessnake.pop();}// skor HUDif(score > highScore){highScore = score;localStorage.setItem('yesilVatanHighScore', String(highScore));}updateHUD();}// Çizimfunction draw(){// temizlectx.clearRect(0,0,canvas.width,canvas.height);// hafif toprak dokusufor(let x=0;x<cols;x++){for(let y=0;y<rows;y++){if((x+y)%2===0){ctx.fillStyle = '#eaf9ec';} else {ctx.fillStyle = 'rgba(238,253,240,0.7)';}ctx.fillRect(x*gridSize,y*gridSize,gridSize,gridSize);}}// engeller (ağaçlar)obstacles.forEach(o => {const cx = o.x*gridSize + gridSize/2;const cy = o.y*gridSize + gridSize/2;// gövdectx.fillStyle = '#8b5a2b';ctx.fillRect(o.x*gridSize + gridSize*0.35, o.y*gridSize + gridSize*0.5, gridSize*0.3, gridSize*0.45);// yaprak katmanlarıctx.fillStyle = '#2f8a3a';ctx.beginPath();ctx.ellipse(cx, cy - 4, gridSize*0.45, gridSize*0.35, 0, 0, Math.PI*2);ctx.fill();ctx.beginPath();ctx.ellipse(cx, cy - gridSize*0.08, gridSize*0.35, gridSize*0.25, 0, 0, Math.PI*2);ctx.fill();});// fidan (food)if(food){const fx = food.x*gridSize;const fy = food.y*gridSize;// toprakctx.fillStyle = '#b3e6b3';ctx.fillRect(fx+4, fy+4, gridSize-8, gridSize-8);// küçük fidanctx.fillStyle = '#2e8b33';ctx.fillRect(fx + gridSize*0.45, fy + gridSize*0.25, gridSize*0.1, gridSize*0.45);ctx.fillStyle = '#4ccc64';ctx.beginPath();ctx.moveTo(fx + gridSize*0.5, fy + gridSize*0.25);ctx.lineTo(fx + gridSize*0.33, fy + gridSize*0.45);ctx.lineTo(fx + gridSize*0.67, fy + gridSize*0.45);ctx.fill();}// yılan (baş farklı renkte)for(let i=0;i<snake.length;i++){const s = snake[i];const x = s.x * gridSize;const y = s.y * gridSize;if(i===0){// başctx.fillStyle = '#15421f';roundRect(ctx, x+1, y+1, gridSize-2, gridSize-2, 6, true);// gözctx.fillStyle = '#dff5e9';ctx.fillRect(x + gridSize*0.55, y + gridSize*0.28, gridSize*0.08, gridSize*0.08);} else {// gövde// degrade için index kullanconst t = 0.3 + 0.7*(i/snake.length);ctx.fillStyle = `rgba(${Math.floor(20*t+30)}, ${Math.floor(90*t+120)}, ${Math.floor(30*t+40)}, 1)`;roundRect(ctx, x+1, y+1, gridSize-2, gridSize-2, 5, true);}}// eğer duraklatıldıysa ekranda mesajif(!running){ctx.fillStyle = 'rgba(0,0,0,0.35)';ctx.fillRect(0, canvas.height/2 - 40, canvas.width, 80);ctx.fillStyle = '#fff';ctx.font = '28px Arial';ctx.textAlign = 'center';ctx.fillText('Oyun Bitti — Yeniden Başlatın', canvas.width/2, canvas.height/2 + 8);}}// yardım: yuvarlak dikdörtgenfunction roundRect(ctx, x, y, w, h, r, fill){ctx.beginPath();ctx.moveTo(x + r, y);ctx.arcTo(x + w, y, x + w, y + h, r);ctx.arcTo(x + w, y + h, x, y + h, r);ctx.arcTo(x, y + h, x, y, r);ctx.arcTo(x, y, x + w, y, r);ctx.closePath();if(fill) ctx.fill();}// Klavye ve buton kontrolleriwindow.addEventListener('keydown', e => {if(['ArrowUp','ArrowDown','ArrowLeft','ArrowRight','w','a','s','d','W','A','S','D'].includes(e.key)){e.preventDefault();handleKey(e.key);} else if(e.key === ' '){ // space pausetogglePause();}});function handleKey(k){if(k === 'ArrowUp' || k === 'w' || k === 'W') nextDir = {x:0,y:-1};if(k === 'ArrowDown' || k === 's' || k === 'S') nextDir = {x:0,y:1};if(k === 'ArrowLeft' || k === 'a' || k === 'A') nextDir = {x:-1,y:0};if(k === 'ArrowRight' || k === 'd' || k === 'D') nextDir = {x:1,y:0};}// Ekran butonlarıdocument.querySelectorAll('[data-dir]').forEach(b => {b.addEventListener('touchstart', (e)=>{e.preventDefault();const d = b.dataset.dir;if(d==='up') nextDir={x:0,y:-1};if(d==='down') nextDir={x:0,y:1};if(d==='left') nextDir={x:-1,y:0};if(d==='right') nextDir={x:1,y:0};});b.addEventListener('mousedown', (e)=>{const d = b.dataset.dir;if(d==='up') nextDir={x:0,y:-1};if(d==='down') nextDir={x:0,y:1};if(d==='left') nextDir={x:-1,y:0};if(d==='right') nextDir={x:1,y:0};});});// Dokunmatik swipe kontrollerilet touchStart = null;canvas.addEventListener('touchstart', e => {const t = e.changedTouches[0];touchStart = {x:t.clientX, y:t.clientY, time:Date.now()};});canvas.addEventListener('touchend', e => {if(!touchStart) return;const t = e.changedTouches[0];const dx = t.clientX - touchStart.x;const dy = t.clientY - touchStart.y;const absx = Math.abs(dx);const absy = Math.abs(dy);if(Math.max(absx,absy) > 30){if(absx > absy){if(dx > 0) nextDir = {x:1,y:0}; else nextDir = {x:-1,y:0};} else {if(dy > 0) nextDir = {x:0,y:1}; else nextDir = {x:0,y:-1};}}touchStart = null;});// ButonlarpauseBtn.addEventListener('click', togglePause);restartBtn.addEventListener('click', ()=>{resetGame();pauseBtn.textContent = 'Duraklat';running = true;});muteBtn.addEventListener('click', ()=>{muted = !muted;muteBtn.textContent = muted ? 'Ses Aç' : 'Ses Kapat';});saveScoreBtn.addEventListener('click', ()=>{localStorage.setItem('yesilVatanHighScore', String(highScore));alert('Yüksek skor kaydedildi: ' + highScore);});// pause togglefunction togglePause(){running = !running;pauseBtn.textContent = running ? 'Duraklat' : 'Devam Et';if(!muted) beep(440,0.06,0.05);}// BaşlangıçspawnFood();updateHUD();requestAnimationFrame(loop);// Ekstra: pencere odağı kaybında duraklatwindow.addEventListener('blur', ()=>{ if(running){ running=false; pauseBtn.textContent='Devam Et'; } });// Touch-friendly: prevent scroll while touching canvas['touchstart','touchmove'].forEach(ev => {canvas.addEventListener(ev, function(e){ e.preventDefault(); }, {passive:false});});</script></body></html>

Yorumlar
Yorum Gönder