いつもお世話になってます。どこにでも居るゆとりの<korです。
今STGを作成中でどうにかシューティングゲームの館の7章までいったのですが、
あそこに書いてある通常移動は理解できました。しかし、あれに加えて『左SHIFT+方向キー』で
通常移動の半分の速度で動く低速移動をつけたいのですが、どうすればいいのでしょうか?
低速移動について
Re:低速移動について
移動する前に一旦変数に値を入れたらいいですよ。
移動分なる変数を用意したとします。
では今移動が3.0だったとし、低速移動はその半分の1.5だとしましょう。
こんな感じでどうでしょうか?
もちろん4方向必要になります。
ちなみに、キャラクタの座標はdouble型であることを前提としています。
龍神録では3.9に設定し、低速移動はその1/3にしています。
移動分なる変数を用意したとします。
では今移動が3.0だったとし、低速移動はその半分の1.5だとしましょう。
移動分=3.0; if(シフトが押されていたら){ 移動分/=2; } if(移動キーが押されていたら){ if(キャラクタ座標と移動分を足した座標が移動可能領域内なら){ キャラクタ座標+=移動分; } }
こんな感じでどうでしょうか?
もちろん4方向必要になります。
ちなみに、キャラクタの座標はdouble型であることを前提としています。
龍神録では3.9に設定し、低速移動はその1/3にしています。
Re:低速移動について
移動分というのは、 Player.x-=4.0f; のことでしょうか?
if(Key[KEY_INPUT_LSHIFT]){
Player.x-=4.0f/=2;
}
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=4.0f;
if(Player.x<10.0)
Player.x=10.0;
}
とやると”error C2106: '/=' : 左のオペランドが、左辺値になっていません。”となってしまうのですが・・・
if(Key[KEY_INPUT_LSHIFT]){
Player.x-=4.0f/=2;
}
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=4.0f;
if(Player.x<10.0)
Player.x=10.0;
}
とやると”error C2106: '/=' : 左のオペランドが、左辺値になっていません。”となってしまうのですが・・・
Re:低速移動について
低速移動を実行できたのですが、
if(Key[KEY_INPUT_LSHIFT]){
Player.x -=4.0f / 2.0f;
}
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=4.0f;
if(Player.x<10.0)
Player.x=10.0;
}
と書くと、左shiftを押すだけで左に移動してしまうのですが、どこを直せばshiftと左キー同時押しで低速移動になるのですか?
if(Key[KEY_INPUT_LSHIFT]){
Player.x -=4.0f / 2.0f;
}
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=4.0f;
if(Player.x<10.0)
Player.x=10.0;
}
と書くと、左shiftを押すだけで左に移動してしまうのですが、どこを直せばshiftと左キー同時押しで低速移動になるのですか?
Re:低速移動について
double move_value = 4.0f; // 移動力(標準が4.0)
// Shiftを押している間は、移動力を半分に
if(Key[KEY_INPUT_LSHIFT]){
move_value /= 2;
}
// 上下左右の移動
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=move_value;
if(Player.x<10.0)
Player.x=10.0;
}
(以下、上下と右について同様)
このような感じでどうでしょうか。
// Shiftを押している間は、移動力を半分に
if(Key[KEY_INPUT_LSHIFT]){
move_value /= 2;
}
// 上下左右の移動
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=move_value;
if(Player.x<10.0)
Player.x=10.0;
}
(以下、上下と右について同様)
このような感じでどうでしょうか。
Re:低速移動について
はじめまして、自分もこのサイトを見ながらSTGを作っていますが、そのプログラムの
if(Key[KEY_INPUT_LSHIFT]){
Player.x -=4.0f / 2.0f;
}
の部分ですが、これだと左シフトを押したとき 2.0fづつPlayer.xが減少して行きます。
上の管理人さんの返信のやり方だと、一旦どこかで変数を宣言しそれに通常時の移動速度を代入し、左シフトを押したときその変数が低速時の移動速度になるようにし(上のものだと 移動分/=2; がそれに該当します)その状態で左キーが押されるとPlayer.xからその変数が引かれていく、ということを書いていくと良いと思います。
最悪このことがわからなければ、変数のことを考えずに
if(Key[KEY_INPUT_LSHIFT]){
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=2.0f;
if(Player.x<10.0)
Player.x=10.0;
}
}
という感じで4方向に設定していけば希望どうりに動くと思います。
if(Key[KEY_INPUT_LSHIFT]){
Player.x -=4.0f / 2.0f;
}
の部分ですが、これだと左シフトを押したとき 2.0fづつPlayer.xが減少して行きます。
上の管理人さんの返信のやり方だと、一旦どこかで変数を宣言しそれに通常時の移動速度を代入し、左シフトを押したときその変数が低速時の移動速度になるようにし(上のものだと 移動分/=2; がそれに該当します)その状態で左キーが押されるとPlayer.xからその変数が引かれていく、ということを書いていくと良いと思います。
最悪このことがわからなければ、変数のことを考えずに
if(Key[KEY_INPUT_LSHIFT]){
if(Key[KEY_INPUT_LEFT]==1){
Player.x-=2.0f;
if(Player.x<10.0)
Player.x=10.0;
}
}
という感じで4方向に設定していけば希望どうりに動くと思います。
Re:低速移動について
わかりやすく
if(キャラクタ座標と移動分を足した座標が移動可能領域内なら){
とかきましたが、移動領域外であり、かつ、移動領域の端では無い場合は、移動領域の端まで移動させて下さい。
なお、単純に横と縦に同じように移動させると、ルート2倍の速さになってしまうので、
斜めに進むときは1/1.41421356倍にして下さい。
sqrt(2.0)を使うと正確ですが、この関数は計算に時間がかかるので、上のようにかいたほうがいいでしょう。
if(キャラクタ座標と移動分を足した座標が移動可能領域内なら){
とかきましたが、移動領域外であり、かつ、移動領域の端では無い場合は、移動領域の端まで移動させて下さい。
なお、単純に横と縦に同じように移動させると、ルート2倍の速さになってしまうので、
斜めに進むときは1/1.41421356倍にして下さい。
sqrt(2.0)を使うと正確ですが、この関数は計算に時間がかかるので、上のようにかいたほうがいいでしょう。
Re:低速移動について
自分はこんな感じでやっています。
どうせ敵弾で三角関数を使いまくっているので1回ぐらい計算が増えてもいいだろう、的な考えです。
どうせ敵弾で三角関数を使いまくっているので1回ぐらい計算が増えてもいいだろう、的な考えです。
#include "DxLib.h" #include "math.h" // ---- 関数の仮宣言 double Get_Angle ( int Input_Direction ); void Move ( double &Temp_X, double &Temp_Y, double Temp_Angle, double Temp_SPD ); void Renge_Check ( double &Temp_Shaft, double Temp_Min, double Temp_Max, double Temp_Size ); // -------- メイン関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { if ( DxLib_Init () == -1 ) { return -1; }// DXライブラリの初期化 SetDrawScreen ( DX_SCREEN_BACK ); ClearDrawScreen (); // ---- 変数の宣言 int Input_Pad = 0; double X = 320.0, Y = 240.0, Angle = 0, SPD = 4.0, SPD_Correct = 1.0; // -------- ループ開始 while ( ProcessMessage () == 0 ) { Input_Pad = GetJoypadInputState ( DX_INPUT_PAD1 ); Angle = Get_Angle ( Input_Pad ); SPD_Correct = ( ( Input_Pad & 16 ) >> 4 ) +1;// 低速ボタン(半分の速度に補正) if ( Angle != -1.0 ) { Move ( X, Y, Angle, SPD /SPD_Correct ); } // ↑角度が-1の時(どの方向も押されていない)は何もしない DrawCircle ( X, Y, 20, GetColor ( 255, 255, 255), TRUE ); Renge_Check ( X, 0, 640, 20 );// X方向の表示範囲 Renge_Check ( Y, 0, 480, 20 );// Y方向の表示範囲 ScreenFlip (); ClearDrawScreen (); if ( CheckHitKey ( KEY_INPUT_F12 ) == 1 ) { break; } } DxLib_End (); return 0; } // ---- 関数の実体 double Get_Angle ( int Input_Direction )// 押されているボタンから角度を返す { double Angle = -1.0; switch ( Input_Direction & 1 +( Input_Direction & 2 ) +( Input_Direction & 4 ) +( Input_Direction & 8 ) ) { case 1:Angle = 90.0; break; case 2:Angle = 180.0; break; case 3:Angle = 135.0; break; case 4:Angle = 0.0; break; case 5:Angle = 45.0; break; case 8:Angle = 270.0; break; case 10:Angle = 225.0; break; case 12:Angle = 315.0; break; default:Angle = -1.0;// どの方向も押されていない break; } return Angle; } void Move ( double &Temp_X, double &Temp_Y, double Temp_Angle, double Temp_SPD ) { Temp_X += cos ( Temp_Angle /180.0 *3.14159265358979323846 ) *Temp_SPD;// 度をラジアンに Temp_Y += sin ( Temp_Angle /180.0 *3.14159265358979323846 ) *Temp_SPD; return; } void Renge_Check ( double &Temp_Shaft, double Temp_Min, double Temp_Max, double Temp_Size ) { if ( Temp_Shaft < ( Temp_Min +Temp_Size ) ) { Temp_Shaft = Temp_Min +Temp_Size; } if ( Temp_Shaft > ( Temp_Max -Temp_Size ) ) { Temp_Shaft = Temp_Max -Temp_Size; } return; }コピペで使えます(BCCで作成)
Re:低速移動について
すみません、説明がほとんどありませんでした。 要は、 Get_Angle関数で、押してるボタンから角度を求め(8方向)、 Move関数で、その方向にSPDの値だけ進む。 ただし△ボタン(PSパッドで)押下中は半分の速度になり、 (SPD_Correct = ( ( Input_Pad & 16 ) >> 4 ) +1; の部分) Check_Range関数で画面端でのストップ、 となっています。 ちなみに表示されている円が画面端を少し行き過ぎて見えるのは、 円の描画の仕様(指定した半径通りの描画が行われていない為)です。