JavaScript Maniax

■RPGの戦闘シーンをつくる その1

オブジェクト指向プログラミングの応用。
シューティングゲームの項でオブジェクト指向プログラミングを学びました。
個人的にはシューティングゲームほどオブジェクト指向を理解しやすいものは無いと思っているため、新しいオブジェクト指向言語を覚える度にシューティングゲームっぽいものを作成しています。

さてオブジェクト指向になれてきたところで、今度はロールプレイングゲームの作成にはいりましょう。
といってもいきなりドラクエを作れといわれるとハードルが高すぎるので、まずは戦闘シーンを作成してみます。
この「RPGの戦闘シーン」もオブジェクト指向言語を学ぶ上で非常に参考になると思います。

まずはキャラクタのクラスを作成します。
最初ですので基本的なパラメータのみをもたせてみましょう。
//--sample--
function chara(a,b,c,d,e){
    this.hp=a;      //体力
    this.sp=b;      //速さ
    this.at=c;      //攻撃力
    this.df=d;      //防御力
    this.name=e;    //名前
}
//--sample--
引数をそのまま各パラメータに割り当てました。
キャラクタオブジェクトを作るには上記クラスを実装すればよいので、
enmy=new chara(50,20,40,40,"魔王");
といった記述をすると、
体力 :50
速さ :20
攻撃力:40
防御力:40
名前 :魔王
というキャラクタオブジェクトenmyが作成されます。

同じように、自分のキャラクタも作成してみたいとおもいます。
mych=new chara(20,20,30,30,"勇者");
魔王に比べて貧弱です。とても勇者と呼べるオブジェクトではありませんが、まぁ彼の成長を期待してとりあえずはこのまま進めたいと思います。

あとは、これらの引数を渡して攻防してくれる関数を作れば、単純な戦闘シーンは完成してしまいます。
ひとまず以下のような関数を作成してみました。
//--sample--
function attack(at, df){
    var a,d,s,p,m,r;
    r=true;
    m=at.name+"の攻撃⇒";
    //スピード計算
    s=Math.floor(Math.random()*(at.sp+df.sp));
    if(s<(df.sp/2)){
        //メッセージ作成
        m+=df.name+"はすばやく身をかわした。";
    }else{
        //ダメージ計算
        a=Math.floor(Math.random()*(at.at*0.4))+Math.floor(at.at*0.8);
        d=Math.floor(Math.random()*(df.df*0.4))+Math.floor(df.df*0.8);
        p=a-d;
        //まぐれ当たりも考慮
        if(p<1)p=Math.floor(Math.random()*4);
        //メッセージ作成
        if(p>0){
            m+=df.name+"に"+p+"ポイントのダメージを与えた。";
            df.hp-=p;
            if(df.hp<1){
                //戦闘終了
                m+="<BR><FONT color=\"red\">"+at.name+"の勝利!(残り体力"+at.hp+")。</FONT>";
                r=false;
            }
        }else{
            m+=df.name+"にダメージを与えられない!";
        }
    }
    m+="<BR>";
    document.all.t.innerHTML+=m;
    return r;
}
//--sample--
引数には攻撃側のオブジェクトと防御側のオブジェクトを渡し、結果を画面に表示します。
また攻撃によって相手が死んだ場合に返値としてfalseを返しますので、呼び出し側は
この関数をfalseになるまで呼び続けることになります。
もちろん各パラメータによるダメージ計算こそRPGプログラミングの醍醐味です。
上記は参考までにご覧下さい。
プログラム的にはこれまでの講座に出てきた技術ばかりです。
//--sample--
flg=true;
while(flg){
    flg=attack(mych, enmy)
    if(flg){
        flg=attack(enmy, mych)
    }
}
//--sample--
これで交互に攻撃が行われます。

[
sample-a] [DL]

まだ特殊攻撃もアイテムも防御もありません。一対一の対決は、どちらかが死ぬまで交互に攻撃をつづけるオートバトルですが、戦闘シーンの基本ができました。



応用編

上記で作成したsampleは完全に乱数によって結果がきまってしまうのでゲーム性がありません。
タコ殴りにされる勇者があまりに不憫です。
そこで、勇者のパラメータを自由に変更できるようにしてみましょう。
画面上にフォーム部品を用意し、その値を各パラメータに登録すればOKです。
//--sample--
val[0]=document.f.t0.value-0;
val[1]=document.f.t1.value-0;
val[2]=document.f.t2.value-0;
val[3]=document.f.t3.value-0;
mych=new chara(val[0],val[1],val[2],val[3],"勇者");
//--sample--
各値から0を引いているのは、「この値は数値です」と明示的に示すときに使われる常套句です。
逆に文字列であることを明示したい場合は
val[0]=document.f.t0.value+"";
というように記載します。

ここで注意しなければならないのは各入力値のチェックです。
計算できない値が入力されては困りますし、余り大きな値や小さな値を入力可にしてしまってはやはりゲーム性がありません。
そこで、
・合計が100以下であること
・0未満の数値がないこと
・体力は1以上であること
を条件に加えました。
//--sample--
if(val[0]+val[1]+val[2]+val[3]>100){
    alert("入力値が不正です\n半角数字で合計100以下になるよう入力してください。")
}else if(val[0]<0||val[1]<0||val[2]<0||val[3]<0){
    alert("入力値が不正です\n半角数字で正の整数を入力してください。")
}else if(val[0]<1){
    alert("入力値が不正です\n体力は1以上の値を入れてください。")
}
//--sample--
たったこれだけでゲーム性がでてきました。
まだ特殊攻撃など作成していないのでオートバトルですし、勇者が貧弱なのは変わりないですが、ひとまず遊ぶことはできるようになりました。

[sample-b] [DL]
[top] [index]
トップメニュー 基礎編 実践編 外部リンク