[M1 Mac, Monterey 12.6.3, clang 13.0.0, SDL 2.26.2, ChatGPT Plus, NO IDE]
テトリスのプレイ画面収録機能を実装中です。
ffmpegコマンドをCPUの別コアで並列実行します。コマンドの末尾に&を付けると別コアでの実行になります。そうしないと録画が終わるまでゲーム開始が保留状態です。
録画開始はスムーズですが、録画停止についてはプロセスIDを終了させる必要があります。これからコードを書いていきます。
画面のx座標がなぜかズレているため要調整です。
void App::Run()
{
Uint32 lastTimeMs = SDL_GetTicks();
auto lastTime = std::chrono::high_resolution_clock::now();
bool bDone = false;
while(!bDone )
{
GameInput gameInput = {};
SDL_JoystickUpdate();
// respond to events
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
if(event.type == SDL_QUIT)
{
bDone = true;
}
// 落下速度ボタン選択
if(event.type == SDL_MOUSEBUTTONDOWN)
{
mouseX = event.motion.x;
mouseY = event.motion.y;
SDL_Delay(10);
selectButton(slowButton, normalButton, fastButton, mouseX, mouseY);
}
if(event.type == SDL_JOYBUTTONDOWN)
{
switch (event.jbutton.button){
case 2:{ // □ボタン:スタート
gameInput.bStart = true;
start = std::chrono::steady_clock::now();
scores = {};
dates = {};
fullDates = {};
numAllScores = {};
rank = 0;
DrawPlayingCount = 0;
GeneratorCount = 0;
arr = {};
modeDetect();
// 画面収録開始
string cmd = "/opt/homebrew/bin/ffmpeg -f avfoundation -framerate 30 -video_size 1280x720 -i \"Capture screen 0\" -vf \"crop=1280:720:400:150\" -vcodec libx264 -pix_fmt yuv420p -r 30 -preset ultrafast -tune zerolatency -crf 28 -x264-params \"nal-hrd=cbr:force-cfr=1\" -maxrate 3M -bufsize 6M /Users/[ユーザID]/TetrisDX/video/test.mp4 &";
system(cmd.c_str());
break;
}
case 13:{ // 左ボタン
gameInput.bMoveLeft = true;
break;
}
case 14:{ // 右ボタン
gameInput.bMoveRight = true;
break;
}
case 1:{ // ○ボタン:反時計回り回転
gameInput.bRotateClockwise = true;
break;
}
case 0:{ // ×ボタン:時計回り回転
gameInput.bRotateAnticlockwise = true;
break;
}
case 12:{ // 下ボタン:一気に落下
gameInput.bHardDrop = true;
break;
}
case 11:{ // 上ボタン:徐々に落下
gameInput.bSoftDrop = true;
break;
}
case 10:{ // R1ボタン:落下速度ボタン選択
buttonCount++;
if (buttonCount % 3 == 1){
fastButton.selected = true;
normalButton.selected = false;
s_initialFramesPerFallStep = 24;
} else if (buttonCount % 3 == 2){
slowButton.selected = true;
fastButton.selected = false;
s_initialFramesPerFallStep = 48;
} else {
normalButton.selected = true;
slowButton.selected = false;
s_initialFramesPerFallStep = 32;
}
break;
}
case 9:{ // L1ボタン:スタート画面
m_gameState = kGameState_TitleScreen;
break;
}
case 6:{ // optionsボタン:ゲーム終了
// cout << "ゲーム終了" << endl;
bDone = true;
break;
}
default:{
// cout << "default" << endl;
break;
}
}
}
}
Uint32 currentTimeMs = SDL_GetTicks();
Uint32 deltaTimeMs = currentTimeMs - lastTimeMs;
lastTimeMs = currentTimeMs;
HP_UNUSED( deltaTimeMs );
auto currentTime = std::chrono::high_resolution_clock::now();
auto deltaTime = currentTime - lastTime;
std::chrono::microseconds deltaTimeMicroseconds = std::chrono::duration_cast<std::chrono::microseconds>(deltaTime);
float deltaTimeSeconds = 0.000001f * (float)deltaTimeMicroseconds.count();
lastTime = currentTime;
mGame->Update(gameInput, deltaTimeSeconds );
mRenderer->Clear();
mGame->Draw( *mRenderer );
mRenderer->Present();
}
}