メタルスラッグにおけるヘヴィマシンガン

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

メタルスラッグにおけるヘヴィマシンガン

#1

投稿記事 by KEYONN_ » 15年前

現在、メタルスラッグのようなゲームを1人(TKOZ)だけで製作しています。(無謀w)
そこで躓いた(つまずいた)のが、ヘヴィマシンガンの実装の仕方です。

現在、作っているゲームでは、Zキーを押した時に、矢印キーの方向を調べて、角度に変換して
その方向に弾を連続発射させています。

しかし、それでは、0°、45°、90°、135°、180°、225°、270°、315°だけしか、
決まった角度しか弾がばら撒け(ばらまけ)ません。

どうしたら、メタルスラッグのように弾が滑らか(なめらか)にばら撒けるか分かりません。

誰か、どうしたら、メタルスラッグのように弾が滑らかに飛ぶか教えてください。

softya

Re:メタルスラッグにおけるヘヴィマシンガン

#2

投稿記事 by softya » 15年前

それは、間のモーションが無いからでしょう。
メタルスラッグ(プレイしたことは無いんですが)は、例えば横から上にキーを入れたとき間の角度のモーションがあります。0°、22.5°、45°、67.5°、90°とモーションすれば良いと思います。

TKOZさんの技術力を把握しきれておりませんので、とりあえずヒントだけ。

KEYONN_

Re:メタルスラッグにおけるヘヴィマシンガン

#3

投稿記事 by KEYONN_ » 15年前

とりあえず、コーディングしてみたのですが、バグが出来てしまいました。

テーブルを参照する形にしたのですが、上手くいきませんでした。
どう上手くいかなかったかというと、逆に斜め方向が飛ばなくなったばかりか、
上下左右しか弾が飛ばなくなりました。

int smooth(int i,int j,int count)
{
//up:0 down:1 left:2 right:3

/*
00,01,02,03
10,11,12,13
20,21,22,23
30,31,32,33
*/
float Table[16][4]={
{90,90,90,90},{90,90-22.5,90-22.5*2,90-22.5*3},{90,120,150,180},{90,60,30,0},
{270,200,150,90},{270,270,270,270},{270,240,210,180},{270,300,330,0},
{180,150,120,90},{180,210,240,270},{180,180,180,180},{180,120,60,0},
{0,30,60,90},{0,330,300,270},{0,60,120,180},{0,0,0,0}
};

return Table[i+j*4][count];

}

int SmoothAngle()
{
static int prevkey[4]={0};
static int angle=0;
static int count[4][4]={0};
static int count2[4][4]={0};
int up[4]={0};

int i,j;

up[0]=CheckHitKey(KEY_INPUT_UP);
up[1]=CheckHitKey(KEY_INPUT_DOWN);
up[2]=CheckHitKey(KEY_INPUT_LEFT);
up[3]=CheckHitKey(KEY_INPUT_RIGHT);


//前回キーがXXXで、今回キーがXXXだったら
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(!prevkey && up[j])
{
return smooth(i,j,count2[j]);
}else if(!prevkey && !up[j])
{
count2[j]=0;
}
count[j]++;
if(count[j]>7)
{
count2[j]++;
if(count2[j]>3)count2[j]=3;
count[j]=0;
}
}
}

prevkey[0]=CheckHitKey(KEY_INPUT_UP);
prevkey[1]=CheckHitKey(KEY_INPUT_DOWN);
prevkey[2]=CheckHitKey(KEY_INPUT_LEFT);
prevkey[3]=CheckHitKey(KEY_INPUT_RIGHT);


return angle;
}

これらの関数を
メインループで
angle2=SmoothAngle();

CreateBullet(Player.x,Player.y+10,0,20,angle2);
として呼び出しています。 画像

Justy

Re:メタルスラッグにおけるヘヴィマシンガン

#4

投稿記事 by Justy » 15年前

 テーブルじゃなくても実際に発射する角度と目標の角度を分けて、矢印キーによって変更するのは目標の角度にし
実際に発射する角度を目標の角度に近づくよう毎フレーム補完する、でいいような。

 例えば真横(90度)に打っていて、上が押されたら目標角度を&#160;0度にして、
実際に発射する角度も90→0になるよう補完すれば滑らかにばらまけるかと。

softya

Re:メタルスラッグにおけるヘヴィマシンガン

#5

投稿記事 by softya » 15年前

仕組みを簡単に説明します。
まず、キーで決まる発射方向があると思います。
あと、今の銃の向いている方向です。
この2つは、連動しますがタイミングは銃の方向が遅れてついてきます。
キー入力がない場合は、最後のキーで決まる発射方向を維持します。
角度は度で持つと誤差が生じるので方向番号として持ちます。

(1)キーで決まる発射方向を変更する。キー入力がなければそのまま。キーの方向番号を決定。
(2)今の銃の方向番号とキーの方向番号がずれていれば、方向番号を1づつ加算又は減算する。
ただし、方向番号の差が90度を超える場合は瞬間的に振り向いた方が良いでしょう。

プログラムは何故か再帰を使っていたりして追いかけるのが大変そうなので見てません。

KEYONN_

Re:メタルスラッグにおけるヘヴィマシンガン

#6

投稿記事 by KEYONN_ » 15年前

float SmoothAngle(int TargetAngle,int Add)
{
static float angle=0;
static float angle2;
static int count=0;
static int count2=0;
static int TargetNumber=0;


switch(TargetAngle)
{
case 0:
TargetNumber=0;
break;
case 45:
TargetNumber=1;
break;
case 90:
TargetNumber=2;
break;
case 135:
TargetNumber=3;
break;
case 180:
TargetNumber=4;
break;
case 225:
TargetNumber=5;
break;
case 270:
TargetNumber=6;
break;
case 315:
TargetNumber=7;
break;
}

if(fabs(TargetNumber-angle)>2.0)
TargetNumber=angle;
if(TargetNumber>angle)
{
angle+=0.1;
}else if(angle<TargetNumber){
angle-=0.1;
}

angle2=angle*45.0;


return angle2;
}

こうなりましたが、バグが出てしまいます。
具体的には、DrawFormatStringで確認したのですが、TargetNumberの値が下がりません。

しかし、処理的には上手くいきましたよ。何がいけなかったのでしょうか? 画像

KEYONN_

Re:メタルスラッグにおけるヘヴィマシンガン

#7

投稿記事 by KEYONN_ » 15年前

結局、Justyさんとsoftyaさんの両方の特徴を使ったアルゴリズムになりました。

softyaさんの
>ただし、方向番号の差が90度を超える場合は瞬間的に振り向いた方が良いでしょう。

Justyさんの
>テーブルじゃなくても実際に発射する角度と目標の角度を分けて、矢印キーによって変更するのは
>目標の角度にし
>実際に発射する角度を目標の角度に近づくよう毎フレーム補完する、でいいような。

>例えば真横(90度)に打っていて、上が押されたら目標角度を 0度にして、
>実際に発射する角度も90→0になるよう補完すれば滑らかにばらまけるかと。

int SmoothAngle(int TargetAngle,int Add)
{
static int Angle=0;
int Angle2;

if(Angle<TargetAngle)
{
if(TargetAngle>Angle)
{
Angle+=Add;
}
if(TargetAngle-Angle>90)
Angle=TargetAngle;
}
else if(TargetAngle<Angle)
{
Angle-=Add;
if(Angle>TargetAngle)
{
Angle-=Add;
}
if(Angle-TargetAngle>90)
Angle=TargetAngle;
}
if(Player.muki==LEFT && TargetAngle==-1)
return 180;


Angle2=Angle;

return Angle2;
}

ありがとうございました。解決です。

閉鎖

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