답변:
예. XNA의 내부를 약간 혼란스럽게 만듭니다. 이 비디오의 후반부에서 픽스 를 시연했습니다 .
배경:
이것이 발생하는 이유는 XNA Game
의 기본 Form
크기가 조정되거나 이벤트가 동일 할 때 게임 시계가 일시 중단되기 때문 입니다. 이것은에서 게임 루프를 구동하고 있기 때문입니다 Application.Idle
. 창의 크기가 조정되면 Windows는 실행 을 막는 미친 win32 메시지 루프 작업 을 수행합니다 Idle
.
따라서 Game
시계를 일시 중단하지 않은 경우 크기를 조정 한 후 단일 버스트로 업데이트해야하는 시간이 엄청나게 늘어 났으므로 바람직하지 않습니다.
수정 방법 :
XNA에는 긴 이벤트 체인이 있으며 (사용하는 경우 Game
사용자 지정 창에는 적용되지 않음) 기본적으로 게임 시계에 대한 기본 Form
,에 Suspend
및 Resume
메서드 의 크기 조정 이벤트를 연결합니다 .
이들은 비공개이므로 리플렉션 을 사용 하여 이벤트의 후크를 해제해야합니다 (은 어디에 this
있습니다 Game
).
this.host.Suspend = null;
this.host.Resume = null;
필요한 주문은 다음과 같습니다.
object host = typeof(Game).GetField("host", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this);
host.GetType().BaseType.GetField("Suspend", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);
host.GetType().BaseType.GetField("Resume", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);
(어딘가에서 체인을 분리 할 수 있습니다. ILSpy를 사용하여 알아낼 수 있습니다. 그러나 창 크기 조정 외에 타이머를 중단시키는 다른 것은 없습니다. 따라서 이러한 이벤트는 어느 것이나 좋습니다.)
그런 다음 XNA가에서 똑딱 거리지 않을 때 자신의 틱 소스를 제공해야합니다 Application.Idle
. 나는 단순히 System.Windows.Forms.Timer
:
timer = new Timer();
timer.Interval = (int)(this.TargetElapsedTime.TotalMilliseconds);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
이제는 timer_Tick
결국을 호출 Game.Tick
합니다. 이제 시계가 일시 중단되지 않았으므로 XNA 고유의 타이밍 코드를 계속 사용할 수 있습니다. 쉬운! XNA의 내장 틱이 발생하지 않을 때만 수동 틱이 발생하기를 원합니다. 간단한 코드는 다음과 같습니다.
bool manualTick;
int manualTickCount = 0;
void timer_Tick(object sender, EventArgs e)
{
if(manualTickCount > 2)
{
manualTick = true;
this.Tick();
manualTick = false;
}
manualTickCount++;
}
그리고 Update
XNA가 정상적으로 작동하는 경우이 코드를 입력하여 카운터를 재설정하십시오.
if(!manualTick)
manualTickCount = 0;
이 틱은 XNA보다 덜 정확합니다. 그러나 실시간으로 정렬되어 있어야합니다.
이 코드에는 여전히 작은 결함이 있습니다. Win32는 어리석은 못생긴 얼굴을 축복하며 마우스가 실제로 움직이기 전에 창의 제목 표시 줄을 클릭하면 본질적으로 모든 메시지를 수백 밀리 초 동안 중지 합니다 ( 동일한 링크 참조 ). 이렇게하면 Timer
메시지 기반의 메시지가 표시되지 않습니다.
우리는 이제 XNA의 게임 시계를 중단하지 않기 때문에 타이머가 다시 똑딱 거리기 시작하면 많은 업데이트가 발생합니다. 그리고 슬프게도 XNA는 누적 가능한 시간을 제목 표시 줄을 클릭 할 때 Windows가 메시지를 중지하는 시간보다 약간 적은 시간으로 제한합니다. 따라서 사용자가 제목 표시 줄을 클릭하지 않고 움직이면 제목 표시 줄이 움직이지 않으면 업데이트가 많아 지고 몇 프레임이 실시간으로 떨어집니다.
(그러나 이것은 여전히 대부분의 경우에 충분 해야합니다 . XNA의 타이머는 이미 말더듬을 방지하기 위해 정확도를 희생하므로 완벽한 타이밍 이 필요한 경우 다른 작업을 수행해야합니다.)