なんか目指してるのがよくわからなくなったのでちょっとサンプルを作ってみました。
キーボードの1 2 3を押してからz xを押すとそれぞれ抵抗 力 重さが変更できますが
0以下にならないような処理をしてないのでとりあえず0以下にしないでください。
あと、あんまり良く考えずに書いていったのでツッコミは御容赦ください(笑)
a=F/m-kv/m
v=v0+(F/m-kv0/m)t
v=V0(1-kt/m)+Ft/m
をそのまま書いた(つもりの)ものです。
main.cpp
コード:
#include <DxLib.h>
#include <math.h>
#define SPDLINE_SIZE (10)
#define ANGLINE_SIZE (50)
#include "Struct.h"
extern int gpUpdateKey();
extern int CheckStateKey(unsigned char);
int ProcessLoop(){
if(ProcessMessage()!=0)return -1;//プロセス処理がエラーなら-1を返す
if(ClearDrawScreen()!=0)return -1;//画面クリア処理がエラーなら-1を返す
gpUpdateKey();//現在のキー入力処理を行う
return 0;
}
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
ch_t player;
player.x = 320.0f; // 座標
player.y = 240.0f;
player.spdX = 0.0f; // 速度(世界座標)
player.spdY = 0.0f;
player.angle = 90.0f; // 初期角度は90度(上向き)
player.spdAngle = 0.0f; // 回転速度0
player.resist = 0.02f; // 空気抵抗
player.force = 0.2f; // 力
player.weight = 1.0f; // 重さ
player.arrowColor1 = GetColor(255,0,0);
player.arrowColor2 = GetColor(0,255,255);
int i = 0;
int debugStringColor = GetColor(0,0,255);
while( ProcessLoop()==0 ){
float aX = 0.0f, aY = 0.0f, aAngle = 0.0f; // 加速量
float accele = player.force/player.weight; // 加速力
if( CheckStateKey(KEY_INPUT_1) == 1 ){ i = 0; }
if( CheckStateKey(KEY_INPUT_2) == 1 ){ i = 1; }
if( CheckStateKey(KEY_INPUT_3) == 1 ){ i = 2; }
if( (CheckStateKey(KEY_INPUT_Z) == 1)&&(i==0) ){ player.resist += 0.001f; }
if( (CheckStateKey(KEY_INPUT_Z) == 1)&&(i==1) ){ player.force += 0.1f; }
if( (CheckStateKey(KEY_INPUT_Z) == 1)&&(i==2) ){ player.weight += 0.1f; }
if( (CheckStateKey(KEY_INPUT_X) == 1)&&(i==0) ){ player.resist -= 0.001f; }
if( (CheckStateKey(KEY_INPUT_X) == 1)&&(i==1) ){ player.force -= 0.1f; }
if( (CheckStateKey(KEY_INPUT_X) == 1)&&(i==2) ){ player.weight -= 0.1f; }
if( CheckStateKey(KEY_INPUT_W) >= 1 ){ aY += accele; }
if( CheckStateKey(KEY_INPUT_A) >= 1 ){ aX -= accele; }
if( CheckStateKey(KEY_INPUT_D) >= 1 ){ aX += accele; }
if( CheckStateKey(KEY_INPUT_LEFT) >= 1 ){ aAngle += accele; }
if( CheckStateKey(KEY_INPUT_RIGHT) >= 1 ){ aAngle -= accele; }
// 減速する V=V0(1-kt/m)+at の1項目
player.spdX *= 1.0f-player.resist/player.weight;
player.spdY *= 1.0f-player.resist/player.weight;
player.spdAngle *= 1.0f-player.resist/player.weight;
// 加速量を速度に加算する 加速はローカル、速度は世界座標なのでangleで変換してから
player.spdX += aY*cos(player.angle*PHI_F/180.0f) + aX*sin(player.angle*PHI_F/180.0f);
player.spdY -= aY*sin(player.angle*PHI_F/180.0f) - aX*cos(player.angle*PHI_F/180.0f);
player.spdAngle += aAngle;
// 画面から出ないようにする
player.x += player.spdX;
if( player.x > 640.0f ){ player.x = 640.0f; }
if( player.x < 0.0f ){ player.x = 0.0f; }
player.y += player.spdY;
if( player.y > 480.0f ){ player.y = 480.0f; }
if( player.y < 0.0f ){ player.y = 0.0f; }
// 角度の値が大きくなり過ぎないようにする
player.angle += player.spdAngle;
if( player.angle > 360.0f ){ player.angle -= 360.0f; }
if( player.angle < 0.0f ){ player.angle += 360.0f; }
// 描画
DrawLine( (int)player.x, (int)player.y,
(int)(player.x+player.spdX*SPDLINE_SIZE), (int)(player.y+player.spdY*SPDLINE_SIZE), player.arrowColor1 );
DrawLine( (int)player.x, (int)player.y,
(int)(player.x+ANGLINE_SIZE*cos(player.angle*PHI_F/180.0f)), (int)(player.y-ANGLINE_SIZE*sin(player.angle*PHI_F/180.0f)),
player.arrowColor2);
DrawCircle( (int)(player.x), (int)(player.y), 5, player.arrowColor2 );
DrawFormatString(0,0,debugStringColor,"X=%.2f",player.x);
DrawFormatString(100,0,debugStringColor,"Y=%.2f",player.y);
DrawFormatString(0,20,debugStringColor,"spd=%.2f",sqrt(player.spdX*player.spdX+player.spdY*player.spdY));
DrawFormatString(100,20,debugStringColor,"ang=%.2f",player.angle);
DrawFormatString(0,40,debugStringColor,"Vmax=%.2f",player.force/player.resist);
DrawFormatString(100,40,debugStringColor,"A=%.4f",accele);
DrawFormatString(200,40,debugStringColor,"κ=%.4f",player.resist);
DrawFormatString(300,40,debugStringColor,"F=%.4f",player.force);
DrawFormatString(400,40,debugStringColor,"M=%.4f",player.weight);
ScreenFlip();
}
DxLib_End();
return 0;
}
key.cpp
コード:
#include <DxLib.h>
int Key[256]; // キーが押されているフレーム数を格納する
int gpUpdateKey(){
char tmpKey[256]; // 現在のキーの入力状態を格納する
GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
for( int i=0; i<256; i++ ){
if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
Key[i]++; // 加算
} else { // 押されていなければ
Key[i] = 0; // 0にする
}
}
return 0;
}
int CheckStateKey(unsigned char Handle){
return Key[Handle];
}
struct.h
コード:
typedef struct
{
float x, y;
float spdX, spdY;
float angle;
float spdAngle;
float resist;
float force;
float weight;
int arrowColor1;
int arrowColor2;
}ch_t;