ポケモンの属性の違いによるダメージ計算方法
-
POC
ポケモンの属性の違いによるダメージ計算方法
はじめまして。
勉強ついでにゲームを作ってるPOCといいます。
この掲示板で、s-rushさんがポケモンのゲームを作っているようなのですが、
実は僕自身も同じ物を作ってるんです。
そこで、ダメージ計算時の弱点、効果はいまいち、効果なしといった
追加効果?の判別する関数を作ろうとしているのですが、できません。
本当にすいませんが、どなたか作ってもらえないでしょうか?
アルゴリズムとか今後の参考にしたいので。
開発環境は
VC++2008 EEです。
よろしくお願いします。
(1/6 18:30 管理人によりタイトル変更しました)
勉強ついでにゲームを作ってるPOCといいます。
この掲示板で、s-rushさんがポケモンのゲームを作っているようなのですが、
実は僕自身も同じ物を作ってるんです。
そこで、ダメージ計算時の弱点、効果はいまいち、効果なしといった
追加効果?の判別する関数を作ろうとしているのですが、できません。
本当にすいませんが、どなたか作ってもらえないでしょうか?
アルゴリズムとか今後の参考にしたいので。
開発環境は
VC++2008 EEです。
よろしくお願いします。
(1/6 18:30 管理人によりタイトル変更しました)
-
s-rush
Re:無題
おっ、仲間発見。
と言いたいところですが、他の方がおっしゃる通り、仕様を考えるべきですよ。
いきなり
「教えてください」
と言われても、中にはポケモンのゲームを知らない方もいらっしゃるはずですよ。
私みたいにまんまパクリでよければ参考にどうぞ
こんなものでいいでしょう。
全部の関係を列挙するのが面倒であれば、ダメージ倍率が変わるものだけを書き出してあげて、
それ以外であれば倍率を変えないように制御してあげれば大丈夫です。
これくらいは自分で考えてみましょう。
かなり力技って感じですが、他の方ならどういう風にプログラム書きますか?
私はまだ未熟なものでこれくらいのアルゴリズムしか思い浮かびませんでしたorz
と言いたいところですが、他の方がおっしゃる通り、仕様を考えるべきですよ。
いきなり
「教えてください」
と言われても、中にはポケモンのゲームを知らない方もいらっしゃるはずですよ。
私みたいにまんまパクリでよければ参考にどうぞ
/*==================================================
タイプの対応表
無し :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:無題
ポケモンは小学校の時に遊んで以来なので、よく覚えていませんが、 確か属性管理がややこしいですよね! ちと 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:無題
→続き
#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:無題
>やっぱりゲームを作るにはこれくらいのプログラムを理解できないと厳しいですかね?
どこか解りにくいところありました?
極力解り易く書いたつもりなのですが・・><
解り易くする為にあえて全角で変数とかつけたんですが、逆にわかりにくかったですかね・・。
一応この全角のままコンパイル出来るんで、よければ実行してみて下さいm(_ _)m
プログラムは毎回書く骨格
http://dixq.net/g/#41
に必要な処理を付け足しただけです。
どの辺がわかりにくいかもしよかったら教えてもらえませんか?
かなり長くなってしまいましたけど、結局一番言いたかったのはこのように作ると
ダメージを計算する関数が
ちなみに攻撃側と受け側が反対になるときは
属性[属性1][属性2] → 属性[属性2][属性1]
でいいと思います。
きっとホントはもっと複雑になるんでしょうけど・・。
対応表は出来れば外部ファイルから読み込んだ方がいいと思います。
エクセルで作って「csv」って拡張子で保存すれば、
プログラムで簡単に扱えるのでオススメです。
どこか解りにくいところありました?
極力解り易く書いたつもりなのですが・・><
解り易くする為にあえて全角で変数とかつけたんですが、逆にわかりにくかったですかね・・。
一応この全角のままコンパイル出来るんで、よければ実行してみて下さいm(_ _)m
プログラムは毎回書く骨格
http://dixq.net/g/#41
に必要な処理を付け足しただけです。
どの辺がわかりにくいかもしよかったら教えてもらえませんか?
かなり長くなってしまいましたけど、結局一番言いたかったのはこのように作ると
ダメージを計算する関数が
int ダメージ計算(int 属性1, int 属性2){
return 50*属性[属性1][属性2];
}
たったこれだけで済みそうです。ってことです。ちなみに攻撃側と受け側が反対になるときは
属性[属性1][属性2] → 属性[属性2][属性1]
でいいと思います。
きっとホントはもっと複雑になるんでしょうけど・・。
対応表は出来れば外部ファイルから読み込んだ方がいいと思います。
エクセルで作って「csv」って拡張子で保存すれば、
プログラムで簡単に扱えるのでオススメです。
-
Dixq (管理人)
Re:無題
ありがとうございます。今後回答するときの参考にしますm(_ _)m
全角はパッと見わかりやすくていいんですが、コンパイル出来るかどうかは環境に依存しますし、
プロの現場では恐らく使われていないですし、「使えるけど使わない」ことが多いですよね。
それに単純には全てを全角には出来ないので、イチイチ全角と半角の入力状態を変えないといけないのも面倒です。
・・と言う事で、やはり使う意味無し・・ですね^^;
エクセルからの読み込みは簡単です。
エクセルで何か表を書き「cvs」形式で保存してみて下さい。
そしてテキストエディタで開いてみて下さい。
データがどのように入ってるか解ると思います。
セルの区切りがカンマになるんですね。
まずfopenでファイルをオープンします。
カンマか改行が現れるまで一文字ずつ取ってきて文字列に入れていきましょう。
カンマか改行が現れたらそこで文字列の格納をやめ、終端記号を入れてやります。
その文字列をatoiという文字列から数値に変換する関数を使ってint型の数値に変換してやります。
こうすることで、エクセルで作った整数を読み込むことが出来ます。
解らない事があればググりながらやってみると案外簡単に実装出来ると思います。
もし興味があればやってみて下さい。
全角はパッと見わかりやすくていいんですが、コンパイル出来るかどうかは環境に依存しますし、
プロの現場では恐らく使われていないですし、「使えるけど使わない」ことが多いですよね。
それに単純には全てを全角には出来ないので、イチイチ全角と半角の入力状態を変えないといけないのも面倒です。
・・と言う事で、やはり使う意味無し・・ですね^^;
エクセルからの読み込みは簡単です。
エクセルで何か表を書き「cvs」形式で保存してみて下さい。
そしてテキストエディタで開いてみて下さい。
データがどのように入ってるか解ると思います。
セルの区切りがカンマになるんですね。
まずfopenでファイルをオープンします。
カンマか改行が現れるまで一文字ずつ取ってきて文字列に入れていきましょう。
カンマか改行が現れたらそこで文字列の格納をやめ、終端記号を入れてやります。
その文字列をatoiという文字列から数値に変換する関数を使ってint型の数値に変換してやります。
こうすることで、エクセルで作った整数を読み込むことが出来ます。
解らない事があればググりながらやってみると案外簡単に実装出来ると思います。
もし興味があればやってみて下さい。