🎮ArcadeLab

مطاردة الكرات 3D

by RapidCoder61
263 lines10.4 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
<html>
<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>
        body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; touch-action: none; }
        #score {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            font-size: 2rem;
            font-weight: bold;
            text-shadow: 0 0 20px rgba(0,0,0,0.8);
            z-index: 10;
            background: rgba(0,0,0,0.5);
            padding: 10px 25px;
            border-radius: 30px;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(255,255,255,0.2);
            pointer-events: none;
        }
        #info {
            position: absolute;
            bottom: 30px;
            left: 0;
            right: 0;
            text-align: center;
            color: rgba(255,255,255,0.6);
            font-size: 1rem;
            text-shadow: 0 0 10px black;
            pointer-events: none;
            z-index: 10;
        }
    </style>
</head>
<body>
    <div id="score">🏆 0</div>
    <div id="info">👆 المس الكرة لتدميرها</div>

    <!-- تحميل مكتبة Three.js -->
    <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(0x0a0a1a); // لون خلفية عميق

        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, 1, 7);
        camera.lookAt(0, 0, 0);

        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMap.enabled = true; // تفعيل الظلال
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        document.body.appendChild(renderer.domElement);

        // --- الإضاءة ---
        // إضاءة محيطية
        const ambientLight = new THREE.AmbientLight(0x404060);
        scene.add(ambientLight);

        // إضاءة رئيسية (مع ظلال)
        const mainLight = new THREE.DirectionalLight(0xffeedd, 1);
        mainLight.position.set(2, 5, 3);
        mainLight.castShadow = true;
        scene.add(mainLight);

        // إضاءة خلفية ملونة
        const backLight = new THREE.PointLight(0x4466ff, 0.5);
        backLight.position.set(-3, 1, -2);
        scene.add(backLight);

        // إضاءة جانبية
        const sideLight = new THREE.PointLight(0xff66aa, 0.4);
        sideLight.position.set(4, 0, 2);
        scene.add(sideLight);

        // --- أرضية شفافة وجميلة (شبكة) ---
        const gridHelper = new THREE.GridHelper(10, 20, 0x8888ff, 0x3344aa);
        gridHelper.position.y = -1.5;
        scene.add(gridHelper);

        // --- نجوم الخلفية (جسيمات) ---
        const starsGeometry = new THREE.BufferGeometry();
        const starsCount = 1000;
        const starPositions = new Float32Array(starsCount * 3);
        for (let i = 0; i < starsCount * 3; i += 3) {
            starPositions[i] = (Math.random() - 0.5) * 200;
            starPositions[i+1] = (Math.random() - 0.5) * 200;
            starPositions[i+2] = (Math.random() - 0.5) * 200 - 50; // توزيع في العمق
        }
        starsGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
        const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.2, transparent: true });
        const stars = new THREE.Points(starsGeometry, starsMaterial);
        scene.add(stars);

        // --- منطق اللعبة ---
        let score = 0;
        const scoreDisplay = document.getElementById('score');
        const spheres = []; // مصفوفة لحفظ الكرات

        // دالة لإنشاء كرة جديدة
        function createSphere() {
            const size = 0.4 + Math.random() * 0.4;
            const geometry = new THREE.SphereGeometry(size, 32, 32);
            
            // ألوان زاهية وعشوائية
            const hue = Math.random();
            const color = new THREE.Color().setHSL(hue, 0.9, 0.6);
            const material = new THREE.MeshStandardMaterial({
                color: color,
                roughness: 0.2,
                metalness: 0.7,
                emissive: color.clone().multiplyScalar(0.2),
                emissiveIntensity: 0.5
            });
            
            const sphere = new THREE.Mesh(geometry, material);
            sphere.castShadow = true;
            sphere.receiveShadow = true;
            
            // موقع عشوائي في مساحة محددة (أمام اللاعب)
            const x = (Math.random() - 0.5) * 6;
            const y = (Math.random() - 0.5) * 4;
            sphere.position.set(x, y, 0);
            
            // تخزين بيانات إضافية للأنيميشن
            sphere.userData = {
                speed: 0.005 + Math.random() * 0.015,
                rotSpeed: 0.01 + Math.random() * 0.03,
                targetZ: -1 - Math.random() * 4, // تتحرك نحو العمق
                isDying: false
            };
            
            scene.add(sphere);
            spheres.push(sphere);
            return sphere;
        }

        // إنشاء 10 كرات ابتدائية
        for (let i = 0; i < 10; i++) {
            createSphere();
        }

        // --- التعامل مع اللمس / النقر (Raycaster) ---
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        function onPointerDown(event) {
            // حساب إحداثيات اللمس/النقر
            const rect = renderer.domElement.getBoundingClientRect();
            let clientX, clientY;
            
            if (event.touches) {
                // حدث لمس (جوال)
                clientX = event.touches[0].clientX;
                clientY = event.touches[0].clientY;
                event.preventDefault();
            } else {
                // حدث ماوس
                clientX = event.clientX;
                clientY = event.clientY;
            }

            mouse.x = ((clientX - rect.left) / rect.width) * 2 - 1;
            mouse.y = -((clientY - rect.top) / rect.height) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);

            // فحص التصادم مع جميع الكرات (التي ليست في حالة احتضار)
            const targets = spheres.filter(s => !s.userData.isDying);
            const intersects = raycaster.intersectObjects(targets);

            if (intersects.length > 0) {
                const hit = intersects[0].object;
                // تشغيل أنيميشن التدمير
                hit.userData.isDying = true;
                // زيادة النقاط
                score++;
                scoreDisplay.textContent = '🏆 ' + score;
                
                // تأثير التدمير: تكبير واختفاء
                const scaleUp = () => {
                    hit.scale.x += 0.1;
                    hit.scale.y += 0.1;
                    hit.scale.z += 0.1;
                    hit.material.emissiveIntensity += 0.1;
                    if (hit.scale.x < 2.5) {
                        requestAnimationFrame(scaleUp);
                    } else {
                        // إزالة الكرة من المشهد والمصفوفة
                        scene.remove(hit);
                        const index = spheres.indexOf(hit);
                        if (index > -1) spheres.splice(index, 1);
                        // إنشاء كرة جديدة لتعويضها
                        createSphere();
                    }
                };
                scaleUp();
            }
        }

        // ربط الأحداث (للماوس واللمس)
        renderer.domElement.addEventListener('pointerdown', onPointerDown);
        renderer.domElement.addEventListener('touchstart', onPointerDown, { passive: false });

        // --- حلقة الأنيميشن (الحركة والدوران) ---
        function animate() {
            requestAnimationFrame(animate);

            // تحريك النجوم ببطء
            stars.rotation.y += 0.0002;

            // تحريك الكرات
            for (let i = spheres.length - 1; i >= 0; i--) {
                const sphere = spheres[i];
                if (!sphere.userData.isDying) {
                    // الدوران
                    sphere.rotation.x += sphere.userData.rotSpeed;
                    sphere.rotation.y += sphere.userData.rotSpeed * 1.5;
                    
                    // الحركة: تتحرك الكرات ببطء في العمق ثم تعود
                    sphere.position.z += sphere.userData.speed;
                    
                    // إذا ابتعدت كثيراً، نعيدها للأمام مع تغيير موقعها
                    if (sphere.position.z > 5) {
                        sphere.position.z = -3;
                        sphere.position.x = (Math.random() - 0.5) * 6;
                        sphere.position.y = (Math.random() - 0.5) * 4;
                        // تغيير اللون قليلاً للتجديد
                        const newHue = Math.random();
                        sphere.material.color.setHSL(newHue, 0.9, 0.6);
                    }
                }
            }

            // تحريك الكاميرا برفق (أنيميشن إضافي)
            // camera.position.x = Math.sin(Date.now() * 0.0003) * 0.5;
            // camera.lookAt(0, 0, 0);

            renderer.render(scene, camera);
        }

        animate();

        // --- تعديل الحجم عند تغيير اتجاه الشاشة ---
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // منع التمرير أثناء اللعب
        document.body.addEventListener('touchmove', (e) => e.preventDefault(), { passive: false });

        console.log('🎮 لعبة 3D بدأت! اضغط على الكرات.');
    </script>
</body>
</html>

Game Source: مطاردة الكرات 3D

Creator: RapidCoder61

Libraries: three

Complexity: complex (263 lines, 10.4 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-rapidcoder61" to link back to the original. Then publish at arcadelab.ai/publish.