لعبة جمع المكعبات 3D - الجوال
by FrozenRider22476 lines16.6 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>لعبة جمع المكعبات 3D - الجوال</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
body {
overflow: hidden;
font-family: Arial, sans-serif;
background: #000;
touch-action: none;
user-select: none;
-webkit-user-select: none;
}
#score {
position: fixed; top: 15px; right: 15px;
color: white; font-size: 20px; font-weight: bold;
text-shadow: 2px 2px 6px black;
background: rgba(0,0,0,0.4);
padding: 8px 16px;
border-radius: 20px;
z-index: 10;
}
#timer {
position: fixed; top: 15px; left: 15px;
color: white; font-size: 20px; font-weight: bold;
text-shadow: 2px 2px 6px black;
background: rgba(0,0,0,0.4);
padding: 8px 16px;
border-radius: 20px;
z-index: 10;
}
/* عصا التحكم */
#joystick {
position: fixed; bottom: 40px; left: 30px;
width: 130px; height: 130px;
background: rgba(255,255,255,0.15);
border: 2px solid rgba(255,255,255,0.4);
border-radius: 50%;
z-index: 20;
touch-action: none;
}
#stick {
position: absolute;
width: 60px; height: 60px;
background: rgba(255,255,255,0.7);
border: 2px solid white;
border-radius: 50%;
top: 33px; left: 33px;
transition: transform 0.05s ease-out;
box-shadow: 0 4px 10px rgba(0,0,0,0.4);
pointer-events: none;
}
/* شاشة النهاية */
#gameOver {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.85);
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
z-index: 100;
text-align: center;
padding: 20px;
}
#gameOver h1 {
font-size: 42px;
margin-bottom: 20px;
color: #ff5722;
text-shadow: 2px 2px 10px black;
}
#gameOver p {
font-size: 24px;
margin-bottom: 15px;
}
#gameOver .finalScore {
font-size: 60px;
font-weight: bold;
color: #ffeb3b;
margin-bottom: 30px;
text-shadow: 3px 3px 10px black;
}
#restartBtn {
padding: 18px 50px;
font-size: 22px;
font-weight: bold;
background: #4CAF50;
color: white;
border: none;
border-radius: 50px;
box-shadow: 0 6px 20px rgba(76,175,80,0.5);
cursor: pointer;
touch-action: manipulation;
}
#restartBtn:active {
transform: scale(0.95);
background: #388E3C;
}
/* شاشة البداية */
#startScreen {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
z-index: 200;
text-align: center;
padding: 20px;
}
#startScreen h1 {
font-size: 38px;
margin-bottom: 15px;
text-shadow: 2px 2px 10px rgba(0,0,0,0.5);
}
#startScreen p {
font-size: 18px;
margin-bottom: 30px;
opacity: 0.9;
line-height: 1.6;
}
#startBtn {
padding: 20px 60px;
font-size: 24px;
font-weight: bold;
background: #ff5722;
color: white;
border: none;
border-radius: 50px;
box-shadow: 0 8px 25px rgba(255,87,34,0.5);
cursor: pointer;
touch-action: manipulation;
}
#startBtn:active {
transform: scale(0.95);
}
</style>
</head>
<body>
<!-- شاشة البداية -->
<div id="startScreen">
<h1>🎮 لعبة جمع المكعبات</h1>
<p>حرك الكرة البرتقالية بلمس الشاشة<br>واجمع أكبر عدد من المكعبات الملونة<br>لديك 30 ثانية فقط!</p>
<button id="startBtn">ابدأ اللعب</button>
</div>
<!-- واجهة اللعب -->
<div id="score">النقاط: 0</div>
<div id="timer">⏱ 30</div>
<!-- عصا التحكم -->
<div id="joystick">
<div id="stick"></div>
</div>
<!-- شاشة النهاية -->
<div id="gameOver">
<h1>انتهى الوقت!</h1>
<p>نتيجتك النهائية</p>
<div class="finalScore" id="finalScore">0</div>
<button id="restartBtn">العب مرة أخرى</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ===== الإعداد الأساسي =====
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB);
scene.fog = new THREE.Fog(0x87CEEB, 12, 45);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0, 10, 14);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
// ===== الإضاءة =====
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 10, 5);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
// ===== الأرضية =====
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(30, 30),
new THREE.MeshStandardMaterial({ color: 0x2ecc71 })
);
floor.rotation.x = -Math.PI / 2;
scene.add(floor);
// ===== اللاعب =====
const player = new THREE.Mesh(
new THREE.SphereGeometry(0.6, 32, 32),
new THREE.MeshStandardMaterial({ color: 0xff5722, emissive: 0x441100 })
);
player.position.y = 0.6;
scene.add(player);
// ===== المكعبات =====
const cubes = [];
const cubeColors = [0xffeb3b, 0xe91e63, 0x9c27b0, 0x00bcd4, 0xff9800, 0x4CAF50];
function createCube() {
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({
color: cubeColors[Math.floor(Math.random()*cubeColors.length)]
})
);
cube.position.set(
(Math.random() - 0.5) * 24,
0.5,
(Math.random() - 0.5) * 24
);
cube.rotation.y = Math.random() * Math.PI;
scene.add(cube);
cubes.push(cube);
}
// ===== متغيرات اللعبة =====
let score = 0;
let gameActive = false;
let timeLeft = 30;
const speed = 0.18;
// ===== إدخال الحركة (متجهي) =====
const moveInput = { x: 0, y: 0 }; // من -1 إلى 1
// كيبورد (للاختبار على الكمبيوتر)
const keys = {};
window.addEventListener('keydown', e => keys[e.key] = true);
window.addEventListener('keyup', e => keys[e.key] = false);
function updateKeyboardInput() {
let x = 0, y = 0;
if (keys['ArrowLeft'] || keys['a'] || keys['A']) x -= 1;
if (keys['ArrowRight'] || keys['d'] || keys['D']) x += 1;
if (keys['ArrowUp'] || keys['w'] || keys['W']) y -= 1;
if (keys['ArrowDown'] || keys['s'] || keys['S']) y += 1;
if (x !== 0 || y !== 0) {
moveInput.x = x;
moveInput.y = y;
}
}
// ===== عصا التحكم =====
const joystick = document.getElementById('joystick');
const stick = document.getElementById('stick');
let joystickActive = false;
let joystickCenter = { x: 0, y: 0 };
const maxDist = 45;
function getJoystickCenter() {
const rect = joystick.getBoundingClientRect();
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}
function handleJoystickStart(e) {
e.preventDefault();
joystickActive = true;
joystickCenter = getJoystickCenter();
handleJoystickMove(e);
}
function handleJoystickMove(e) {
if (!joystickActive) return;
e.preventDefault();
const touch = e.touches ? e.touches[0] : e;
let dx = touch.clientX - joystickCenter.x;
let dy = touch.clientY - joystickCenter.y;
const dist = Math.sqrt(dx*dx + dy*dy);
const clampedDist = Math.min(dist, maxDist);
const angle = Math.atan2(dy, dx);
const stickX = Math.cos(angle) * clampedDist;
const stickY = Math.sin(angle) * clampedDist;
stick.style.transform = `translate(${stickX}px, ${stickY}px)`;
// تحويل إلى مدخلات (-1 إلى 1)
moveInput.x = (dx / maxDist);
moveInput.y = (dy / maxDist);
// تحديد القيمة القصوى بـ 1
const mag = Math.sqrt(moveInput.x**2 + moveInput.y**2);
if (mag > 1) {
moveInput.x /= mag;
moveInput.y /= mag;
}
}
function handleJoystickEnd(e) {
e.preventDefault();
joystickActive = false;
stick.style.transform = 'translate(0, 0)';
moveInput.x = 0;
moveInput.y = 0;
}
joystick.addEventListener('touchstart', handleJoystickStart, { passive: false });
joystick.addEventListener('touchmove', handleJoystickMove, { passive: false });
joystick.addEventListener('touchend', handleJoystickEnd, { passive: false });
joystick.addEventListener('touchcancel', handleJoystickEnd, { passive: false });
// دعم الماوس (للتجربة على الكمبيوتر)
joystick.addEventListener('mousedown', handleJoystickStart);
window.addEventListener('mousemove', handleJoystickMove);
window.addEventListener('mouseup', handleJoystickEnd);
// ===== بدء اللعبة =====
function startGame() {
// إعادة تعيين
score = 0;
timeLeft = 30;
gameActive = true;
// حذف المكعبات القديمة
cubes.forEach(c => scene.remove(c));
cubes.length = 0;
// إنشاء مكعبات جديدة
for (let i = 0; i < 15; i++) createCube();
// إعادة اللاعب
player.position.set(0, 0.6, 0);
// تحديث الواجهة
document.getElementById('score').textContent = 'النقاط: 0';
document.getElementById('timer').textContent = '⏱ 30';
document.getElementById('startScreen').style.display = 'none';
document.getElementById('gameOver').style.display = 'none';
// بدء الحلقة
lastTime = performance.now();
animate();
}
// ===== حلقة اللعبة =====
let lastTime = performance.now();
function animate() {
if (!gameActive) return;
requestAnimationFrame(animate);
const now = performance.now();
const delta = Math.min((now - lastTime) / 1000, 0.1);
lastTime = now;
// تحديث مدخلات الكيبورد إذا لم تكن العصا نشطة
if (!joystickActive) {
const prevX = moveInput.x, prevY = moveInput.y;
updateKeyboardInput();
// إذا لم تكن هناك ضغطة كيبورد، صفر المدخلات
if (prevX === moveInput.x && prevY === moveInput.y) {
let x = 0, y = 0;
if (keys['ArrowLeft'] || keys['a'] || keys['A']) x -= 1;
if (keys['ArrowRight'] || keys['d'] || keys['D']) x += 1;
if (keys['ArrowUp'] || keys['w'] || keys['W']) y -= 1;
if (keys['ArrowDown'] || keys['s'] || keys['S']) y += 1;
moveInput.x = x;
moveInput.y = y;
}
}
// حركة اللاعب
player.position.x += moveInput.x * speed * 60 * delta;
player.position.z += moveInput.y * speed * 60 * delta;
// حدود الملعب
player.position.x = Math.max(-14, Math.min(14, player.position.x));
player.position.z = Math.max(-14, Math.min(14, player.position.z));
// تدوير اللاعب قليلاً حسب الحركة
player.rotation.z = -moveInput.x * 0.3;
// تدوير المكعبات + كشف التصادم
for (let i = cubes.length - 1; i >= 0; i--) {
const cube = cubes[i];
cube.rotation.y += 0.03;
cube.rotation.x += 0.015;
cube.position.y = 0.5 + Math.sin(now * 0.003 + i) * 0.15;
const dx = player.position.x - cube.position.x;
const dz = player.position.z - cube.position.z;
const dist = Math.sqrt(dx*dx + dz*dz);
if (dist < 1.1) {
scene.remove(cube);
cubes.splice(i, 1);
score += 10;
document.getElementById('score').textContent = 'النقاط: ' + score;
createCube();
}
}
// المؤقت
timeLeft -= delta;
const displayTime = Math.max(0, Math.ceil(timeLeft));
document.getElementById('timer').textContent = '⏱ ' + displayTime;
if (timeLeft <= 0) {
endGame();
return;
}
// الكاميرا تتبع اللاعب
camera.position.x = player.position.x * 0.4;
camera.position.z = player.position.z * 0.4 + 14;
camera.position.y = 10;
camera.lookAt(player.position.x * 0.4, 0, player.position.z * 0.4);
renderer.render(scene, camera);
}
// ===== إنهاء اللعبة =====
function endGame() {
gameActive = false;
document.getElementById('finalScore').textContent = score;
document.getElementById('gameOver').style.display = 'flex';
}
// ===== الأزرار =====
document.getElementById('startBtn').addEventListener('click', startGame);
document.getElementById('startBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
startGame();
}, { passive: false });
document.getElementById('restartBtn').addEventListener('click', startGame);
document.getElementById('restartBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
startGame();
}, { passive: false });
// ===== تعديل حجم الشاشة =====
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// منع التمرير والسحب على الشاشة
document.addEventListener('touchmove', (e) => {
if (e.target.closest('#joystick')) return;
e.preventDefault();
}, { passive: false });
</script>
</body>
</html>Game Source: لعبة جمع المكعبات 3D - الجوال
Creator: FrozenRider22
Libraries: three
Complexity: complex (476 lines, 16.6 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: 3d-frozenrider22" to link back to the original. Then publish at arcadelab.ai/publish.