加速度運動でぬるっとした動き出しを表現する
やってることは簡単で、フレーム間の時間を計算して、時間分のスピードを上げてあげる処理です。
$ v = v_0 + at $
をそのまま表現します。
$at$はフレーム間時間$t$に$a$だけスピードがアップするよってのを表しています。
あとは今の速度に、加速分の速さを足すだけ。
Listing. 1: 加速度運動の導入
- "theMain.cpp"
#include "DxLib.h" #include "Input.h" //位置を表す構造体 struct Vec2D { float x; float y; }; enum CHR_STATE { IDLE, //アイドリング WALK, //歩き MAX_CHR_STATE //最大値 }; namespace { const int WIN_WIDTH = 1024; const int WIN_HEIGHT = 768; int hGroundImage = -1; float groundH = 600; int BoxW = 64; int BoxH = 128; Vec2D BoxPos = { 100, groundH - BoxH }; float speed = 0; float accel = 300; const float MAX_SPEED = 500;//最大スピード CHR_STATE myState = IDLE; int crrTime; int prevTime; } void DxInit() { ChangeWindowMode(true); SetWindowSizeChangeEnableFlag(false, false); SetMainWindowText("TITLE"); SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32); SetWindowSizeExtendRate(1.0); SetBackgroundColor(255, 250, 205); // DXライブラリ初期化処理 if (DxLib_Init() == -1) { DxLib_End(); } SetDrawScreen(DX_SCREEN_BACK); } int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { DxInit(); hGroundImage = LoadGraph("Image\\bg_dote.jpg"); crrTime = GetNowCount(); prevTime = GetNowCount(); while (true) { ClearDrawScreen(); Input::KeyStateUpdate(); //ここにやりたい処理を書く //画像自体を画面の大きさに合わせてもいいよ //DrawRotaGraph(WIN_WIDTH /2, WIN_HEIGHT /2, // WIN_WIDTH /(float)groundH, 0, hGroundImage, FALSE, FALSE); static float chrSpeed = 0;//歩いてたらspeed,歩いてなかったら0 static float sign = 0; //右向いてるか左向いてるか 右 1, 左 -1 crrTime = GetNowCount(); float deltaTime = (crrTime - prevTime) / 1000.0;//フレーム間時間(s) DrawExtendGraph(0, 0, WIN_WIDTH, WIN_HEIGHT + 1, hGroundImage, FALSE); DrawLine(0, groundH, WIN_WIDTH, groundH, GetColor(255, 0, 0), 2); if (Input::IsKeyDown(KEY_INPUT_LEFT) || Input::IsKeyDown(KEY_INPUT_A)) { //BoxPos.x = BoxPos.x - speed; myState = WALK; sign = -1.0; } else if(Input::IsKeyDown(KEY_INPUT_RIGHT) || Input::IsKeyDown(KEY_INPUT_D)) { //BoxPos.x = BoxPos.x + speed; myState = WALK; sign = 1.0f; } if (Input::IsKeyUP(KEY_INPUT_LEFT) || Input::IsKeyUP(KEY_INPUT_A)) { myState = IDLE; sign = 0.0; } else if (Input::IsKeyUP(KEY_INPUT_RIGHT) || Input::IsKeyUP(KEY_INPUT_D)) { myState = IDLE; sign = 0.0; } if (myState == WALK) { speed += accel * deltaTime; chrSpeed = min(MAX_SPEED, speed);//これspeedそのまま使えばよくね? } else { speed = 0; chrSpeed = 0; } BoxPos.x = BoxPos.x + sign * chrSpeed * deltaTime; DrawBox(BoxPos.x, BoxPos.y, BoxPos.x + BoxW, BoxPos.y + BoxH, GetColor(0, 255, 0), TRUE); DrawFormatString(20, 20, GetColor(0, 0, 0), "%d", myState); DrawFormatString(20, 50, GetColor(0, 0, 0), "%lf", deltaTime); ScreenFlip(); WaitTimer(16); prevTime = crrTime; if (ProcessMessage() == -1) break; if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) break; } DxLib_End(); return 0; }