Agent Skills by ALSEL
Anthropic Claudeその他⭐ リポ 3品質スコア 61/100

threejs-game

Three.jsを使用した3Dゲーム開発ができます。WebGL レンダリング、ゲームメカニクス、物理演算の統合、キャラクターコントローラー、カメラシステム、ライティング、アニメーション、ブラウザ上でのインタラクティブな3D体験など、Web上での3Dゲーム開発に対応しています。

description の原文を見る

Three.js game development. Use for 3D web games, WebGL rendering, game mechanics, physics integration, character controllers, camera systems, lighting, animations, and interactive 3D experiences in the browser.

SKILL.md 本文

Three.js ゲーム開発スキル

WebGL を使用した Three.js ゲーム開発に関する包括的なサポート。3D レンダリング、ゲームメカニクス、物理演算、アニメーション、インタラクティブなブラウザベースのゲーム開発をカバーしています。

このスキルを使用する場合

以下の場合にこのスキルを活用してください:

  • Three.js を使用して 3D ウェブゲームを構築する
  • ゲームメカニクス(プレイヤーの移動、衝突判定、スコアリング)の実装
  • カメラ、ライティング、シーン管理のセットアップ
  • 3D モデルの読み込み(GLTF、OBJ、FBX)
  • ユーザー入力の処理(キーボード、マウス、タッチ、ゲームパッド)
  • アニメーションとキャラクターコントローラーの作成
  • 物理エンジンの統合(Cannon.js、Ammo.js)
  • 3D ゲームのパフォーマンス最適化
  • ゲーム画像用のシェーダーとマテリアルの操作

クイックリファレンス

基本的なゲームセットアップ

import * as THREE from 'three';

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

// Game loop
function animate(time) {
  requestAnimationFrame(animate);

  // Update game logic here
  updatePlayer(time);
  updateEnemies(time);
  checkCollisions();

  renderer.render(scene, camera);
}

animate();

プレイヤーコントローラー(三人称視点)

class PlayerController {
  constructor(camera, target) {
    this.camera = camera;
    this.target = target;
    this.distance = 10;
    this.height = 5;
    this.rotationSpeed = 0.005;
    this.moveSpeed = 0.1;
  }

  update(input) {
    // Movement
    const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(this.target.quaternion);
    const right = new THREE.Vector3(1, 0, 0).applyQuaternion(this.target.quaternion);

    if (input.forward) this.target.position.add(forward.multiplyScalar(this.moveSpeed));
    if (input.backward) this.target.position.add(forward.multiplyScalar(-this.moveSpeed));
    if (input.left) this.target.position.add(right.multiplyScalar(-this.moveSpeed));
    if (input.right) this.target.position.add(right.multiplyScalar(this.moveSpeed));

    // Rotation
    if (input.rotateLeft) this.target.rotation.y += this.rotationSpeed;
    if (input.rotateRight) this.target.rotation.y -= this.rotationSpeed;

    // Update camera position
    const offset = new THREE.Vector3(0, this.height, this.distance);
    offset.applyQuaternion(this.target.quaternion);
    this.camera.position.copy(this.target.position).add(offset);
    this.camera.lookAt(this.target.position);
  }
}

入力処理

class InputManager {
  constructor() {
    this.keys = {};
    this.mouse = { x: 0, y: 0, buttons: {} };

    window.addEventListener('keydown', (e) => this.keys[e.code] = true);
    window.addEventListener('keyup', (e) => this.keys[e.code] = false);
    window.addEventListener('mousemove', (e) => {
      this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
      this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
    });
  }

  getInput() {
    return {
      forward: this.keys['KeyW'] || this.keys['ArrowUp'],
      backward: this.keys['KeyS'] || this.keys['ArrowDown'],
      left: this.keys['KeyA'] || this.keys['ArrowLeft'],
      right: this.keys['KeyD'] || this.keys['ArrowRight'],
      jump: this.keys['Space'],
      action: this.keys['KeyE'],
      rotateLeft: this.keys['KeyQ'],
      rotateRight: this.keys['KeyE']
    };
  }
}

衝突検出(レイキャスティング)

function checkCollisions(player, obstacles) {
  const raycaster = new THREE.Raycaster();
  const directions = [
    new THREE.Vector3(1, 0, 0),   // right
    new THREE.Vector3(-1, 0, 0),  // left
    new THREE.Vector3(0, 0, 1),   // forward
    new THREE.Vector3(0, 0, -1),  // backward
  ];

  for (const direction of directions) {
    raycaster.set(player.position, direction);
    const intersects = raycaster.intersectObjects(obstacles);

    if (intersects.length > 0 && intersects[0].distance < 1.0) {
      return {
        collision: true,
        object: intersects[0].object,
        distance: intersects[0].distance,
        point: intersects[0].point
      };
    }
  }

  return { collision: false };
}

3D モデルの読み込み(GLTF)

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

const loader = new GLTFLoader();

function loadCharacter(path) {
  return new Promise((resolve, reject) => {
    loader.load(
      path,
      (gltf) => {
        const model = gltf.scene;
        model.scale.set(1, 1, 1);
        scene.add(model);

        // Setup animations if available
        const mixer = new THREE.AnimationMixer(model);
        const animations = {};
        gltf.animations.forEach(clip => {
          animations[clip.name] = mixer.clipAction(clip);
        });

        resolve({ model, mixer, animations });
      },
      (progress) => {
        console.log(`Loading: ${(progress.loaded / progress.total * 100).toFixed(2)}%`);
      },
      (error) => reject(error)
    );
  });
}

// Usage
const character = await loadCharacter('/models/character.glb');
character.animations.idle.play();

基本的な物理演算(重力とジャンプ)

class PhysicsBody {
  constructor(mesh) {
    this.mesh = mesh;
    this.velocity = new THREE.Vector3();
    this.onGround = false;
    this.gravity = -9.8;
    this.jumpPower = 5;
  }

  update(deltaTime) {
    // Apply gravity
    if (!this.onGround) {
      this.velocity.y += this.gravity * deltaTime;
    }

    // Apply velocity
    this.mesh.position.add(this.velocity.clone().multiplyScalar(deltaTime));

    // Ground check
    if (this.mesh.position.y <= 0) {
      this.mesh.position.y = 0;
      this.velocity.y = 0;
      this.onGround = true;
    }
  }

  jump() {
    if (this.onGround) {
      this.velocity.y = this.jumpPower;
      this.onGround = false;
    }
  }
}

インタラクティブなオブジェクト(ピッキング)

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

function onMouseClick(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(interactableObjects);

  if (intersects.length > 0) {
    const object = intersects[0].object;
    object.userData.onInteract?.();
  }
}

window.addEventListener('click', onMouseClick);

ヘルス&ダメージシステム

class Entity {
  constructor(mesh, maxHealth) {
    this.mesh = mesh;
    this.maxHealth = maxHealth;
    this.health = maxHealth;
    this.isDead = false;
  }

  takeDamage(amount) {
    if (this.isDead) return;

    this.health = Math.max(0, this.health - amount);

    if (this.health === 0) {
      this.die();
    }

    return this.health;
  }

  heal(amount) {
    this.health = Math.min(this.maxHealth, this.health + amount);
    return this.health;
  }

  die() {
    this.isDead = true;
    this.mesh.visible = false;
    // Trigger death animation, effects, etc.
  }
}

主要概念

シーングラフ

  • ゲームオブジェクトを階層的に整理する
  • 複雑なオブジェクトにはグループを使用する
  • 親子間の変換を活用する

ゲームループ

  • requestAnimationFrame で 60fps を実現する
  • フレーム非依存の移動のためにデルタタイムを計算する
  • 更新ロジックとレンダリングを分離する

カメラシステム

  • PerspectiveCamera: 一人称・三人称ゲーム
  • OrthographicCamera: 2D・アイソメトリックゲーム
  • カメラ追従とスムーズな遷移を実装する

ライティング

  • AmbientLight: 基本的な照明
  • DirectionalLight: 太陽・月光(影対応)
  • PointLight: 懐中電灯、爆発
  • SpotLight: スポットライト、舞台照明

パフォーマンス最適化

  • 繰り返されるオブジェクトにインスタンシングを使用する
  • フラスタムカリングを実装する
  • 遠いオブジェクトに LOD(詳細度レベル)を使用する
  • ドローコールを最小化する
  • テクスチャアトラスを使用する
  • シャドウマップの最適化を有効にする

アセット読み込み

  • ゲーム開始前にすべてのアセットをプリロードする
  • ローディングプログレスバーを表示する
  • LoadingManager で調整する
  • 読み込まれたアセットをキャッシュする

一般的なゲームパターン

ステートマシン(ゲームステート)

class GameStateMachine {
  constructor() {
    this.states = {
      menu: new MenuState(),
      playing: new PlayingState(),
      paused: new PausedState(),
      gameOver: new GameOverState()
    };
    this.currentState = this.states.menu;
  }

  changeState(stateName) {
    this.currentState.exit();
    this.currentState = this.states[stateName];
    this.currentState.enter();
  }

  update(deltaTime) {
    this.currentState.update(deltaTime);
  }
}

オブジェクトプーリング

class ObjectPool {
  constructor(factory, initialSize = 10) {
    this.factory = factory;
    this.available = [];
    this.inUse = [];

    for (let i = 0; i < initialSize; i++) {
      this.available.push(factory());
    }
  }

  acquire() {
    let obj = this.available.pop();
    if (!obj) obj = this.factory();
    this.inUse.push(obj);
    return obj;
  }

  release(obj) {
    const index = this.inUse.indexOf(obj);
    if (index > -1) {
      this.inUse.splice(index, 1);
      this.available.push(obj);
    }
  }
}

// Usage
const bulletPool = new ObjectPool(() => createBullet(), 20);
const bullet = bulletPool.acquire();
// ... use bullet
bulletPool.release(bullet);

参考資料

トピック別に整理された詳細なドキュメント:

  • getting_started.md - Three.js の基礎知識、セットアップ、基本概念
  • game_development.md - ゲームループ、プレイヤーコントローラー、ゲームメカニクス
  • scene_graph.md - シーン組織、階層構造、変換
  • materials.md - マテリアルタイプ、シェーダー、ビジュアルエフェクト
  • textures.md - テクスチャ読み込み、UV マッピング、アトラス
  • lighting.md - ライトタイプ、影、HDR
  • cameras.md - カメラタイプ、操作、ビューポート管理
  • geometry.md - ビルトインジオメトリ、カスタムジオメトリ、バッファ
  • loading.md - アセット読み込み(モデル、テクスチャ、オーディオ)
  • animation.md - アニメーションシステム、スケルタルアニメーション、トゥイーン
  • interactivity.md - レイキャスティング、ピッキング、UI 統合
  • effects.md - ポストプロセッシング、パーティクル、フォグ

リソース

公式ドキュメント

物理演算統合

  • Cannon.js: 軽量 3D 物理エンジン
  • Ammo.js: Bullet 物理エンジンの完全ポート
  • Rapier: 高パフォーマンス物理エンジン

便利なライブラリ

  • three-mesh-bvh: 高速レイキャスティング
  • three-pathfinding: ナビゲーションメッシュ
  • postprocessing: 高度なエフェクト

このスキルの使用方法

初心者向け

  1. 基本的なシーンセットアップから始める
  2. 座標系を理解する
  3. ゲームループを理解する
  4. モデルを使用する前にシンプルな図形で練習する

ゲーム開発向け

  1. ゲームアーキテクチャを計画する
  2. 入力処理を最初に実装する
  3. シンプルなプレイヤーコントローラーを構築する
  4. ゲームメカニクスを段階的に追加する
  5. 全体を通してパフォーマンスを最適化する

高度な機能向け

  1. 物理エンジンを統合する
  2. 高度なシェーダーを実装する
  3. ポストプロセッシングエフェクトを追加する
  4. マルチプレイヤーネットワーキングを構築する

注記

  • Three.js は右手座標系を使用します(X 右、Y 上、Z 奥)
  • 早期に最適化してください: 定期的にプロファイルし、ドローコールを最小化する
  • デバッグには開発ビルド、リリースには本番ビルドを使用してください
  • モダンブラウザでは WebGL 2 の機能を検討してください
  • モバイルパフォーマンスは慎重な最適化が必要です

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
natea
リポジトリ
natea/fitfinder
ライセンス
MIT
最終更新
2025/10/26

Source: https://github.com/natea/fitfinder / ライセンス: MIT

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: natea · natea/fitfinder · ライセンス: MIT