ポケモンの属性の違いによるダメージ計算方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
POC

ポケモンの属性の違いによるダメージ計算方法

#1

投稿記事 by POC » 16年前

はじめまして。
勉強ついでにゲームを作ってるPOCといいます。
この掲示板で、s-rushさんがポケモンのゲームを作っているようなのですが、
実は僕自身も同じ物を作ってるんです。

そこで、ダメージ計算時の弱点、効果はいまいち、効果なしといった
追加効果?の判別する関数を作ろうとしているのですが、できません。

本当にすいませんが、どなたか作ってもらえないでしょうか?
アルゴリズムとか今後の参考にしたいので。

開発環境は
VC++2008 EEです。
よろしくお願いします。

(1/6 18:30 管理人によりタイトル変更しました)

バグ

Re:無題

#2

投稿記事 by バグ » 16年前

せめて、属性ごとの相性とかダメージ計算式の仕様くらいは自分で考えるべきだと思いますよ。

lbfuvab

Re:無題

#3

投稿記事 by lbfuvab » 16年前

ファイナルファンタジー等の攻略サイトによくダメージ計算式が載っていますので参考にされてはいかがでしょうか?

s-rush

Re:無題

#4

投稿記事 by s-rush » 16年前

おっ、仲間発見。
と言いたいところですが、他の方がおっしゃる通り、仕様を考えるべきですよ。
いきなり
「教えてください」
と言われても、中にはポケモンのゲームを知らない方もいらっしゃるはずですよ。

私みたいにまんまパクリでよければ参考にどうぞ
/*==================================================
タイプの対応表
無し  :0  ノーマル:1  ほのお :2 
みず  :3  でんき :4  くさ  :5 
こおり :6  かくとう:7  どく  :8 
じめん :9  ひこう :10 エスパー:11 
むし  :12 いわ  :13 ゴースト:14 
ドラゴン:15 あく  :16 はがね :17
===================================================*/

/*==================================================
弱点の対応表
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  ---------------------------------------------
1| 2 2 2 2 2 2 2 2 2 2  2  2  1  0  2  2  1 
2| 2 1 1 2 3 3 2 2 2 2  2  3  1  2  1  2  3
3| 2 3 1 2 1 2 2 2 3 2  2  2  3  2  1  2  2
4| 2 2 3 1 1 2 2 2 0 3  2  2  2  2  1  2  2
5| 2 1 3 2 1 2 2 1 3 1  2  1  3  2  1  2  1
6| 2 1 1 2 3 1 2 2 3 3  2  2  2  2  3  2  1
7| 3 2 2 2 2 3 2 1 2 1  1  1  3  0  2  3  3
8| 2 2 2 2 3 2 2 1 1 2  2  2  1  1  2  2  0
9| 2 3 2 3 1 2 2 3 2 0  2  1  3  2  2  2  3
10| 2 2 2 1 3 2 3 2 2 2  2  3  1  2  2  2  1
11| 2 2 2 2 2 2 3 3 2 2  1  2  2  2  2  0  1
12| 2 1 2 2 3 2 1 1 2 1  3  2  2  1  2  3  1
13| 2 3 2 2 2 3 1 2 1 3  2  3  2  2  2  2  1
14| 0 2 2 2 2 2 2 2 2 2  3  2  2  3  2  1  1
15| 2 2 2 2 2 2 2 2 2 2  2  2  2  2  3  2  1
16| 2 2 2 2 2 2 1 2 2 2  3  2  2  3  2  1  1
17| 2 1 1 1 2 3 2 2 2 2  2  2  3  2  2  2  1

効果は抜群   :3 普通   :2
効果はいまひとつ:1 効果が無い:0
===================================================*/

===================================================*/
ダメージ倍率
効果は抜群    ×2
普通       ×1
効果はいまひとつ ×0.5
効果がない    ×0
===================================================*/


float relation(int attck_type1, int attck_type2, int deffenc_type1, int deffenc_type2)
{
	float relation = 1;    //ダメージ倍率

	switch attak_type1{
	cace 1:  if(deffenc_type1 == 1)
	            relation = relation*1;
	         else if(deffenc_type1 == 2)
	            relation = relation*1;
	         else if(deffenc_type1 == 3)
	            relation = relation*1;
--------------以下省略-------------------
==========================================
同様にcace2~cace17についても
==========================================

	}
	return relation;
}
まだコンパイルしてないので、エラーがあるかもしれませんが、考え方の1つとしては
こんなものでいいでしょう。

全部の関係を列挙するのが面倒であれば、ダメージ倍率が変わるものだけを書き出してあげて、
それ以外であれば倍率を変えないように制御してあげれば大丈夫です。
これくらいは自分で考えてみましょう。


かなり力技って感じですが、他の方ならどういう風にプログラム書きますか?
私はまだ未熟なものでこれくらいのアルゴリズムしか思い浮かびませんでしたorz

Dixq (管理人)

Re:無題

#5

投稿記事 by Dixq (管理人) » 16年前

ポケモンは小学校の時に遊んで以来なので、よく覚えていませんが、
確か属性管理がややこしいですよね!

ちと
http://pokemon-xd.info/pokexd_begin1.html
こちらのデータを使わせてもらってダメージ計算を行ってみましょう。

簡単にする為に、

なし→通常ダメージ
× →ダメージ0
△ →1/2のダメージ
◎ →2倍のダメージ

こんな感じで対応させて見ます。

リンク先の表を数字に置き換えたものがこちらです。

2,2,2,2,2,2,2,2,2,2,2,2,1,0,2,2,1
2,1,1,2,4,4,2,2,2,2,2,4,1,2,1,2,4
2,4,1,2,1,2,2,2,4,2,2,2,4,2,1,2,2
2,2,4,1,1,2,2,2,0,4,2,2,2,2,1,2,2
2,1,4,2,1,2,2,1,4,1,2,1,4,2,1,2,1
2,1,1,2,4,1,2,2,4,4,2,2,2,2,4,2,1
4,2,2,2,2,4,2,1,2,1,1,1,4,0,2,4,4
2,2,2,2,4,2,2,1,1,2,2,2,1,1,2,2,0
2,4,2,4,1,2,2,4,2,0,2,1,4,2,2,2,4
2,2,2,1,4,2,4,2,2,2,2,4,1,2,2,2,1
2,2,2,2,2,2,4,4,2,2,1,2,2,2,2,0,1
2,1,2,2,4,2,1,1,2,1,4,2,2,1,2,4,1
2,4,2,2,2,4,1,2,1,4,2,4,2,2,2,2,1
0,2,2,2,2,2,2,2,2,2,4,2,2,4,2,1,1
2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,1
2,2,2,2,2,2,1,2,2,2,4,2,2,4,2,1,1
2,1,1,1,2,4,2,2,2,2,2,2,4,2,2,2,1

こういうのはエクセルで表を作り、ファイルから読み取ってやるともっと楽だと思います。
2というのが通常ダメージです。
サンプルでは通常だと100のダメージを食らう計算にしてあります。

Zキーを押しながら上下キーを押すと攻撃側の属性が変更でき、
Xキーを押しながら上下キーを押すと受け側の属性が変更できます。

エンターを押すと計算結果を表示します。

→続く

Dixq (管理人)

Re:無題

#6

投稿記事 by Dixq (管理人) » 16年前

→続き


#include "DxLib.h"

typedef struct{
    int 属性;
}キャラデータ_t;

int Key[256];

キャラデータ_t キャラデータ[2];

int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[/url]){
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );
    for(int i=0;i<256;i++){
        if(GetHitKeyStateAll_Key==1) GetHitKeyStateAll_InputKey++;
        else                            GetHitKeyStateAll_InputKey=0;
    }
    return 0;
}

int 属性[17][17]=
{
    {2,2,2,2,2,2,2,2,2,2,2,2,1,0,2,2,1},
    {2,1,1,2,4,4,2,2,2,2,2,4,1,2,1,2,4},
    {2,4,1,2,1,2,2,2,4,2,2,2,4,2,1,2,2},
    {2,2,4,1,1,2,2,2,0,4,2,2,2,2,1,2,2},
    {2,1,4,2,1,2,2,1,4,1,2,1,4,2,1,2,1},
    {2,1,1,2,4,1,2,2,4,4,2,2,2,2,4,2,1},
    {4,2,2,2,2,4,2,1,2,1,1,1,4,0,2,4,4},
    {2,2,2,2,4,2,2,1,1,2,2,2,1,1,2,2,0},
    {2,4,2,4,1,2,2,4,2,0,2,1,4,2,2,2,4},
    {2,2,2,1,4,2,4,2,2,2,2,4,1,2,2,2,1},
    {2,2,2,2,2,2,4,4,2,2,1,2,2,2,2,0,1},
    {2,1,2,2,4,2,1,1,2,1,4,2,2,1,2,4,1},
    {2,4,2,2,2,4,1,2,1,4,2,4,2,2,2,2,1},
    {0,2,2,2,2,2,2,2,2,2,4,2,2,4,2,1,1},
    {2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,1},
    {2,2,2,2,2,2,1,2,2,2,4,2,2,4,2,1,1},
    {2,1,1,1,2,4,2,2,2,2,2,2,4,2,2,2,1}
};

char 属性の名前[17][32]={
    {"ノーマル"},
    {"炎   "},
    {"水   "},
    {"電気  "},
    {"草   "},
    {"氷   "},
    {"格闘  "},
    {"毒   "},
    {"地面  "},
    {"飛行  "},
    {"エスパー"},
    {"虫   "},
    {"岩   "},
    {"ゴースト"},
    {"ドラゴン"},
    {"悪   "},
    {"ハガネ "}
};

int ダメージ計算(int 属性1, int 属性2){
    return 50*属性[属性1][属性2];
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない

        if(Key[KEY_INPUT_Z]>0 && Key[KEY_INPUT_UP]==2){
            キャラデータ[0].属性 = (++キャラデータ[0].属性)%17;
        }
        if(Key[KEY_INPUT_Z]>0 && Key[KEY_INPUT_DOWN]==2){
            キャラデータ[0].属性 = --キャラデータ[0].属性;
            if(キャラデータ[0].属性<0)
                キャラデータ[0].属性=16;
        }
        if(Key[KEY_INPUT_X]>0 && Key[KEY_INPUT_UP]==2){
            キャラデータ[1].属性 = (++キャラデータ[1].属性)%17;
        }
        if(Key[KEY_INPUT_X]>0 && Key[KEY_INPUT_DOWN]==2){
            キャラデータ[1].属性 = --キャラデータ[1].属性;
            if(キャラデータ[1].属性<0)
                キャラデータ[1].属性=16;
        }
        if(Key[KEY_INPUT_RETURN]==2){
            int ダメージ = ダメージ計算(キャラデータ[0].属性,キャラデータ[1].属性);
            printfDx("%s から %s への攻撃!→%dのダメージ\n",属性の名前[キャラデータ[0].属性],属性の名前[キャラデータ[1].属性],ダメージ);
        }

        DrawFormatString(450, 0,GetColor(255,255,255),"攻撃側属性:%s",属性の名前[キャラデータ[0].属性]);
        DrawFormatString(450,17,GetColor(255,255,255),"  Zキー+上下キー");
        DrawFormatString(450,40,GetColor(255,255,255),"受け側属性:%s",属性の名前[キャラデータ[1].属性]);
        DrawFormatString(450,57,GetColor(255,255,255),"  Xキー+上下キー");
        DrawFormatString(450,80,GetColor(255,255,255),"エンターで攻撃!");

        for(int i=0;i<17;i++){
            DrawFormatString(450,150+17*i,GetColor(255,255,255),"%s",属性の名前);
        }

        ScreenFlip();
    }

    DxLib_End();
    return 0;
}

実行結果例

画像


攻撃力や防御力はまぁ適当に計算してやって下さい。

Dixq (管理人)

Re:無題

#7

投稿記事 by Dixq (管理人) » 16年前

う、のんびりやってたら被ってしまった^^;

s-rushさん、対応表もプレタグで囲むといいですよ☆

s-rush

Re:無題

#8

投稿記事 by s-rush » 16年前

うわっ!
すごい・・・
私の作ってみたサンプルとレベルが違いすぎる。

まだまだ勉強しないといけないなぁ・・・
やっぱりゲームを作るにはこれくらいのプログラムを理解できないと
厳しいですかね?

私も似たようなことやってるので、参考にさせていただきます^^

雑談の横槍すみませんでしたm(_ _)m

PS
管理人さんとアドバイス通り対応表もプレタブで囲んでおきました。

Dixq (管理人)

Re:無題

#9

投稿記事 by Dixq (管理人) » 16年前

>やっぱりゲームを作るにはこれくらいのプログラムを理解できないと厳しいですかね?

どこか解りにくいところありました?
極力解り易く書いたつもりなのですが・・><

解り易くする為にあえて全角で変数とかつけたんですが、逆にわかりにくかったですかね・・。
一応この全角のままコンパイル出来るんで、よければ実行してみて下さいm(_ _)m

プログラムは毎回書く骨格
http://dixq.net/g/#41

に必要な処理を付け足しただけです。
どの辺がわかりにくいかもしよかったら教えてもらえませんか?

かなり長くなってしまいましたけど、結局一番言いたかったのはこのように作ると

ダメージを計算する関数が
int ダメージ計算(int 属性1, int 属性2){

    return 50*属性[属性1][属性2];

}
たったこれだけで済みそうです。ってことです。
ちなみに攻撃側と受け側が反対になるときは

属性[属性1][属性2] → 属性[属性2][属性1]

でいいと思います。
きっとホントはもっと複雑になるんでしょうけど・・。

対応表は出来れば外部ファイルから読み込んだ方がいいと思います。
エクセルで作って「csv」って拡張子で保存すれば、
プログラムで簡単に扱えるのでオススメです。

s-rush

Re:無題

#10

投稿記事 by s-rush » 16年前

全角はあえてそうしてたんですね^^;
プログラム中に何故全角表記があるのかなって思ったので。
全角のままコンパイルできるとは知りませんでした。

あと、エクセルもそうですが、外部ファイルからの読み込みもわからなかったので。

私自身DXライブラリの知識不足もあるのですが。

ともあれ私よりもスレ主であるPOCさんが理解できれば問題ないので気にしないでください。

Dixq (管理人)

Re:無題

#11

投稿記事 by Dixq (管理人) » 16年前

ありがとうございます。今後回答するときの参考にしますm(_ _)m

全角はパッと見わかりやすくていいんですが、コンパイル出来るかどうかは環境に依存しますし、
プロの現場では恐らく使われていないですし、「使えるけど使わない」ことが多いですよね。

それに単純には全てを全角には出来ないので、イチイチ全角と半角の入力状態を変えないといけないのも面倒です。
・・と言う事で、やはり使う意味無し・・ですね^^;

エクセルからの読み込みは簡単です。
エクセルで何か表を書き「cvs」形式で保存してみて下さい。
そしてテキストエディタで開いてみて下さい。
データがどのように入ってるか解ると思います。

セルの区切りがカンマになるんですね。

まずfopenでファイルをオープンします。
カンマか改行が現れるまで一文字ずつ取ってきて文字列に入れていきましょう。
カンマか改行が現れたらそこで文字列の格納をやめ、終端記号を入れてやります。
その文字列をatoiという文字列から数値に変換する関数を使ってint型の数値に変換してやります。

こうすることで、エクセルで作った整数を読み込むことが出来ます。

解らない事があればググりながらやってみると案外簡単に実装出来ると思います。
もし興味があればやってみて下さい。

s-rush

Re:無題

#12

投稿記事 by s-rush » 16年前

そんなやり方もあったんですね。
知りませんでした。

確かにエクセルを使用した方が、効率よく作業できますよね。

ちなみにワードでも同じようにできますよね。
拡張子は変わりそうですけど・・・


ちょっと調べてみます。

POC

Re:無題

#13

投稿記事 by POC » 16年前

みなさんありがとうございます。

面倒ついでにもう1つお願いしたいのですが・・・

フィールドマップはどうやってつくればいいんでしょうか?
読み込みとかスクロールのやりかたも分からないのでよろしくお願いします。

SCI

Re:無題

#14

投稿記事 by SCI » 16年前

全角コンパイルについて補足。

2バイト文字で構成される識別子が許されているのはVC++固有だった気がします。
C#では言語でサポートされていた気がしますが・・・
少なくとも、BCC5.5.1は2バイト文字の識別子を認識してくれないので(笑)

御津凪

Re:無題

#15

投稿記事 by 御津凪 » 16年前

> フィールドマップはどうやってつくればいいんでしょうか?
> 読み込みとかスクロールのやりかたも分からないのでよろしくお願いします。

過去ログにも似た質問がありましたが、マップも上記のようなエクセルを利用した方法で
マップをエクセルに書いて作ることが出来ます。

とは言うものの、マップを作るのに番号とにらめっこでは無駄な時間がかかります。
汎用マップエディタのようなものがネット上でちらほら見かけるので、
そちらを使ってみるという手もあります。

詳しいことは過去ログを見るか、他の方の回答を待つか、検索してみてください。

s-rush

Re:無題

#16

投稿記事 by s-rush » 16年前

マップの作り方ですね。
以前私も同じ質問をさせていただきました。

まだマップそのものは制作中ですが、回答してくださった方々のアドバイスを参考にしてます。
過去ログで
”マップ” ”作り方”
あたりで検索していただければ引っかかると思います。

閉鎖

“C言語何でも質問掲示板” へ戻る