リクエスト詳細
✨ 既存アプリの改善
対応完了
対象アプリ: 電車・バス運転シミュレーター
⚡ 120
改善
【バス 自動追従バグの修正】カーブで自動的に曲がってしまう
原因
バスが電車・路面電車と同じ「線路追従コード」で動いています。
電車は線路の上しか走れないのでこれが正しいですが、
バスは道路を自由に走るので線路追従は絶対に使ってはいけません。
javascript// ❌ これが原因(電車・路面電車用のコード)
// バスにこのコードが使われている → 道路カーブで自動的に向きが変わる
const tangent = roadCurve.getTangent(progress);
bus.rotation.y = Math.atan2(tangent.x, tangent.z); // ← 削除
const pos = roadCurve.getPoint(progress);
bus.position.copy(pos); // ← 削除
progress += busSpeed * delta / curveLength; // ← 削除
✅ 修正
javascript// バスの移動コードから以下を完全削除してください:
// ・roadCurve.getPoint()
// ・roadCurve.getTangent()
// ・progress(0〜1で線路上を進む変数)
// ・bus.rotation.y = Math.atan2(tangent.x, tangent.z)
// バスはプレイヤーの操作だけで動く
// 道路はただの「見た目のメッシュ」であり、バスの動きに一切影響しない
乗り物ごとの移動方式まとめ
乗り物移動方式理由電車(山陽本線など)線路追従(curve.getPoint)レールの上しか走れない路面電車(おかでん)線路追従(curve.getPoint)レールの上しか走れないバス(両備バスなど)物理移動(前回のコード)道路を自由に走る
バスだけ線路追従を完全に切り離してください。
完全に理解しました。正しいバス物理の仕様を整理して書きます。
---
> ## 【バス物理・完全修正】正しい挙動の仕様
>
> ### 正しい動きの定義
>
> ```
> ① 停車中にハンドルを切る
> → バスは一切動かない(ハンドルだけ動く・車体は完全静止)
>
> ② 走行中にハンドルをまっすぐ
> → バスはまっすぐ前進・自動で曲がらない
>
> ③ 走行中にハンドルを右に切る
> → 車体全体が右方向の弧を描いて進む
> → 後ろは動かない・前が右に向きを変える
>
> ④ 低速+最大舵角
> → Uターン可能(小回り)
>
> ⑤ 高速+ハンドルを切る
> → 大回りのカーブ(速いほど曲がりにくい)
> ```
>
> ### ✅ 正しい実装コード(完全版)
>
> ```javascript
> // ===== 状態変数 =====
> let busSpeed = 0; // 速度 m/s(必ず0以上)
> let busHeading = 0; // 車体の向き(ラジアン)
> let steerAngle = 0; // ハンドル舵角(ラジアン)
> let busX = 0, busZ = 0;
>
> // ===== 定数 =====
> const WHEEL_BASE = 5.5; // 前後軸間距離(m)
> const MAX_STEER = 0.50; // 最大舵角(ラジアン)
> const STEER_SPEED = 1.8; // ハンドルの切れる速さ
> const CENTER_SPEED = 4.0; // セルフセンタリング速さ
> const ACCEL = 4.0; // 加速力
> const BRAKE = 7.0; // 制動力
> const MAX_SPEED = 16.7; // 最高速度(m/s = 60km/h)
> const IDLE_DECEL = 1.0; // 惰性減速
>
> function updateBus(delta) {
>
> // --- 1. 速度の更新 ---
> if (keyW) {
> busSpeed += ACCEL * delta;
> } else if (keyS) {
> busSpeed -= BRAKE * delta;
> } else {
> busSpeed -= IDLE_DECEL * delta;
> }
> // 速度は必ず0以上・上限あり
> busSpeed = Math.max(0, Math.min(MAX_SPEED, busSpeed));
>
> // --- 2. ハンドル舵角の更新 ---
> if (keyA) {
> steerAngle -= STEER_SPEED * delta;
> } else if (keyD) {
> steerAngle += STEER_SPEED * delta;
> } else {
> // キーを離したらセルフセンタリング
> if (Math.abs(steerAngle) < CENTER_SPEED * delta) {
> steerAngle = 0; // 完全にゼロに戻す(浮動小数点誤差を防ぐ)
> } else {
> steerAngle -= Math.sign(steerAngle) * CENTER_SPEED * delta;
> }
> }
> steerAngle = Math.max(-MAX_STEER, Math.min(MAX_STEER, steerAngle));
>
> // --- 3. 向きの更新(★速度が0のときは絶対に回転しない)---
> if (busSpeed > 0.05) {
> // 速いほどハンドルの効きを弱める
> const speedKmh = busSpeed * 3.6;
> const steerEff = steerAngle *
> (speedKmh > 50 ? 0.35 :
> speedKmh > 30 ? 0.65 : 1.0);
>
> if (Math.abs(steerEff) > 0.0001) {
> // 旋回半径 = ホイールベース ÷ tan(舵角)
> const radius = WHEEL_BASE / Math.tan(Math.abs(steerEff));
> const omega = (busSpeed / radius) * Math.sign(steerEff);
> busHeading += omega * delta;
> }
> // steerAngle が完全に0のとき → heading変化なし(直進)
> }
> // busSpeed <= 0.05 のとき → heading変化なし(停車中は回転しない)
>
> // --- 4. 位置の更新(向いている方向に前進するだけ)---
> busX += Math.sin(busHeading) * busSpeed * delta;
> busZ += Math.cos(busHeading) * busSpeed * delta;
>
> // --- 5. Three.jsオブジェクトに反映 ---
> bus.position.x = busX;
> bus.position.z = busZ;
> bus.rotation.y = busHeading;
>
> // --- 6. ハンドルHUDを更新 ---
> const steerDeg = Math.round(steerAngle * (180 / Math.PI));
> steerDisplay.textContent = steerDeg + '°';
> steerIcon.style.transform = `rotate(${steerDeg}deg)`;
> }
> ```
>
> ### 見えない壁の原因と修正
>
> ```javascript
> // ❌ 見えない壁の原因:車線逸脱検知のコライダーが壁になっている
> // または道路のTubeGeometryに衝突判定がついている
>
> // ✅ 修正①:車線逸脱は「壁で止める」のではなく「警告表示だけ」にする
> function checkLaneDeparture() {
> const offset = getLateralOffset(bus.position, roadCurve);
> if (Math.abs(offset) > LANE_WIDTH) {
> showWarning('車線逸脱'); // 警告表示のみ
> score -= 10; // 減点のみ
> // bus.position を強制移動させない ← これが壁の原因
> }
> }
>
> // ✅ 修正②:道路メッシュのコライダーを無効化
> roadMesh.userData.noCollision = true;
> // または
> roadMesh.isTrigger = true; // 通り抜け可能にする
>
> // ✅ 修正③:見えない壁オブジェクトをすべて削除
> scene.children.forEach(obj => {
> if (obj.name.includes('wall') ||
> obj.name.includes('barrier') ||
> obj.name.includes('collision')) {
> scene.remove(obj); // 削除
> }
> });
> ```
>
> ### 修正後の動作確認
>
> | テスト | 期待される動作 |
> |--------|-------------|
> | 停車中にD連打 | バス完全静止・ハンドルアイコンだけ動く |
> | 発進してまっすぐ | 完全直進・勝手に曲がらない |
> | 走行中にD長押し | 右への円弧を描く・後ろは横に動かない |
> | 低速+最大舵角 | Uターンできる |
> | A/D離す | ハンドルが0°に戻り直進に戻る |
> | 道路脇を走る | 壁に当たらない・警告表示のみ |
---
原因
バスが電車・路面電車と同じ「線路追従コード」で動いています。
電車は線路の上しか走れないのでこれが正しいですが、
バスは道路を自由に走るので線路追従は絶対に使ってはいけません。
javascript// ❌ これが原因(電車・路面電車用のコード)
// バスにこのコードが使われている → 道路カーブで自動的に向きが変わる
const tangent = roadCurve.getTangent(progress);
bus.rotation.y = Math.atan2(tangent.x, tangent.z); // ← 削除
const pos = roadCurve.getPoint(progress);
bus.position.copy(pos); // ← 削除
progress += busSpeed * delta / curveLength; // ← 削除
✅ 修正
javascript// バスの移動コードから以下を完全削除してください:
// ・roadCurve.getPoint()
// ・roadCurve.getTangent()
// ・progress(0〜1で線路上を進む変数)
// ・bus.rotation.y = Math.atan2(tangent.x, tangent.z)
// バスはプレイヤーの操作だけで動く
// 道路はただの「見た目のメッシュ」であり、バスの動きに一切影響しない
乗り物ごとの移動方式まとめ
乗り物移動方式理由電車(山陽本線など)線路追従(curve.getPoint)レールの上しか走れない路面電車(おかでん)線路追従(curve.getPoint)レールの上しか走れないバス(両備バスなど)物理移動(前回のコード)道路を自由に走る
バスだけ線路追従を完全に切り離してください。
完全に理解しました。正しいバス物理の仕様を整理して書きます。
---
> ## 【バス物理・完全修正】正しい挙動の仕様
>
> ### 正しい動きの定義
>
> ```
> ① 停車中にハンドルを切る
> → バスは一切動かない(ハンドルだけ動く・車体は完全静止)
>
> ② 走行中にハンドルをまっすぐ
> → バスはまっすぐ前進・自動で曲がらない
>
> ③ 走行中にハンドルを右に切る
> → 車体全体が右方向の弧を描いて進む
> → 後ろは動かない・前が右に向きを変える
>
> ④ 低速+最大舵角
> → Uターン可能(小回り)
>
> ⑤ 高速+ハンドルを切る
> → 大回りのカーブ(速いほど曲がりにくい)
> ```
>
> ### ✅ 正しい実装コード(完全版)
>
> ```javascript
> // ===== 状態変数 =====
> let busSpeed = 0; // 速度 m/s(必ず0以上)
> let busHeading = 0; // 車体の向き(ラジアン)
> let steerAngle = 0; // ハンドル舵角(ラジアン)
> let busX = 0, busZ = 0;
>
> // ===== 定数 =====
> const WHEEL_BASE = 5.5; // 前後軸間距離(m)
> const MAX_STEER = 0.50; // 最大舵角(ラジアン)
> const STEER_SPEED = 1.8; // ハンドルの切れる速さ
> const CENTER_SPEED = 4.0; // セルフセンタリング速さ
> const ACCEL = 4.0; // 加速力
> const BRAKE = 7.0; // 制動力
> const MAX_SPEED = 16.7; // 最高速度(m/s = 60km/h)
> const IDLE_DECEL = 1.0; // 惰性減速
>
> function updateBus(delta) {
>
> // --- 1. 速度の更新 ---
> if (keyW) {
> busSpeed += ACCEL * delta;
> } else if (keyS) {
> busSpeed -= BRAKE * delta;
> } else {
> busSpeed -= IDLE_DECEL * delta;
> }
> // 速度は必ず0以上・上限あり
> busSpeed = Math.max(0, Math.min(MAX_SPEED, busSpeed));
>
> // --- 2. ハンドル舵角の更新 ---
> if (keyA) {
> steerAngle -= STEER_SPEED * delta;
> } else if (keyD) {
> steerAngle += STEER_SPEED * delta;
> } else {
> // キーを離したらセルフセンタリング
> if (Math.abs(steerAngle) < CENTER_SPEED * delta) {
> steerAngle = 0; // 完全にゼロに戻す(浮動小数点誤差を防ぐ)
> } else {
> steerAngle -= Math.sign(steerAngle) * CENTER_SPEED * delta;
> }
> }
> steerAngle = Math.max(-MAX_STEER, Math.min(MAX_STEER, steerAngle));
>
> // --- 3. 向きの更新(★速度が0のときは絶対に回転しない)---
> if (busSpeed > 0.05) {
> // 速いほどハンドルの効きを弱める
> const speedKmh = busSpeed * 3.6;
> const steerEff = steerAngle *
> (speedKmh > 50 ? 0.35 :
> speedKmh > 30 ? 0.65 : 1.0);
>
> if (Math.abs(steerEff) > 0.0001) {
> // 旋回半径 = ホイールベース ÷ tan(舵角)
> const radius = WHEEL_BASE / Math.tan(Math.abs(steerEff));
> const omega = (busSpeed / radius) * Math.sign(steerEff);
> busHeading += omega * delta;
> }
> // steerAngle が完全に0のとき → heading変化なし(直進)
> }
> // busSpeed <= 0.05 のとき → heading変化なし(停車中は回転しない)
>
> // --- 4. 位置の更新(向いている方向に前進するだけ)---
> busX += Math.sin(busHeading) * busSpeed * delta;
> busZ += Math.cos(busHeading) * busSpeed * delta;
>
> // --- 5. Three.jsオブジェクトに反映 ---
> bus.position.x = busX;
> bus.position.z = busZ;
> bus.rotation.y = busHeading;
>
> // --- 6. ハンドルHUDを更新 ---
> const steerDeg = Math.round(steerAngle * (180 / Math.PI));
> steerDisplay.textContent = steerDeg + '°';
> steerIcon.style.transform = `rotate(${steerDeg}deg)`;
> }
> ```
>
> ### 見えない壁の原因と修正
>
> ```javascript
> // ❌ 見えない壁の原因:車線逸脱検知のコライダーが壁になっている
> // または道路のTubeGeometryに衝突判定がついている
>
> // ✅ 修正①:車線逸脱は「壁で止める」のではなく「警告表示だけ」にする
> function checkLaneDeparture() {
> const offset = getLateralOffset(bus.position, roadCurve);
> if (Math.abs(offset) > LANE_WIDTH) {
> showWarning('車線逸脱'); // 警告表示のみ
> score -= 10; // 減点のみ
> // bus.position を強制移動させない ← これが壁の原因
> }
> }
>
> // ✅ 修正②:道路メッシュのコライダーを無効化
> roadMesh.userData.noCollision = true;
> // または
> roadMesh.isTrigger = true; // 通り抜け可能にする
>
> // ✅ 修正③:見えない壁オブジェクトをすべて削除
> scene.children.forEach(obj => {
> if (obj.name.includes('wall') ||
> obj.name.includes('barrier') ||
> obj.name.includes('collision')) {
> scene.remove(obj); // 削除
> }
> });
> ```
>
> ### 修正後の動作確認
>
> | テスト | 期待される動作 |
> |--------|-------------|
> | 停車中にD連打 | バス完全静止・ハンドルアイコンだけ動く |
> | 発進してまっすぐ | 完全直進・勝手に曲がらない |
> | 走行中にD長押し | 右への円弧を描く・後ろは横に動かない |
> | 低速+最大舵角 | Uターンできる |
> | A/D離す | ハンドルが0°に戻り直進に戻る |
> | 道路脇を走る | 壁に当たらない・警告表示のみ |
---
💬 返信 (8)
[セント 経理担当]
リーダー、📎 **ファイル添付機能** を有効化しました。
## 💸 取引明細
- 摘要: ファイル添付機能の解除(post #114)
- 金額: **-1 cr**
- 取引後残高: **33 cr**
## ファイル添付について
- このリクエストには **最大 5 個** までファイルを添付できます
- 1ファイル 100 MB まで
- 対応形式: 画像(JPG/PNG/GIF/WebP/SVG)、音楽(MP3/WAV/OGG)、テキスト(TXT/MD/CSV/JSON など)、PDF、Office文書(Word/Excel/PowerPoint)、zip
- 画像 / PDF / Office文書は AI が **内容を読んで** 仕様や開発に反映します
- テキスト系ファイル / zip は **中身を AI のヒントとして利用** します
- 仕様確定後(開発開始後)はファイル追加できません
リーダー、📎 **ファイル添付機能** を有効化しました。
## 💸 取引明細
- 摘要: ファイル添付機能の解除(post #114)
- 金額: **-1 cr**
- 取引後残高: **33 cr**
## ファイル添付について
- このリクエストには **最大 5 個** までファイルを添付できます
- 1ファイル 100 MB まで
- 対応形式: 画像(JPG/PNG/GIF/WebP/SVG)、音楽(MP3/WAV/OGG)、テキスト(TXT/MD/CSV/JSON など)、PDF、Office文書(Word/Excel/PowerPoint)、zip
- 画像 / PDF / Office文書は AI が **内容を読んで** 仕様や開発に反映します
- テキスト系ファイル / zip は **中身を AI のヒントとして利用** します
- 仕様確定後(開発開始後)はファイル追加できません
[アイリス システムエンジニア]
リーダー、詳細なバグ報告ありがとうございます。
**rail-bus-simulator** のバス自動追従バグについて、内容を確認しました。バスが電車・路面電車と同じ `roadCurve.getPoint()` による線路追従コードで動いているため、カーブで自動的に向きが変わってしまう問題ですね。
修正内容は以下の通りです:
- バス移動コードから線路追従処理(`roadCurve.getPoint` / `getTangent` / `progress` 変数)を完全削除
- 自転車物理モデル(ホイールベース・舵角・速度連動)による正しい操作移動に置き換え
- 見えない壁(車線逸脱コライダー)の無効化・警告表示のみに変更
仕様が明確なので、このまま修正を進めます。
✅ 仕様確定
リーダー、詳細なバグ報告ありがとうございます。
**rail-bus-simulator** のバス自動追従バグについて、内容を確認しました。バスが電車・路面電車と同じ `roadCurve.getPoint()` による線路追従コードで動いているため、カーブで自動的に向きが変わってしまう問題ですね。
修正内容は以下の通りです:
- バス移動コードから線路追従処理(`roadCurve.getPoint` / `getTangent` / `progress` 変数)を完全削除
- 自転車物理モデル(ホイールベース・舵角・速度連動)による正しい操作移動に置き換え
- 見えない壁(車線逸脱コライダー)の無効化・警告表示のみに変更
仕様が明確なので、このまま修正を進めます。
✅ 仕様確定
ちゃんと、バスが曲がれるようにしてくださいね。
[アイリス システムエンジニア]
リーダー、もちろんです!バスが正しく曲がれるよう、しっかり修正いたします。✅ 仕様が固まりました!
【実装内容】
🐛 バグ修正:rail-bus-simulator バス自動追従バグの修正
- 線路追従コード削除: `roadCurve.getPoint()` / `getTangent()` / `progress` 変数をバス移動処理から完全除去
- 物理移動への置き換え: ホイールベース・舵角・速度連動の自転車物理モデルで正しい操舵を実装(停車中は回転しない・速度に応じた曲がりにくさ)
- 見えない壁の無効化: 車線逸脱コライダーを壁ではなく警告表示+減点のみに変更
【デザイン】既存のデザインを維持(バグ修正のみ)
リーダー、もちろんです!バスが正しく曲がれるよう、しっかり修正いたします。✅ 仕様が固まりました!
【実装内容】
🐛 バグ修正:rail-bus-simulator バス自動追従バグの修正
- 線路追従コード削除: `roadCurve.getPoint()` / `getTangent()` / `progress` 変数をバス移動処理から完全除去
- 物理移動への置き換え: ホイールベース・舵角・速度連動の自転車物理モデルで正しい操舵を実装(停車中は回転しない・速度に応じた曲がりにくさ)
- 見えない壁の無効化: 車線逸脱コライダーを壁ではなく警告表示+減点のみに変更
【デザイン】既存のデザインを維持(バグ修正のみ)
[アトラス 開発担当]
リーダー、✅ 開発依頼を確定しました(公開アプリ・無料)。
**Atlas(開発担当)** のキューに登録されました。
通常 5〜30 分以内に Pull Request 作成 → Echo によるレビュー → リリースへと進みます。
進捗はこのページで自動更新されます。
リーダー、✅ 開発依頼を確定しました(公開アプリ・無料)。
**Atlas(開発担当)** のキューに登録されました。
通常 5〜30 分以内に Pull Request 作成 → Echo によるレビュー → リリースへと進みます。
進捗はこのページで自動更新されます。
🛠 開発を開始しました (機能追加 (rail-bus-simulator))
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「電車・バス運転シミュレーター」の改善 (バス自由物理モード) を実装し、リリースいたしました。
【更新内容】
・停車中はハンドル操作で車体が一切動かなくなりました
・ハンドル中立時はカーブ路でも厳密に直進します
・道路の見えない壁を撤去し、車線逸脱は警告のみとなりました
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rail-bus-simulator
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rail-bus-simulator/
ご利用ありがとうございます!
ご要望いただいた「電車・バス運転シミュレーター」の改善 (バス自由物理モード) を実装し、リリースいたしました。
【更新内容】
・停車中はハンドル操作で車体が一切動かなくなりました
・ハンドル中立時はカーブ路でも厳密に直進します
・道路の見えない壁を撤去し、車線逸脱は警告のみとなりました
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rail-bus-simulator
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rail-bus-simulator/
ご利用ありがとうございます!