| <!DOCTYPE html> |
| <html lang="tr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Kedi vs Fare</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap'); |
| |
| body { |
| font-family: 'Poppins', sans-serif; |
| overflow: hidden; |
| touch-action: none; |
| user-select: none; |
| -webkit-user-select: none; |
| margin: 0; |
| padding: 0; |
| background: linear-gradient(135deg, #1e3a8a, #3b82f6, #10b981, #f59e0b); |
| background-size: 400% 400%; |
| animation: gradientBG 15s ease infinite; |
| } |
| |
| @keyframes gradientBG { |
| 0% { background-position: 0% 50%; } |
| 50% { background-position: 100% 50%; } |
| 100% { background-position: 0% 50%; } |
| } |
| |
| #gameContainer { |
| position: relative; |
| width: 100vw; |
| height: 100vh; |
| overflow: hidden; |
| } |
| |
| .letter { |
| position: absolute; |
| font-weight: 900; |
| cursor: default; |
| color: white; |
| text-shadow: 0 0 10px rgba(0,0,0,0.5); |
| pointer-events: none; |
| z-index: 5; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| animation: float 3s ease-in-out infinite, colorChange 5s infinite alternate; |
| transform-origin: center; |
| font-size: 40px; |
| opacity: 0.9; |
| width: 40px; |
| height: 40px; |
| } |
| |
| @keyframes float { |
| 0%, 100% { transform: translateY(0) rotate(0deg) scale(1); } |
| 50% { transform: translateY(-10px) rotate(5deg) scale(1.05); } |
| } |
| |
| @keyframes colorChange { |
| 0% { color: #f87171; } |
| 25% { color: #60a5fa; } |
| 50% { color: #34d399; } |
| 75% { color: #fbbf24; } |
| 100% { color: #a78bfa; } |
| } |
| |
| #cat { |
| position: absolute; |
| width: 60px; |
| height: 60px; |
| background-image: url('https://cdn-icons-png.flaticon.com/512/616/616430.png'); |
| background-size: contain; |
| background-repeat: no-repeat; |
| background-position: center; |
| transition: transform 0.05s ease; |
| z-index: 10; |
| filter: drop-shadow(0 0 5px rgba(0,0,0,0.5)); |
| animation: catBounce 0.5s infinite alternate; |
| } |
| |
| @keyframes catBounce { |
| 0% { transform: translateY(0) scale(1); } |
| 100% { transform: translateY(-3px) scale(1.02); } |
| } |
| |
| #mouse { |
| position: absolute; |
| width: 40px; |
| height: 40px; |
| z-index: 10; |
| filter: drop-shadow(0 0 5px rgba(0,0,0,0.5)); |
| animation: mouseShake 0.3s infinite alternate; |
| } |
| |
| @keyframes mouseShake { |
| 0% { transform: rotate(-2deg); } |
| 100% { transform: rotate(2deg); } |
| } |
| |
| .mouse-body { |
| position: absolute; |
| width: 30px; |
| height: 20px; |
| background-color: #8B4513; |
| border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; |
| top: 10px; |
| left: 5px; |
| } |
| |
| .mouse-ear { |
| position: absolute; |
| width: 10px; |
| height: 10px; |
| background-color: #A0522D; |
| border-radius: 50%; |
| top: 5px; |
| } |
| |
| .mouse-ear.left { |
| left: 5px; |
| } |
| |
| .mouse-ear.right { |
| right: 5px; |
| } |
| |
| .mouse-eye { |
| position: absolute; |
| width: 4px; |
| height: 4px; |
| background-color: black; |
| border-radius: 50%; |
| top: 10px; |
| } |
| |
| .mouse-eye.left { |
| left: 8px; |
| } |
| |
| .mouse-eye.right { |
| right: 8px; |
| } |
| |
| .mouse-nose { |
| position: absolute; |
| width: 3px; |
| height: 3px; |
| background-color: pink; |
| border-radius: 50%; |
| top: 15px; |
| left: 13px; |
| } |
| |
| .mouse-tail { |
| position: absolute; |
| width: 20px; |
| height: 3px; |
| background-color: #FFD700; |
| border-radius: 3px; |
| top: 15px; |
| left: -10px; |
| transform-origin: right center; |
| animation: tailWag 0.3s infinite alternate; |
| } |
| |
| @keyframes tailWag { |
| 0% { transform: rotate(-30deg); } |
| 100% { transform: rotate(30deg); } |
| } |
| |
| .joystick { |
| position: absolute; |
| width: 80px; |
| height: 80px; |
| background-color: rgba(255, 255, 255, 0.3); |
| border-radius: 50%; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| z-index: 20; |
| border: 2px solid rgba(255,255,255,0.5); |
| backdrop-filter: blur(5px); |
| } |
| |
| .joystick-knob { |
| width: 30px; |
| height: 30px; |
| background-color: rgba(255, 255, 255, 0.7); |
| border-radius: 50%; |
| touch-action: none; |
| border: 2px solid rgba(255,255,255,0.9); |
| } |
| |
| #joystick1 { |
| bottom: 60px; |
| left: 50%; |
| transform: translateX(-50%); |
| } |
| |
| #joystick2 { |
| top: 60px; |
| left: 50%; |
| transform: translateX(-50%); |
| } |
| |
| #startScreen, #gameOverScreen { |
| position: absolute; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| display: flex; |
| flex-direction: column; |
| justify-content: center; |
| align-items: center; |
| background-color: rgba(0, 0, 0, 0.7); |
| color: white; |
| z-index: 30; |
| backdrop-filter: blur(5px); |
| } |
| |
| #fullscreenBtn { |
| position: absolute; |
| top: 15px; |
| right: 15px; |
| background-color: rgba(255, 255, 255, 0.3); |
| border: none; |
| color: white; |
| width: 40px; |
| height: 40px; |
| border-radius: 50%; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| cursor: pointer; |
| z-index: 20; |
| font-size: 1.2rem; |
| border: 2px solid rgba(255,255,255,0.5); |
| backdrop-filter: blur(5px); |
| transition: all 0.2s ease; |
| } |
| |
| #fullscreenBtn:hover { |
| transform: scale(1.1); |
| background-color: rgba(255, 255, 255, 0.5); |
| } |
| |
| .btn { |
| background: linear-gradient(45deg, #f97316, #ef4444); |
| color: white; |
| border: none; |
| padding: 12px 25px; |
| margin: 12px; |
| border-radius: 25px; |
| font-size: 1rem; |
| font-weight: bold; |
| cursor: pointer; |
| box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3); |
| transition: all 0.2s ease; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .btn::before { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: -100%; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); |
| transition: 0.5s; |
| } |
| |
| .btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4); |
| } |
| |
| .btn:hover::before { |
| left: 100%; |
| } |
| |
| .input-text { |
| padding: 12px 15px; |
| margin: 15px 0; |
| width: 80%; |
| max-width: 400px; |
| border: 2px solid #f97316; |
| border-radius: 25px; |
| font-size: 1rem; |
| text-align: center; |
| background-color: rgba(255, 255, 255, 0.9); |
| transition: all 0.2s ease; |
| box-shadow: 0 3px 8px rgba(0,0,0,0.1); |
| color: #1e3a8a; |
| font-weight: bold; |
| } |
| |
| .input-text:focus { |
| outline: none; |
| border-color: #ef4444; |
| box-shadow: 0 0 10px rgba(239, 68, 68, 0.5); |
| } |
| |
| .title { |
| font-size: 3rem; |
| font-weight: bold; |
| margin-bottom: 8px; |
| color: white; |
| text-shadow: 0 3px 10px rgba(0, 0, 0, 0.5); |
| background: linear-gradient(45deg, #f97316, #ef4444, #f59e0b); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| animation: titleGlow 2s ease infinite alternate; |
| } |
| |
| @keyframes titleGlow { |
| 0% { text-shadow: 0 0 8px rgba(249, 115, 22, 0.5); } |
| 100% { text-shadow: 0 0 15px rgba(239, 68, 68, 0.8); } |
| } |
| |
| .subtitle { |
| font-size: 1.2rem; |
| margin-bottom: 15px; |
| text-align: center; |
| max-width: 80%; |
| color: white; |
| text-shadow: 0 1px 3px rgba(0,0,0,0.3); |
| } |
| |
| .timer { |
| position: absolute; |
| top: 10px; |
| left: 50%; |
| transform: translateX(-50%); |
| color: white; |
| font-size: 0.9rem; |
| z-index: 20; |
| background-color: rgba(0,0,0,0.5); |
| padding: 5px 10px; |
| border-radius: 15px; |
| backdrop-filter: blur(5px); |
| border: 1px solid rgba(255,255,255,0.2); |
| box-shadow: 0 2px 5px rgba(0,0,0,0.2); |
| } |
| |
| .countdown { |
| position: absolute; |
| top: 15px; |
| left: 50%; |
| transform: translateX(-50%); |
| font-size: 1.5rem; |
| color: white; |
| text-shadow: 0 0 10px rgba(255,255,255,0.7); |
| z-index: 40; |
| background-color: rgba(0,0,0,0.5); |
| padding: 8px 15px; |
| border-radius: 25px; |
| backdrop-filter: blur(5px); |
| border: 2px solid rgba(255,255,255,0.2); |
| box-shadow: 0 3px 10px rgba(0,0,0,0.2); |
| } |
| |
| .game-mode-selector { |
| display: flex; |
| flex-wrap: wrap; |
| justify-content: center; |
| margin: 15px 0; |
| width: 100%; |
| max-width: 500px; |
| } |
| |
| .game-mode-btn { |
| margin: 8px; |
| padding: 10px 15px; |
| border-radius: 25px; |
| font-weight: bold; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| border: 2px solid transparent; |
| box-shadow: 0 3px 8px rgba(0,0,0,0.2); |
| font-size: 0.9rem; |
| min-width: 120px; |
| } |
| |
| .game-mode-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 12px rgba(0,0,0,0.3); |
| } |
| |
| .game-mode-btn.active { |
| transform: scale(1.05); |
| border-color: white; |
| box-shadow: 0 0 10px rgba(255,255,255,0.5); |
| } |
| |
| .single-player { |
| background: linear-gradient(45deg, #3b82f6, #60a5fa); |
| color: white; |
| } |
| |
| .multiplayer { |
| background: linear-gradient(45deg, #10b981, #34d399); |
| color: white; |
| } |
| |
| .difficulty-selector { |
| display: flex; |
| flex-wrap: wrap; |
| justify-content: center; |
| margin: 15px 0; |
| width: 100%; |
| max-width: 500px; |
| } |
| |
| .difficulty-btn { |
| margin: 8px; |
| padding: 8px 15px; |
| border-radius: 25px; |
| font-weight: bold; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| border: 2px solid transparent; |
| box-shadow: 0 3px 8px rgba(0,0,0,0.2); |
| font-size: 0.8rem; |
| } |
| |
| .difficulty-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 12px rgba(0,0,0,0.3); |
| } |
| |
| .difficulty-btn.active { |
| transform: scale(1.05); |
| border-color: white; |
| box-shadow: 0 0 10px rgba(255,255,255,0.5); |
| } |
| |
| .easy { |
| background: linear-gradient(45deg, #10b981, #34d399); |
| color: white; |
| } |
| |
| .medium { |
| background: linear-gradient(45deg, #f59e0b, #f97316); |
| color: white; |
| } |
| |
| .hard { |
| background: linear-gradient(45deg, #ef4444, #f87171); |
| color: white; |
| } |
| |
| .extreme { |
| background: linear-gradient(45deg, #8b5cf6, #7c3aed); |
| color: white; |
| } |
| |
| .role-selector { |
| display: flex; |
| flex-wrap: wrap; |
| justify-content: center; |
| margin: 15px 0; |
| width: 100%; |
| max-width: 500px; |
| } |
| |
| .role-btn { |
| margin: 8px; |
| padding: 10px 15px; |
| border-radius: 25px; |
| font-weight: bold; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| border: 2px solid transparent; |
| box-shadow: 0 3px 8px rgba(0,0,0,0.2); |
| font-size: 0.9rem; |
| min-width: 100px; |
| } |
| |
| .role-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 12px rgba(0,0,0,0.3); |
| } |
| |
| .role-btn.active { |
| transform: scale(1.05); |
| border-color: white; |
| box-shadow: 0 0 10px rgba(255,255,255,0.5); |
| } |
| |
| .cat-role { |
| background: linear-gradient(45deg, #f97316, #ef4444); |
| color: white; |
| } |
| |
| .mouse-role { |
| background: linear-gradient(45deg, #8B4513, #A0522D); |
| color: white; |
| } |
| |
| .pulse { |
| animation: pulse 1.5s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { transform: scale(1); } |
| 50% { transform: scale(1.1); } |
| 100% { transform: scale(1); } |
| } |
| |
| .shake { |
| animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; |
| } |
| |
| @keyframes shake { |
| 10%, 90% { transform: translateX(-1px); } |
| 20%, 80% { transform: translateX(2px); } |
| 30%, 50%, 70% { transform: translateX(-4px); } |
| 40%, 60% { transform: translateX(4px); } |
| } |
| </style> |
| </head> |
| <body> |
| <div id="gameContainer"> |
| <div id="cat"></div> |
| <div id="mouse"> |
| <div class="mouse-ear left"></div> |
| <div class="mouse-ear right"></div> |
| <div class="mouse-body"></div> |
| <div class="mouse-eye left"></div> |
| <div class="mouse-eye right"></div> |
| <div class="mouse-nose"></div> |
| <div class="mouse-tail"></div> |
| </div> |
| |
| <div id="joystick1" class="joystick"> |
| <div id="joystickKnob1" class="joystick-knob"></div> |
| </div> |
| |
| <div id="joystick2" class="joystick" style="display: none;"> |
| <div id="joystickKnob2" class="joystick-knob"></div> |
| </div> |
| |
| <button id="fullscreenBtn"> |
| <i class="fas fa-expand"></i> |
| </button> |
| <div class="timer"> |
| Kalan Süre: <span id="time">30</span>s |
| </div> |
| |
| <div id="startScreen"> |
| <h1 class="title">Kedi vs Fare</h1> |
| <p class="subtitle">Fareyi yakalamak için kediyi kontrol et veya fare olup kaçmayı dene!<br>Harfler hem kedi hem fare için engel olacak.</p> |
| |
| <div class="game-mode-selector"> |
| <button class="game-mode-btn single-player active" data-mode="single">TEK OYUNCU</button> |
| <button class="game-mode-btn multiplayer" data-mode="multi">ÇİFT OYUNCU</button> |
| </div> |
| |
| <div id="roleSelection" class="role-selector"> |
| <button class="role-btn cat-role active" data-role="cat">KEDİ OL</button> |
| <button class="role-btn mouse-role" data-role="mouse">FARE OL</button> |
| </div> |
| |
| <div class="difficulty-selector"> |
| <button class="difficulty-btn easy active" data-difficulty="easy">KOLAY</button> |
| <button class="difficulty-btn medium" data-difficulty="medium">ORTA</button> |
| <button class="difficulty-btn hard" data-difficulty="hard">ZOR</button> |
| <button class="difficulty-btn extreme" data-difficulty="extreme">ÇOK ZOR</button> |
| </div> |
| |
| <input type="text" id="sentenceInput" class="input-text" placeholder="Bir cümle yazın (örnek: KEDİFARE)" maxlength="15"> |
| <button id="startBtn" class="btn pulse">OYUNA BAŞLA</button> |
| </div> |
| |
| <div id="gameOverScreen" style="display: none;"> |
| <h1 class="title">Oyun Bitti!</h1> |
| <p class="subtitle" id="resultMessage">Fareyi yakaladın!<br>Geçen Süre: <span id="finalTime">0</span>s</p> |
| <button id="restartBtn" class="btn">TEKRAR OYNA</button> |
| </div> |
| </div> |
|
|
| <script> |
| |
| let gameActive = false; |
| let letters = []; |
| let joystick1Active = false; |
| let joystick2Active = false; |
| let joystick1Angle = 0; |
| let joystick2Angle = 0; |
| let joystick1Distance = 0; |
| let joystick2Distance = 0; |
| let catSpeed = 15; |
| let mouseSpeed = 30; |
| let catPosition = { x: 0, y: 0 }; |
| let mousePosition = { x: 0, y: 0 }; |
| let joystick1Position = { x: 0, y: 0 }; |
| let joystick2Position = { x: 0, y: 0 }; |
| let joystick1KnobPosition = { x: 0, y: 0 }; |
| let joystick2KnobPosition = { x: 0, y: 0 }; |
| let joystickRadius = 40; |
| let gameWidth = window.innerWidth; |
| let gameHeight = window.innerHeight; |
| let gameTime = 30; |
| let timerInterval; |
| let countdownInterval; |
| let mouseCaught = false; |
| let sentence = ""; |
| let lastFrameTime = 0; |
| let deltaTime = 0; |
| let currentDifficulty = "easy"; |
| let gameMode = "single"; |
| let playerRole = "cat"; |
| let multiplayer = false; |
| let player1ControlsCat = true; |
| |
| |
| const difficultySettings = { |
| easy: { |
| catSpeed: 12, |
| mouseSpeed: 30, |
| mouseIntelligence: 0.3, |
| gameTime: 30, |
| letterSpeed: 2, |
| letterCount: 5 |
| }, |
| medium: { |
| catSpeed: 18, |
| mouseSpeed: 45, |
| mouseIntelligence: 0.5, |
| gameTime: 30, |
| letterSpeed: 3, |
| letterCount: 7 |
| }, |
| hard: { |
| catSpeed: 24, |
| mouseSpeed: 60, |
| mouseIntelligence: 0.7, |
| gameTime: 30, |
| letterSpeed: 4, |
| letterCount: 10 |
| }, |
| extreme: { |
| catSpeed: 30, |
| mouseSpeed: 75, |
| mouseIntelligence: 0.9, |
| gameTime: 30, |
| letterSpeed: 5, |
| letterCount: 12 |
| } |
| }; |
| |
| |
| const gameContainer = document.getElementById('gameContainer'); |
| const cat = document.getElementById('cat'); |
| const mouse = document.getElementById('mouse'); |
| const joystick1 = document.getElementById('joystick1'); |
| const joystick2 = document.getElementById('joystick2'); |
| const joystickKnob1 = document.getElementById('joystickKnob1'); |
| const joystickKnob2 = document.getElementById('joystickKnob2'); |
| const startScreen = document.getElementById('startScreen'); |
| const gameOverScreen = document.getElementById('gameOverScreen'); |
| const startBtn = document.getElementById('startBtn'); |
| const restartBtn = document.getElementById('restartBtn'); |
| const sentenceInput = document.getElementById('sentenceInput'); |
| const timeDisplay = document.getElementById('time'); |
| const finalTimeDisplay = document.getElementById('finalTime'); |
| const resultMessage = document.getElementById('resultMessage'); |
| const fullscreenBtn = document.getElementById('fullscreenBtn'); |
| const difficultyBtns = document.querySelectorAll('.difficulty-btn'); |
| const gameModeBtns = document.querySelectorAll('.game-mode-btn'); |
| const roleBtns = document.querySelectorAll('.role-btn'); |
| const roleSelection = document.getElementById('roleSelection'); |
| const mouseTail = document.querySelector('.mouse-tail'); |
| |
| |
| function initGame() { |
| |
| mouseCaught = false; |
| gameTime = difficultySettings[currentDifficulty].gameTime; |
| timeDisplay.textContent = gameTime; |
| |
| |
| catSpeed = difficultySettings[currentDifficulty].catSpeed; |
| mouseSpeed = difficultySettings[currentDifficulty].mouseSpeed; |
| |
| |
| catPosition = { |
| x: gameWidth / 2 - 30, |
| y: gameHeight / 2 - 30 |
| }; |
| |
| mousePosition = { |
| x: Math.random() * (gameWidth - 40), |
| y: Math.random() * (gameHeight - 40) |
| }; |
| |
| |
| joystick1Position = { |
| x: gameWidth / 2, |
| y: gameHeight - 60 - 40 |
| }; |
| |
| joystick2Position = { |
| x: gameWidth / 2, |
| y: 60 + 40 |
| }; |
| |
| joystick1KnobPosition = { |
| x: joystick1Position.x, |
| y: joystick1Position.y |
| }; |
| |
| joystick2KnobPosition = { |
| x: joystick2Position.x, |
| y: joystick2Position.y |
| }; |
| |
| |
| updateCatPosition(); |
| updateMousePosition(); |
| updateJoystickPositions(); |
| |
| |
| createLetters(); |
| |
| |
| startCountdown(); |
| } |
| |
| |
| function startCountdown() { |
| let count = 3; |
| const countdownElement = document.createElement('div'); |
| countdownElement.className = 'countdown'; |
| countdownElement.textContent = count; |
| gameContainer.appendChild(countdownElement); |
| |
| countdownInterval = setInterval(() => { |
| count--; |
| if (count > 0) { |
| countdownElement.textContent = count; |
| } else { |
| clearInterval(countdownInterval); |
| countdownElement.textContent = 'BAŞLA!'; |
| setTimeout(() => { |
| gameContainer.removeChild(countdownElement); |
| startGame(); |
| }, 500); |
| } |
| }, 1000); |
| } |
| |
| |
| function startGame() { |
| |
| timerInterval = setInterval(updateTimer, 1000); |
| |
| |
| gameActive = true; |
| lastFrameTime = performance.now(); |
| requestAnimationFrame(gameLoop); |
| } |
| |
| |
| function updateTimer() { |
| if (gameActive) { |
| gameTime--; |
| timeDisplay.textContent = gameTime; |
| |
| if (gameTime <= 0) { |
| |
| gameOver(false); |
| } |
| } |
| } |
| |
| |
| function createLetters() { |
| |
| letters.forEach(letter => { |
| if (letter.element && letter.element.parentNode) { |
| gameContainer.removeChild(letter.element); |
| } |
| }); |
| letters = []; |
| |
| |
| const chars = sentence.split(''); |
| const maxLetters = Math.min(chars.length, difficultySettings[currentDifficulty].letterCount); |
| |
| for (let i = 0; i < maxLetters; i++) { |
| const char = chars[i % chars.length]; |
| if (char.trim() === '') continue; |
| |
| const letter = { |
| char: char, |
| element: document.createElement('div'), |
| x: Math.random() * (gameWidth - 40), |
| y: Math.random() * (gameHeight - 40), |
| size: 40, |
| speedX: (Math.random() - 0.5) * difficultySettings[currentDifficulty].letterSpeed * 2, |
| speedY: (Math.random() - 0.5) * difficultySettings[currentDifficulty].letterSpeed * 2, |
| rotation: Math.random() * 360, |
| rotationSpeed: (Math.random() - 0.5) * 4 |
| }; |
| |
| letter.element.className = 'letter'; |
| letter.element.textContent = char; |
| letter.element.style.fontSize = `40px`; |
| letter.element.style.left = `${letter.x}px`; |
| letter.element.style.top = `${letter.y}px`; |
| letter.element.style.transform = `rotate(${letter.rotation}deg)`; |
| letter.element.style.zIndex = '5'; |
| |
| gameContainer.appendChild(letter.element); |
| letters.push(letter); |
| } |
| } |
| |
| |
| function gameLoop(timestamp) { |
| if (!gameActive) return; |
| |
| |
| deltaTime = (timestamp - lastFrameTime) / 16.67; |
| lastFrameTime = timestamp; |
| |
| |
| if (joystick1Active && (playerRole === "cat" || multiplayer)) { |
| const moveX = Math.cos(joystick1Angle) * catSpeed * (joystick1Distance / joystickRadius) * deltaTime; |
| const moveY = Math.sin(joystick1Angle) * catSpeed * (joystick1Distance / joystickRadius) * deltaTime; |
| |
| |
| const newCatX = catPosition.x + moveX; |
| const newCatY = catPosition.y + moveY; |
| |
| let canMove = true; |
| |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newCatX, newCatY, 60, 60, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| catPosition.x = newCatX; |
| catPosition.y = newCatY; |
| } |
| |
| |
| catPosition.x = Math.max(0, Math.min(gameWidth - 60, catPosition.x)); |
| catPosition.y = Math.max(0, Math.min(gameHeight - 60, catPosition.y)); |
| } |
| |
| |
| if (multiplayer && joystick2Active) { |
| const moveX = Math.cos(joystick2Angle) * mouseSpeed * (joystick2Distance / joystickRadius) * deltaTime; |
| const moveY = Math.sin(joystick2Angle) * mouseSpeed * (joystick2Distance / joystickRadius) * deltaTime; |
| |
| |
| const newMouseX = mousePosition.x + moveX; |
| const newMouseY = mousePosition.y + moveY; |
| |
| let canMove = true; |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newMouseX, newMouseY, 40, 40, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| mousePosition.x += moveX; |
| mousePosition.y += moveY; |
| } |
| |
| |
| mousePosition.x = Math.max(0, Math.min(gameWidth - 40, mousePosition.x)); |
| mousePosition.y = Math.max(0, Math.min(gameHeight - 40, mousePosition.y)); |
| } else if (!multiplayer && playerRole === "mouse") { |
| |
| if (joystick1Active) { |
| const moveX = Math.cos(joystick1Angle) * mouseSpeed * (joystick1Distance / joystickRadius) * deltaTime; |
| const moveY = Math.sin(joystick1Angle) * mouseSpeed * (joystick1Distance / joystickRadius) * deltaTime; |
| |
| |
| const newMouseX = mousePosition.x + moveX; |
| const newMouseY = mousePosition.y + moveY; |
| |
| let canMove = true; |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newMouseX, newMouseY, 40, 40, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| mousePosition.x += moveX; |
| mousePosition.y += moveY; |
| } |
| |
| |
| mousePosition.x = Math.max(0, Math.min(gameWidth - 40, mousePosition.x)); |
| mousePosition.y = Math.max(0, Math.min(gameHeight - 40, mousePosition.y)); |
| } |
| |
| |
| moveCatAI(deltaTime); |
| } else if (!multiplayer) { |
| |
| moveMouseAI(deltaTime); |
| } |
| |
| |
| moveLetters(deltaTime); |
| |
| |
| checkCollision(); |
| |
| |
| updateCatPosition(); |
| updateMousePosition(); |
| updateLettersPosition(); |
| updateJoystickPositions(); |
| |
| |
| requestAnimationFrame(gameLoop); |
| } |
| |
| |
| function moveCatAI(deltaTime) { |
| const dx = catPosition.x - mousePosition.x; |
| const dy = catPosition.y - mousePosition.y; |
| const distance = Math.sqrt(dx * dx + dy * dy); |
| |
| if (distance > 0) { |
| const moveX = (dx / distance) * catSpeed * deltaTime; |
| const moveY = (dy / distance) * catSpeed * deltaTime; |
| |
| |
| const newCatX = catPosition.x - moveX; |
| const newCatY = catPosition.y - moveY; |
| |
| let canMove = true; |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newCatX, newCatY, 60, 60, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| catPosition.x = newCatX; |
| catPosition.y = newCatY; |
| } |
| |
| |
| catPosition.x = Math.max(0, Math.min(gameWidth - 60, catPosition.x)); |
| catPosition.y = Math.max(0, Math.min(gameHeight - 60, catPosition.y)); |
| } |
| } |
| |
| |
| function checkCollisionWithObject(x1, y1, w1, h1, x2, y2, w2, h2) { |
| return x1 < x2 + w2 && |
| x1 + w1 > x2 && |
| y1 < y2 + h2 && |
| y1 + h1 > y2; |
| } |
| |
| |
| function moveMouseAI(deltaTime) { |
| const difficulty = difficultySettings[currentDifficulty]; |
| const intelligence = difficulty.mouseIntelligence; |
| |
| |
| const dx = mousePosition.x - catPosition.x; |
| const dy = mousePosition.y - catPosition.y; |
| const distance = Math.sqrt(dx * dx + dy * dy); |
| |
| |
| if (distance < 300) { |
| |
| const runX = (dx / distance) * mouseSpeed * (1 + intelligence) * deltaTime; |
| const runY = (dy / distance) * mouseSpeed * (1 + intelligence) * deltaTime; |
| |
| |
| const newMouseX = mousePosition.x + runX; |
| const newMouseY = mousePosition.y + runY; |
| |
| let canMove = true; |
| |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newMouseX, newMouseY, 40, 40, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| mousePosition.x += runX; |
| mousePosition.y += runY; |
| } else { |
| |
| const perpendicularX = -dy / distance * mouseSpeed * deltaTime; |
| const perpendicularY = dx / distance * mouseSpeed * deltaTime; |
| |
| const altMouseX = mousePosition.x + perpendicularX; |
| const altMouseY = mousePosition.y + perpendicularY; |
| |
| let altCanMove = true; |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(altMouseX, altMouseY, 40, 40, letter.x, letter.y, letter.size, letter.size)) { |
| altCanMove = false; |
| break; |
| } |
| } |
| |
| if (altCanMove) { |
| mousePosition.x = altMouseX; |
| mousePosition.y = altMouseY; |
| } |
| } |
| |
| |
| if (mousePosition.x < 0 || mousePosition.x > gameWidth - 40) { |
| mousePosition.x = Math.max(0, Math.min(gameWidth - 40, mousePosition.x)); |
| mousePosition.y += (Math.random() - 0.5) * mouseSpeed * 2 * deltaTime; |
| } |
| |
| if (mousePosition.y < 0 || mousePosition.y > gameHeight - 40) { |
| mousePosition.y = Math.max(0, Math.min(gameHeight - 40, mousePosition.y)); |
| mousePosition.x += (Math.random() - 0.5) * mouseSpeed * 2 * deltaTime; |
| } |
| } else { |
| |
| if (Math.random() < intelligence) { |
| |
| mouseSpeed = difficulty.mouseSpeed * (0.8 + Math.random() * 0.4); |
| } |
| |
| |
| let bestDirection = { x: 0, y: 0 }; |
| let bestScore = -Infinity; |
| |
| |
| for (let angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) { |
| const testX = mousePosition.x + Math.cos(angle) * 150; |
| const testY = mousePosition.y + Math.sin(angle) * 150; |
| |
| |
| if (testX < 0 || testX > gameWidth - 40 || testY < 0 || testY > gameHeight - 40) { |
| continue; |
| } |
| |
| |
| let score = 0; |
| |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| const ldx = testX - (letter.x + letter.size/2); |
| const ldy = testY - (letter.y + letter.size/2); |
| const ldistance = Math.sqrt(ldx * ldx + ldy * ldy); |
| |
| score += Math.max(0, 200 - ldistance); |
| } |
| |
| |
| const cdx = testX - catPosition.x; |
| const cdy = testY - catPosition.y; |
| const cdistance = Math.sqrt(cdx * cdx + cdy * cdy); |
| score -= Math.max(0, 400 - cdistance); |
| |
| if (score > bestScore) { |
| bestScore = score; |
| bestDirection = { x: Math.cos(angle), y: Math.sin(angle) }; |
| } |
| } |
| |
| |
| const newMouseX = mousePosition.x + bestDirection.x * mouseSpeed * deltaTime; |
| const newMouseY = mousePosition.y + bestDirection.y * mouseSpeed * deltaTime; |
| |
| let canMove = true; |
| |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| if (checkCollisionWithObject(newMouseX, newMouseY, 40, 40, letter.x, letter.y, letter.size, letter.size)) { |
| canMove = false; |
| break; |
| } |
| } |
| |
| if (canMove) { |
| mousePosition.x += bestDirection.x * mouseSpeed * deltaTime; |
| mousePosition.y += bestDirection.y * mouseSpeed * deltaTime; |
| } |
| } |
| |
| |
| mousePosition.x = Math.max(0, Math.min(gameWidth - 40, mousePosition.x)); |
| mousePosition.y = Math.max(0, Math.min(gameHeight - 40, mousePosition.y)); |
| } |
| |
| |
| function moveLetters(deltaTime) { |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| |
| letter.x += letter.speedX * deltaTime; |
| letter.y += letter.speedY * deltaTime; |
| |
| |
| if (letter.x < 0 || letter.x > gameWidth - letter.size) { |
| letter.speedX *= -1.1; |
| letter.x = Math.max(0, Math.min(gameWidth - letter.size, letter.x)); |
| } |
| |
| if (letter.y < 0 || letter.y > gameHeight - letter.size) { |
| letter.speedY *= -1.1; |
| letter.y = Math.max(0, Math.min(gameHeight - letter.size, letter.y)); |
| } |
| |
| |
| letter.rotation += letter.rotationSpeed * deltaTime; |
| } |
| } |
| |
| |
| function checkCollision() { |
| const dx = catPosition.x + 30 - (mousePosition.x + 20); |
| const dy = catPosition.y + 30 - (mousePosition.y + 20); |
| const distance = Math.sqrt(dx * dx + dy * dy); |
| |
| if (distance < 35) { |
| |
| mouseCaught = true; |
| gameOver(true); |
| } |
| } |
| |
| |
| function updateCatPosition() { |
| cat.style.left = `${catPosition.x}px`; |
| cat.style.top = `${catPosition.y}px`; |
| |
| |
| if (joystick1Active && (playerRole === "cat" || multiplayer)) { |
| const rotation = joystick1Angle * (180 / Math.PI) + 90; |
| cat.style.transform = `rotate(${rotation}deg)`; |
| } else if (!multiplayer && playerRole === "mouse") { |
| |
| const dx = catPosition.x - mousePosition.x; |
| const dy = catPosition.y - mousePosition.y; |
| const angle = Math.atan2(dy, dx) * (180 / Math.PI) + 180; |
| cat.style.transform = `rotate(${angle}deg)`; |
| } |
| } |
| |
| |
| function updateMousePosition() { |
| mouse.style.left = `${mousePosition.x}px`; |
| mouse.style.top = `${mousePosition.y}px`; |
| |
| |
| if (multiplayer && joystick2Active) { |
| const rotation = joystick2Angle * (180 / Math.PI) + 180; |
| mouse.style.transform = `rotate(${rotation}deg)`; |
| } else if (!multiplayer && playerRole === "mouse") { |
| |
| if (joystick1Active) { |
| const rotation = joystick1Angle * (180 / Math.PI) + 180; |
| mouse.style.transform = `rotate(${rotation}deg)`; |
| } |
| } else { |
| |
| const dx = mousePosition.x - catPosition.x; |
| const dy = mousePosition.y - catPosition.y; |
| const angle = Math.atan2(dy, dx) * (180 / Math.PI) + 180; |
| mouse.style.transform = `rotate(${angle}deg)`; |
| } |
| } |
| |
| |
| function updateLettersPosition() { |
| for (let i = 0; i < letters.length; i++) { |
| const letter = letters[i]; |
| letter.element.style.left = `${letter.x}px`; |
| letter.element.style.top = `${letter.y}px`; |
| letter.element.style.transform = `rotate(${letter.rotation}deg)`; |
| } |
| } |
| |
| |
| function updateJoystickPositions() { |
| joystickKnob1.style.left = `${joystick1KnobPosition.x - joystick1Position.x + 40 - 15}px`; |
| joystickKnob1.style.top = `${joystick1KnobPosition.y - joystick1Position.y + 40 - 15}px`; |
| |
| if (multiplayer) { |
| joystickKnob2.style.left = `${joystick2KnobPosition.x - joystick2Position.x + 40 - 15}px`; |
| joystickKnob2.style.top = `${joystick2KnobPosition.y - joystick2Position.y + 40 - 15}px`; |
| } |
| } |
| |
| |
| function gameOver(caught) { |
| gameActive = false; |
| clearInterval(timerInterval); |
| |
| finalTimeDisplay.textContent = (difficultySettings[currentDifficulty].gameTime - gameTime).toFixed(1); |
| |
| |
| if (caught) { |
| if (playerRole === "cat" || multiplayer) { |
| resultMessage.innerHTML = "Fareyi yakaladın!<br>Geçen Süre: <span id='finalTime'>" + (difficultySettings[currentDifficulty].gameTime - gameTime).toFixed(1) + "</span>s"; |
| } else { |
| resultMessage.innerHTML = "Kedi seni yakaladı!<br>Geçen Süre: <span id='finalTime'>" + (difficultySettings[currentDifficulty].gameTime - gameTime).toFixed(1) + "</span>s"; |
| } |
| } else { |
| if (playerRole === "cat" || multiplayer) { |
| resultMessage.innerHTML = "Fare kaçtı!<br>Geçen Süre: <span id='finalTime'>" + difficultySettings[currentDifficulty].gameTime + "</span>s"; |
| } else { |
| resultMessage.innerHTML = "Kaçmayı başardın!<br>Geçen Süre: <span id='finalTime'>" + difficultySettings[currentDifficulty].gameTime + "</span>s"; |
| } |
| } |
| |
| gameOverScreen.style.display = 'flex'; |
| } |
| |
| |
| function resetGame() { |
| gameOverScreen.style.display = 'none'; |
| initGame(); |
| } |
| |
| |
| startBtn.addEventListener('click', () => { |
| sentence = sentenceInput.value.trim().toUpperCase(); |
| if (sentence === '') { |
| alert('Lütfen bir cümle girin!'); |
| return; |
| } |
| |
| startScreen.style.display = 'none'; |
| |
| |
| multiplayer = gameMode === "multi"; |
| |
| |
| if (multiplayer) { |
| joystick2.style.display = "flex"; |
| } else { |
| joystick2.style.display = "none"; |
| } |
| |
| initGame(); |
| }); |
| |
| restartBtn.addEventListener('click', resetGame); |
| |
| fullscreenBtn.addEventListener('click', () => { |
| if (!document.fullscreenElement) { |
| gameContainer.requestFullscreen().catch(err => { |
| console.error(`Fullscreen error: ${err.message}`); |
| }); |
| } else { |
| document.exitFullscreen(); |
| } |
| }); |
| |
| |
| difficultyBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| difficultyBtns.forEach(b => b.classList.remove('active')); |
| btn.classList.add('active'); |
| currentDifficulty = btn.dataset.difficulty; |
| }); |
| }); |
| |
| |
| gameModeBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| gameModeBtns.forEach(b => b.classList.remove('active')); |
| btn.classList.add('active'); |
| gameMode = btn.dataset.mode; |
| |
| |
| if (gameMode === "single") { |
| roleSelection.style.display = "flex"; |
| } else { |
| roleSelection.style.display = "none"; |
| } |
| }); |
| }); |
| |
| |
| roleBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| roleBtns.forEach(b => b.classList.remove('active')); |
| btn.classList.add('active'); |
| playerRole = btn.dataset.role; |
| }); |
| }); |
| |
| |
| joystickKnob1.addEventListener('touchstart', (e) => handleJoystickStart(e, 1)); |
| joystickKnob1.addEventListener('mousedown', (e) => handleJoystickStart(e, 1)); |
| |
| |
| joystickKnob2.addEventListener('touchstart', (e) => handleJoystickStart(e, 2)); |
| joystickKnob2.addEventListener('mousedown', (e) => handleJoystickStart(e, 2)); |
| |
| document.addEventListener('touchmove', (e) => handleJoystickMove(e)); |
| document.addEventListener('mousemove', (e) => handleJoystickMove(e)); |
| |
| document.addEventListener('touchend', (e) => handleJoystickEnd(e)); |
| document.addEventListener('mouseup', (e) => handleJoystickEnd(e)); |
| |
| function handleJoystickStart(e, playerNum) { |
| e.preventDefault(); |
| if (playerNum === 1) { |
| joystick1Active = true; |
| |
| |
| const rect = joystick1.getBoundingClientRect(); |
| joystick1Position = { |
| x: rect.left + rect.width / 2, |
| y: rect.top + rect.height / 2 |
| }; |
| |
| |
| if (e.type === 'mousedown') { |
| joystick1KnobPosition = { x: e.clientX, y: e.clientY }; |
| } else { |
| joystick1KnobPosition = { x: e.touches[0].clientX, y: e.touches[0].clientY }; |
| } |
| } else if (playerNum === 2 && multiplayer) { |
| joystick2Active = true; |
| |
| |
| const rect = joystick2.getBoundingClientRect(); |
| joystick2Position = { |
| x: rect.left + rect.width / 2, |
| y: rect.top + rect.height / 2 |
| }; |
| |
| |
| if (e.type === 'mousedown') { |
| joystick2KnobPosition = { x: e.clientX, y: e.clientY }; |
| } else { |
| joystick2KnobPosition = { x: e.touches[0].clientX, y: e.touches[0].clientY }; |
| } |
| } |
| |
| updateJoystickPositions(); |
| } |
| |
| function handleJoystickMove(e) { |
| if (!joystick1Active && !joystick2Active) return; |
| e.preventDefault(); |
| |
| |
| let clientX, clientY; |
| if (e.type === 'mousemove') { |
| clientX = e.clientX; |
| clientY = e.clientY; |
| } else { |
| clientX = e.touches[0].clientX; |
| clientY = e.touches[0].clientY; |
| } |
| |
| |
| if (joystick1Active) { |
| |
| const dx = clientX - joystick1Position.x; |
| const dy = clientY - joystick1Position.y; |
| joystick1Angle = Math.atan2(dy, dx); |
| joystick1Distance = Math.min(joystickRadius, Math.sqrt(dx * dx + dy * dy)); |
| |
| |
| joystick1KnobPosition = { |
| x: joystick1Position.x + Math.cos(joystick1Angle) * joystick1Distance, |
| y: joystick1Position.y + Math.sin(joystick1Angle) * joystick1Distance |
| }; |
| } |
| |
| |
| if (joystick2Active && multiplayer) { |
| |
| const dx = clientX - joystick2Position.x; |
| const dy = clientY - joystick2Position.y; |
| joystick2Angle = Math.atan2(dy, dx); |
| joystick2Distance = Math.min(joystickRadius, Math.sqrt(dx * dx + dy * dy)); |
| |
| |
| joystick2KnobPosition = { |
| x: joystick2Position.x + Math.cos(joystick2Angle) * joystick2Distance, |
| y: joystick2Position.y + Math.sin(joystick2Angle) * joystick2Distance |
| }; |
| } |
| |
| updateJoystickPositions(); |
| } |
| |
| function handleJoystickEnd(e) { |
| if (!joystick1Active && !joystick2Active) return; |
| e.preventDefault(); |
| |
| if (joystick1Active) { |
| joystick1Active = false; |
| joystick1KnobPosition = { x: joystick1Position.x, y: joystick1Position.y }; |
| } |
| |
| if (joystick2Active) { |
| joystick2Active = false; |
| joystick2KnobPosition = { x: joystick2Position.x, y: joystick2Position.y }; |
| } |
| |
| updateJoystickPositions(); |
| } |
| |
| |
| window.addEventListener('resize', () => { |
| gameWidth = window.innerWidth; |
| gameHeight = window.innerHeight; |
| |
| if (gameActive) { |
| |
| catPosition.x = Math.min(catPosition.x, gameWidth - 60); |
| catPosition.y = Math.min(catPosition.y, gameHeight - 60); |
| |
| mousePosition.x = Math.min(mousePosition.x, gameWidth - 40); |
| mousePosition.y = Math.min(mousePosition.y, gameHeight - 40); |
| |
| |
| joystick1Position = { |
| x: gameWidth / 2, |
| y: gameHeight - 60 - 40 |
| }; |
| |
| joystick2Position = { |
| x: gameWidth / 2, |
| y: 60 + 40 |
| }; |
| |
| if (!joystick1Active) { |
| joystick1KnobPosition = { |
| x: joystick1Position.x, |
| y: joystick1Position.y |
| }; |
| } |
| |
| if (!joystick2Active) { |
| joystick2KnobPosition = { |
| x: joystick2Position.x, |
| y: joystick2Position.y |
| }; |
| } |
| |
| updateCatPosition(); |
| updateMousePosition(); |
| updateJoystickPositions(); |
| } |
| }); |
| |
| |
| catPosition = { |
| x: gameWidth / 2 - 30, |
| y: gameHeight / 2 - 30 |
| }; |
| |
| mousePosition = { |
| x: Math.random() * (gameWidth - 40), |
| y: Math.random() * (gameHeight - 40) |
| }; |
| |
| updateCatPosition(); |
| updateMousePosition(); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=0c0ps2619/catmause" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |