Meta Description" name="description" />
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<title>3D Parkur - Roblox Tarzı!</title>
<style>
body { margin:0; overflow:hidden; background:#000; font-family:Arial; }
canvas { display:block; }
#ui {
position: absolute;
top: 20px; left: 20px; color: #fff; font-size: 28px; font-weight:bold;
text-shadow: 2px 2px 4px #000; pointer-events: none; z-index:10;
}
#startScreen, #gameOverScreen {
position: absolute; inset: 0;
background: rgba(0,0,0,0.9);
color: #fff; display: flex; flex-direction: column;
justify-content: center; align-items: center; font-size: 32px; z-index:20;
}
#startScreen h1 { font-size:48px; margin:0; color:#00ff88; text-shadow:0 0 20px #00ff88; }
#gameOverScreen h1 { font-size:40px; margin:10px 0; color:#ff4444; }
button {
margin-top: 30px; padding: 20px 50px; font-size: 28px;
background: linear-gradient(45deg, #00ff88, #00cc66); border: none; color: #000;
border-radius: 50px; box-shadow: 0 10px 20px rgba(0,255,136,0.3);
cursor:pointer; transition: all 0.2s;
}
button:hover, button:active { transform: scale(1.05); box-shadow: 0 15px 30px rgba(0,255,136,0.5); }
#instructions {
font-size:20px; margin:20px 0; text-align:center; max-width:80%; line-height:1.4;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="ui">Skor: <span id="score">0</span></div>
<div id="startScreen">
<h1>3D PARKUR</h1>
<div id="instructions">
Parmağınla ekranı kaydır:<br>
• Yukarı: Zıpla<br>
• Sol/Sağ: Şerit değiştir<br>
Ne kadar uzağa gidersen skorun o kadar artar!
</div>
<button onclick="startGame()">BAŞLA</button>
</div>
<div id="gameOverScreen" style="display:none;">
<h1>Oyun Bitti!</h1>
<div style="font-size:24px; margin:20px 0;">Skorun: <span id="finalScore">0</span></div>
<button onclick="startGame()">TEKRAR Oyna</button>
</div>
<script>
let scene, camera, renderer, player;
let segments = [], velocity = {x:0, y:0, z:0}, gravity = -0.015, jumpPower = 0.35;
let speed = 0.4, lanes = [-2.5, 0, 2.5], currentLane = 1, gameRunning = false, score = 0;
let touchStart = {x:0, y:0}, onGround = true;
const segmentLength = 15, maxSegments = 15;
const scoreEl = document.getElementById("score");
const finalScoreEl = document.getElementById("finalScore");
function init() {
const w = window.innerWidth, h = window.innerHeight;
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x222244, 50, 200);
camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 1000);
camera.position.set(0, 8, 15);
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(w, h);
renderer.setClearColor(0x000011, 1);
document.body.appendChild(renderer.domElement);
// Lights
const ambient = new THREE.AmbientLight(0x404040, 0.6);
scene.add(ambient);
const directional = new THREE.DirectionalLight(0xffffff, 0.8);
directional.position.set(0, 10, 5);
scene.add(directional);
// Player
const playerGeo = new THREE.BoxGeometry(1.2, 1.2, 1.2);
const playerMat = new THREE.MeshLambertMaterial({ color: 0xff4444 });
player = new THREE.Mesh(playerGeo, playerMat);
player.position.set(0, 0.6, 0);
scene.add(player);
// Particles for fun
const particlesGeo = new THREE.BufferGeometry();
const particlesCnt = 1000;
const posArray = new Float32Array(particlesCnt * 3);
for(let i=0; i<particlesCnt*3; i++) posArray[i] = (Math.random()-0.5)*100;
particlesGeo.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
const particlesMat = new THREE.PointsMaterial({ size: 0.02, color: 0x00ff88 });
const particlesMesh = new THREE.Points(particlesGeo, particlesMat);
scene.add(particlesMesh);
resize();
window.addEventListener('resize', resize);
// Controls
renderer.domElement.addEventListener('touchstart', onTouchStart, {passive:false});
renderer.domElement.addEventListener('touchend', onTouchEnd, {passive:false});
renderer.domElement.addEventListener('touchmove', e=>e.preventDefault(), {passive:false});
}
function resize() {
const w = window.innerWidth, h = window.innerHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize(w, h);
}
function onTouchStart(e) {
e.preventDefault();
const touch = e.touches[0];
touchStart.x = touch.clientX;
touchStart.y = touch.clientY;
}
function onTouchEnd(e) {
e.preventDefault();
if(!gameRunning) return;
const touch = e.changedTouches[0];
const deltaX = touch.clientX - touchStart.x;
const deltaY = touch.clientY - touchStart.y;
// Jump
if(deltaY < -40 && onGround) {
velocity.y = jumpPower;
onGround = false;
}
// Lane change
if(Math.abs(deltaX) > 40) {
const dir = deltaX > 0 ? 1 : -1;
const newLane = Math.max(0, Math.min(2, currentLane + dir));
if(newLane !== currentLane) {
currentLane = newLane;
}
}
}
function createSegment(zPos) {
const group = new THREE.Group();
// Ground
const groundGeo = new THREE.PlaneGeometry(segmentLength, 8);
const groundMat = new THREE.MeshLambertMaterial({ color: 0x3366bb });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.position.y = 0;
group.add(ground);
// Side walls
const wallGeo = new THREE.BoxGeometry(0.5, 4, segmentLength);
const wallMat = new THREE.MeshLambertMaterial({ color: 0x444466 });
const leftWall = new THREE.Mesh(wallGeo, wallMat);
leftWall.position.set(-5, 2, 0);
group.add(leftWall);
const rightWall = new THREE.Mesh(wallGeo, wallMat);
rightWall.position.set(5, 2, 0);
group.add(rightWall);
// Random obstacle
if(Math.random() < 0.4) {
const obsLane = Math.floor(Math.random() * 3);
const obsPos = lanes[obsLane];
const obsGeo = new THREE.BoxGeometry(1.8, 3.5, 3);
const obsMat = new THREE.MeshLambertMaterial({ color: 0xffaa00 });
const obstacle = new THREE.Mesh(obsGeo, obsMat);
obstacle.position.set(obsPos, 1.75, Math.random()*2 -1);
group.add(obstacle);
group.userData.obstacleLane = obsLane;
}
group.position.z = zPos;
return group;
}
function spawnSegments() {
while(segments.length < maxSegments) {
const zPos = player.position.z + segments.length * segmentLength;
const seg = createSegment(zPos);
scene.add(seg);
segments.push(seg);
}
}
function checkCollisions() {
const playerBox = new THREE.Box3().setFromObject(player);
const playerLane = Math.round((player.position.x + 3) / 5); // Approximate lane 0-2
for(let i=0; i<5; i++) { // Check recent segments
const seg = segments[i];
if(!seg || !seg.userData.obstacleLane) continue;
if(seg.userData.obstacleLane === playerLane) {
const segBox = new THREE.Box3().setFromObject(seg.children.find(c=>c.geometry.type==='BoxGeometry'));
if(playerBox.intersectsBox(segBox)) {
gameOver();
return;
}
}
}
}
function update() {
if(!gameRunning) return;
// Smooth lane movement
const targetX = lanes[currentLane];
velocity.x = (targetX - player.position.x) * 0.15;
// Physics
velocity.y += gravity;
player.position.x += velocity.x;
player.position.y += velocity.y;
player.position.z += speed;
// Ground collision
if(player.position.y <= 0.6) {
player.position.y = 0.6;
velocity.y = 0;
onGround = true;
}
// Camera follow
camera.position.x = THREE.MathUtils.lerp(camera.position.x, player.position.x * 0.4, 0.08);
camera.position.y = THREE.MathUtils.lerp(camera.position.y, player.position.y + 6, 0.08);
camera.position.z = player.position.z + 12;
camera.lookAt(player.position);
// Segments
spawnSegments();
for(let i=segments.length-1; i>=0; i--) {
if(segments[i].position.z < player.position.z - segmentLength * 2) {
scene.remove(segments[i]);
segments.splice(i, 1);
}
}
// Score
score = Math.floor(player.position.z / 10);
scoreEl.textContent = score;
// Collisions
checkCollisions();
renderer.render(scene, camera);
requestAnimationFrame(update);
}
function startGame() {
document.getElementById("startScreen").style.display = "none";
document.getElementById("gameOverScreen").style.display = "none";
gameRunning = true;
score = 0;
player.position.set(0, 0.6, 0);
currentLane = 1;
velocity = {x:0, y:0, z:0};
segments.forEach(s => scene.remove(s));
segments = [];
scoreEl.textContent = "0";
update();
}
function gameOver() {
gameRunning = false;
finalScoreEl.textContent = score;
document.getElementById("gameOverScreen").style.display = "flex";
}
init();
update(); // Initial render
</script>
</body>
</html>2
2
128KB
599KB
277.0ms
104.0ms
278.0ms