🎮ArcadeLab

ساحة الأبطال 3D - قاتلي الشياطين

by RapidPenguin10
244 lines10.4 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <title>ساحة الأبطال 3D - قاتلي الشياطين</title>
  <style>
    body { margin: 0; overflow: hidden; background: #050811; font-family: Arial, sans-serif; user-select: none; touch-action: none; }
    #ui { position: fixed; top: 15px; right: 15px; color: #fff; z-index: 10; font-size: 18px; font-weight: bold; text-shadow: 0 0 5px #000; }
    #controls { position: fixed; bottom: 20px; left: 20px; right: 20px; display: flex; justify-content: space-between; align-items: flex-end; z-index: 10; pointer-events: none; }
    .btn { width: 70px; height: 70px; border-radius: 50%; background: rgba(255,255,255,0.2); border: 2px solid #fff; color: white; font-weight: bold; font-size: 14px; pointer-events: auto; cursor: pointer; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(5px); transition: transform 0.1s; }
    .btn:active { background: rgba(255,255,255,0.5); transform: scale(0.95); }
    #skills { display: flex; gap: 10px; }
    #joy-area { width: 120px; height: 120px; border-radius: 50%; background: rgba(255,255,255,0.1); border: 2px solid rgba(255,255,255,0.3); pointer-events: auto; position: relative; touch-action: none; }
    #stick { width: 50px; height: 50px; border-radius: 50%; background: #fff; position: absolute; top: 35px; left: 35px; pointer-events: none; }
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>

  <div id="ui">⚔️ قاتل الشياطين 3D | الصحة: <span id="hp">100</span> | الأعداء المهزومين: <span id="kills">0</span></div>

  <div id="controls">
    <div id="joy-area"><div id="stick"></div></div>
    <div id="skills">
      <div class="btn" onclick="attack('fire')" style="border-color: #ff4500; color: #ffaa00;">تنفس النار</div>
      <div class="btn" onclick="attack('water')" style="border-color: #00bfff; color: #87cefa;">تنفس الماء</div>
    </div>
  </div>

  <script>
    // 1. إعداد المشهد والكاميرا والمحرك
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x050811);
    scene.fog = new THREE.FogExp2(0x050811, 0.03);

    const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    document.body.appendChild(renderer.domElement);

    // 2. الإضاءة
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
    scene.add(ambientLight);

    const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
    dirLight.position.set(20, 40, 20);
    dirLight.castShadow = true;
    scene.add(dirLight);

    // 3. الأرضية (ساحة القتال)
    const floorGeo = new THREE.PlaneGeometry(100, 100);
    const floorMat = new THREE.MeshStandardMaterial({ color: 0x111625, roughness: 0.8 });
    const floor = new THREE.Mesh(floorGeo, floorMat);
    floor.rotation.x = -Math.PI / 2;
    floor.receiveShadow = true;
    scene.add(floor);

    // إضافة خطوط شبكية كزينة للأرضية
    const grid = new THREE.GridHelper(100, 50, 0x3f51b5, 0x1a237e);
    grid.position.y = 0.01;
    scene.add(grid);

    // 4. اللاعب (البطل)
    const playerGeo = new THREE.CylinderGeometry(0.6, 0.6, 2, 16);
    const playerMat = new THREE.MeshStandardMaterial({ color: 0x00bfff, roughness: 0.5 });
    const player = new THREE.Mesh(playerGeo, playerMat);
    player.position.y = 1;
    player.castShadow = true;
    scene.add(player);

    // بيانات اللاعب
    let playerStats = { hp: 100, kills: 0 };
    let moveDir = { x: 0, z: 0 };
    const playerSpeed = 0.15;

    // 5. الأعداء (الشياطين)
    const enemies = [];
    const enemyGeo = new THREE.BoxGeometry(1.2, 2, 1.2);
    const enemyMat = new THREE.MeshStandardMaterial({ color: 0xff4500 });

    function spawnEnemy() {
      if (enemies.length < 5) {
        const enemy = new THREE.Mesh(enemyGeo, enemyMat);
        // توليد العدو في مكان عشوائي بعيد عن اللاعب
        const angle = Math.random() * Math.PI * 2;
        const radius = 15 + Math.random() * 10;
        enemy.position.set(
          player.position.x + Math.cos(angle) * radius,
          1,
          player.position.z + Math.sin(angle) * radius
        );
        enemy.castShadow = true;
        scene.add(enemy);
        enemies.push(enemy);
      }
    }
    // توليد عدو كل 3 ثوانٍ
    setInterval(spawnEnemy, 3000);

    // 6. تأثيرات الهجوم (القدرات السحرية)
    let activeEffects = [];

    function attack(type) {
      const effectGeo = new THREE.SphereGeometry(3, 16, 16);
      let effectMat;

      if (type === 'fire') {
        effectMat = new THREE.MeshBasicMaterial({ color: 0xffa500, transparent: true, opacity: 0.6, wireframe: true });
      } else {
        effectMat = new THREE.MeshBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.6, wireframe: true });
      }

      const effect = new THREE.Mesh(effectGeo, effectMat);
      effect.position.copy(player.position);
      scene.add(effect);

      activeEffects.push({
        mesh: effect,
        type: type,
        spawnTime: Date.now(),
        duration: 400 // ميكانيكية الاختفاء بعد 0.4 ثانية
      });

      // التحقق من إصابة الأعداء داخل نطاق الهجوم
      for (let i = enemies.length - 1; i >= 0; i--) {
        const dist = player.position.distanceTo(enemies[i].position);
        if (dist <= 4) { // إذا كان العدو قريباً من مدى الضرب
          scene.remove(enemies[i]);
          enemies.splice(i, 1);
          playerStats.kills++;
          document.getElementById('kills').innerText = playerStats.kills;
        }
      }
    }

    // 7. نظام التحكم عبر عصا التحكم (Joystick) للموبايل والماوس
    const joyArea = document.getElementById('joy-area');
    const stick = document.getElementById('stick');
    let isDragging = false;

    function handleMove(clientX, clientY) {
      const rect = joyArea.getBoundingClientRect();
      const centerX = rect.left + rect.width / 2;
      const centerY = rect.top + rect.height / 2;
      
      let deltaX = clientX - centerX;
      let deltaY = clientY - centerY;
      const distance = Math.min(Math.sqrt(deltaX * deltaX + deltaY * deltaY), 45);
      
      const angle = Math.atan2(deltaY, deltaX);
      const stickX = Math.cos(angle) * distance;
      const stickY = Math.sin(angle) * distance;

      stick.style.transform = `translate(${stickX}px, ${stickY}px)`;

      // تحديث اتجاه الحركة للبطل
      moveDir.x = Math.cos(angle) * (distance / 45);
      moveDir.z = Math.sin(angle) * (distance / 45);
    }

    joyArea.addEventListener('pointerdown', (e) => { isDragging = true; joyArea.setPointerCapture(e.pointerId); handleMove(e.clientX, e.clientY); });
    joyArea.addEventListener('pointermove', (e) => { if (isDragging) handleMove(e.clientX, e.clientY); });
    joyArea.addEventListener('pointerup', (e) => { 
      isDragging = false; 
      stick.style.transform = 'translate(0px, 0px)'; 
      moveDir = { x: 0, z: 0 }; 
    });

    // التحكم بالوحة المفاتيح للكمبيوتر (WASD / Arrows)
    window.addEventListener('keydown', (e) => {
      if (e.key === 'w' || e.key === 'ArrowUp') moveDir.z = -1;
      if (e.key === 's' || e.key === 'ArrowDown') moveDir.z = 1;
      if (e.key === 'a' || e.key === 'ArrowLeft') moveDir.x = -1;
      if (e.key === 'd' || e.key === 'ArrowRight') moveDir.x = 1;
    });
    window.addEventListener('keyup', (e) => {
      if (['w', 's', 'ArrowUp', 'ArrowDown'].includes(e.key)) moveDir.z = 0;
      if (['a', 'd', 'ArrowLeft', 'ArrowRight'].includes(e.key)) moveDir.x = 0;
    });

    // 8. حلقة التحديث المستمر (Game Loop)
    function animate() {
      requestAnimationFrame(animate);

      // تحريك اللاعب
      if (moveDir.x !== 0 || moveDir.z !== 0) {
        player.position.x += moveDir.x * playerSpeed;
        player.position.z += moveDir.z * playerSpeed;
        
        // تدوير وجه اللاعب باتجاه الحركة
        player.rotation.y = Math.atan2(-moveDir.x, -moveDir.z);
      }

      // تحريك وتحديث الأعداء (لحاق اللاعب)
      for (let i = enemies.length - 1; i >= 0; i--) {
        const enemy = enemies[i];
        const dir = new THREE.Vector3().subVectors(player.position, enemy.position).normalize();
        
        enemy.position.x += dir.x * 0.05;
        enemy.position.z += dir.z * 0.05;
        enemy.lookAt(player.position.x, enemy.position.y, player.position.z);

        // لمس العدو للاعب ينقص من الصحة
        if (enemy.position.distanceTo(player.position) < 1.2) {
          playerStats.hp -= 0.2; // نقص تدريجي عند اللمس
          document.getElementById('hp').innerText = Math.max(0, Math.floor(playerStats.hp));
          if (playerStats.hp <= 0) {
            alert("لقد هزمتك الشياطين! حاول مجدداً.");
            playerStats.hp = 100;
            playerStats.kills = 0;
            player.position.set(0, 1, 0);
            document.getElementById('hp').innerText = "100";
            document.getElementById('kills').innerText = "0";
            // تنظيف الأعداء
            enemies.forEach(en => scene.remove(en));
            enemies.length = 0;
          }
        }
      }

      // تحديث تأثيرات المهارات القتالية وانكماشها
      const now = Date.now();
      for (let i = activeEffects.length - 1; i >= 0; i--) {
        const fx = activeEffects[i];
        if (now - fx.spawnTime > fx.duration) {
          scene.remove(fx.mesh);
          activeEffects.splice(i, 1);
        } else {
          fx.mesh.scale.addScalar(0.1); // جعل التأثير يتسع كالموجة
        }
      }

      // جعل الكاميرا تلاحق اللاعب من الأعلى بنمط RPG
      camera.position.set(player.position.x, player.position.y + 12, player.position.z + 14);
      camera.lookAt(player.position);

      renderer.render(scene, camera);
    }

    // ضبط الشاشة عند تغيير الحجم
    window.addEventListener('resize', () => {

Game Source: ساحة الأبطال 3D - قاتلي الشياطين

Creator: RapidPenguin10

Libraries: three

Complexity: complex (244 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-rapidpenguin10" to link back to the original. Then publish at arcadelab.ai/publish.