集めた仲間によって評価が変わるRPGの作成 ~SEの追加、不具合の解消、評価ランクの設定など~

集めた仲間によって評価が変わるRPGの作成

SEの追加、不具合の解消、評価ランクの設定など

こんにちは、東京経済大学3年のSTです。
前回は、全NPCのフラグ(会話、アイテム)と仲間加入イベント①~③の説明をしました。
今回は、SEの追加、不具合の解消、評価ランクの設定などをやります。



効果音(SE)一式 + 加入特別SE

実装内容

  • 共通SE管理用オブジェクトを追加

    • 移動 / 決定 / キャンセル / メニュー / 戦闘 / 撃破 / クリア など

  • playSE(name) 関数で統一的に再生

  • 加入時は以下の2段階構成

    1. 通常加入SE

    2. 少し遅れて「特別加入SE」

var SE = {};
var seEnabled = true;
var seVolume = 0.6; // 0.0~1.0

function initSE(){
  SE.move   = document.getElementById("seMove");
  SE.talk   = document.getElementById("seTalk");
  SE.open   = document.getElementById("seOpen");
  SE.decide = document.getElementById("seDecide");
  SE.cancel = document.getElementById("seCancel");
  SE.item   = document.getElementById("seItem");
  SE.save   = document.getElementById("seSave");
  SE.boat   = document.getElementById("seBoat");
  SE.battle = document.getElementById("seBattle");
  SE.clear  = document.getElementById("seClear");
  SE.vanish = document.getElementById("seVanish");
  SE.join   = document.getElementById("seJoin");
  SE.joinSp = document.getElementById("seJoinSp");

  Object.values(SE).forEach(a=>{
    if(a){ a.volume = seVolume; }
  });
}

function playSE(name){
  if(!seEnabled) return;
  const a = SE[name];
  if(!a) return;
  try{
    a.pause();
    a.currentTime = 0;
    a.volume = seVolume;
    a.play();
  }catch(e){
  }
}

function playJoinSpecial(){
  // 通常加入SE → 少し遅らせて特別加入SE
  playSE("join");
  setTimeout(()=>playSE("joinSp"), 220);
}


function init(){
  cv=document.getElementById("field");
  gc=cv.getContext("2d");
  if('imageSmoothingEnabled' in gc) gc.imageSmoothingEnabled=false;



<audio id="seMove"    src="semove.mp3"   preload="auto"></audio>
  <audio id="seTalk"    src="setalk.mp3"   preload="auto"></audio>
  <audio id="seOpen"    src="seopen.mp3"   preload="auto"></audio>
  <audio id="seDecide"  src="sedecide.mp3" preload="auto"></audio>
  <audio id="seCancel"  src="secancel.mp3" preload="auto"></audio>
  <audio id="seItem"    src="seitem.mp3"   preload="auto"></audio>
  <audio id="seSave"    src="sesave.mp3"   preload="auto"></audio>
  <audio id="seBoat"    src="seboat.mp3"   preload="auto"></audio>
  <audio id="seBattle"  src="sebattle.mp3" preload="auto"></audio>
  <audio id="seClear"   src="seclear.mp3"  preload="auto"></audio>
  <audio id="seVanish"  src="sevanish.mp3"  preload="auto"></audio>
  <audio id="seJoin"    src="sejoin.mp3"    preload="auto"></audio>
  <audio id="seJoinSp"  src="sejoinsp.mp3"  preload="auto"></audio>


メニュー右パネルのスクロール(仲間/アイテム)

実装内容

  • スクロール用変数を追加

    • partyScroll

    • itemScroll

  • 表示数を超えた場合は、表示範囲を切り替えて描画

  • 現在位置を

    • 1–10 / 24
      のように表示

操作仕様

  • メニュー表示中に左右キーでスクロール

  • 対象は「仲間」「アイテム」選択時のみ


 // メニュー


    if(gameMode==='menu'){
    if(code===38){ menuIndex=(menuIndex+menuItems.length-1)%menuItems.length; fieldpaint(); return; }
    if(code===40){ menuIndex=(menuIndex+1)%menuItems.length; fieldpaint(); return; }

    // ★追加:右パネルスクロール(←→)
    const current = menuItems[menuIndex];
    const maxLines = 11;
    if(code===37 || code===39){
      const dir = (code===37)? -1 : 1;
      if(current==="仲間"){
        const maxScroll = Math.max(0, party.length - maxLines);
        partyScroll = Math.max(0, Math.min(maxScroll, partyScroll + dir));
        playSE("move");
        fieldpaint();
        return;
      }
      if(current==="アイテム"){
        const maxScroll = Math.max(0, items.length - maxLines);
        itemScroll = Math.max(0, Math.min(maxScroll, itemScroll + dir));
        playSE("move");
        fieldpaint();
        return;
      }
    }

    if(code===27){ playSE("cancel"); gameMode='play'; fieldpaint(); return; }
    if(code===13||code===88){ playSE("decide"); handleMenuSelect(menuItems[menuIndex]); return; }
    return;
  }


ボス戦の確認 + 長いカットシーン

実装内容

  • ボスに話しかけると

    • 現在の評価スコア

    • 評価ランク
      を表示

  • 「挑む/やめる」の選択肢を表示

  • 条件を満たすと、複数ページの戦闘カットシーンが開始

条件

  • 評価ランクが A以上

演出内容

  • 数ページに分かれた戦闘描写

  • テキスト送りによる緊張感の演出

  • 最後に撃破処理へ移行

ゲーム体験への効果

  • ボス戦が「物語上の山場」として強調される

  • 評価システムとストーリーが自然に結びつく


3体の撃破後消滅(骸骨剣士/骸骨騎士/ゴースト)

実装内容

  • 各NPCに専用フラグを用意

    • defeated_skeletonSword

    • defeated_skeletonKnight

    • defeated_ghost

  • フラグが立つと

    • this.active=false

    • 再出現しない

イベント発生時

  • 条件を満たすと撃破/成仏

  • 専用メッセージ表示

  • アイテム取得

  • 消滅SEを再生


ボス撃破 → 王に報告 → エンディング

役割

ボス撃破をゴールにせず、物語としての締めを用意する。

実装内容

  • ボス撃破時に専用フラグを立てる

  • 王に話しかけると

    • 最終評価処理

    • エンディング演出
      が発生

流れ

  1. ダンジョンボス撃破

  2. 城へ戻る

  3. 王に報告

  4. 最終評価+エンディング表示

ゲーム体験への効果

  • 「倒して終わり」ではない余韻を残す

  • 集めた仲間や達成度を振り返る導線になる


評価ランク SSS〜E(A以上でボス戦可能)

役割

仲間集め・イベント達成を数値化して評価する中核システム。

実装内容

  • 評価ランクを以下に拡張
    SSS / SS / S / A / B / C / D / E

  • 評価対象

    • 仲間加入数

    • 撃破/成仏フラグ

    • 特殊イベント達成状況

ボス戦との関係

  • ランク A以上でのみボス戦可能

  • 低ランクでは挑戦自体ができない

ゲーム体験への効果

  • 「どれだけ準備したか」が明確に反映される

  • やり込み要素として機能する


 const evalFlags = [
    "bossCleared",
    "skeletonKingDefeated",
    "defeated_skeletonSword",
    "defeated_ghost"
  ];

  let memberScore = 0;
  for(const n of joinableMembers){
    if(inParty(n)) memberScore++;
  }

  let flagScore = 0;
  for(const f of evalFlags){
    if(hasFlag(f)) flagScore++;
  }

  const score = memberScore + flagScore;
  const maxScore = joinableMembers.length + evalFlags.length;
  const ratio = maxScore > 0 ? (score / maxScore) : 0;

   let rank = "E";
  if(ratio >= 0.95)      rank = "SSS";
  else if(ratio >= 0.85) rank = "SS";
  else if(ratio >= 0.70) rank = "S";
  else if(ratio >= 0.55) rank = "A";
  else if(ratio >= 0.40) rank = "B";
  else if(ratio >= 0.25) rank = "C";
  else if(ratio >= 0.10) rank = "D";
  else                   rank = "E";


  return { score, rank };
}

function finalEvaluate(){
  const {score,rank} = calcFinalEvaluation();
  showChoice(
    "エンディング",
    "ダンジョンボスは倒され、島に静寂が戻った。\n\n" +
    "あなたの最終評価は: "+rank+
    "\nスコア:"+score+
    "\n\n集めた仲間やこなした試練の数で評価が変化する。\n" +
    "タイトルへ戻ります。",
    ["タイトルへ戻る"],
    (i)=>{
      backToTitle();
    }
  );
}


セーブ/ロード + タイトル画面

実装内容

  • セーブデータを localStorage に保存

  • 保存内容

    • 現在位置

    • 仲間

    • アイテム

    • フラグ

  • タイトル画面を追加

    • ニューゲーム

    • コンティニュー

操作

  • セーブ済みデータがあれば「続きから」が選択可能

  • いつでも再開できる設計

まとめ

今回の更新では、

  • 演出(SE・カットシーン)

  • 評価システム

  • 世界の変化(消滅・エンディング)

  • 遊びやすさ(UI・セーブ)



参考文献・引用サイト

ぴぽや倉庫
ドット絵世界
DOT  ILLOST
効果音ラボ