JavaScriptによるRPG制作 Volume.3

以前、インターネット上の動画を参考にして、
HSPで製作した自作RPGゲームを
JavaScriptとjQueryで書き直してみることにした。
ジャンル的には、シミュレーションRPGに近いと思われる。
他サイトへの無断転載及び、外部サイトから
このページへの直接リンクをすることは、禁止する。

17 18 19 20 21 22 23




第17講. 擬似乱数を利用した特殊攻撃の実装

jsrpg017.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第17講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg017.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第17講</h1>

<form>
<table border="0" frame="void" rules="none">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する" onclick="seventeen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="poison" style="background-color:#c0c0c0;color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する" onclick="nineteen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="barrier" style="background-color:#c0c0c0;color:#ff0000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する" onclick="twentythree()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message1"> </span></td>
<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する" onclick="twentynine()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message2"> </span></td>
<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する" onclick="thirtyone()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする" onclick="special3()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="winlose"> </span></td>
<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する" onclick="special1()">
</span></td>
<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する" onclick="special4()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="ending"> </span></td>
<td align="center"><span>
<input type="button" value="エネルギーを使って回復する" onclick="special2()">
</span></td>

<td align="center"><span>
<input type="button" value="ランダムダメージを与える" onclick="special5()">
</span></td>

</tr>
<tr>
<td align="center" colspan="2"><span id="score"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="next"> </span></td>
<td align="center" colspan="2"><span>
<input type="button" value="次のステージへ" onclick="NextStage()">
</span></td>
</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg017.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター

var RandomDamage; // ランダムダメージの数値を格納する変数を宣言

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {
    ATKenemy += 2;
  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {
    ATKenemy += 3;
  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。

  if (stage >= 3 && HPenemy % 5 == 0) {
    ATKenemy += 5;
  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {
    ATKenemy += 7;
  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {
    ATKenemy += 11;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {
    ATKenemy += 13;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {
    ATKenemy += 17;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {
    ATKenemy += 19;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {
    ATKenemy += 23;
  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {
    ATKenemy += 29;
  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {
    ATKenemy += 31;
  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。

      $("#winlose").text("");
      ATKplayer = 0; // プレイヤーの攻撃力を初期化
      $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
      // 現在の全蓄積エネルギー
      PoisonCounter = 0; // ポイズンカウンターを0にする
      BarrierCounter = 0; // バリアカウンターを0にする

      TurnStart();

    if (stage < 5 || (stage > 5 && stage < 10)) {

      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング
    }
  }
  $("#next").text("");
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");
  if (BarrierCounter == 0 && PoisonCounter == 0) {
    document.bgColor = "#c0c0c0";
    // ポイズンカウンターとバリアカウンターが
    // 共に0の場合は、背景を銀色に戻す。
  }
  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").text("You lose!"); // 敗北メッセージ
    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {
    TurnStart();

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");
    document.bgColor = "#800080"; // 背景を紫色にする

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {
    TurnStart();

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");
    document.bgColor = "#ff0000"; // 背景を赤色にする

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {
    TurnStart();

    RandomDamage = Math.floor(Math.random() * (stage * 10 + 1));
    // ランダムダメージの威力を決定
    HPenemy -= RandomDamage;
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#message1").text("ランダムダメージを与える攻撃!");
    $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
    // ランダムダメージの威力だけダメ―ジを与える

    main();
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

(解説) これまでのプログラムは、乱数を使っていないので、理詰めで最適解を得ることができた。
今回は、擬似乱数を用いて、運の要素を取り入れてゲームらしくしてみる。
ここでは、ランダムな数値のダメージを与える特殊攻撃を定義する。
擬似乱数を用いるには、Math.randomで0以上1未満の実数を得て、それを何倍かして、
端数をMath.floor(或いは、parseInt)で切り捨てればよい。
各ステージでの威力は、RandomDamage = Math.floor(Math.random() * (stage * 10 + 1));
設定した場合、次の表の様になる。
ステージ ランダムダメージ
の数値の範囲
ステージ ランダムダメージ
の数値の範囲
ステージ1 0~10 ステージ6 0~60
ステージ2 0~20 ステージ7 0~70
ステージ3 0~30 ステージ8 0~80
ステージ4 0~40 ステージ9 0~90
ステージ5 0~50 ステージ10 0~100
中ボス戦 0~500 最終ボス戦 0~1000
つまり、ダメージを全く与えられない可能性や、一撃必殺の可能性があることになる。
しかし、ステージ数が高いほど数値の範囲が広い為、そうした確率は低くなっていくのだが。
或いは、RandomDamage = Math.floor(Math.random() * (stage * 10) + 1);として、1を足す処理を括弧の外に出した場合、
各ステージでの威力は、次の表の様になる。
ステージ ランダムダメージ
の数値の範囲
ステージ ランダムダメージ
の数値の範囲
ステージ1 1~10 ステージ6 1~60
ステージ2 1~20 ステージ7 1~70
ステージ3 1~30 ステージ8 1~80
ステージ4 1~40 ステージ9 1~90
ステージ5 1~50 ステージ10 1~100
中ボス戦 1~500 最終ボス戦 1~1000
この場合、ダメージを全く与えられない、ということはなくなる。




第18講. 乱数調整

jsrpg018.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第18講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg018.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第18講</h1>

<form>
<table border="0" frame="void" rules="none">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する" onclick="seventeen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="poison" style="background-color:#c0c0c0;color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する" onclick="nineteen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="barrier" style="background-color:#c0c0c0;color:#ff0000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する" onclick="twentythree()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message1"> </span></td>
<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する" onclick="twentynine()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message2"> </span></td>
<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する" onclick="thirtyone()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする" onclick="special3()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="winlose"> </span></td>
<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する" onclick="special1()">
</span></td>
<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する" onclick="special4()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="ending"> </span></td>
<td align="center"><span>
<input type="button" value="エネルギーを使って回復する" onclick="special2()">
</span></td>
<td align="center"><span>
<input type="button" value="ランダムダメージを与える" onclick="special5()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="score"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="next"> </span></td>
<td align="center" colspan="2"><span>
<input type="button" value="次のステージへ" onclick="NextStage()">
</span></td>
</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg018.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言

var RandomMax; // ステージ数との積がランダムダメージの上限

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {
    ATKenemy += 2;
  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {
    ATKenemy += 3;
  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。

  if (stage >= 3 && HPenemy % 5 == 0) {
    ATKenemy += 5;
  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {
    ATKenemy += 7;
  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {
    ATKenemy += 11;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {
    ATKenemy += 13;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {
    ATKenemy += 17;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {
    ATKenemy += 19;
  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {
    ATKenemy += 23;
  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {
    ATKenemy += 29;
  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {
    ATKenemy += 31;
  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。

      $("#winlose").text("");
      ATKplayer = 0; // プレイヤーの攻撃力を初期化
      $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
      // 現在の全蓄積エネルギー
      PoisonCounter = 0; // ポイズンカウンターを0にする
      BarrierCounter = 0; // バリアカウンターを0にする

      TurnStart();

    if (stage < 5 || (stage > 5 && stage < 10)) {

      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング
    }
  }
  $("#next").text("");
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");
  if (BarrierCounter == 0 && PoisonCounter == 0) {
    document.bgColor = "#c0c0c0";
    // ポイズンカウンターとバリアカウンターが
    // 共に0の場合は、背景を銀色に戻す。
  }
  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").text("You lose!"); // 敗北メッセージ
    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {
    TurnStart();

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");
    document.bgColor = "#800080"; // 背景を紫色にする

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {
    TurnStart();

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");
    document.bgColor = "#ff0000"; // 背景を赤色にする

    main();
  }
}

function special5(){

  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }

}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

(解説) 第17講で、擬似乱数を用いて、ランダムな数値のダメージを与える特殊攻撃を
実装したが、実行してみれば分かる通り、中ボスであろうが、最終ボスであろうが、
大抵の場合、2回か3回この技を使えば、倒すことができてしまう。
何故そうなるかというと、このランダムなダメージは、どの数値も等確率で出る為、
ダメージの期待値は、その平均をとってみると、そのステージの敵の初期HPの半分になることが分かる。
即ち、ゲームバランスを著しく崩壊させかねない技となっており、威力を再調整する必要がある。

各ステージの敵の初期HPは、そのステージ数×10であった。ここで、今まで無条件に10を掛けていた部分を、
10を上限とする乱数RandomMaxとし、これとステージ数との積をランダムダメージの上限とすることで、
低い数値ほど高確率で、高い数値ほど低確率で出るようにする。
但し、0での剰余算を避ける必要があるので、RandomMaxが0となった場合、敵が攻撃を回避したことにする。
また、中ボス戦と最終ボス戦では、この技を使用不可にするように変更を施した。




第19講. ゲームデザイン

jsrpg019.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第19講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg019.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第19講</h1>

<form>

<table border="0" frame="void" rules="none" background="lattice.png">

<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>

<input type="button" value="13ダメージを与え、13充電する"
 style="background-color:#808080;width:250px;" onclick="thirteen()">

</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>

<input type="button" value="2ダメージを与え、2充電する"
 style="background-color:#808080;width:250px;" onclick="two()">

</span></td>
<td align="center"><span>

<input type="button" value="17ダメージを与え、17充電する"
 style="background-color:#808080;width:250px;" onclick="seventeen()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2">

<span id="poison" style="color:#800080;"> </span>

</td>
<td align="center"><span>

<input type="button" value="3ダメージを与え、3充電する"
 style="background-color:#808080;width:250px;" onclick="three()">

</span></td>
<td align="center"><span>

<input type="button" value="19ダメージを与え、19充電する"
 style="background-color:#808080;width:250px;" onclick="nineteen()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2">

<span id="barrier" style="color:#008000;"> </span>

</td>
<td align="center"><span>

<input type="button" value="5ダメージを与え、5充電する"
 style="background-color:#808080;width:250px;" onclick="five()">

</span></td>
<td align="center"><span>

<input type="button" value="23ダメージを与え、23充電する"
 style="background-color:#808080;width:250px;" onclick="twentythree()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message1"> </span></td>
<td align="center"><span>

<input type="button" value="7ダメージを与え、7充電する"
 style="background-color:#808080;width:250px;" onclick="seven()">

</span></td>
<td align="center"><span>

<input type="button" value="29ダメージを与え、29充電する"
 style="background-color:#808080;width:250px;" onclick="twentynine()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message2"> </span></td>
<td align="center"><span>

<input type="button" value="11ダメージを与え、11充電する"
 style="background-color:#808080;width:250px;" onclick="eleven()">

</span></td>
<td align="center"><span>

<input type="button" value="31ダメージを与え、31充電する"
 style="background-color:#808080;width:250px;" onclick="thirtyone()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>

<input type="button" value="敵に毒を与え、毒状態にする"
 style="background-color:#800080;width:250px;" onclick="special3()">

</span></td>
</tr>
<tr>

<td align="center" colspan="2"><span id="winlose" style="color:#000000;"> </span></td>

<td align="center"><span>

<input type="button" value="全蓄積エネルギーを放電する"
 style="background-color:#000000;color:#ffff00;width:250px;" onclick="special1()">

</span></td>
<td align="center"><span>

<input type="button" value="ダメージを半減させる結界を発動する"
 style="background-color:#008000;width:250px;" onclick="special4()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="ending"> </span></td>
<td align="center"><span>

<input type="button" value="エネルギーを使って回復する"
 style="background-color:#000000;color:#ff0000;width:250px;" onclick="special2()">

</span></td>
<td align="center"><span>

<input type="button" value="ランダムダメージを与える"
 style="background-color:#ffff00;width:250px;" onclick="special5()">

</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="score"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>

<tr>
<td align="center" colspan="2"><span id="next"> </span></td>
<td align="center"><span>メニュー:</span></td>
<td align="center"><span> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span> </span></td>
<td align="center"><span>

<input type="button" value="次のステージへ/メッセージクリア"
 style="background-color:#808080;width:250px;" onclick="NextStage()">

</span></td>
<td align="center"><span> </span></td>
</tr>

</table>
</form>

</center>
</body>
</html>

jsrpg019.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言
var RandomMax; // ステージ数との積がランダムダメージの上限

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {  ATKenemy += 2;  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {  ATKenemy += 3;  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。
  if (stage >= 3 && HPenemy % 5 == 0) {  ATKenemy += 5;  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {  ATKenemy += 7;  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {  ATKenemy += 11;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {  ATKenemy += 13;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {  ATKenemy += 17;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {  ATKenemy += 19;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {  ATKenemy += 23;  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {  ATKenemy += 29;  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {  ATKenemy += 31;  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    if (stage < 5 || (stage > 5 && stage < 10)) {
      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング
    }
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す

  $("#next").text("");
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");

  if (BarrierCounter > 0 || PoisonCounter > 0) {
    if (BarrierCounter > PoisonCounter){
      document.bgColor = "#008000"; // 背景を緑色にする
    } else {
      document.bgColor = "#800080"; // 背景を紫色にする
    }
  } else {
    document.bgColor = "#c0c0c0"; // 背景を銀色に戻す
  }

  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");

    $("#winlose").css("color","#ff0000"); // 勝利メッセージの色を赤にする

    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");

      $("#winlose").css("color","#800080"); // 勝利メッセージの色を紫にする

      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");

      $("#winlose").css("color","#0000ff"); // 敗北メッセージの色を青にする

      $("#winlose").text("You lose!"); // 敗北メッセージ
    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ff0000"; // 背景を赤にする

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#800080"; // 背景を紫色にする

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#008000"; // 背景を緑色にする

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

(解説) 特殊攻撃3(毒攻撃)と特殊攻撃4(ダメージ半減技)には、背景色が変化するというエフェクトが存在したが、
これまで特殊攻撃1(充放電)と特殊攻撃2(回復技)と特殊攻撃5(ランダムダメージ)には、エフェクトがなかったので、
背景色の変化をエフェクトに追加した。特殊攻撃4(ダメージ半減技)は、に変更した。次のターンで、
通常攻撃を使用した際、毒または結界が発動した状態であれば、背景色は、 に戻る。

特殊攻撃1(充放電)
特殊攻撃2(回復技)
特殊攻撃3(毒攻撃)
紫(永続)
特殊攻撃4(ダメージ半減技)
緑(永続)
特殊攻撃5(ランダムダメージ)

HTMLサイドでは、テーブルの背景を格子模様の画像に変更して、毒と結界のメッセージ欄の背景色指定も削除した。
他にもボタンに色とサイズを与えてみた。「次のステージへ」ボタンには、メッセージクリアの機能を持たせて、
明示することにした。ボタンの背景色が黒の技は、エネルギーを使用する技を意味する。

また、勝敗メッセージの欄も、勝利メッセージは赤毒による勝利メッセージは紫敗北メッセージは青
表示されるようにした。念の為、勝利後のイベント処理をする関数において、黒に戻している。




第20講. 最初から始める

jsrpg020.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第20講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg020.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第20講</h1>

<form>
<table border="0" frame="void" rules="none" background="lattice.png">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する"
 style="background-color:#808080;width:250px;" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する"
 style="background-color:#808080;width:250px;" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する"
 style="background-color:#808080;width:250px;" onclick="seventeen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="poison" style="color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する"
 style="background-color:#808080;width:250px;" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する"
 style="background-color:#808080;width:250px;" onclick="nineteen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="barrier" style="color:#008000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する"
 style="background-color:#808080;width:250px;" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する"
 style="background-color:#808080;width:250px;" onclick="twentythree()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message1"> </span></td>
<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する"
 style="background-color:#808080;width:250px;" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する"
 style="background-color:#808080;width:250px;" onclick="twentynine()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message2"> </span></td>
<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する"
 style="background-color:#808080;width:250px;" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する"
 style="background-color:#808080;width:250px;" onclick="thirtyone()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする"
 style="background-color:#800080;width:250px;" onclick="special3()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="winlose" style="color:#000000;"> </span></td>
<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する"
 style="background-color:#000000;color:#ffff00;width:250px;" onclick="special1()">
</span></td>
<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する"
 style="background-color:#008000;width:250px;" onclick="special4()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="ending"> </span></td>
<td align="center"><span>
<input type="button" value="エネルギーを使って回復する"
 style="background-color:#000000;color:#ff0000;width:250px;" onclick="special2()">
</span></td>
<td align="center"><span>
<input type="button" value="ランダムダメージを与える"
 style="background-color:#ffff00;width:250px;" onclick="special5()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="score"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="next"> </span></td>
<td align="center"><span>メニュー:</span></td>

<td align="center"><span>
<input type="button" value="最初から始める"
 style="background-color:#808080;width:250px;" onclick="GameStart()">
</span></td>

</tr>
<tr>
<td align="center" colspan="2"><span> </span></td>
<td align="center"><span>
<input type="button" value="次のステージへ/メッセージクリア"
 style="background-color:#808080;width:250px;" onclick="NextStage()">
</span></td>
<td align="center"><span> </span></td>
</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg020.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言
var RandomMax; // ステージ数との積がランダムダメージの上限

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {  ATKenemy += 2;  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {  ATKenemy += 3;  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。
  if (stage >= 3 && HPenemy % 5 == 0) {  ATKenemy += 5;  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {  ATKenemy += 7;  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {  ATKenemy += 11;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {  ATKenemy += 13;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {  ATKenemy += 17;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {  ATKenemy += 19;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {  ATKenemy += 23;  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {  ATKenemy += 29;  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {  ATKenemy += 31;  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
    $("#winlose").text("");

    $("#next").text("");

    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    if (stage < 5 || (stage > 5 && stage < 10)) {
      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング

      $("#next").text("もう一回?(Yes→「最初から始める」)");

    }
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");

  if (BarrierCounter > 0 || PoisonCounter > 0) {
    if (BarrierCounter > PoisonCounter){
      document.bgColor = "#008000"; // 背景を緑色にする
    } else {
      document.bgColor = "#800080"; // 背景を紫色にする
    }
  } else {
    document.bgColor = "#c0c0c0"; // 背景を銀色に戻す
  }

  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").css("color","#ff0000"); // 勝利メッセージの色を赤にする
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").css("color","#800080"); // 勝利メッセージの色を紫にする
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").css("color","#0000ff"); // 敗北メッセージの色を青にする
      $("#winlose").text("You lose!"); // 敗北メッセージ

      $("#next").text("もう一回?(Yes→「最初から始める」)");

    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ff0000"; // 背景を赤にする

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#800080"; // 背景を紫色にする

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#008000"; // 背景を緑色にする

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

// 最初から始める
function GameStart(){
  if ((HPplayer <= 0) || (stage == 100 && HPenemy <= 0)){
  // ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer = 10; // プレイヤーの初期HPへ
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

  } else {
    alert("ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

(解説) これまでは、ゲームオーバー時になったとき、或いは、ゲームを全てクリアしたとき、
リトライするには、F5キーを押すなどしてリロードする必要があったが、
「最初から始める」ボタンを押せば、同様のことができるようになった。




第21講. 強くてニューゲーム

jsrpg021.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第21講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg021.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第21講</h1>

<form>
<table border="0" frame="void" rules="none" background="lattice.png">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する"
 style="background-color:#808080;width:250px;" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する"
 style="background-color:#808080;width:250px;" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する"
 style="background-color:#808080;width:250px;" onclick="seventeen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="poison" style="color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する"
 style="background-color:#808080;width:250px;" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する"
 style="background-color:#808080;width:250px;" onclick="nineteen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="barrier" style="color:#008000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する"
 style="background-color:#808080;width:250px;" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する"
 style="background-color:#808080;width:250px;" onclick="twentythree()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message1"> </span></td>
<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する"
 style="background-color:#808080;width:250px;" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する"
 style="background-color:#808080;width:250px;" onclick="twentynine()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message2"> </span></td>
<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する"
 style="background-color:#808080;width:250px;" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する"
 style="background-color:#808080;width:250px;" onclick="thirtyone()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする"
 style="background-color:#800080;width:250px;" onclick="special3()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="winlose" style="color:#000000;"> </span></td>
<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する"
 style="background-color:#000000;color:#ffff00;width:250px;" onclick="special1()">
</span></td>
<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する"
 style="background-color:#008000;width:250px;" onclick="special4()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="ending"> </span></td>
<td align="center"><span>
<input type="button" value="エネルギーを使って回復する"
 style="background-color:#000000;color:#ff0000;width:250px;" onclick="special2()">
</span></td>
<td align="center"><span>
<input type="button" value="ランダムダメージを与える"
 style="background-color:#ffff00;width:250px;" onclick="special5()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="score"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="2"><span id="next"> </span></td>
<td align="center"><span>メニュー:</span></td>
<td align="center"><span>
<input type="button" value="最初から始める"
 style="background-color:#808080;width:250px;" onclick="GameStart()">
</span></td>
</tr>
<tr>
<td align="center" colspan="2"><span> </span></td>
<td align="center"><span>
<input type="button" value="次のステージへ/メッセージクリア"
 style="background-color:#808080;width:250px;" onclick="NextStage()">
</span></td>

<td align="center"><span>
<input type="button" value="強くてニューゲーム"
 style="background-color:#808080;width:250px;" onclick="NewGameStart()">
</span></td>

</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg021.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言
var RandomMax; // ステージ数との積がランダムダメージの上限

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {  ATKenemy += 2;  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {  ATKenemy += 3;  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。
  if (stage >= 3 && HPenemy % 5 == 0) {  ATKenemy += 5;  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {  ATKenemy += 7;  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {  ATKenemy += 11;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {  ATKenemy += 13;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {  ATKenemy += 17;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {  ATKenemy += 19;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {  ATKenemy += 23;  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {  ATKenemy += 29;  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {  ATKenemy += 31;  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
    $("#winlose").text("");

    $("#next").text("");

    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    if (stage < 5 || (stage > 5 && stage < 10)) {
      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング

      $("#next").text("「最初から始める」? or 「強くてニューゲーム」?");

    }
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");

  if (BarrierCounter > 0 || PoisonCounter > 0) {
    if (BarrierCounter > PoisonCounter){
      document.bgColor = "#008000"; // 背景を緑色にする
    } else {
      document.bgColor = "#800080"; // 背景を紫色にする
    }
  } else {
    document.bgColor = "#c0c0c0"; // 背景を銀色に戻す
  }

  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").css("color","#ff0000"); // 勝利メッセージの色を赤にする
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").css("color","#800080"); // 勝利メッセージの色を紫にする
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").css("color","#0000ff"); // 敗北メッセージの色を青にする
      $("#winlose").text("You lose!"); // 敗北メッセージ

      $("#next").text("もう一回?(Yes→「最初から始める」)");

    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ff0000"; // 背景を赤にする

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#800080"; // 背景を紫色にする

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#008000"; // 背景を緑色にする

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

// 最初から始める
function GameStart(){
  if ((HPplayer <= 0) || (stage == 100 && HPenemy <= 0)){
  // ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer = 10; // プレイヤーの初期HPへ
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

  } else {
    alert("ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

// 強くてニューゲーム
function NewGameStart(){
  if (stage == 100 && HPenemy <= 0){
  // 全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer += 10; // クリア後のプレイヤーのHPに10を加算
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

  } else {
    alert("全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

(解説) ゲームを全てクリアしたとき、「最初から始める」ボタンではなく、
「強くてニューゲーム」ボタンを押すと、クリア時のHPを引き継いで、
プレイすることができるよう、上級者向けの変更を施した。




第22講. 属性システムの導入

jsrpg022.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第22講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg022.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第22講</h1>

<form>
<table border="0" frame="void" rules="none" background="lattice.png">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>

<td align="center">敵属性:<span id="TypeEnemy" style="color:#000000;">???</span></td>

<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する"
 style="background-color:#808080;width:250px;" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>

<td align="center">属性:<span id="TypePlayer" style="color:#000000;">???</span></td>

<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する"
 style="background-color:#808080;width:250px;" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する"
 style="background-color:#808080;width:250px;" onclick="seventeen()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3">

<span id="poison" style="color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する"
 style="background-color:#808080;width:250px;" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する"
 style="background-color:#808080;width:250px;" onclick="nineteen()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3">

<span id="barrier" style="color:#008000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する"
 style="background-color:#808080;width:250px;" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する"
 style="background-color:#808080;width:250px;" onclick="twentythree()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="message1"> </span></td>

<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する"
 style="background-color:#808080;width:250px;" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する"
 style="background-color:#808080;width:250px;" onclick="twentynine()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="message2"> </span></td>

<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する"
 style="background-color:#808080;width:250px;" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する"
 style="background-color:#808080;width:250px;" onclick="thirtyone()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="message3"> </span></td>

<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="message4"> </span></td>

<td align="center"><span>特殊攻撃:</span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする"
 style="background-color:#800080;width:250px;" onclick="special3()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="winlose" style="color:#000000;"> </span></td>

<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する"
 style="background-color:#000000;color:#ffff00;width:250px;" onclick="special1()">
</span></td>
<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する"
 style="background-color:#008000;width:250px;" onclick="special4()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="ending"> </span></td>

<td align="center"><span>
<input type="button" value="エネルギーを使って回復する"
 style="background-color:#000000;color:#ff0000;width:250px;" onclick="special2()">
</span></td>
<td align="center"><span>
<input type="button" value="ランダムダメージを与える"
 style="background-color:#ffff00;width:250px;" onclick="special5()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="score"> </span></td>

<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="next"> </span></td>

<td align="center"><span>メニュー:</span></td>
<td align="center"><span>
<input type="button" value="最初から始める"
 style="background-color:#808080;width:250px;" onclick="GameStart()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span> </span></td>

<td align="center"><span>
<input type="button" value="次のステージへ/メッセージクリア"
 style="background-color:#808080;width:250px;" onclick="NextStage()">
</span></td>
<td align="center"><span>
<input type="button" value="強くてニューゲーム"
 style="background-color:#808080;width:250px;" onclick="NewGameStart()">
</span></td>
</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg022.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言
var RandomMax; // ステージ数との積がランダムダメージの上限

var TypeName = new Array("Feuer", "Eis", "Donner");
// 属性名称(0:Feuer, 1:Eis, 2:Donner)
var TypeColor = new Array("#ff0000", "#0000ff", "#008000");
// 属性の色(0:赤, 1:青, 2:緑)
var TypeEnemy; // 敵の属性
var TypePlayer; // プレイヤーの属性

window.onload = function() {
  TypeChangeEnemy();
  TypeChangePlayer();
}

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {  ATKenemy += 2;  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {  ATKenemy += 3;  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。
  if (stage >= 3 && HPenemy % 5 == 0) {  ATKenemy += 5;  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {  ATKenemy += 7;  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {  ATKenemy += 11;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {  ATKenemy += 13;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {  ATKenemy += 17;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {  ATKenemy += 19;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {  ATKenemy += 23;  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {  ATKenemy += 29;  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {  ATKenemy += 31;  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。
}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
    $("#winlose").text("");
    $("#next").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    if (stage < 5 || (stage > 5 && stage < 10)) {
      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。

    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。

    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);

      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。

    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);

      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。

    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング
      $("#next").text("「最初から始める」? or 「強くてニューゲーム」?");
    }
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");

  if (BarrierCounter > 0 || PoisonCounter > 0) {
    if (BarrierCounter > PoisonCounter){
      document.bgColor = "#008000"; // 背景を緑色にする
    } else {
      document.bgColor = "#800080"; // 背景を紫色にする
    }
  } else {
    document.bgColor = "#c0c0c0"; // 背景を銀色に戻す
  }

  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").css("color","#ff0000"); // 勝利メッセージの色を赤にする
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").css("color","#800080"); // 勝利メッセージの色を紫にする
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").css("color","#0000ff"); // 敗北メッセージの色を青にする
      $("#winlose").text("You lose!"); // 敗北メッセージ
      $("#next").text("もう一回?(Yes→「最初から始める」)");
    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ff0000"; // 背景を赤にする

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#800080"; // 背景を紫色にする

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#008000"; // 背景を緑色にする

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

// 最初から始める
function GameStart(){
  if ((HPplayer <= 0) || (stage == 100 && HPenemy <= 0)){
  // ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer = 10; // プレイヤーの初期HPへ
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

    TypeChangeEnemy();
    TypeChangePlayer();

  } else {
    alert("ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

// 強くてニューゲーム
function NewGameStart(){
  if (stage == 100 && HPenemy <= 0){
  // 全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer += 10; // クリア後のプレイヤーのHPに10を加算
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

    TypeChangeEnemy(); // 強くてニューゲームの場合は、敵のみ。

  } else {
    alert("全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

function TypeChangeEnemy(){
  TypeEnemy = Math.floor(Math.random() * 3);
  $("#TypeEnemy").css("color", TypeColor[TypeEnemy]);
  $("#TypeEnemy").text(TypeName[TypeEnemy]);
}

function TypeChangePlayer(){
  TypePlayer = Math.floor(Math.random() * 3);
  $("#TypePlayer").css("color", TypeColor[TypePlayer]);
  $("#TypePlayer").text(TypeName[TypePlayer]);
}

(解説) このゲームは、運の要素が少なく、ランダムダメージを与える技を選んだ時ぐらいしか、
乱数の出番がない。そこで、ジャンケンゲームの様な要素として、属性を導入してみたい。

Feuer」は、独逸語で「」を、 「Eis」は、独逸語で「」を、 「Donner」は、独逸語で「」を意味する。
物質は、引火点に満たない低温では燃焼することができないので、 「Feuer(火)」は、 「Eis(氷)」に弱く、
また、特定の物質は、極めて低温において、電気抵抗が殆どゼロに近づくので、 「Eis(氷)」は、 「Donner(雷)」に弱く、
また、特定の物質は、高温では、磁場が消失するので、 「Donner(雷)」は、 「Feuer(火)」に弱いものと定義する。
上記の定義に従えば、三者の間には、ジャンケンの様な関係があることになる。

今回は、準備段階として、敵の属性とプレイヤーの属性を変更する関数を作り、ブラウザがページを読み込んだとき、
window.onload = function()を用いて、両者の属性を乱数を用いて選ぶ。次のステージへ行く場合は、敵のみ、
「最初から始める」の場合は、両者、「強くてニューゲーム」の場合は、敵のみ、属性を変更する。




第23講. 属性システムの実装

jsrpg023.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>JavaScriptによるRPG制作・第23講</title>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="jsrpg023.js"></script>
</head>
<body bgcolor="#c0c0c0">
<center>
<h1>JavaScriptによるRPG制作・第23講</h1>

<form>
<table border="0" frame="void" rules="none" background="lattice.png">
<tr>
<td align="center"><span id="stage">ステージ:1</span></td>
<td align="center"><span id="HPenemy">敵HP:10</span></td>
<td align="center">敵属性:<span id="TypeEnemy" style="color:#000000;">???</span></td>
<td align="center"><span>通常攻撃:</span></td>
<td align="center"><span>
<input type="button" value="13ダメージを与え、13充電する"
 style="background-color:#808080;width:250px;" onclick="thirteen()">
</span></td>
</tr>
<tr>
<td align="center"><span id="HPplayer">HP:10</span></td>
<td align="center">属性:<span id="TypePlayer" style="color:#000000;">???</span></td>
<td align="center"><span id="ATKplayer">全蓄積エネルギー:0</span></td>
<td align="center"><span>
<input type="button" value="2ダメージを与え、2充電する"
 style="background-color:#808080;width:250px;" onclick="two()">
</span></td>
<td align="center"><span>
<input type="button" value="17ダメージを与え、17充電する"
 style="background-color:#808080;width:250px;" onclick="seventeen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="3">
<span id="poison" style="color:#800080;"> </span>
</td>
<td align="center"><span>
<input type="button" value="3ダメージを与え、3充電する"
 style="background-color:#808080;width:250px;" onclick="three()">
</span></td>
<td align="center"><span>
<input type="button" value="19ダメージを与え、19充電する"
 style="background-color:#808080;width:250px;" onclick="nineteen()">
</span></td>
</tr>
<tr>
<td align="center" colspan="3">
<span id="barrier" style="color:#008000;"> </span>
</td>
<td align="center"><span>
<input type="button" value="5ダメージを与え、5充電する"
 style="background-color:#808080;width:250px;" onclick="five()">
</span></td>
<td align="center"><span>
<input type="button" value="23ダメージを与え、23充電する"
 style="background-color:#808080;width:250px;" onclick="twentythree()">
</span></td>
</tr>
<tr>
<td align="center" colspan="3"><span id="message1"> </span></td>
<td align="center"><span>
<input type="button" value="7ダメージを与え、7充電する"
 style="background-color:#808080;width:250px;" onclick="seven()">
</span></td>
<td align="center"><span>
<input type="button" value="29ダメージを与え、29充電する"
 style="background-color:#808080;width:250px;" onclick="twentynine()">
</span></td>
</tr>
<tr>
<td align="center" colspan="3"><span id="message2"> </span></td>
<td align="center"><span>
<input type="button" value="11ダメージを与え、11充電する"
 style="background-color:#808080;width:250px;" onclick="eleven()">
</span></td>
<td align="center"><span>
<input type="button" value="31ダメージを与え、31充電する"
 style="background-color:#808080;width:250px;" onclick="thirtyone()">
</span></td>
</tr>
<tr>
<td align="center" colspan="3"><span id="message3"> </span></td>
<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>
<td align="center" colspan="3"><span id="message4"> </span></td>
<td align="center"><span>特殊攻撃:</span></td>

<td align="center"><span>
<input type="button" value="ダメージを半減させる結界を発動する"
 style="background-color:#008000;width:250px;" onclick="special4()">
</span></td>

</tr>
<tr>

<td align="center" colspan="3"><span id="message5"> </span></td>

<td align="center"><span>
<input type="button" value="全蓄積エネルギーを放電する"
 style="background-color:#000000;color:#ffff00;width:250px;" onclick="special1()">
</span></td>

<td align="center"><span>
<input type="button" value="ランダムダメージを与える"
 style="background-color:#ffff00;width:250px;" onclick="special5()">
</span></td>

</tr>
<tr>

<td align="center" colspan="3"><span id="message6"> </span></td>

<td align="center"><span>
<input type="button" value="エネルギーを使って回復する"
 style="background-color:#000000;color:#ff0000;width:250px;" onclick="special2()">
</span></td>

<td align="center"><span>
<input type="button" value="プレイヤーの属性を変更する"
 style="background-color:#808080;width:250px;" onclick="special6()">
</span></td>

</tr>
<tr>

<td align="center" colspan="3"><span id="winlose" style="color:#000000;"> </span></td>
<td align="center"><span>
<input type="button" value="敵に毒を与え、毒状態にする"
 style="background-color:#800080;width:250px;" onclick="special3()">
</span></td>
<td align="center"><span> </span></td>

</tr>
<tr>

<td align="center" colspan="3"><span id="ending"> </span></td>

<td align="center" colspan="2"><span> <hr> </span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="score"> </span></td>

<td align="center"><span>メニュー:</span></td>
<td align="center"><span>
<input type="button" value="最初から始める"
 style="background-color:#808080;width:250px;" onclick="GameStart()">
</span></td>
</tr>
<tr>

<td align="center" colspan="3"><span id="next"> </span></td>

<td align="center"><span>
<input type="button" value="次のステージへ/メッセージクリア"
 style="background-color:#808080;width:250px;" onclick="NextStage()">
</span></td>
<td align="center"><span>
<input type="button" value="強くてニューゲーム"
 style="background-color:#808080;width:250px;" onclick="NewGameStart()">
</span></td>
</tr>
</table>
</form>

</center>
</body>
</html>

jsrpg023.js

var HPenemy = 10;
var HPplayer = 10;
var ATKenemy = 0; // 敵の攻撃力を初期化
var ATKplayer = 0; // プレイヤーの攻撃力を初期化
var stage = 1; // ステージ数
var power; // 技の威力
var PoisonCounter = 0; // ポイズンカウンター
var BarrierCounter = 0; // バリアカウンター
var RandomDamage; // ランダムダメージの数値を格納する変数を宣言
var RandomMax; // ステージ数との積がランダムダメージの上限

var TypeName = new Array("Feuer", "Eis", "Donner");
// 属性名称(0:Feuer, 1:Eis, 2:Donner)
var TypeColor = new Array("#ff0000", "#0000ff", "#008000");
// 属性の色(0:赤, 1:青, 2:緑)

var TypeBackGroundColor = new Array("#ff00ff", "#00ffff", "#00ff00");
// 属性の色(0:マゼンタ, 1:シアン, 2:ライム)

var TypeEnemy; // 敵の属性
var TypePlayer; // プレイヤーの属性

var TypeChange; // 属性変更用の乱数
var TypeEffect; // 属性による補正効果用の乱数
var TypeEffectATK; // 攻撃時の属性による補正効果
var TypeEffectDEF; // 防御時の属性による補正効果

window.onload = function() {
  TypeChangeEnemy();
  TypeChangePlayer();
}

function ATKcalc(){ // 敵の攻撃力を計算する関数
  ATKenemy = 0; // 敵の攻撃力を初期化
  if (HPenemy % 2 == 0) {  ATKenemy += 2;  }
  // 敵のHPが2の倍数の時、敵の攻撃力が2上昇する。
  if (HPenemy % 3 == 0) {  ATKenemy += 3;  }
  // 敵のHPが3の倍数の時、敵の攻撃力が3上昇する。
  if (stage >= 3 && HPenemy % 5 == 0) {  ATKenemy += 5;  }
  // ステージ3以降、敵のHPが5の倍数の時、敵の攻撃力が5上昇する。
  if (stage >= 5 && HPenemy % 7 == 0) {  ATKenemy += 7;  }
  // ステージ5以降、敵のHPが7の倍数の時、敵の攻撃力が7上昇する。

  if (stage >= 50 && HPenemy % 11 == 0) {  ATKenemy += 11;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが11の倍数の時、敵の攻撃力が11上昇する。
  if (stage >= 50 && HPenemy % 13 == 0) {  ATKenemy += 13;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが13の倍数の時、敵の攻撃力が13上昇する。
  if (stage >= 50 && HPenemy % 17 == 0) {  ATKenemy += 17;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが17の倍数の時、敵の攻撃力が17上昇する。
  if (stage >= 50 && HPenemy % 19 == 0) {  ATKenemy += 19;  }
  // 中ボス戦及び、最終ボス戦の時、敵のHPが19の倍数の時、敵の攻撃力が19上昇する。

  if (stage >= 100 && HPenemy % 23 == 0) {  ATKenemy += 23;  }
  // 最終ボス戦時のみ、敵のHPが23の倍数の時、敵の攻撃力が23上昇する。
  if (stage >= 100 && HPenemy % 29 == 0) {  ATKenemy += 29;  }
  // 最終ボス戦時のみ、敵のHPが29の倍数の時、敵の攻撃力が29上昇する。
  if (stage >= 100 && HPenemy % 31 == 0) {  ATKenemy += 31;  }
  // 最終ボス戦時のみ、敵のHPが31の倍数の時、敵の攻撃力が31上昇する。

  TypeEffect = (TypeEnemy + 3 - TypePlayer) % 3;
  switch(TypeEffect){
    case 0 : TypeEffectDEF = 1; break;
    case 1 : TypeEffectDEF = 2; break;
    case 2 : TypeEffectDEF = 0.5; break;
    default : break;
  }
  ATKenemy = parseInt(ATKenemy * TypeEffectDEF);

}

function BarrierState(){ // 結界を表示する関数
  if (BarrierCounter > 0) {
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    // バリアカウンターが0以外のとき、結界が発動中であることを表示する。
  } else {
    $("#barrier").text("");
  }
}

function NextStage(){ // 勝利後のイベント処理をする関数
  if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
    $("#winlose").text("");
    $("#next").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    if (stage < 5 || (stage > 5 && stage < 10)) {
      stage += 1; // 次のステージへ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。
    } else if (stage == 5) {
      stage = 50; // 中ボス戦のステージへ
      HPenemy = 500; // 中ボスのHP
      $("#stage").text("中ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。
    } else if (stage == 10) {
      stage = 100; // 最終ボス戦のステージへ
      HPenemy = 1000; // 最終ボスのHP
      $("#stage").text("最終ボス戦");
      $("#HPenemy").text("敵HP:" + HPenemy);
      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。
    } else if (stage == 50) {
      stage = 6; // 中ボスを倒した後は、ステージ6へ
      HPenemy = stage * 10; // 次のステージの敵のHP
      HPplayer += stage * 10; // HPを加算
      $("#stage").text("ステージ:" + stage);
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#HPplayer").text("HP:" + HPplayer);
      TypeChangeEnemy(); // 次のステージへ行く場合は、敵のみ属性を変更。
    } else {
      $("#ending").text("祝!ゲームクリア");
      $("#score").text("スコア:" + HPplayer);
      // エンディング
      $("#next").text("「最初から始める」? or 「強くてニューゲーム」?");
    }
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
}

function PoisonState(){ // 毒状態を表示する関数
  if (PoisonCounter > 0) {
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    // ポイズンカウンターが0以外のとき、敵のHPが残っていれば、毒状態であることを表示する。
  } else {
    $("#poison").text("");
  }
}

function TurnStart(){ // ターン開始時の処理をする関数
  $("#message1").text("");
  $("#message2").text("");
  $("#message3").text("");
  $("#message4").text("");

  $("#message5").text("");
  $("#message6").text("");

  if (BarrierCounter > 0 || PoisonCounter > 0) {
    if (BarrierCounter > PoisonCounter){
      document.bgColor = "#008000"; // 背景を緑色にする
    } else {
      document.bgColor = "#800080"; // 背景を紫色にする
    }
  } else {
    document.bgColor = "#c0c0c0"; // 背景を銀色に戻す
  }

  PoisonState();
  BarrierState();
}

// メイン関数
function main(){
  if (HPenemy <= 0) { // 敵のHPが0以下ならば、勝利。
    $("#HPenemy").text("敵HP:0");
    $("#winlose").css("color","#ff0000"); // 勝利メッセージの色を赤にする
    $("#winlose").text("You win!"); // 勝利メッセージ
    $("#next").text("「次のステージへ」ボタンを押してください。");
  } else {
    ATKcalc();
    if (BarrierCounter > 0) {
      ATKenemy =  parseInt( ATKenemy / 2); // 敵の攻撃力を半減させる。
      // JavaScriptでは、自動で実数化されてしまうので、整数化する。
      BarrierCounter -= 1; // バリアカウンターを1減らす
    }
    HPplayer -= ATKenemy; // 敵の攻撃によるダメージを受ける。
    $("#HPplayer").text("HP:" + HPplayer);
    $("#message3").text("プレイヤーは " + ATKenemy + " のダメージを受けた");

    if (PoisonCounter > 0) {
      HPenemy -= ATKenemy; // ポイズンカウンターが0以外の場合は、敵は毒によるダメージを受ける。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵は毒により " + ATKenemy + " のダメージを受けた");
      // 敵が毒によるダメージを受けた場合のメッセージ
      PoisonCounter -= 1; // ポイズンカウンターを1減らす
    } else {
      HPenemy += ATKenemy; // ポイズンカウンターが0の場合は敵はその数値分HPを回復する。
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message4").text("敵はHPを " + ATKenemy + " 回復した");
      // 敵がHPを回復した場合のメッセージ
    }
    if (HPenemy <= 0) {  // 敵のHPが0以下ならば、勝利。
      $("#HPenemy").text("敵HP:0");
      $("#winlose").css("color","#800080"); // 勝利メッセージの色を紫にする
      $("#winlose").text("You win!"); // 勝利メッセージ
      $("#next").text("「次のステージへ」ボタンを押してください。");
    }
    // 敵が毒のダメージで力尽きた場合にも、
    // 戦闘を継続させずに、次のステージへ行く為の処理

    if (HPplayer <= 0) {  // プレイヤーのHPが0以下ならば、敗北。
      $("#HPplayer").text("HP:0");
      $("#winlose").css("color","#0000ff"); // 敗北メッセージの色を青にする
      $("#winlose").text("You lose!"); // 敗北メッセージ
      $("#next").text("もう一回?(Yes→「最初から始める」)");
    }

  }
}

// 通常攻撃(コア)
function NormalAttack(power){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){
    TurnStart();

    TypeEffect = (TypePlayer + 3 - TypeEnemy) % 3;
    switch(TypeEffect){
      case 0 : TypeEffectATK = 1; break;
      case 1 : TypeEffectATK = 2; break;
      case 2 : TypeEffectATK = 0.5; break;
      default : break;
    }
    power = parseInt(power * TypeEffectATK);

    HPenemy -= power;  // 技の威力だけダメ―ジを与え、
    ATKplayer += power; // その数値分充電する。
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    $("#message1").text("敵に " + power + " のダメージを与えた");
    $("#message2").text("エネルギーを " + power + " 充電した");

    main();
  }
}

// 特殊攻撃
function special1(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    HPenemy -= ATKplayer; // 全蓄積エネルギーを放電する
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを放電した");
    $("#message2").text("敵に " + ATKplayer + " のダメージを与えた");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special2(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100){

    TurnStart();
    document.bgColor = "#ff0000"; // 背景を赤にする

    HPplayer += ATKplayer; // エネルギーを使って回復する
    $("#HPplayer").text("HP:" + HPplayer);
    $("#ATKplayer").text("全蓄積エネルギー:" + 0);
    $("#message1").text("蓄積されていた全エネルギーを吸収した");
    $("#message2").text("プレイヤーはHPを " + ATKplayer + " 回復した");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化

    main();
  }
}

function special3(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#800080"; // 背景を紫色にする

    PoisonCounter = stage + 1; // ポイズンカウンターにはステージ数+1を代入
    $("#poison").text("敵は、毒状態(あと " + PoisonCounter + " ターン)");
    $("#message1").text("敵を毒状態にした");

    main();
  }
}

function special4(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    document.bgColor = "#008000"; // 背景を緑色にする

    BarrierCounter = stage + 1; // バリアカウンターにはステージ数+1を代入
    $("#barrier").text("結界が発動中(あと " + BarrierCounter + " ターン)");
    $("#message1").text("ダメージを半減させる結界を発動した");

    main();
  }
}

function special5(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 10) {

    TurnStart();
    document.bgColor = "#ffff00"; // 背景を黄色にする

    RandomMax = Math.floor(Math.random() * 11); // RandomMaxは、0から10の値をとる。
    if (RandomMax > 0) { // RandomMaxが0以外の時、
      RandomDamage = Math.floor(Math.random() * (RandomMax * stage + 1));
      // ランダムダメージの威力を決定
      HPenemy -= RandomDamage;
      $("#HPenemy").text("敵HP:" + HPenemy);
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵に " + RandomDamage + " のダメージを与えた");
      // ランダムダメージの威力だけダメ―ジを与える
    } else { // RandomMaxが0の時、敵は攻撃を回避する(0での剰余算を避ける)。
      $("#message1").text("ランダムダメージを与える攻撃!");
      $("#message2").text("敵は攻撃を回避した。");
    }

    main();
  } else {
    alert("中ボス戦・最終ボス戦では、この技を選択することができません。");
  }
}

function special6(){
  if (HPplayer > 0 && HPenemy > 0 && stage <= 100) {

    TurnStart();
    TypeChange = Math.floor(Math.random() * 2) + 1; // 1~2の変数
    TypePlayer = (TypePlayer + TypeChange) % 3; // 属性を変更する
    document.bgColor = TypeBackGroundColor[TypePlayer]; // 背景を属性の色にする

    $("#TypePlayer").css("color", TypeColor[TypePlayer]);
    $("#TypePlayer").text(TypeName[TypePlayer]);
    $("#message1").text("属性を" + TypeName[TypePlayer] + "に変更した。");

    main();
  }
}

// 通常攻撃
function two() { NormalAttack(2); }
function three() { NormalAttack(3); }

function five(){
  if (stage >= 3) {
    NormalAttack(5);
  } else {
    alert("ステージ数3未満では、この技を選択することができません。");
  }
}

function seven(){
  if (stage >= 5){
    NormalAttack(7);
  } else {
    alert("ステージ数5未満では、この技を選択することができません。");
  }
}

function eleven(){
  if (stage >= 50){
    NormalAttack(11);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirteen(){
  if (stage >= 50){
    NormalAttack(13);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function seventeen(){
  if (stage >= 50){
    NormalAttack(17);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function nineteen(){
  if (stage >= 50){
    NormalAttack(19);
  } else {
    alert("中ボス戦・最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentythree(){
  if (stage >= 100){
    NormalAttack(23);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function twentynine(){
  if (stage >= 100){
    NormalAttack(29);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

function thirtyone(){
  if (stage >= 100){
    NormalAttack(31);
  } else {
    alert("最終ボス戦以外では、この技を選択することができません。");
  }
}

// 最初から始める
function GameStart(){
  if ((HPplayer <= 0) || (stage == 100 && HPenemy <= 0)){
  // ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer = 10; // プレイヤーの初期HPへ
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

    TypeChangeEnemy();
    TypeChangePlayer();

  } else {
    alert("ゲームオーバー時または、全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

// 強くてニューゲーム
function NewGameStart(){
  if (stage == 100 && HPenemy <= 0){
  // 全てのステージクリア後にのみ、選択可能。

    $("#winlose").text("");
    ATKplayer = 0; // プレイヤーの攻撃力を初期化
    $("#ATKplayer").text("全蓄積エネルギー:" + ATKplayer);
    // 現在の全蓄積エネルギー
    PoisonCounter = 0; // ポイズンカウンターを0にする
    BarrierCounter = 0; // バリアカウンターを0にする

    stage = 1; // ステージ1へ
    HPenemy = 10; // 最初の敵へ
    HPplayer += 10; // クリア後のプレイヤーのHPに10を加算
    $("#stage").text("ステージ:" + stage);
    $("#HPenemy").text("敵HP:" + HPenemy);
    $("#HPplayer").text("HP:" + HPplayer);

    TypeChangeEnemy(); // 強くてニューゲームの場合は、敵のみ。

  } else {
    alert("全てのステージクリア後にのみ、選択可能。");
  }

  TurnStart();
  $("#winlose").css("color","#000000"); // 色を黒に戻す
  $("#ending").text("");
  $("#score").text("");
  $("#next").text("");
}

function TypeChangeEnemy(){
  TypeEnemy = Math.floor(Math.random() * 3);
  $("#TypeEnemy").css("color", TypeColor[TypeEnemy]);
  $("#TypeEnemy").text(TypeName[TypeEnemy]);
}

function TypeChangePlayer(){
  TypePlayer = Math.floor(Math.random() * 3);
  $("#TypePlayer").css("color", TypeColor[TypePlayer]);
  $("#TypePlayer").text(TypeName[TypePlayer]);
}

(解説) 第22講において、属性システムを導入したが、このままではただ単に属性が表示されるに過ぎない。
敵の属性とプレイヤーの属性の間には、次のような相性が存在する。
プレイヤー\敵 0:Feuer(火) 1:Eis(氷) 2:Donner(雷)
0:Feuer(火) 攻撃時:×1
防御時:×1
攻撃時:×0.5
防御時:×2
攻撃時:×2
防御時:×0.5
1:Eis(氷) 攻撃時:×2
防御時:×0.5
攻撃時:×1
防御時:×1
攻撃時:×0.5
防御時:×2
2:Donner(雷) 攻撃時:×0.5
防御時:×2
攻撃時:×2
防御時:×0.5
攻撃時:×1
防御時:×1
これを実装する際に、防御のとき、

TypeEffect = (TypeEnemy + 3 - TypePlayer) % 3;
として、攻撃のとき、
TypeEffect = (TypePlayer + 3 - TypeEnemy) % 3;
とすると、TypeEffectが0のとき互角、1のとき有利、2のとき不利、のようにswitch-case文を用いて、
表現することができる。逆に書くと、0のとき互角、1のとき不利、2のとき有利、となる。

このように、相性が戦闘に影響するので、プレイヤーの属性が変わらないと不利な戦いを強いられる。
そこで、特殊攻撃6として、プレイヤーの属性を変更する技を実装することになるのだが、
ただ単に、TypeChangePlayer()を利用すると、

TypePlayer = Math.floor(Math.random() * 3);
となって、現在の属性が変わらない、という可能性もある為、
TypeChange = Math.floor(Math.random() * 2) + 1;
TypePlayer = (TypePlayer + TypeChange) % 3;
として、1または2の乱数を加算して、3で割った剰余を求めることで、属性が必ず変更されるようにしている。
但し、属性を変更したターンも敵の攻撃を受けることになる為、通常はこちらが不利のときにのみ、この技は選択される。

また、技を発動するときの背景色を属性の色にしようとすると、特殊攻撃2が赤、特殊攻撃4が緑で重複してしまうので、
マゼンタ、シアン、ライムを指定したが、むしろ特殊攻撃2や特殊攻撃4の方を変更しても構わない。
HTMLサイドのmessage5とmessage6は、次回以降の変更の際に使用する予定。




Shadow Academy トップへ戻る

inserted by FC2 system