프레임 독립 운동


11

여기에 움직임에 대한 두 개의 다른 스레드를 읽었습니다. 시간 기반 움직임 대 프레임 속도 기반 움직임? , 언제 고정 또는 가변 시간 단계를 사용해야합니까?

그러나 나는 그 스레드 중 하나가 무엇을 말하고 있는지 이해하지 못하기 때문에 프레임 독립적 인 움직임에 대한 기본 이해가 부족하다고 생각합니다.

나는 lazyfoo의 SDL 튜토리얼을 따르고 프레임 독립적 인 수업을 받았습니다. http://lazyfoo.net/SDL_tutorials/lesson32/index.php

코드의 움직임 부분이 무엇을 말하려고하는지 잘 모르겠지만 이것이 맞다고 생각합니다 (잘못되면 수정하십시오) : 프레임 독립적 인 움직임을 얻으려면 객체가 얼마나 멀리 있는지 알아야합니다 ( 예를 들어 스프라이트)는 특정 시간 프레임 내에서 이동합니다 (예 : 1 초). 점이 초당 200 픽셀로 이동하면 200 pps에 1/1000 초를 곱하여 해당 초 내에 얼마나 많이 이동하는지 계산해야합니다.

맞습니까? 수업 내용 :

"마지막 프레임 이후 초 당 픽셀 단위의 속도 * 시간입니다. 따라서 프로그램이 초당 200 프레임으로 실행되는 경우 : 200 pps * 1/200 초 = 1 픽셀"

하지만 ... 200pps에 1/1000 초를 곱한다고 생각했습니다. 초당 프레임이있는이 비즈니스는 무엇입니까?

프레임 독립적 인 움직임이 어떻게 작동하는지에 대해 누군가가 좀 더 자세한 설명을 해줄 수 있다면 고맙겠습니다.

감사합니다.

부가:

SDL_Rect posRect;
posRect.x = 0;
posRect.y = 0;

float y, yVel;
y = 0;
yVel = 0;

Uint32 startTicks = SDL_GetTicks();

bool quit = false;
SDL_Event gEvent;

while ( quit == false )
{
    while ( SDL_PollEvent( &gEvent ) )
    {
        if ( gEvent.type == SDL_QUIT )
            quit = true;
    }

    if ( y <= 580 )
    {
        yVel += DOT_VEL;
        y += (yVel * (SDL_GetTicks() - startTicks)/1000.f);
        posRect.y = (int)y;
    }

    startTicks = SDL_GetTicks();
    SDL_BlitSurface( bg, NULL, screen, NULL );
    SDL_BlitSurface( dot, NULL, screen, &posRect );
    SDL_Flip( screen );
}

화면 아래로 점을 이동시키는 코드입니다. 나는 지금까지 모든 것이 정확하다고 생각합니다. 화면 아래로 이동하지만 설명 할 수없는 이상한 일이 있습니다. 점은 y 값보다 커질 때 y = 580을 유지해야합니다. 그러나 프로그램을 실행할 때마다 점이 다른 위치에있게됩니다. 점은 580 이상을 조금 의미합니다. 점은 화면의 중간 또는 절반 이상입니다 (점은 20 픽셀, 화면) 크기 800x600). 프로그램의 제목 표시 줄을 클릭 한 다음 놓으면 점이 화면에서 사라집니다. 매번 변수가 어떻게 변합니까? 제목 표시 줄 문제에 관해서는 제목 표시 줄을 잡을 때 타이머가 계속 실행되고 경과 시간이 길어지기 때문에 다음 프레임에서 점이 이동하는 거리가 멀어집니다. 맞습니까?


당신의 추가는 실제로 또 다른 질문입니다. 기존 질문에 추가하는 대신 두 번째 질문을 작성해야합니다. 그래도 쉽게 대답 할 수 있습니다 : 예를 들어 y 움직임을 계산하십시오. yMovement = (yVel * (SDL_GetTicks() - startTicks)/1000.f);다음을 수행하십시오if(y + yMovement <= 580){ y += yMovement; } else { y = 580; }
bummzack

답변:


10

참고 : 모든 분수는 부동 소수점입니다.

프레임 독립 운동은 시간이 아닌 움직임을 기반으로 작동합니다. 마지막 프레임 이후에 소비되는 시간을 얻습니다 (따라서 1 초에 60 프레임이있는 경우 모든 프레임이 같은 시간이 걸린다면 각 프레임은 1.0 / 60.0 초가 걸립니다). 로 번역됩니다.

엔터티가 지정된 시간 단위 (일초마다 100 픽셀이라고 함) 동안 일정량의 공간을 이동 시키려면 프레임 당 이동량을 곱하여 프레임 당 이동해야하는 픽셀 수를 확인할 수 있습니다. 현재 프레임에서 얼마나 많은 움직임이 발생하는지 파악하기 위해 초 단위의 시간 (초) (100 / 60.0)을 초 단위로 표시합니다 (1.0 / 60.0).

경과 시간과 일정한 시간 단위 (초 또는 밀리 초가 바람직 함)로 정의 된 속도를 사용하여 프레임 당 얼마나 많은 움직임을 수행해야하는지 파악하여 작동합니다. 따라서 계산은 다음과 같습니다.movementPerSecond * (timeElapsedInMilliseconds / 1000.0)

나는 그것이 당신에게 어떤 의미를 갖기를 바랍니다.

매초마다 200 픽셀 씩 오른쪽으로 이동하고 싶습니다. 현재 프레임이 이전 프레임 후 50 밀리 초 동안 실행되면 이전에 지정한 속도 (200 픽셀)의 일부를 이동시켜야합니다. 1/20 번째 (50/1000 = 1/20) 시간 만 지나갔으므로 거리의 50/1000 번째로 이동해야합니다. 따라서 10 픽셀 만 이동시키는 것이 합리적입니다 (19 프레임이 더 발생하면 서로 50 밀리 초 간격을 유지 한 다음 해당 초의 총 이동량은 200 픽셀, 원하는 양임).

프레임 독립 이동이 작동하는 방식은 일반적으로 프레임이 가변 시간 단계에서 발생한다는 것입니다 (후속 프레임간에 다른 시간이 발생 함). 프레임마다 일정한 거리로 엔티티를 지속적으로 이동하면 프레임 속도를 기준으로 이동합니다. 프레임간에 시간이 많으면 게임이 너무 느리게 움직이는 것처럼 보이고 프레임간에 시간이 많지 않으면 게임이 빠르게 진행되는 것 같습니다. (프레임 간 시간이 너무 적음 = 많은 프레임 = 더 많은 움직임)이를 극복하기 위해 시간 측면에서 속도를 사용하고 프레임 간 시간을 추적합니다. 그렇게하면 마지막으로 위치를 업데이트 한 지 얼마나 지 났는지, 엔티티를 얼마나 더 멀리 옮겨야하는지 알 수 있습니다.

초당 프레임 수 : 초당 발생하는 프레임 수입니다. 일반적으로 프레임 속도는 게임이 1 초에 몇 번 그려 지거나 렌더링되는지 또는 1 초에 게임 루프가 완료되는 횟수입니다.

고정 절 가변 시간 단계 : 프레임 간 시간을 나타냅니다. 일반적으로 프레임 사이의 시간은 일정하지 않습니다. 물리와 같은 특정 시스템 / 코어는 무언가를 시뮬레이션 / 실행하기 위해 어느 정도의 시간이 필요합니다. 일반적으로 물리 단계는 시간 단계가 고정되어 있으면 더 안정적입니다. 고정 / 가변 시간 단계의 차이점은 이름에 있습니다. 고정 시간 단계는 소리처럼 들립니다. 고정 시간 속도로 발생하는 시간 단계. 가변 시간 단계는 다양한 / 다른 시간 비율에서 발생하는 시간 단계입니다.


예를 들어, 각 프레임의 시간은 50 밀리 초입니다. 맞습니까? 그리고 그것은 1000 / FPS에 의해 계산 되었습니까? 따라서 각 프레임을 만드는 데 필요한 움직임은 초당 픽셀 * 50/1000입니까?
ShrimpCrackers

흠, 나는 각 시간 프레임에 대한 밀리 초가 가변적 일 것임을 깨달았습니다. getTicks ()-startTicks와 같은 것은 항상 다르고 일정하지 않습니다.
ShrimpCrackers

@Omnion : "초당 픽셀 수"로 거리를 지정하면 밀리 초를 사용할 수 없습니다. 1000/60이 아닌 1.0 / 60.0이어야합니다. 이는 완전히 다른 결과를 초래합니다.
bummzack

@ShrimpCrackers 예, 경과 시간이 변경됩니다. 60fps를 렌더링 할 수없는 구형 PC를 상상해보십시오. 그런 머신에서 게임이 같은 속도 (동일한 fps는 아님)로 실행되기를 원합니다.
bummzack

그렇다면 lazyfoo 튜토리얼에서 1000은 deltaticks / 1000.f에서 무엇을 의미합니까? FPS? 1000 밀리 초? 지금 조금 혼란 스러워요. 각 프레임에 필요한 시간을 결정하는 데 FPS가 필요한 것 같지만 실제로 움직임을 계산하지는 않습니다.
ShrimpCrackers

7

프레임 역학에서 엔티티를 이동하는 코드는 다음과 같습니다.

x = x + speedPerFrame

프레임 독립적이 되려면 다음과 같이 보일 수 있습니다.

x = x + speedPerSecond * secondsElapsedSinceLastFrame

감사합니다. 위의 다른 질문이 있습니다.
ShrimpCrackers

1

추가 질문에 관해서.

포인트를 이동할 때 경계 (y> 580)를 확인하지 않기 때문에 포인트가 매번 다른 위치에서 멈 춥니 다. 과거 580 번만 더 이상 업데이트를 중지하십시오.

580을 교차하기 전의 마지막 프레임에서 579에서 시작하거나 570에서 또는 100에있을 수 있습니다. 마지막 프레임을 실행하는 데 걸린 시간에 따라 1 픽셀 앞으로 또는 1000 씩 스테핑 할 수도 있습니다.

IF 조건을 이와 같은 것으로 변경하면 괜찮을 것입니다.

if ( y <= 580 )
{
    yVel += DOT_VEL;
    y += (yVel * (SDL_GetTicks() - startTicks)/1000.f);
    if( y > 580 )
    {
        y = 580;
    }
    posRect.y = (int)y;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.