mario / index.html
Mrttbn's picture
Update index.html
d8a3e84 verified
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Turkuaz Kış Macerası</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #202020;
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', sans-serif;
overflow: hidden; /* Kaydırmayı engelle */
touch-action: none; /* Mobilde dokunmatik gecikmesini önle */
}
/* Oyun Alanı Çerçevesi */
/* Oyun içi koordinatlar bozulmasın diye sabit 800x500 tutuyoruz */
/* JS ile ekrana sığacak şekilde scale (ölçekleme) yapacağız */
#game-container {
position: relative;
width: 800px;
height: 500px;
background: linear-gradient(to bottom, #87CEEB, #E0F7FA);
border: 5px solid #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
transform-origin: center center; /* Ortadan küçülsün */
}
/* --- KARAKTER --- */
#player {
position: absolute;
width: 40px;
height: 60px;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
#player .head {
width: 24px;
height: 24px;
background-color: #40E0D0;
border: 2px solid #008B8B;
border-radius: 50%;
position: relative;
z-index: 2;
}
#player .body {
width: 30px;
height: 34px;
background-color: #40E0D0;
border: 2px solid #008B8B;
border-radius: 5px;
margin-top: -2px; /* Kafa ile birleşsin */
z-index: 1;
}
#player .eye {
position: absolute;
width: 5px;
height: 5px;
background: black;
border-radius: 50%;
top: 8px;
right: 5px;
}
/* --- PLATFORMLAR --- */
.platform {
position: absolute;
background-color: #fff;
border-top: 5px solid #aeeeee;
border-radius: 5px;
box-shadow: 0 5px 5px rgba(0,0,0,0.1);
}
/* --- HEDEF --- */
#goal {
position: absolute;
width: 50px;
height: 70px;
background-color: #FFD700;
border: 3px solid #DAA520;
border-radius: 10px 10px 0 0;
z-index: 5;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
color: #d35400;
font-size: 14px;
box-shadow: 0 0 15px rgba(255, 215, 0, 0.6);
}
/* --- ARAYÜZ --- */
#ui-layer {
position: absolute;
top: 10px;
left: 10px;
font-size: 16px;
color: #005f6b;
font-weight: bold;
z-index: 20;
background: rgba(255,255,255,0.5);
padding: 5px 10px;
border-radius: 10px;
}
#message-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
z-index: 100;
display: none; /* Başlangıçta gizli */
}
#message-text {
color: white;
font-size: 40px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
#restart-btn {
padding: 10px 20px;
font-size: 20px;
background: #40E0D0;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
color: #005f6b;
}
/* --- MOBİL KONTROLLER --- */
#controls {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
display: flex;
justify-content: space-between;
z-index: 50;
pointer-events: none; /* Arkadaki oyunu engelleme */
}
.btn {
width: 70px;
height: 70px;
background: rgba(255, 255, 255, 0.3);
border: 2px solid rgba(255, 255, 255, 0.6);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
color: white;
pointer-events: auto; /* Sadece butona basılsın */
user-select: none;
backdrop-filter: blur(2px);
transition: background 0.1s;
}
.btn:active {
background: rgba(255, 255, 255, 0.6);
transform: scale(0.95);
}
/* Kar Tanesi */
.snowflake {
position: absolute;
color: white;
pointer-events: none;
animation: fall linear forwards;
}
@keyframes fall {
to { transform: translateY(550px); }
}
</style>
</head>
<body>
<div id="game-container">
<div id="ui-layer">Yön Tuşları veya Ekran Butonları</div>
<div id="player">
<div class="head"><div class="eye"></div></div>
<div class="body"></div>
</div>
<div id="goal">FINISH</div>
<div id="message-overlay">
<div id="message-text">KAZANDIN!</div>
<button id="restart-btn" onclick="resetGame()">Tekrar Oyna</button>
</div>
<div id="controls">
<div style="display: flex; gap: 15px;">
<div id="btn-left" class="btn">⬅️</div>
<div id="btn-right" class="btn">➡️</div>
</div>
<div id="btn-jump" class="btn">⬆️</div>
</div>
</div>
<script>
// --- DEĞİŞKENLER ---
const container = document.getElementById('game-container');
const player = document.getElementById('player');
const playerEye = document.querySelector('.eye');
const goal = document.getElementById('goal');
const msgOverlay = document.getElementById('message-overlay');
const msgText = document.getElementById('message-text');
// Mobil Butonlar
const btnLeft = document.getElementById('btn-left');
const btnRight = document.getElementById('btn-right');
const btnJump = document.getElementById('btn-jump');
// Oyun Değerleri
let pX = 50; // Oyuncu X
let pY = 300; // Oyuncu Y (Başlangıçta havada başlatıyoruz ki düşerek insin)
let vX = 0; // Hız X
let vY = 0; // Hız Y
const pW = 40; // Genişlik
const pH = 60; // Yükseklik
const speed = 5;
const jump = 13;
const grav = 0.6;
const fric = 0.8;
let isGrounded = false;
let gameRunning = true;
// Tuş Durumları
const keys = { left: false, right: false, jump: false };
// --- HARİTA ---
// Zemin (Ground) en alttaki büyük platformdur (y: 450)
const platforms = [
{x: 0, y: 450, w: 800, h: 50}, // Zemin
{x: 250, y: 350, w: 120, h: 20}, // Basamak 1
{x: 450, y: 260, w: 100, h: 20}, // Basamak 2
{x: 600, y: 170, w: 150, h: 20}, // Basamak 3 (Hedef Altı)
{x: 50, y: 200, w: 100, h: 20}, // Sol ekstra basamak
];
const goalPos = { x: 650, y: 100 }; // Hedefin konumu
// --- BAŞLATMA ---
function init() {
// Platformları Çiz
platforms.forEach(p => {
let div = document.createElement('div');
div.className = 'platform';
div.style.left = p.x + 'px';
div.style.top = p.y + 'px';
div.style.width = p.w + 'px';
div.style.height = p.h + 'px';
container.appendChild(div);
});
// Hedefi Yerleştir
goal.style.left = goalPos.x + 'px';
goal.style.top = goalPos.y + 'px';
// Kar Yağışı
setInterval(spawnSnow, 300);
// Ekran Boyutlandırma
resizeGame();
window.addEventListener('resize', resizeGame);
// Döngü
requestAnimationFrame(loop);
}
// --- OYUN DÖNGÜSÜ ---
function loop() {
if (!gameRunning) return;
// --- Hareket Mantığı ---
if (keys.right) {
vX = speed;
playerEye.style.right = '5px'; playerEye.style.left = 'auto';
} else if (keys.left) {
vX = -speed;
playerEye.style.left = '5px'; playerEye.style.right = 'auto';
} else {
vX *= fric;
}
// Zıplama
if (keys.jump && isGrounded) {
vY = -jump;
isGrounded = false;
keys.jump = false; // Basılı tutmayı engellemek için (isteğe bağlı)
}
vY += grav; // Yerçekimi
pX += vX;
pY += vY;
// Ekran Sınırları
if (pX < 0) { pX = 0; vX = 0; }
if (pX > 760) { pX = 760; vX = 0; } // 800 - 40(genişlik)
// --- ÇARPIŞMA KONTROLÜ ---
isGrounded = false;
platforms.forEach(p => {
// Kutuların çakışması (AABB)
if (pX < p.x + p.w &&
pX + pW > p.x &&
pY < p.y + p.h &&
pY + pH > p.y) {
// Sadece yukarıdan düşerken (ayağımız platformun üstüne gelince) dur
if (vY > 0 && pY + pH - vY <= p.y + 10) { // +10 tolerans
pY = p.y - pH;
vY = 0;
isGrounded = true;
}
}
});
// --- ÖLME (Aşağı Düşme) ---
// Konteynır yüksekliği 500px. 550'ye gelirse ölmüş sayalım.
if (pY > 550) {
gameOver("DÜŞTÜN!");
}
// --- KAZANMA ---
if (pX < goalPos.x + 50 &&
pX + pW > goalPos.x &&
pY < goalPos.y + 70 &&
pY + pH > goalPos.y) {
gameOver("KAZANDIN!", true);
}
// Konumu Güncelle
player.style.transform = `translate(${pX}px, ${pY}px)`;
requestAnimationFrame(loop);
}
// --- YARDIMCI FONKSİYONLAR ---
function gameOver(text, isWin = false) {
gameRunning = false;
msgText.innerText = text;
msgText.style.color = isWin ? '#76ff03' : '#ff3d00';
msgOverlay.style.display = 'flex';
}
function resetGame() {
pX = 50;
pY = 300;
vX = 0;
vY = 0;
gameRunning = true;
msgOverlay.style.display = 'none';
requestAnimationFrame(loop);
}
// Otomatik Ölçekleme (Telefona Sığdırma)
function resizeGame() {
const winW = window.innerWidth;
const winH = window.innerHeight;
// 800x500 oranını koruyarak ekranı doldur
const scale = Math.min(winW / 800, winH / 500);
// Çok büyütmesin (masaüstünde dev gibi olmasın)
const finalScale = Math.min(scale, 1.2);
container.style.transform = `scale(${finalScale})`;
}
function spawnSnow() {
const s = document.createElement('div');
s.className = 'snowflake';
s.innerText = '❄';
s.style.left = Math.random() * 800 + 'px';
s.style.fontSize = (Math.random() * 15 + 10) + 'px';
s.style.animationDuration = (Math.random() * 3 + 2) + 's';
container.appendChild(s);
setTimeout(() => s.remove(), 5000);
}
// --- KONTROLLER ---
// Klavye
document.addEventListener('keydown', e => {
if(e.key === "ArrowRight" || e.key === "d") keys.right = true;
if(e.key === "ArrowLeft" || e.key === "a") keys.left = true;
if(e.key === "ArrowUp" || e.key === "w" || e.key === " ") { keys.jump = true; }
});
document.addEventListener('keyup', e => {
if(e.key === "ArrowRight" || e.key === "d") keys.right = false;
if(e.key === "ArrowLeft" || e.key === "a") keys.left = false;
if(e.key === "ArrowUp" || e.key === "w" || e.key === " ") keys.jump = false;
});
// Dokunmatik (Mobil)
const touchHandler = (btn, key, val) => {
btn.addEventListener('touchstart', (e) => { e.preventDefault(); keys[key] = true; });
btn.addEventListener('touchend', (e) => { e.preventDefault(); keys[key] = false; });
// Mouse ile test etmek için
btn.addEventListener('mousedown', (e) => { keys[key] = true; });
btn.addEventListener('mouseup', (e) => { keys[key] = false; });
};
touchHandler(btnLeft, 'left');
touchHandler(btnRight, 'right');
// Zıplama için sadece basınca tetiklemesi yeterli ama tutarlılık için böyle bırakıyorum
btnJump.addEventListener('touchstart', (e) => {
e.preventDefault();
if(isGrounded) { vY = -jump; isGrounded = false; }
});
btnJump.addEventListener('mousedown', (e) => {
if(isGrounded) { vY = -jump; isGrounded = false; }
});
init();
</script>
</body>
</html>