// Basic settings const canvas = document.getElementById('game-canvas'); const roleLabel = document.getElementById('role

Pasted Oct 8, 2026, 2:17 PM1 file1 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgt11cmkcsxte0g
// Basic settings const canvas = document.getElementById('game-canvas'); const roleLabel = document.getElementById('role
// Basic settings const canvas = document.getElementById('game-canvas'); const roleLabel = document.getElementById('role-label'); const hpLabel = document.getElementById('hp-label'); const coinsLabel = document.getElementById('coins-label'); const messageEl = document.getElementById('message'); const hud = document.getElementById('hud'); const roleSelect = document.getElementById('role-select'); const shopEl = document.getElementById('shop'); const shopItemsEl = document.getElementById('shop-items'); let role = null; // "Zombie" or "Shooter" let hp = 100; let coins = 0; let damage = 10; let moveSpeed = 10; let canAttack = true; let attackCooldown = 0.4; // seconds // Three.js setup const scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); const renderer = new THREE.WebGLRenderer({ canvas }); renderer.setSize(window.innerWidth, window.innerHeight); // Light const light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(10, 20, 10); scene.add(light); scene.add(new THREE.AmbientLight(0x404040)); // Ground const groundGeo = new THREE.PlaneGeometry(200, 200); const groundMat = new THREE.MeshPhongMaterial({ color: 0x222222 }); const ground = new THREE.Mesh(groundGeo, groundMat); ground.rotation.x = -Math.PI / 2; scene.add(ground); // Simple "base" walls const wallMat = new THREE.MeshPhongMaterial({ color: 0x333366 }); function addWall(x, z, w, h, d) { const geo = new THREE.BoxGeometry(w, h, d); const mesh = new THREE.Mesh(geo, wallMat); mesh.position.set(x, h / 2, z); mesh.castShadow = true; scene.add(mesh); } addWall(0, -30, 40, 10, 2); // front wall addWall(-20, -10, 2, 10, 40); // left wall addWall(20, -10, 2, 10, 40); // right wall addWall(0, 10, 40, 10, 2); // back wall // Enemies (dummy cubes to attack) const enemies = []; const enemyGeo = new THREE.BoxGeometry(1, 2, 1); const zombieMat = new THREE.MeshPhongMaterial({ color: 0x00ff00 }); const shooterMat = new THREE.MeshPhongMaterial({ color: 0xff0000 }); function spawnEnemy(type, x, z) { const mat = type === 'Zombie' ? zombieMat : shooterMat; const mesh = new THREE.Mesh(enemyGeo, mat); mesh.position.set(x, 1, z); mesh.userData = { type, hp: 30, }; scene.add(mesh); enemies.push(mesh); } // Spawn some enemies around spawnEnemy('Zombie', 0, -20); spawnEnemy('Zombie', -10, -15); spawnEnemy('Shooter', 10, -5); spawnEnemy('Shooter', -5, 5); // Controls const controls = new THREE.PointerLockControls(camera, document.body); camera.position.set(0, 2, 10); document.addEventListener('click', () => { if (!controls.isLocked) { controls.lock(); } }); const keys = {}; document.addEventListener('keydown', (e) => { keys[e.code] = true; // E to open shop if (e.code === 'KeyE') { toggleShop(); } }); document.addEventListener('keyup', (e) => { keys[e.code] = false; }); // Role selection document.getElementById('play-zombie').addEventListener('click', () => { startGame('Zombie'); }); document.getElementById('play-shooter').addEventListener('click', () => { startGame('Shooter'); }); function startGame(selectedRole) { role = selectedRole; roleLabel.textContent = role; hp = role === 'Zombie' ? 150 : 100; hpLabel.textContent = hp.toString(); coins = 0; coinsLabel.textContent = coins.toString(); damage = role === 'Shooter' ? 15 : 10; moveSpeed = role === 'Zombie' ? 7 : 10; roleSelect.classList.add('hidden'); hud.classList.remove('hidden'); messageEl.textContent = 'Find enemies and attack them!'; } // Shop const shopItems = [ { id: 'dmg1', label: '+10 Damage (Cost 20)', cost: 20, apply: () => { damage += 10; } }, { id: 'spd1', label: '+2 Speed (Cost 20)', cost: 20, apply: () => { moveSpeed += 2; } }, { id: 'hp1', label: '+50 Max HP (Cost 30)', cost: 30, apply: () => { hp += 50; } }, ]; function buildShop() { shopItemsEl.innerHTML = ''; shopItems.forEach(item => { const btn = document.createElement('button'); btn.textContent = item.label; btn.addEventListener('click', () => { if (coins >= item.cost) { coins -= item.cost; coinsLabel.textContent = coins.toString(); item.apply(); messageEl.textContent = 'Upgrade purchased!'; } else { messageEl.textContent = 'Not enough coins.'; } }); shopItemsEl.appendChild(btn); }); } buildShop(); function toggleShop() { if (!role) return; if (shopEl.classList.contains('hidden')) { shopEl.classList.remove('hidden'); } else { shopEl.classList.add('hidden'); } } document.getElementById('close-shop').addEventListener('click', () => { shopEl.classList.add('hidden'); }); // Attack / shoot document.addEventListener('mousedown', (e) => { if (e.button === 0) { attemptAttack(); } }); function attemptAttack() { if (!role || !canAttack) return; canAttack = false; setTimeout(() => { canAttack = true; }, attackCooldown * 1000); // Raycast from camera center const raycaster = new THREE.Raycaster(); const dir = new THREE.Vector3(); camera.getWorldDirection(dir); raycaster.set(camera.position, dir); const intersects = raycaster.intersectObjects(enemies, false); if (intersects.length > 0) { const hit = intersects[0].object; hit.userData.hp -= damage; messageEl.textContent = `Hit ${hit.userData.type}! HP left: ${hit.userData.hp}`; if (hit.userData.hp <= 0) { // Reward coins const reward = hit.userData.type === 'Zombie' ? 15 : 10; coins += reward; coinsLabel.textContent = coins.toString(); messageEl.textContent = `Killed ${hit.userData.type}! +${reward} coins`; // Remove from scene scene.remove(hit); const idx = enemies.indexOf(hit); if (idx >= 0) enemies.splice(idx, 1); } } else { messageEl.textContent = 'Missed.'; } } // Movement & game loop let lastTime = performance.now(); function update(delta) { if (controls.isLocked && role) { const velocity = new THREE.Vector3(); const forward = new THREE.Vector3(); camera.getWorldDirection(forward); forward.y = 0; forward.normalize(); const right = new THREE.Vector3().crossVectors(forward, new THREE.Vector3(0, 1, 0)).normalize(); if (keys['KeyW']) velocity.add(forward); if (keys['KeyS']) velocity.sub(forward); if (keys['KeyA']) velocity.sub(right); if (keys['KeyD']) velocity.add(right); if (velocity.length() > 0) { velocity.normalize().multiplyScalar(moveSpeed * delta); controls.getObject().position.add(velocity); } } // Simple dummy damage over time if inside base as zombie (example) if (role === 'Zombie') { const pos = controls.getObject().position; const insideBase = pos.x > -20 && pos.x < 20 && pos.z > -30 && pos.z < 10; if (insideBase) { hp -= 5 * delta; // slow damage if (hp <= 0) { hp = 0; messageEl.textContent = 'You died! Refresh to restart.'; } hpLabel.textContent = hp.toFixed(0); } } } function animate() { requestAnimationFrame(animate); const now = performance.now(); const delta = (now - lastTime) / 1000; lastTime = now; update(delta); renderer.render(scene, camera); } animate(); window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); });

7,021 chars · codepastes.com