VRMMORPGβ版

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>エルダークロニクル:VR超完全版 – ロードなし(拾う/装備修正)</title>
  <script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
  <style>
    body, html { margin:0; padding:0; overflow:hidden; font-family:'Yu Gothic',system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; background:#000;}
    #ui {
      position:absolute; top:20px; left:20px; z-index:10; width:400px; color:#fff;
      background:linear-gradient(180deg,rgba(0,0,0,.92),rgba(0,10,30,.85));
      border-radius:16px; padding:14px 16px; box-shadow:0 0 25px #0ff,0 0 18px #33f4; font-size:15px;
    }
    h2 { margin:0 0 8px 0; font-size:22px; letter-spacing:1px;}
    .row { display:flex; gap:8px; align-items:center; flex-wrap:wrap;}
    .row > * { flex: 1 1 auto; }
    input, select { width:100%; padding:6px 8px; border-radius:8px; border:1px solid #024; background:#00131f; color:#cfe9ff; }
    button {
      background:linear-gradient(90deg,#555,#222 80%);
      color:#fff; padding:10px; margin:5px 0; border:none; cursor:pointer; width:100%;
      border-radius:8px; font-weight:bold; letter-spacing:1px; box-shadow:0 1px 8px #0cf5; transition:background .25s;
    }
    button:hover { background:linear-gradient(90deg,#888 40%,#3cf); }
    .section-title { font-weight:bold; font-size:17px; margin-top:10px; border-bottom:2px solid #5ef; letter-spacing:1.2px; }
    .bar { height:14px; background:#13202a; border-radius:7px; overflow:hidden; margin:6px 0; box-shadow:0 1px 6px #0ff6 inset; }
    .bar-inner { height:100%; background:linear-gradient(90deg,#0f0,#3af); transition:width .25s; }
    .mana-bar .bar-inner { background:linear-gradient(90deg,#33d,#6ff); }
    .enemyhp-bar .bar-inner { background:linear-gradient(90deg,#f55,#fdd); }
    #scenario { margin:10px 0 6px 0; background:rgba(0,10,32,0.7); padding:8px 12px; border-radius:8px; min-height:44px; }
    .kbd { display:inline-block; padding:1px 6px; border-radius:6px; background:#0a2636; border:1px solid #124; font-family:monospace; }
    #hint {
      position:absolute; bottom:18px; left:50%; transform:translateX(-50%);
      color:#eaffff; background:rgba(0,20,35,.72); border:1px solid #0af; padding:8px 12px; border-radius:10px;
      box-shadow:0 0 18px #08f5; font-size:14px; z-index:10;
    }
    #pickupPrompt {
      position:absolute; bottom:70px; left:50%; transform:translateX(-50%);
      color:#fff; background:rgba(0,0,0,.7); border:1px solid #38f; padding:8px 12px; border-radius:10px;
      display:none; z-index:10;
    }
    .tag { display:inline-block; padding:2px 6px; border-radius:6px; background:#012233; border:1px solid #1a4e6c; margin-left:6px; font-size:12px; color:#bfe6ff;}
    .on { background:#0b3754; border-color:#3db3ff; color:#fff; }
  </style>
</head>
<body>
  <div id="ui">
    <h2>エルダークロニクルVR</h2>
    <div class="row">
      <span>プレイヤー名:</span>
      <input id="playerName" placeholder="名前を入力">
    </div>

    <div class="row"><span>レベル:</span><span id="level" class="tag on">1</span>
      <span>装備:</span><span id="equipment" class="tag">なし</span>
    </div>

    <div>HP: <span id="hpText">100</span></div>
    <div class="bar"><div id="hpBar" class="bar-inner" style="width:100%"></div></div>
    <div>魔力: <span id="manaText">100</span></div>
    <div class="bar mana-bar"><div id="manaBar" class="bar-inner" style="width:100%"></div></div>

    <div>敵HP: <span id="enemyHpText">120</span></div>
    <div class="bar enemyhp-bar"><div id="enemyHpBar" class="bar-inner" style="width:100%"></div></div>

    <div class="section-title">シナリオ</div>
    <div id="scenario"></div>

    <div class="section-title">行動</div>
    <button onclick="levelUp()">🎉 レベルアップ</button>
    <button onclick="castSpell()">🪄 魔法発動</button>
    <button onclick="choosePath('wizard')">🧙‍♂️ 魔導士に話す</button>
    <button onclick="choosePath('knight')">🛡️ 騎士に話す</button>
    <button onclick="receiveQuest()">📜 クエスト受注</button>
    <button onclick="toggleEnvironment()">🌄 昼夜切替</button>

    <div class="section-title">移動</div>
    <div class="row">
      <button onclick="changeField('town')">🏘️ 街</button>
      <button onclick="changeField('castle')">🏰 城</button>
    </div>
    <div class="row">
      <button onclick="changeField('cave')">🕳️ 洞窟</button>
      <button onclick="changeField('ruins')">🏛️ 遺跡</button>
    </div>
    <div class="row">
      <button onclick="changeField('dungeon')">🧩 ダンジョン</button>
    </div>

    <div class="section-title">操作</div>
    <div style="line-height:1.6">
      <span class="kbd">WASD</span> 移動 
      <span class="kbd">マウス</span> 視点 
      <span class="kbd">E</span> 拾う 
      <span class="kbd">1</span> 剣装備 
      <span class="kbd">2</span> 銃装備 
      <span class="kbd">クリック</span> 攻撃
    </div>
  </div>

  <div id="pickupPrompt">Eで拾う</div>
  <div id="hint">近くの武器に近づいて <span class="kbd">E</span> で拾い、<span class="kbd">1/2</span> で装備、クリックで攻撃!</div>

  <a-scene loading-screen="enabled:false" renderer="colorManagement:true" shadow="true">
    <a-sky id="sky" color="#0e163e"></a-sky>

    <a-entity id="starParticles" position="0 25 -40" visible="false">
      <a-entity geometry="primitive:sphere; radius:0.18" material="color:#fff; opacity:0.6" position="-10 3 0"></a-entity>
      <a-entity geometry="primitive:sphere; radius:0.12" material="color:#fff; opacity:0.8" position="7 2 -2"></a-entity>
      <a-entity geometry="primitive:sphere; radius:0.11" material="color:#eaf6ff; opacity:0.9" position="3 5 2"></a-entity>
      <a-entity geometry="primitive:sphere; radius:0.10" material="color:#ffe; opacity:0.7" position="13 3 5"></a-entity>
    </a-entity>
    <a-entity id="cloudParticles" position="0 30 -35" visible="true">
      <a-sphere radius="5" position="8 2 -8" color="#f6fbff" opacity="0.18"></a-sphere>
      <a-sphere radius="6" position="-7 3 5" color="#eefbff" opacity="0.14"></a-sphere>
    </a-entity>

    <a-light type="ambient" color="#fff" intensity="1"></a-light>
    <a-light id="sunlight" type="directional" intensity="1.6" position="20 25 -8" castShadow="true" shadow-mapWidth="1024" shadow-mapHeight="1024"></a-light>
    <a-light type="point" color="#cff" intensity="2.2" distance="50" position="2 9 -3"></a-light>
    <a-light type="spot" color="#55aaff" position="0 15 -10" intensity="1.2" angle="30" penumbra="0.7"></a-light>

    <a-plane id="ground" position="0 0 0" rotation="-90 0 0" width="120" height="120" color="#375047" shadow="receive:true"></a-plane>

    <a-entity id="field-town" visible="true">
      <a-circle position="0 0 -6" radius="4" color="#7d7d7d" material="roughness:.9; metalness:.05; opacity:.84; transparent:true"></a-circle>
      <a-entity position="-2 0 -7">
        <a-box width="3.6" height="2.6" depth="2.4" color="#c0a47b" material="roughness:0.3; metalness:0.05" position="0 1.3 0"></a-box>
        <a-cone position="0 3 -0.1" radius-bottom="2.1" height="1.4" color="#7b5322"></a-cone>
        <a-text value="街の家" position="0 3.7 0" color="#fff" width="5" align="center"></a-text>
      </a-entity>
      <a-entity position="2 0 -9">
        <a-box width="2.2" height="2.2" depth="2.4" color="#a86f23" position="0 1.1 0"></a-box>
        <a-cone position="0 2.6 0" radius-bottom="1.4" height="1.0" color="#5c3a12"></a-cone>
      </a-entity>
      <a-entity position="5 0 -5">
        <a-cylinder radius="0.25" height="4" color="#3a2a1a" position="0 2 0"></a-cylinder>
        <a-sphere radius="1.2" color="#174d1f" position="0 3.2 0"></a-sphere>
      </a-entity>
    </a-entity>

    <a-entity id="field-castle" visible="false">
      <a-box position="0 2.8 -12" depth="6" height="6" width="10" color="#ccd2df" material="roughness:0.25; metalness:0.12"></a-box>
      <a-cylinder position="-4 1.2 -13" radius="1.1" height="3.8" color="#858ca3"></a-cylinder>
      <a-cylinder position="4 1.2 -13" radius="1.1" height="3.8" color="#858ca3"></a-cylinder>
      <a-cone position="0 6.4 -12" radius-bottom="3.2" height="2" color="#dba"></a-cone>
      <a-entity geometry="primitive:torus; radius:2.5; tube:0.07" material="color:#66aaff; opacity:.25; transparent:true" position="0 4.5 -12"></a-entity>
      <a-text value="王の城" position="0 6.3 -12" color="#0bf" width="6" align="center"></a-text>
    </a-entity>

    <a-entity id="field-cave" visible="false">
      <a-torus position="2 1.1 -10" radius="1.8" tube="0.8" arc="230" color="#363636" rotation="40 0 90"></a-torus>
      <a-sphere position="2 0.4 -10" radius="1.1" color="#151515"></a-sphere>
      <a-entity position="-2 0 -8">
        <a-cone radius-bottom="0.8" height="2.2" color="#2a2a2a"></a-cone>
        <a-cone radius-bottom="0.5" height="1.4" color="#393939" position="0.7 0 0.4"></a-cone>
      </a-entity>
      <a-text value="洞窟の入口" position="2 2.9 -10" color="#fff" width="6" align="center"></a-text>
    </a-entity>

    <a-entity id="field-ruins" visible="false">
      <a-cylinder position="-2 1.1 -9" radius="0.8" height="2.6" color="#babbb2"></a-cylinder>
      <a-box position="-3.1 1.8 -9" width="3.5" height="0.32" depth="0.7" color="#e0dfc7"></a-box>
      <a-torus position="-2 2.3 -9" radius="0.6" tube="0.09" arc="340" color="#fffeee"></a-torus>
      <a-entity geometry="primitive:torusKnot; p:2; q:7; radius:0.7; tube:0.07" position="2 1.8 -8" material="color:#bcd; opacity:.7; transparent:true"></a-entity>
      <a-text value="古代の遺構" position="0 3.3 -8.5" color="#fff" width="6" align="center"></a-text>
    </a-entity>

    <a-entity id="field-dungeon" visible="false">
      <a-box position="2 1.2 -8.8" depth="3.3" height="2.3" width="3.6" color="#161651"></a-box>
      <a-torus-knot position="-1.5 2.7 -8.2" radius="0.9" tube="0.12" p="3" q="7" color="#64eaff"></a-torus-knot>
      <a-cylinder position="-3 0.7 -9.6" radius="0.8" height="1.2" color="#333"></a-cylinder>
      <a-entity geometry="primitive:torus; radius:1.4; tube:0.05" material="color:#aaeeff; opacity:.18; transparent:true" position="0 2.1 -8.6" rotation="90 0 0"></a-entity>
      <a-text value="ダンジョン入口" position="0 3.1 -8.4" color="#fff" width="6" align="center"></a-text>
    </a-entity>

    <!-- 武器ピックアップ -->
    <a-entity id="swordPickup" class="pickup" data-weapon="sword" position="-1 0 -5">
      <a-box width="0.16" height="1.3" depth="0.08" color="#cfe7ff" material="metalness:0.8; roughness:0.15" position="0 0.75 0"></a-box>
      <a-box width="0.5" height="0.08" depth="0.08" color="#333" position="0 0.1 0"></a-box>
      <a-cylinder radius="0.06" height="0.42" color="#7c5a2b" position="0 -0.1 0"></a-cylinder>
      <a-entity geometry="primitive:ring; radiusInner:0.45; radiusOuter:0.5" rotation="-90 0 0" position="0 0 0" material="color:#44d; opacity:.35; transparent:true"></a-entity>
      <a-text value="剣" color="#fff" position="0 1.7 0" align="center"></a-text>
    </a-entity>

    <a-entity id="gunPickup" class="pickup" data-weapon="gun" position="2 0 -5.5">
      <a-box width="0.7" height="0.18" depth="0.18" color="#222" position="0 0.4 0"></a-box>
      <a-box width="0.3" height="0.28" depth="0.18" color="#444" position="-0.2 0.2 0"></a-box>
      <a-box width="0.12" height="0.40" depth="0.16" color="#333" position="0.2 0.15 0"></a-box>
      <a-cylinder radius="0.06" height="0.28" color="#555" position="0.34 0.46 0" rotation="0 0 90"></a-cylinder>
      <a-entity geometry="primitive:ring; radiusInner:0.45; radiusOuter:0.5" rotation="-90 0 0" position="0 0 0" material="color:#0aa; opacity:.35; transparent:true"></a-entity>
      <a-text value="銃" color="#fff" position="0 1.0 0" align="center"></a-text>
    </a-entity>

    <!-- プレイヤー(リグが移動する:★修正) -->
    <a-entity id="rig" position="0 0 0" wasd-controls="acceleration:30">
      <a-entity id="cam" camera look-controls="pointerLockEnabled:true" position="0 1.6 3"></a-entity>
      <a-entity id="player" position="0 0 -1.5" rotation="0 180 0" shadow="cast:true">
        <a-sphere radius="0.18" color="#ffd7f0" position="0 1.58 0"></a-sphere>
        <a-cylinder radius="0.23" height="0.9" color="#9ad" position="0 1.02 0"></a-cylinder>
        <a-cylinder radius="0.08" height="0.55" color="#9ad" position="-0.16 0.74 0" rotation="0 0 18"></a-cylinder>
        <a-cylinder radius="0.08" height="0.55" color="#9ad" position="0.16 0.74 0" rotation="0 0 -18"></a-cylinder>
        <a-cylinder radius="0.09" height="0.7" color="#79b" position="-0.10 0.35 0"></a-cylinder>
        <a-cylinder radius="0.09" height="0.7" color="#79b" position="0.10 0.35 0"></a-cylinder>
      </a-entity>
    </a-entity>

    <!-- 敵 -->
    <a-entity id="enemy" position="0 0 -9" visible="true">
      <a-sphere id="enemyBody" radius="1.25" color="#9b1e1e" material="metalness:0.35; roughness:.25; emissive:#330000"></a-sphere>
      <a-entity geometry="primitive:torus; radius:1.4; tube:0.05" material="color:#ffeeaa; opacity:.18; transparent:true" position="0 0.3 0" rotation="90 0 0"></a-entity>
      <a-entity geometry="primitive:torusKnot; radius:0.45; tube:0.05; p:2; q:5" material="color:#ffa033; opacity:.22; transparent:true" position="0 1.0 0"></a-entity>
      <a-sphere position="-0.38 0.42 0.95" radius="0.14" color="#fff" material="metalness:.9; roughness:.05; emissive:#a0f"></a-sphere>
      <a-sphere position="0.38 0.42 0.95" radius="0.14" color="#fff" material="metalness:.9; roughness:.05; emissive:#a0f"></a-sphere>
      <a-cone position="-0.45 1.35 0.15" radius-bottom="0.16" height="0.62" color="#f5f3ff" rotation="15 0 60"></a-cone>
      <a-cone position="0.45 1.35 0.15" radius-bottom="0.16" height="0.62" color="#f5f3ff" rotation="15 0 -60"></a-cone>
      <a-text value="敵モンスター" position="0 2.15 0" align="center" color="#fff"></a-text>
    </a-entity>

    <a-entity id="spellEffect" geometry="primitive:sphere; radius:0.55"
              material="color:#72f3ff; opacity:.86; emissive:#88f; transparent:true"
              position="0 1.7 -3" visible="false"
              animation__move="property: position; to: 0 3.1 -6; dur:500; dir:alternate; loop:false">
      <a-entity geometry="primitive:torus; radius:0.7; tube:0.08" material="color:#fff; opacity:.3; transparent:true"></a-entity>
    </a-entity>

    <a-entity id="game" game-manager></a-entity>
  </a-scene>

<script>
let isDay=false, hp=100, mana=100, level=1;
let enemyHP=120, enemyHPMax=120;
function updateBars(){
  document.getElementById("hpText").innerText = Math.max(0,Math.floor(hp));
  document.getElementById("manaText").innerText = Math.max(0,Math.floor(mana));
  document.getElementById("hpBar").style.width = Math.max(0,Math.min(100,hp))+"%";
  document.getElementById("manaBar").style.width = Math.max(0,Math.min(100,mana))+"%";
  document.getElementById("level").innerText = level;
  document.getElementById("enemyHpText").innerText = Math.max(0,enemyHP);
  const w = Math.max(0, Math.min(100, enemyHP*100/enemyHPMax));
  document.getElementById("enemyHpBar").style.width = w+"%";
}
function levelUp(){ level++; hp=Math.min(100,hp+20); mana+=30; showScenario("🎉 レベルアップ!新しい力が湧いてくる!"); updateBars(); }
function castSpell(){
  if(mana<20){ showScenario("💤 魔力が足りない!"); return; }
  mana-=20; updateBars();
  const effect=document.getElementById("spellEffect");
  effect.setAttribute("visible","true");
  setTimeout(()=>{ effect.setAttribute("visible","false"); applyDamageToEnemy(30,"魔法ヒット"); },700);
}
function choosePath(choice){
  if(choice==="wizard"){ document.getElementById("equipment").innerText="魔導士のローブ"; mana+=50; showScenario("🧙‍♂️ 魔導士の試練が始まる…"); }
  else{ document.getElementById("equipment").innerText="騎士の剣"; hp+=30; showScenario("⚔️ 騎士と共に魔王城へ向かう!"); }
  updateBars();
}
function toggleEnvironment(){
  const sky=document.getElementById("sky");
  const star=document.getElementById("starParticles");
  const cloud=document.getElementById("cloudParticles");
  const ground=document.getElementById("ground");
  const sunlight=document.getElementById("sunlight");
  if(isDay){
    sky.setAttribute("color","#0e163e"); star.setAttribute("visible","false"); cloud.setAttribute("visible","true");
    ground.setAttribute("color","#375047"); sunlight.setAttribute("intensity","1.6"); showScenario("🌌 夜の世界へ…");
  }else{
    sky.setAttribute("color","#7ddfff"); star.setAttribute("visible","true"); cloud.setAttribute("visible","false");
    ground.setAttribute("color","#b8ffcc"); sunlight.setAttribute("intensity","2.1"); showScenario("🌞 昼の世界へ…");
  }
  isDay=!isDay;
}
function changeField(fieldName){
  const fields=['town','castle','cave','ruins','dungeon'];
  fields.forEach(name=>{
    const el=document.getElementById(`field-${name}`);
    el.setAttribute('visible', name===fieldName);
  });
  showScenario(`📍 ${fieldName} に移動しました`);
}
function receiveQuest(){
  const quests=[
    "魔導士の塔で失われた書を探せ!","騎士団の旗を取り戻せ!","洞窟の奥に眠る魔石を発見せよ!",
    "遺跡に隠された封印を解け!","ダンジョンの魔王を討伐せよ!"
  ];
  const index=Math.floor(Math.random()*quests.length);
  showScenario("📜 クエスト受注: "+quests[index]);
}

const scenarioList=[
  "目覚めたあなたは不思議な世界にいた。","最初のクエストを受注しよう。","フィールド移動で冒険の扉が開く。",
  "行動や魔法でストーリーが動く。","街で情報を集め、仲間と出会おう。","クエストを進め、魔王に立ち向かえ!"
];
let scenarioIndex=0;
function showScenario(text){ document.getElementById('scenario').innerHTML=text; }
function advanceScenario(){ if(scenarioIndex<scenarioList.length){ showScenario(scenarioList[scenarioIndex]); scenarioIndex++; } }
['levelUp','castSpell','choosePath','changeField','receiveQuest'].forEach(fn=>{
  const orig=window[fn]; window[fn]=function(){ orig.apply(this, arguments); advanceScenario(); }
});

/* ---- ここが拾う/装備の中核 ---- */
const rigEl=()=>document.getElementById('rig');
const camEl=()=>document.getElementById('cam');
const enemyEl=()=>document.getElementById('enemy');
const enemyBodyEl=()=>document.getElementById('enemyBody');

let hasSword=false, hasGun=false, equipped='none';
let attackCooldown=false;
const bullets=[];

function setEquipmentLabel(){
  let label="なし";
  if(equipped==='sword') label="剣";
  if(equipped==='gun') label="銃";
  document.getElementById('equipment').innerText=label;
}

function tryPickup(){
  const rpos=rigEl().object3D.position; // ★リグが移動するのでOK
  const items=[document.getElementById('swordPickup'),document.getElementById('gunPickup')];
  for(const it of items){
    if(!it.getAttribute('visible')) continue;
    const wpos=it.object3D.position;
    const d=rpos.distanceTo(wpos);
    if(d<2.0){
      const w=it.getAttribute('data-weapon');
      it.setAttribute('visible','false');
      if(w==='sword'){ hasSword=true; if(equipped==='none') equipped='sword'; showScenario("🗡️ 剣を拾った! 1で装備。"); }
      if(w==='gun'){ hasGun=true; if(equipped==='none') equipped='gun'; showScenario("🔫 銃を拾った! 2で装備。"); }
      setEquipmentLabel();
      return;
    }
  }
  showScenario("近くに拾えるものはない。");
}

function equipSword(){ if(hasSword){ equipped='sword'; setEquipmentLabel(); showScenario("🗡️ 剣を装備した。"); } else { showScenario("剣をまだ拾っていない。"); } }
function equipGun(){ if(hasGun){ equipped='gun'; setEquipmentLabel(); showScenario("🔫 銃を装備した。"); } else { showScenario("銃をまだ拾っていない。"); } }

function attack(){
  if(attackCooldown) return;
  if(equipped==='sword'){ swordSlash(); }
  else if(equipped==='gun'){ shootBullet(); }
  else{ showScenario("装備がありません。剣や銃を拾ってください。"); }
}

function swordSlash(){
  attackCooldown=true;
  const slash=document.createElement('a-entity');
  slash.setAttribute('geometry','primitive: torus; radius:0.9; tube:0.08; arc:200');
  slash.setAttribute('material','color:#fff; opacity:.6; transparent:true');
  const dir=new AFRAME.THREE.Vector3(); camEl().object3D.getWorldDirection(dir); dir.y=0; dir.normalize();
  const base=rigEl().object3D.position.clone().add(new AFRAME.THREE.Vector3(0,1.2,0)).add(dir.clone().multiplyScalar(0.8));
  slash.setAttribute('position',`${base.x} ${base.y} ${base.z}`);
  const rotY=Math.atan2(dir.x,dir.z)*AFRAME.THREE.MathUtils.RAD2DEG;
  slash.setAttribute('rotation',`0 ${rotY} 0`);
  slash.setAttribute('animation__fade','property: material.opacity; to:0; dur:200; easing:easeOutQuad');
  document.querySelector('a-scene').appendChild(slash);
  setTimeout(()=>slash.parentNode && slash.parentNode.removeChild(slash),220);

  const enemyPos=enemyEl().object3D.position.clone();
  const toEnemy=enemyPos.clone().sub(rigEl().object3D.position.clone().add(new AFRAME.THREE.Vector3(0,1.0,0)));
  const dist=toEnemy.length();
  toEnemy.y=0; toEnemy.normalize();
  const forward=dir.clone();
  const angle=forward.dot(toEnemy);
  if(dist<2.6 && angle>0.5 && enemyEl().getAttribute('visible')){
    applyDamageToEnemy(25,"斬撃");
  } else {
    showScenario("空振り…");
  }
  setTimeout(()=>attackCooldown=false,280);
}

function shootBullet(){
  attackCooldown=true;
  const bullet=document.createElement('a-sphere');
  bullet.setAttribute('radius','0.07');
  bullet.setAttribute('color','#e6f7ff');
  bullet.setAttribute('material','emissive:#88d; metalness:.6; roughness:.2');
  const dir=new AFRAME.THREE.Vector3(); camEl().object3D.getWorldDirection(dir); dir.normalize();
  const start=rigEl().object3D.position.clone().add(new AFRAME.THREE.Vector3(0,1.3,0)).add(dir.clone().multiplyScalar(0.9));
  bullet.setAttribute('position',`${start.x} ${start.y} ${start.z}`);
  document.querySelector('a-scene').appendChild(bullet);
  bullets.push({el:bullet, dir:dir.clone(), life:1800, speed:24});
  setTimeout(()=>attackCooldown=false,120);
}

function applyDamageToEnemy(dmg,label){
  if(!enemyEl().getAttribute('visible')) return;
  enemyHP=Math.max(0, enemyHP - dmg);
  updateBars();
  const origColor=enemyBodyEl().getAttribute('color');
  enemyBodyEl().setAttribute('color','#ffffff');
  setTimeout(()=>enemyBodyEl().setAttribute('color', origColor), 80);
  spawnDamageText(dmg,label);
  if(enemyHP<=0){ killEnemy(); }
}

function spawnDamageText(dmg,label){
  const t=document.createElement('a-text');
  t.setAttribute('value',`${label} -${dmg}`);
  t.setAttribute('color','#ffe6e6');
  t.setAttribute('align','center');
  const p=enemyEl().object3D.position.clone();
  t.setAttribute('position',`${p.x} ${p.y+2.4} ${p.z}`);
  t.setAttribute('animation__rise','property: position; to: '+`${p.x} ${p.y+3.2} ${p.z}`+'; dur:650; easing:easeOutQuad');
  t.setAttribute('animation__fade','property: opacity; to:0; dur:650; easing:easeOutQuad');
  document.querySelector('a-scene').appendChild(t);
  setTimeout(()=>t.parentNode && t.parentNode.removeChild(t),700);
}

function killEnemy(){
  enemyEl().setAttribute('visible','false');
  showScenario("✅ 敵を倒した! 5秒後に再出現する…");
  setTimeout(()=>respawnEnemy(), 5000);
}
function respawnEnemy(){
  enemyHP=enemyHPMax; updateBars();
  const e=enemyEl();
  const x = (Math.random()*6 - 3);
  const z = -8.5 + (Math.random()*3 - 1.5);
  e.setAttribute('position',`${x} 0 ${z}`);
  e.setAttribute('visible','true');
  showScenario("⚠️ 新たな敵が現れた!");
}

/* 入力(E/1/2 の互換強化:★修正) */
AFRAME.registerComponent('game-manager',{
  init:function(){
    window.addEventListener('keydown',(e)=>{
      const k=e.key;
      const c=e.code;
      if(c==='KeyE' || k==='e' || k==='E') tryPickup();
      if(c==='Digit1' || c==='Numpad1' || k==='1') equipSword();
      if(c==='Digit2' || c==='Numpad2' || k==='2') equipGun();
    });
    window.addEventListener('mousedown',()=>attack());
    updateBars(); advanceScenario(); setEquipmentLabel();
  },
  tick:function(time,dt){
    const delta=dt/1000;
    const prompt=document.getElementById('pickupPrompt');
    const rpos=rigEl().object3D.position;
    let near=false;
    ['swordPickup','gunPickup'].forEach(id=>{
      const el=document.getElementById(id);
      if(el.getAttribute('visible')){
        const d=rpos.distanceTo(el.object3D.position);
        if(d<2.0) near=true;
      }
    });
    prompt.style.display = near?'block':'none';

    // 弾
    for(let i=bullets.length-1;i>=0;i--){
      const b=bullets[i];
      if(!b.el.parentNode){ bullets.splice(i,1); continue; }
      b.life -= dt;
      const pos=b.el.object3D.position;
      pos.add(b.dir.clone().multiplyScalar(24*delta));
      if(b.life<=0){ b.el.parentNode.removeChild(b.el); bullets.splice(i,1); continue; }
      if(enemyEl().getAttribute('visible')){
        const d=pos.distanceTo(enemyEl().object3D.position);
        if(d<1.35){
          applyDamageToEnemy(15,"射撃");
          b.el.parentNode.removeChild(b.el);
          bullets.splice(i,1);
        }
      }
    }
    enemyEl().object3D.rotation.y += delta*0.3;
  }
});

updateBars();
advanceScenario();
</script>
</body>
</html>

投稿者: chosuke

趣味はゲームやアニメや漫画などです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です