MyCSSGrid

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My CSS Grid</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="container">
        <ul>
            <li>item 1</li>
            <li>item 2 item 2 item 2 item 2 item 2</li>
            <li>item 3</li>
            <li>item 4</li>
        </ul>
        <ul>
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3 item 3 item 3 item 3</li>
            <li>item 4</li>
        </ul>
    </div>
</body>

</html>

style.css

@charset "utf-8";

.container {
    display: grid;
    grid-template-columns: 200px 200px;
    grid-template-rows: repeat(4, auto);
}

ul {
    grid-row: span 4;

    display: grid;
    grid-template-rows: subgrid;
}

ドメイン検索&購入(フロントエンド)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>ドメイン検索&購入</title>
  <style>
    body {
      font-family: sans-serif;
      background: #f9f9f9;
      padding: 2rem;
      margin: 0;
      display: flex;
      justify-content: center;
    }
    .container {
      max-width: 600px;
      width: 100%;
      background: white;
      padding: 2rem;
      border-radius: 12px;
      box-shadow: 0 4px 10px rgba(0,0,0,0.1);
    }
    h1 {
      color: #e60033;
      text-align: center;
      margin-bottom: 1.5rem;
    }
    .form {
      display: flex;
      gap: 0.5rem;
      margin-bottom: 1rem;
    }
    input {
      flex: 1;
      padding: 0.8rem;
      border: 1px solid #ccc;
      border-radius: 8px;
      font-size: 1rem;
    }
    button {
      padding: 0.8rem 1rem;
      background-color: #e60033;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
    }
    .result {
      margin-top: 1rem;
    }
    .item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      border-bottom: 1px solid #eee;
      padding: 0.5rem 0;
    }
    .available {
      color: green;
      font-weight: bold;
    }
    .unavailable {
      color: red;
      font-weight: bold;
    }
    .buy-btn {
      background-color: #0070f3;
      color: white;
      padding: 0.3rem 0.7rem;
      border-radius: 6px;
      text-decoration: none;
      font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>ドメイン検索</h1>
    <div class="form">
      <input type="text" id="domainInput" placeholder="例: mydomain" />
      <button onclick="search()">検索</button>
    </div>
    <div class="result" id="resultArea"></div>
  </div>

  <script>
    const takenDomains = ["example.com", "mydomain.net", "taken.jp"];
    const tlds = [".com", ".net", ".jp"];

    function search() {
      const name = document.getElementById("domainInput").value.trim().toLowerCase();
      const area = document.getElementById("resultArea");
      area.innerHTML = "";

      if (!name) {
        area.innerHTML = "<p>⚠ ドメイン名を入力してください。</p>";
        return;
      }

      tlds.forEach(tld => {
        const domain = name + tld;
        const available = !takenDomains.includes(domain);
        const item = document.createElement("div");
        item.className = "item";
        item.innerHTML = `
          <span>${domain}</span>
          ${available
            ? `<span class="available">取得可能</span>
               <a href="https://buy.stripe.com/test_checkout_link" class="buy-btn" target="_blank">購入する</a>`
            : `<span class="unavailable">登録済み</span>`}
        `;
        area.appendChild(item);
      });
    }
  </script>
</body>
</html>

ゲームBGM自動生成サービス.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>🎮 ゲームBGM自動生成サービス</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    :root {
      --bg: #121212;
      --card: #1e1e2e;
      --text: #ffffff;
      --accent: #ffd700;
      --shadow: rgba(0, 0, 0, 0.3);
      --button: #ffd700;
    }
    [data-theme='light'] {
      --bg: #f5f5f5;
      --card: #ffffff;
      --text: #111;
      --accent: #ff9800;
      --shadow: rgba(0, 0, 0, 0.1);
      --button: #ff9800;
    }

    body {
      margin: 0;
      font-family: 'Segoe UI', sans-serif;
      background: var(--bg);
      color: var(--text);
      transition: 0.3s;
      padding: 1rem;
    }

    header {
      text-align: center;
      margin-bottom: 1rem;
    }

    h1 {
      color: var(--accent);
      font-size: 2rem;
    }

    .container {
      max-width: 600px;
      margin: auto;
      background: var(--card);
      border-radius: 12px;
      box-shadow: 0 0 10px var(--shadow);
      padding: 1.5rem;
    }

    label {
      font-weight: bold;
      display: block;
      margin-top: 1rem;
    }

    select, button {
      width: 100%;
      padding: 0.6rem;
      margin-top: 0.5rem;
      border-radius: 8px;
      border: none;
      font-size: 1rem;
    }

    button {
      background: var(--button);
      color: #000;
      font-weight: bold;
      cursor: pointer;
      transition: 0.3s;
    }

    button:disabled {
      background: #999;
      cursor: not-allowed;
    }

    button:hover:enabled {
      opacity: 0.85;
    }

    .desc, .msg {
      margin-top: 1rem;
      font-size: 0.9rem;
      color: #ccc;
    }

    .result, .history {
      margin-top: 2rem;
    }

    audio {
      width: 100%;
      margin-top: 0.5rem;
    }

    .visualizer {
      width: 100%;
      height: 4px;
      background: linear-gradient(90deg, #ffd700, #ff9800);
      animation: pulse 2s infinite linear;
      opacity: 0;
    }

    .playing .visualizer {
      opacity: 1;
    }

    @keyframes pulse {
      0% { transform: scaleX(1); }
      50% { transform: scaleX(1.05); }
      100% { transform: scaleX(1); }
    }

    .toggle-theme {
      text-align: right;
      margin-bottom: 0.5rem;
    }

    .accordion {
      background: transparent;
      color: var(--accent);
      border: none;
      font-weight: bold;
      cursor: pointer;
      margin-top: 1rem;
      width: 100%;
      text-align: left;
      font-size: 1rem;
    }

    .accordion-content {
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.3s ease;
    }

    .accordion.open + .accordion-content {
      max-height: 600px;
    }
  </style>
</head>
<body>

  <header>
    <h1>🎮 ゲームBGM自動生成</h1>
  </header>

  <div class="toggle-theme">
    <button onclick="toggleTheme()">🌓 テーマ切替</button>
  </div>

  <div class="container">
    <label for="genre">🎼 ジャンル</label>
    <select id="genre" onchange="updateDescription()">
      <option value="fantasy">ファンタジー</option>
      <option value="cyberpunk">サイバーパンク</option>
      <option value="horror">ホラー</option>
      <option value="symphonic">シンフォニック</option>
    </select>

    <label for="mood">🎭 雰囲気</label>
    <select id="mood" onchange="updateDescription()">
      <option value="mysterious">神秘的</option>
      <option value="sad">悲しい</option>
      <option value="heroic">勇ましい</option>
      <option value="fun">楽しい</option>
    </select>

    <div class="desc" id="descText">選択内容に応じてBGMを生成します。</div>

    <button id="generateBtn" onclick="generateBGM()">🎶 BGMを生成する</button>

    <div class="msg" id="msg"></div>

    <div class="result" id="result" style="display:none;">
      <h3>🎧 再生中のBGM</h3>
      <audio controls id="player" onplay="startVisualizer()" onpause="stopVisualizer()"></audio>
      <div class="visualizer" id="visualizer"></div>
    </div>

    <button class="accordion" onclick="toggleAccordion(this)">📜 再生履歴</button>
    <div class="accordion-content" id="historyList"></div>
  </div>

  <script>
    const descMap = {
      fantasy: "魔法の世界、冒険と伝説の音楽",
      cyberpunk: "近未来都市とテクノ感の融合",
      horror: "不安と恐怖を煽るBGM",
      symphonic: "壮大で感動的なオーケストラ風",
      mysterious: "謎解き、探検にぴったり",
      sad: "涙や喪失感を表現する旋律",
      heroic: "勇ましさ、戦い、勝利の象徴",
      fun: "軽快で明るいリズム"
    };

    const history = [];
    const maxHistory = 5;

    function updateDescription() {
      const g = document.getElementById('genre').value;
      const m = document.getElementById('mood').value;
      document.getElementById('descText').textContent = `🧠 ${descMap[g]} × ${descMap[m]}`;
    }

    function generateBGM() {
      const genre = document.getElementById('genre').value;
      const mood = document.getElementById('mood').value;
      const btn = document.getElementById('generateBtn');
      const player = document.getElementById('player');
      const msg = document.getElementById('msg');
      const result = document.getElementById('result');

      btn.disabled = true;
      msg.textContent = "⏳ BGMを生成中...";

      const url = `https://example.com/bgm/${genre}_${mood}_${Math.floor(Math.random()*3)+1}.mp3`;

      setTimeout(() => {
        msg.textContent = "✅ BGM生成完了!再生できます。";
        player.src = url;
        result.style.display = 'block';

        // 保存履歴
        history.unshift({ genre, mood, url });
        if (history.length > maxHistory) history.pop();
        renderHistory();
        btn.disabled = false;
      }, 1500);
    }

    function renderHistory() {
      const list = document.getElementById('historyList');
      list.innerHTML = "";
      history.forEach(item => {
        const div = document.createElement('div');
        div.innerHTML = `<strong>${item.genre} × ${item.mood}</strong><br><audio controls src="${item.url}"></audio><hr>`;
        list.appendChild(div);
      });
    }

    function toggleTheme() {
      const theme = document.documentElement.getAttribute("data-theme");
      document.documentElement.setAttribute("data-theme", theme === "light" ? "dark" : "light");
    }

    function toggleAccordion(el) {
      el.classList.toggle('open');
    }

    function startVisualizer() {
      document.getElementById('visualizer').style.opacity = '1';
    }

    function stopVisualizer() {
      document.getElementById('visualizer').style.opacity = '0';
    }

    // 初期設定
    document.documentElement.setAttribute("data-theme", "dark");
    updateDescription();
  </script>

</body>
</html>

MyAOS.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Site</title>
  <link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <section>
    <h1>記事一覧</h1>
    <article>
      <img src="forest.png" width="240" height="160" data-aos="my-animation">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
    <article>
      <img src="forest.png" width="240" height="160">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
    <article>
      <img src="forest.png" width="240" height="160">
      <div class="text">
        <h2>タイトル</h2>
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
      </div>
    </article>
  </section>

  <section>
    <h1>お客様の声</h1>
    <div class="voices">
      <section data-aos="fade-up">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
      <section data-aos="fade-up" data-aos-delay="300">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
      <section data-aos="fade-up" data-aos-delay="600">
        <h2>すばらしい</h2>
        <p>素晴らしいです。素晴らしいです。</p>
      </section>
    </div>
  </section>

  <footer id="footer">
    (c) dotinstall.com
  </footer>

  <a href="#" class="to-top" data-aos="fade-up" data-aos-anchor="#footer" data-aos-offset="0">先頭へ</a>

  <script src="https://unpkg.com/aos@next/dist/aos.js"></script>
  <script>
    AOS.init();
  </script>
</body>

</html>

style.css

@charset "utf-8";

body {
  margin: 0;
}

body>section {
  margin: 0 32px;
}

h1 {
  text-align: center;
  padding: 160px 0;
}

article {
  display: flex;
  gap: 16px;
  align-items: center;
}

article .text {
  flex: 1;
}

article h2 {
  margin: 0;
  font-size: 22px;
}

article+article {
  margin-top: 32px;
}

article:nth-child(even) {
  flex-direction: row-reverse;
}

.voices {
  display: flex;
  gap: 16px;
}

.voices>section {
  border-radius: 8px;
  border: 1px solid #ccc;
  padding: 16px 32px;
  text-align: center;
}

footer {
  margin-top: 160px;
  text-align: center;
  padding: 80px 0;
  background: #eee;
}

.to-top {
  position: fixed;
  bottom: 16px;
  right: 16px;
}

ロックマンEXE VR ― 企画書

ロックマンEXE VR ― 企画書


【タイトル】

ロックマンEXE VR(仮)


【コンセプト】

電脳世界と現実を融合させた「フルダイブ・ネットバトル体験」――
プレイヤーがナビゲーターを操作し、リアルタイムにネットバトルを行う、完全没入型VRアクションRPG。


【ジャンル】

  • フルダイブVRアクションRPG
  • オンラインネット対戦型コンテンツ
  • ストーリー付きシングルプレイキャンペーンモード

【プラットフォーム】

  • Meta Quest 3 / Quest Pro
  • SteamVR(PCVR)
  • 将来的にはApple Vision Pro、PlayStation VR2にも展開予定

【想定ターゲット】

  • 20代〜40代のロックマンEXEシリーズ経験者
  • VR体験に慣れているコアゲーマー層
  • 近未来・サイバーSF世界観が好きなユーザー

【主な特徴】

1. 電脳世界へのフルダイブ

  • プレイヤーは“オペレーター”として、VR空間から自分のナビ(ロックマンなど)を操作。
  • 視点はナビ視点とオペレーター視点を自由に切り替え可能。

2. リアルタイム・ネットバトル

  • 従来のマス目バトルにVRならではの要素を追加(例:手でチップを選び、発動動作を行う)。
  • 複数人の協力プレイやPvP対戦にも対応。

3. チップ実体化ギミック

  • 実際に手を伸ばして“バトルチップ”を物理的に選択・使用する没入型インターフェース。
  • チップの選択ミスやタイミングなど、直感操作が勝負の鍵に。

4. 電脳都市の探索

  • “ACDCタウン”や“電脳世界”を自由に歩き回り、NPCとの対話やミッション受注が可能。
  • 実世界(オペレータールーム)とネット世界(ナビ視点)を行き来して物語が展開。

【ゲームモード】

  • ストーリーモード
    原作シリーズを踏襲しつつ、オリジナル展開も用意。名シーンをVRで再現。
  • VR対戦モード
    フレンド・ランダム対戦機能付き。ランキングや報酬制度あり。
  • カスタムルームモード
    プレイヤーのVRオペレータールームを自由にカスタマイズ。

【開発スケジュール(案)】

フェーズ期間内容
企画・プロト制作0〜3ヶ月世界観設定、試作バトルシステム
アルファ版開発4〜8ヶ月探索・戦闘・UIの実装
ベータ版開発9〜12ヶ月ストーリー、マルチ対戦
リリース準備13〜15ヶ月デバッグ、配信準備、マーケ

【必要開発体制(最小構成)】

  • VRエンジニア(Unreal Engine or Unity XR経験者)
  • キャラクター/背景3Dモデラー
  • アニメーター
  • プランナー / シナリオライター
  • UI/UXデザイナー
  • ネットワークエンジニア

【将来的展開】

  • DLC:フォルテ、サーチマン、ブルース編など
  • eスポーツ大会の開催
  • コラボイベント(EXEシリーズ20周年企画など)
  • AR版ロックマンペットの開発(スマホ連携)

【ビジュアルモック・参考資料】

※必要であれば後日、UI/UX・ワールドデザインのモックアップをご用意します。


【備考】

※本企画はファン提案ベースであり、カプコン社の正式な許諾が必要です。商業化にあたってはライセンス取得が前提条件となります。

Z

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Z – 次世代ソーシャルネットワーク</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/1.5.0/aframe.min.js"></script>
<style>
:root{
  --primary:#1DA1F2;--background:#fff;--text:#000;--border:#E1E8ED;--card:#F7F9F9;--danger:#E0245E;
}
[data-theme="dark"]{--background:#15202B;--text:#fff;--border:#38444D;--card:#192734}
*{box-sizing:border-box;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
body{background:var(--background);color:var(--text);min-height:100vh;transition:.3s}
.hidden{display:none}
.wrapper{max-width:640px;margin-inline:auto;padding:20px}
.timeline{margin-top:2rem}
.timeline-item{background:var(--card);border-radius:12px;padding:1rem;margin-bottom:1rem;box-shadow:0 2px 6px rgba(0,0,0,.05)}
.timeline-item h3{margin:0 0 .5rem;font-size:1.1rem}
.timeline-item p{margin:0;white-space:pre-wrap;line-height:1.4}
.timeline-item small{display:block;margin-top:.5rem;font-size:.75rem;color:var(--border)}
.auth-box{background:var(--card);border-radius:12px;padding:1.5rem;margin-bottom:2rem}
.auth-box input{padding:.75rem;border:1px solid var(--border);border-radius:8px;width:100%;margin-bottom:.5rem}
.auth-box button{background:var(--primary);color:white;border:none;border-radius:8px;padding:.75rem;margin-top:.5rem;width:100%;cursor:pointer;font-weight:bold}
.profile-edit{background:var(--card);padding:1rem;border-radius:12px;margin-bottom:2rem}
.profile-edit h3{margin-bottom:.75rem}
.profile-edit input{width:100%;margin:.5rem 0;padding:.5rem;border:1px solid var(--border);border-radius:8px}
.follow-btn{background:#ccc;padding:.3rem .8rem;border-radius:8px;border:none;cursor:pointer;font-size:.85rem;margin-top:.5rem}
img.upload-preview{max-width:100px;border-radius:8px;margin-top:.5rem}
</style>
</head>
<body>
<div class="wrapper">
  <div id="authBox" class="auth-box">
    <h2>ログイン / 登録</h2>
    <input type="email" id="email" placeholder="メールアドレス">
    <input type="tel" id="phone" placeholder="電話番号">
    <input type="password" id="password" placeholder="パスワード">
    <input type="text" id="username" placeholder="ユーザー名">
    <button onclick="loginOrRegister()">ログイン / 登録</button>
  </div>
  <div id="mainBox" class="hidden">
    <h1 style="font-size:1.5rem;margin-bottom:1rem">Zタイムライン</h1>
    <div style="margin-bottom:1rem">ようこそ、<span id="userEmail"></span> さん!</div>
    <div class="profile-edit">
      <h3>プロフィール編集</h3>
      <input type="text" id="editName" placeholder="表示名を編集">
      <input type="text" id="editBio" placeholder="自己紹介を編集">
      <button onclick="saveProfile()">プロフィール保存</button>
    </div>
    <form id="timelineForm" style="display:flex;flex-direction:column;gap:.75rem;margin-bottom:2rem">
      <input id="timelineTitle" type="text" placeholder="タイトル" required>
      <textarea id="timelineContent" placeholder="投稿内容" required style="min-height:100px"></textarea>
      <input type="file" id="imageUpload" accept="image/*">
      <img id="preview" class="upload-preview hidden">
      <button type="submit">タイムラインに投稿</button>
    </form>
    <section id="timelineList" class="timeline"></section>
    <button onclick="logout()">ログアウト</button>
  </div>
</div>
<div id="vrScene" class="hidden" style="position:fixed;inset:0;z-index:9999"></div>
<button id="vrBtn" style="position:fixed;bottom:20px;right:20px;width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;border:none;font-size:1.3rem;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 12px rgba(0,0,0,.25)" onclick="enterVR()"><i class="fa-brands fa-vr-cardboard"></i></button>
<script>
let timeline = JSON.parse(localStorage.getItem('z_timeline')||'[]');
let feeds = JSON.parse(localStorage.getItem('z_feeds')||'[]');
let currentUser = JSON.parse(localStorage.getItem('z_user')||'null');
const authBox = document.getElementById('authBox');
const mainBox = document.getElementById('mainBox');
const timelineForm = document.getElementById('timelineForm');
const timelineList = document.getElementById('timelineList');
const userEmailSpan = document.getElementById('userEmail');
const previewImg = document.getElementById('preview');
const imageUpload = document.getElementById('imageUpload');
function loginOrRegister(){
  const email = document.getElementById('email').value.trim();
  const phone = document.getElementById('phone').value.trim();
  const pass = document.getElementById('password').value;
  const name = document.getElementById('username').value.trim();
  if(!email || !pass || !name){ alert('メール、パスワード、ユーザー名を入力してください'); return; }
  currentUser = {email, phone, name, bio:"", followers:[], following:[]};
  localStorage.setItem('z_user', JSON.stringify(currentUser));
  authBox.classList.add('hidden');
  mainBox.classList.remove('hidden');
  userEmailSpan.textContent = email;
  renderTimeline();
}
function logout(){ localStorage.removeItem('z_user'); location.reload(); }
function saveProfile(){
  const name = document.getElementById('editName').value;
  const bio = document.getElementById('editBio').value;
  if(name) currentUser.name = name;
  if(bio) currentUser.bio = bio;
  localStorage.setItem('z_user', JSON.stringify(currentUser));
  alert('プロフィールを保存しました');
}
function renderTimeline(){
  if(!timeline.length){ timelineList.innerHTML = '<p style="color:var(--border)">投稿がまだありません</p>'; return; }
  timelineList.innerHTML = timeline.map((t, index)=>{
    return `<div class="timeline-item">
      <h3>${t.title}</h3>
      <p>${t.content}</p>
      ${t.image ? `<img src="${t.image}" style="max-width:100%;margin-top:.5rem;border-radius:8px">` : ''}
      <small>${new Date(t.created).toLocaleString()}</small>
      <button onclick="followUser('${t.email}')" class="follow-btn">フォロー</button>
      <button onclick="deletePost(${index})" style="margin-top:.5rem;padding:.3rem .6rem;border:none;background:#eee;border-radius:6px;font-size:.8rem;cursor:pointer">削除</button>
    </div>`;
  }).join('');
}
function followUser(email){
  if(!currentUser.following.includes(email)){
    currentUser.following.push(email);
    localStorage.setItem('z_user', JSON.stringify(currentUser));
    alert(`${email} をフォローしました`);
  }
}
function deletePost(index){
  if(confirm('この投稿を削除しますか?')){
    timeline.splice(index,1);
    localStorage.setItem('z_timeline', JSON.stringify(timeline));
    renderTimeline();
  }
}
timelineForm.addEventListener('submit',e=>{
  e.preventDefault();
  const title = document.getElementById('timelineTitle').value.trim();
  const content = document.getElementById('timelineContent').value.trim();
  const file = imageUpload.files[0];
  if(!title || !content) return;
  const newPost = {title, content, image:null, created:new Date().toISOString(), email: currentUser.email};
  if(file){
    const reader = new FileReader();
    reader.onload = ()=>{
      newPost.image = reader.result;
      timeline.unshift(newPost);
      localStorage.setItem('z_timeline', JSON.stringify(timeline));
      renderTimeline();
    };
    reader.readAsDataURL(file);
  } else {
    timeline.unshift(newPost);
    localStorage.setItem('z_timeline', JSON.stringify(timeline));
    renderTimeline();
  }
  timelineForm.reset();
  previewImg.classList.add('hidden');
});
imageUpload.addEventListener('change',()=>{
  const file = imageUpload.files[0];
  if(file){
    const reader = new FileReader();
    reader.onload = ()=>{
      previewImg.src = reader.result;
      previewImg.classList.remove('hidden');
    };
    reader.readAsDataURL(file);
  }
});
function botAutoPost(){
  const phrases = ['こんにちは!', '今日も頑張ろう!', 'Zへようこそ!'];
  const msg = phrases[Math.floor(Math.random()*phrases.length)];
  timeline.unshift({title:'BOT投稿', content:msg, image:null, created:new Date().toISOString(), email:'bot@z.jp'});
  localStorage.setItem('z_timeline', JSON.stringify(timeline));
  renderTimeline();
}
setInterval(botAutoPost, 60000);
function fetchFeed(url){
  fetch(`https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(url)}`)
    .then(res=>res.json())
    .then(data=>{
      if(!data.items) return;
      data.items.slice(0,3).forEach(item=>{
        timeline.unshift({title:item.title, content:item.link, image:null, created:new Date().toISOString(), email:data.feed.title});
      });
      localStorage.setItem('z_timeline', JSON.stringify(timeline));
      renderTimeline();
    }).catch(e=>console.error('feed error',e));
}
feeds.forEach(fetchFeed);
function enterVR(){
  document.getElementById('vrScene').innerHTML = `
    <a-scene embedded>
      <a-sky color="#ECECEC"></a-sky>
      ${timeline.slice(0,10).map((p,i)=>`<a-entity text="value:${p.title}: ${p.content.replace(/\n/g,' ')};wrapCount:30" position="0 ${3-i*1.5} -3"></a-entity>`).join('')}
      <a-camera position="0 1.6 0"></a-camera>
    </a-scene>`;
  document.getElementById('vrScene').classList.remove('hidden');
  document.getElementById('vrBtn').classList.add('hidden');
}
document.addEventListener('keydown',e=>{
  if(e.key==='Escape' && !document.getElementById('vrScene').classList.contains('hidden')){
    document.getElementById('vrScene').classList.add('hidden');
    document.getElementById('vrBtn').classList.remove('hidden');
    document.getElementById('vrScene').innerHTML='';
  }
});
if(currentUser){
  authBox.classList.add('hidden');
  mainBox.classList.remove('hidden');
  userEmailSpan.textContent = currentUser.email;
  renderTimeline();
}
</script>
</body>
</html>

MusicPlayer.java

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

import javazoom.jl.player.Player;     // JLayer

/** 超シンプル MP3 プレイヤー */
public class MusicPlayer extends JFrame {
    private static final long serialVersionUID = 1L;

    private JButton playBtn = new JButton("▶ 再生");
    private JButton stopBtn = new JButton("■ 停止");
    private JLabel  status  = new JLabel("ファイルを開いてください");
    private File    currentFile;
    private Player  player;           // 再生用スレッド
    private Thread  playThread;

    public MusicPlayer() {
        super("Java Swing Music Player");

        // 画面レイアウト
        JPanel ctrl = new JPanel();
        ctrl.add(playBtn);
        ctrl.add(stopBtn);
        add(ctrl, BorderLayout.CENTER);
        add(status, BorderLayout.SOUTH);

        // メニュー
        JMenuBar bar = new JMenuBar();
        JMenu     f  = new JMenu("ファイル");
        JMenuItem open = new JMenuItem("開く...");
        open.addActionListener(e -> chooseFile());
        f.add(open);
        bar.add(f);
        setJMenuBar(bar);

        // ボタン挙動
        playBtn.addActionListener(e -> play());
        stopBtn.addActionListener(e -> stop());

        // ウィンドウ設定
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(320, 120);
        setResizable(false);
        setLocationRelativeTo(null);
    }

    /** ファイル選択ダイアログ */
    private void chooseFile() {
        JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new FileNameExtensionFilter("MP3 Audio", "mp3"));
        if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            currentFile = fc.getSelectedFile();
            status.setText("選択中: " + currentFile.getName());
        }
    }

    /** 再生開始 */
    private void play() {
        if (currentFile == null) {
            JOptionPane.showMessageDialog(this, "まず MP3 を選択してください");
            return;
        }
        stop(); // 既に再生中なら停止
        playThread = new Thread(() -> {
            try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(currentFile))) {
                player = new Player(in);
                status.setText("再生中: " + currentFile.getName());
                player.play();                  // ブロッキング
                SwingUtilities.invokeLater(() -> status.setText("停止"));
            } catch (Exception ex) {
                ex.printStackTrace();
                SwingUtilities.invokeLater(() -> status.setText("再生失敗"));
            }
        });
        playThread.start();
    }

    /** 再生停止 */
    private void stop() {
        if (player != null) {
            player.close();
        }
        if (playThread != null) {
            playThread.interrupt();
        }
        status.setText("停止");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MusicPlayer().setVisible(true));
    }
}

C:\java> dir jlayer-1.0.1.jar
2025/05/06 92,109 jlayer-1.0.1.jar ← この行が出れば OK
コンパイル
C:\java> javac -encoding UTF-8 -cp “.;jlayer-1.0.1.jar” MusicPlayer.java

Unity C# SaveManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class SaveManager
{
    const string location = "Assets/Resources/Data";

    public static void SaveData<T>(string fileName, T template)
    {
        if (!Directory.Exists(location))
        {
            Directory.CreateDirectory(location);
        }
        string data = JsonUtility.ToJson(template);
        string path = Path.Combine(location, fileName);
        using (FileStream stream = new FileStream(path, FileMode.Create))
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(data);
            }
            stream.Close();
        }
        Debug.Log("game saved");
    }

    public static T LoadData<T>(string fileName) where T : class
    {
        T load = null;
        string read = "";
        string path = Path.Combine(location, fileName);
        if(!File.Exists(path))
        {
            return null;
        }

        using (FileStream stream=new FileStream(path,FileMode.Open))
        {
            using (StreamReader reader=new StreamReader(stream))
            {
                read = reader.ReadToEnd();
            }
            stream.Close();
        }
        load = JsonUtility.FromJson<T>(read);
            return load;
    }
}

Unity C# Stats.cs

using UnityEngine;

[System.Serializable]
public class Stats // ← MonoBehaviourを削除
{
    public int Level = 1;
    public int maxHp = 1;
    public int atk = 1;
    public int def = 1;
    public int mana = 1;
    public int manaXSecond = 5;
    public CharacterClass charClass = CharacterClass.warrior;
}

public enum CharacterClass
{
    warrior,
    maga,
    priest,
    paladin,
    shamano,
    druid,
    rogue,
    ranger
}

Unity player.cs

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : Entity
{
    CameraFollow follow;
    [SerializeField]
    float rotSpeed = 2;
    [SerializeField]
    float scrollAmount = 3;
    [SerializeField]
    float minZoom = 10, maxZoom = 120;
    ActionController controller;
    const float second = 1;
    float manaCounter = 1;
    public SaveData data = new SaveData();
    // Start is called before the first frame update
    public override void Init()
    {
        base.Init();
        if (!photonView.IsMine) return;
        data = SaveManager.LoadData<SaveData>(data.characterName);
        if(data==null)
        {
            data = new SaveData();
        }
        controller = GetComponent<ActionController>();
        controller.sync = sync;
        controller.Init(this);
        var f = Resources.Load<CameraFollow>(StaticStrings.follow);
        follow = Instantiate(f, transform.position, transform.rotation);
        follow.Init(transform);
        WorldManager.instance.playerList.Add(transform);
        UIManager.instance.player = this;
        onDeathEvent = () =>
        {
            UIManager.instance.deathPanel.SetActive(true);
        };
    }

    public override void Tick()
    {
        UseCamera();
        if(controller.mana<stats.mana)
        {
            manaCounter -= Time.deltaTime;
            if (manaCounter<=0)
            {
                manaCounter = second;
                controller.mana += stats.manaXSecond;
                if (controller.mana > stats.mana) controller.mana = stats.mana;
            }
        }
        if (!CanMove()) return;
        float x = Input.GetAxisRaw(StaticStrings.horizontal);
        float y = Input.GetAxisRaw(StaticStrings.vertical);
        Vector3 move = (transform.right * x) + (transform.forward * y);
        move *= Time.deltaTime * moveMultipler * moveSpeed;
        move.y = rb.velocity.y;
        rb.velocity = move;
        sync.Move(x, y);
        controller.Tick(follow.transform,x,y);
    }

    void UseCamera()
    {
        float x = Input.GetAxis(StaticStrings.mouseX);
        float scroll = Input.GetAxisRaw(StaticStrings.scroll);
        Vector3 rot = follow.arm.rotation.eulerAngles;
        follow.transform.rotation = Quaternion.Euler(rot.x, rot.y + x * rotSpeed, rot.z);
        if(scroll!=0)
        {
            float val = scrollAmount * scroll;
            val += follow.cam.fieldOfView;
            val = Mathf.Clamp(val, minZoom, maxZoom);
            follow.cam.fieldOfView = val;
        }
    }

    bool CanMove()
    {
        if (isDeath) return false;
        return true;
    }

    public void Respawn()
    {
        transform.position = WorldManager.instance.respawnPoint.position;
        isDeath = false;
        hp = stats.maxHp;
        sync.IsDead(false);
        if(Photon.Pun.PhotonNetwork.IsConnected)
        {
            view.RPC("SyncronizeStat", Photon.Pun.RpcTarget.All, hp);
        }
    }
}