野球ゲームの変化球の軌道について
Posted: 2013年4月13日(土) 21:53
野球ゲームでの変化球の軌道についての質問です。
現在、変化球の実装を試みているのですがゲームをするに当たって支障は無いのですが
少しボールの挙動が変なので質問させていただきました。
どのように変なのかと言いますと現在ボールの挙動はあらかじめボールの終着点であるBallXENDとBallYEND
を乱数で決めてそこにボールの座標とのラジアンをatan2でとりsinとcosでを使ってボールの座標であるBallX,BallYを増加させて
いるのですがストレートを投げる分にはそれでいいのですが横に変化するようなボールを投げた時にBallXENDとBallYEND
を通りすぎると急に軌道がストレートに変わってしまいます。(言葉だけではちょっと伝えにくいのでgifをつけました^^;)
恐らくラジアンが0に近づくために起きると思っているのですがどうすればいいかわかりません。どうかよろしくお願いします。

以下野球部分のソースとボール部分のソース
ボール
現在、変化球の実装を試みているのですがゲームをするに当たって支障は無いのですが
少しボールの挙動が変なので質問させていただきました。
どのように変なのかと言いますと現在ボールの挙動はあらかじめボールの終着点であるBallXENDとBallYEND
を乱数で決めてそこにボールの座標とのラジアンをatan2でとりsinとcosでを使ってボールの座標であるBallX,BallYを増加させて
いるのですがストレートを投げる分にはそれでいいのですが横に変化するようなボールを投げた時にBallXENDとBallYEND
を通りすぎると急に軌道がストレートに変わってしまいます。(言葉だけではちょっと伝えにくいのでgifをつけました^^;)
恐らくラジアンが0に近づくために起きると思っているのですがどうすればいいかわかりません。どうかよろしくお願いします。

以下野球部分のソースとボール部分のソース
/*yakyuu*/
#include<DxLib.h>
#include<math.h>
#include<time.h>
#include"grand.h"
#include"keybord.h"
#include"player.h"
#include"ball.h"
#define PAI 3.1415926535897932384//円周率
//プロトタイプ宣言
bool CollisionCC(double r1,double r2,double x1,double x2,double y1,double y2);
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
// ウインドウモードに変更
ChangeWindowMode( TRUE );
// DXライブラリ初期化
if( DxLib_Init() == -1 )
{
return 0;
}
SetDrawScreen( DX_SCREEN_BACK );
/////////////////ゲーム用///////////////////
Player_t Player;//バッター
Ball_t Ball;//ボール
double radmeat;//ミートの中心とボールの角度
double direction;//曲がる時進むべき角度
bool change=false;//変化球フラグ
bool hit=false;//ヒットフラッグ
bool SWING=false;//スイングフラッグ
bool PITCH=true;//投球フラッグ
bool NOWPITCH=false;//投球中フラッグ
int batter[3];//バッターの画像
int count=0;//アニメーション管理用
int Cr ;
Cr= GetColor( 255 , 255, 255 ) ; // 白色の値を取得
LoadDivGraph( "bat.bmp" , 3, 1 , 3, 310 , 270, batter ); // 画像の分割読み込み
Player_Initialize(&Player);//プレイヤー初期化
int i;
while(ProcessMessage()==0)
{
if(SWING==true)
{
count++;
}
ClearDrawScreen(); // 画面を消す
Keyboard_Update();//キーの初期化
grand();//グランド描写
Player_meat(&Player);//ミートカーソル
DrawBox(270,330,370,430,GetColor(255,100,0),FALSE);//ストライクゾーン描画
if(CheckHitKey( KEY_INPUT_C) ==1&& PITCH==true)//ピッチング用
{
Ball_Initialize( &Ball);//ボール初期化
PITCH=false;
NOWPITCH=true;
}
if( CheckHitKey( KEY_INPUT_Z) == 1 && SWING==false)//Zが入力されている
{
SWING=true;
}
////////////////////カーソル移動/////////////////////////////////////////
if(SWING==false)
{
Player_Update(&Player);
}
/////////////////////////////////////////////////////////////////////////////
if(SWING==true&&count<=5)//スイングの構えと途中の切り替え
{
Player_Draw1(&Player);
///////////////ミートの判定//////////////////////////////
if(7.5>=Ball.BallZ&&Ball.BallZ>=6&&CollisionCC(6,Player.meat,Ball.BallXEND,Player.X+320,Ball.BallYEND,Player.Y+380)==true)
{
hit=true;
}
}
else if(SWING==true && NOWPITCH==true||5<count&&count<=50)//スイングして0.5秒後に振り終わりに
{
Player_Draw2(&Player);
}
else if(SWING==true&&PITCH==true)//振り終わって訳1秒後にフラッグをfalse
{
SWING=false;
count=0;
}
else
{
hit=false;
Player_Draw0(&Player);
}
if(NOWPITCH==true)
{
Ball_Draw( &Ball );
}
if(Ball.BallZ<=8)
{
Ball.BallZ=Ball.BallY/60;
}
if(Ball.BallY>=540||Ball.BallY<0)//ボールが画面外に行けば次に行く
{
NOWPITCH=false;
PITCH=true;
}
//変化球テスト
if(200<Ball.BallY&&Ball.BallY<Ball.BallYEND&&hit==false)
{
Ball.BallXEND+=2;
}
/////////////////////////////////////////
if(NOWPITCH==true)
{
if(hit==false)
{
Ball_Update(&Ball );
}
else//ボールがミートされた時
{
radmeat=atan2(Ball.BallYEND-Player.Y,Ball.BallXEND-Player.X);
Ball.BallY+=sin(radmeat*180/PAI)*Ball.BallSpeed;//ボールの縦ベクトル
Ball.BallX+=cos(radmeat*180/PAI)*Ball.BallSpeed;//ボールの横ベクトル
}
}
///////////////////デバッグ用////////////////////////////////////////////
DrawFormatString( 30, 30, Cr, "BallZ=%d", (int)Ball.BallZ ) ;//デバッグ用
DrawFormatString( 30, 50, Cr, "BallX=%d", (int)Ball.BallX ) ;//デバッグ用
DrawFormatString( 30, 70, Cr, "BallY=%d", (int)Ball.BallY ) ;//デバッグ用
DrawFormatString( 30, 130, Cr, "rad=%f",Ball.rad*180/PAI) ;//デバッグ用
DrawFormatString( 30, 90, Cr, "BallTXEND=%d", (int)Ball.BallTXEND ) ;//デバッグ用
DrawFormatString( 30, 110, Cr, "BallTYEND=%d", (int)Ball.BallTYEND ) ;//デバッグ用
ScreenFlip(); //裏画面を表画面に反映
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0;
}
/*ball*/
#include "DxLib.h"
#include "Keybord.h"
#include "Ball.h"
#include<time.h>
#include<math.h>
//////////////////////////////////////////////////
// srand関数で、乱数パターンを初期化する
unsigned int now = (unsigned int)time( 0 );
////////////////////////////////////////////////
// 初期化をする
void Ball_Initialize( Ball_t *Ball)
{
Ball->BallX=320;
Ball->BallY=120;
Ball->BallZ=1;
Ball->BallXEND=270+(int)( rand() * (370 - 270 + 1.0) / (1.0 + RAND_MAX) );
Ball->BallYEND=330+(int)( rand() * (430 - 330 + 1.0) / (1.0 + RAND_MAX) );
Ball->BallSpeed=5;
Ball->BallA=((Ball->BallYEND-120)/(Ball->BallXEND-320));
Ball->BallTYEND=120+1.5*(Ball->BallYEND-120);
Ball->BallTXEND=320+1.5*(Ball->BallXEND-320);
//////////////////ボールの影定義//////////////
if(400<=Ball->BallYEND)
{
Ball->Ballkage=50;//高さ90,70,50,
}
else if(Ball->BallYEND<=360)
{
Ball->Ballkage=90;//高さ90,70,50,
}
else
{
Ball->Ballkage=70;
}
///////////////////////////////////////////////
}
// 動きを計算する
void Ball_Update( Ball_t *Ball )
{
Ball->rad=atan2((double)Ball->BallYEND-(double)Ball->BallY,(double)Ball->BallXEND-(double)Ball->BallX);
Ball->BallTYEND=120+1.5*(Ball->BallYEND-120);
Ball->BallTXEND=320+1.5*(Ball->BallXEND-320);
if(sin(Ball->rad)>0)
{
Ball->BallX+=cos(Ball->rad)*Ball->BallSpeed;
Ball->BallY+=sin(Ball->rad)*Ball->BallSpeed;
}
else
{
Ball->BallX+=cos(Ball->rad)*Ball->BallSpeed;
Ball->BallY+=sin(-Ball->rad)*Ball->BallSpeed;
}
}
// 描画する
void Ball_Draw( Ball_t *Ball )
{
DrawCircle( Ball->BallX , Ball->BallY , Ball->BallZ ,GetColor(255,255,255), TRUE) ;// ボールを描画
DrawCircle( Ball->BallX , Ball->BallY +Ball->Ballkage, Ball->BallZ-2, GetColor(0,0,0) , TRUE) ;//ボールの影
DrawCircle( Ball->BallXEND ,Ball->BallYEND, 6, GetColor(255,0,0) , FALSE);//ストライクゾーンのボール
}