2012-08-05 3 views
3

게임 루프를 화면 전체를 이동하는 상자로 단순화했습니다 (Click Here). 어떤 이유로 든 상자가 원활하게 움직이지 않는 것 같습니다. 나는 video of it here을 만들었습니다. JavaScript 게임 루프가있는 부드러운 애니메이션

게임 루프

은과 같이 호출됩니다 내가 메인 게임 루프에서 draw 호출을 분리 시도하고 requestAnimationFrame에 넣어하지만, 한

var game = function() { 
    var now = Date.now(); 
    var delta = now - then; 

    update(delta/1000); 
    draw(); 

    then = now; 
}; 

setInterval(game, 1000/50); 

문제가 지속. 나는 매끄럽게 달리는 자습서를 보았다. 나는 심지어 fixed time-step game loop을 사용해 보았습니다. 그러나 그것은 단지 내 게임을 관리하기 어려울 정도로 빠르게 만들었습니다.

requestAnimationFrame을 사용하고 update 호출을 위해 deltaTime을 유지하면서 위의 논리를 개선하려면 어떻게해야합니까?

+0

나는 전혀 보지 못했다. 그것은 또한 항상 '59'라고 말했다. 그게 fps 야? – Esailija

+0

Hmmm, yes 59 초당 업데이트 수를 표시하려고했습니다. 사파리와 크롬 모두 내 Mac에서, 나는 부드럽게 움직이지 않고 패들과 공이 조금 앞으로 뛰는 것을보고 있습니다. 나는 다른 컴퓨터에서 확인해야 할 것 같아. – Quantastical

+0

내가 정말 가깝게 보면 공이 약간 엉망이된다고 생각합니다 ... 이것은 어떤 프레임에서는 볼이 한 번에 1px 이상 움직이기 때문입니다. – Esailija

답변

3

캔버스를 사용할 때 위치 변수는 픽셀을 나타내고 부동 소수점 값은 의미가 없으므로 정수 값이어야한다고 생각합니다. 콘솔을 열고 sceneManager.currentScene.GameplayLayer.ball.position.x에 입력하면 정말 긴 십진수가됩니다. 나는 때때로 공이 1px 대신에 2px 움직이는 것을 제안하는 OP에 대한 의견이 뭔가있을 수 있다고 생각합니다. 당신이 당신의 위치를 ​​업데이트 할 때 당신은 부동 소수점 값으로 끝납니다.

때로는 아래쪽으로 높은 픽셀 위치로 올림하는 경우가 있습니다. 나는 바닥이나 천정을 그렇게하려고 노력할 것이다 :

this.position.x += Math.floor(this.speed * 100 * deltaTime * Math.cos(directionInRadians)); 
this.position.y += Math.floor(this.speed * 100 * deltaTime * Math.sin(directionInRadians)); 

나는이 두 가지 변화를 만들고 그것의 행동을 볼 것이다.

편집 : 논리를 단순화하기 위해 질문을 편집 했으므로. 시도 할 항목을 제안 할 수 있습니다.이 클립은 내가 항상 사용하는 Clock 객체를 사용하는 것입니다. 그것은 나에게 부드러운 애니메이션을 제공하고 오히려 간단합니다. 그것은 clock that Three.JS uses을 기반으로하므로 체크 아웃 할 수도 있습니다. 자신 만의 코드를 사용하고자 할 때조차도이 기성품 솔루션을 사용해보고 동일한 결과를 얻을 수 있는지 확인하십시오. 그것은 나를 위해 잘 작동하는 것 같다. 또한 shim을 사용하여 게임 기능의 호출이 requestAnimFrame(game);이되도록 했습니까?

var Clock = function() { 

    /** Member startTime will remain fixed at its integer 
     millisecond value returned by Date.now(). Will always 
     be equal to the time the clock was started */ 
    this.startTime = Date.now(); 

    /** Member ms is updated by tick() to a integer value reprsenting 
     the number of milliseconds between the epoch (January 1, 1970) 
     and the current date and time of the system. */ 
    this.ms = this.startTime; 
    this.last = this.startTime; /** millis at last call to tick() */ 
    this.time = 0;    /** ms in floating point seconds not millis */ 

    /** Member dt is updated by tick() to an integer value representing 
     the number of milliseconds since the last call to tick(). */ 
    this.dt = 0; 
    this.delta = 0; /** dt in floating point seconds not millis */ 

    /** Member fps is updated by tick() to a floating point value representing 
     frames per second, updated and averaged approximately once per second */ 
    this.fps = 0.0; 

    /** Member frameCount is updated to an integer value representing the 
     total number of calls to tick() since the clock was created. */ 
    this.frameCount = 0; 

    /** The frameCounter member is a flag you can turn off if you don't need to 
     calculate the frameCount or do the average FPS calculation every second */ 
    this.frameCounter = true; 

    /** Private globals needed to calculcate/average fps over eachs second */ 
    var timeToUpdate = 0; 
    var framesToUpdate = 0; 

    /************************************************************************************ 
     The tick() method updates ALL the Clock members, which should only 
     be read from and never written to manually. It is recommended that 
     tick() is called from a callback loop using requestAnimationFrame 

     Learn more: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 
    *************************************************************************************/ 
    this.tick = function() { 
     /** This is a new frame with it's very own unique number */ 

     if (this.frameCounter) this.frameCount++; 

     /** Set the private currentTime variable */ 
     this.ms = Date.now(); 

     /** Update time delta and immediately set last time to 
      be as accurate as possible in our timings. */ 
     this.dt = this.ms - this.last; 
     this.last = this.ms; 

     /** Calculate floating-point delta and increment time member */ 
     this.delta = 0.001 * this.dt; 
     this.time += this.delta; 

     /** Calculate private temp variables for fps calculation */ 
     if (this.frameCounter) { 
      timeToUpdate += this.dt; 
      framesToUpdate++; 
      if (timeToUpdate > 1000) { 
       this.fps = Math.round((framesToUpdate * 1000)/timeToUpdate); 
       framesToUpdate = 0; 
       timeToUpdate = 0; 
      } 
     } 
    } 
} 

당신이 다음이 객체를 사용하는 경우 너무 clock = new Clock();처럼 초기화 함수에 새로운 시계 객체를 생성하기 만하면됩니다. 그런 다음 각 애니메이션 통화에서 clock.tick()으로 전화하십시오. clock.deltaclock.time 멤버에 액세스하면 델타 및 시간을 초 단위로 부동 소수점 값으로 사용할 수 있습니다. clock.dtclock.ms은 밀리 초 단위로 정수를 제공합니다. clock.fps을 사용하여 fps에 액세스하거나 clock.frameCounter = false을 설정하여 fps를 비활성화 할 수도 있습니다.

+0

글쎄, 당신의 제안을 시도하고, 그것은 여전히 ​​동일한 문제를 제시했다. 내 게임 루프 논리가 옳은 일은 아니라고 생각하며, 내가 시도한 모든 것이 같은 방식으로 반응하는 것 같습니다. 나는 다른 사람의 코드를 가져 와서 내 컴퓨터에서 부드러운 애니메이션을 만들 수 있었기 때문에 내 게임을 기본 루프로 재구성하고 어떤 일이 일어나는지 살펴야 할 수도 있습니다. 도움에 다시 한번 감사드립니다. JavaScript 용 게임 루프 로직이 있었으면 좋겠습니다. – Quantastical

+0

좋은 아이디어 인 것 같습니다.이 응용 프로그램에서 구조화가 잘 수행되었지만 지금까지 가지고있는 것에 대해 실제로 복잡해 보입니다. init, animate 및 render의 3 가지 함수로 시작합니다. 가능한 한 가장 간단한 용어로 잘 작동하도록하고 게임에 복잡성을 추가 할 때 추상화를 구축하십시오. 모든 다른 파일과 클래스는 지금까지 가지고있는 것에 대한 약간의 과잉 보입니다. 그것은 나에게 좋은 프로그래밍처럼 보입니다. 약간의 작은 일은 아마도 올바르지 않을 것입니다. 프로그램 흐름을 간단하게 시각화하는 것은 어렵습니다. –

+0

헤드 업 : 논리를 단순화하고 질문을 업데이트했습니다. 이 대답은 더 이상 적절하지 않을 수 있습니다. – Quantastical

1

three.js을 사용하면 내 애니메이션이 부드럽게 처리됩니다. 나는 그것을 매우 추천한다. 거기에 다른 좋은 코드들도 많습니다.

+0

'clock.js'는 구현을 위해'Date.now()'를 사용합니다. 나는 그것이 어떻게 OP에서 코드보다 부드럽게 될 수 있는지 궁금해. – tigrou

관련 문제