물리적으로 '움직임'이란 '시간동안 움직인 거리'다. 우리는 특정 시간동안 움직인 거리가 많을수록 속도가 빠르다고 말한다. 그래서 움직인 거리를 구할 때는 '속도 x 시간'으로 계산한다. '시간'과 '거리'는 물리에서 필수적인 요소이며, 현실을 모방하는 가상 공간(컴퓨터)역시 시간과 거리는 필수다. 단, 현실과 물리적 단위가 다를 뿐이다.
[현실]시간 => [컴퓨터]프레임률
[현실]거리 => [컴퓨터]픽셀
컴퓨터 세계에서는 시간을 프레임률로 계산하며, 거리는 픽셀이다. 따라서 움직임을 만들어야하는 프로그램의 핵심은 프레임률, 픽셀에 따른 가속도에 있다.
1 컴퓨터의 시간
컴퓨터의 시간을 알아보기 위해서 브라우저(크롬 or Edge)에서 F12키를 클릭해보자. 콘솔 항목에서 console.log(Date.now()); 명령어를 입력하면 아래와 같은 숫자가 나올 것이다.
오늘의 날짜와 시간이 아닌 14자리의 숫자가 찍혀나온다. 이와 관련한 자바스크립트 |MDN의 설명은 아래와 같다.
즉, "1580777086164"란 숫자는 1970년 1월 1일 0시 0분 0초로부터 현재까지의 지나간 시간을 의미하며, 단위는 '밀리초'다.(밀리초:1000/1초)
자바스크립트로 컴퓨터의 시간은 밀리초 단위로 돌아간다고 일단 이해하고, 이제 개발자는 해당 시간을 프로그램 내의 프레임이란 단위로 변환해야한다.
1) Delta : 시간 차이
2) Frame : 이미지 프레임의 전환속도
3) Duration : 이미지 프레임의 움직이는 속도
4) currentTime : delta값 저장
'밀리초'를 이용해서 움직임을 만들기 위해서는 위의 4가지 값(Delta, Frame, Duration, currentTime)이 필요하다. 그리고 전체적인 작동원리는 다음과 같다.
* init() : 초기 시간값 저장
* refresh() : 시간 변화량(delta) 저장, 초기 시간값 갱신
* update(delta) : 이미지 객체의 update()메서드에 시간변화량 전달
requestAnimationFrame()에서 refresh()메서드가 반복(재귀)될 때마다 시간변화량(delta)이 발생한다. 해당 시간변화량을 update()메서드를 통해 이미지 객체에 전달하는 것으로 Game클래스의 책임은 끝난다.
2 프레임 계산
프레임은 1초당 실행하는 이미지의 개수다. 가령, 영화에서 24프레임이라고 하면 초당 24장의 이미지가 실행되는 셈이다. 게임은 어떨까?
다음과 같은 상황을 상상해보자.
"당신은 의자에 앉아있고, 플립 애니메이션이 그려진 책 한권과 옆에는 물통 A, B가 있다. 그리고 잠시 뒤 쪽지가 전달된다. 물통에는 다음과 같은 단어가 새겨져 있고, 감독관이 전달한 쪽지에는 숫자(정수)와 규칙이 적혀있다.
*A물통 : Delta
*B물통 : currenTime
*쪽지 : Duration(정수값)
규칙1: B물통의 물이 Duration과 같아지면,
B물통의 물을 A물통에 채워진 양만큼 비워라
규칙2: B물통에 채워진 물의 양을 index공식에 넣어서,
정수값이 되면 책장을 한장 넘겨라.
*index공식: (B물통의 물의 양 / Duration) * 책장에 그려진 그림의 개수
이제 당신은 A(Delta)물통의 물이 채워질 때마다 B(currentTime)물통에 쏟아부어야한다. B물통(currentTime)에는 "index"란 눈금이 그려져있다. 해당 눈금은 정수단위이며, 물의 높이가 눈금에 다다를 때마다 당신은 빨리 책장을 한장씩 넘겨야 한다.
위의 예시를 게임에 비유하자면 빠진 것은 프레임이다. 하지만 프레임은 준비한 이미지의 개수마다 달라질 수 있고, 개발자가 임의로 정해야하기 때문에 일부로 표시를 하지 않았다.
* Duration : 1초 동안 나타나는 이미지의 개수 x (1.0 / 개발자가 정한 frame수)
만일 10장의 이미지를 준비했고, frame을 '10'으로 설정했다면 Duration은 '1'이다. Duration이 1이라 가정했을 때 '물통 예시'를 생각해보자. 참고로 delta값은 0.001초로 지정했다.
감독관은 '1'이 적힌 쪽지를 전달했고, A물통의 물은 0.001초(delta)마다 한번씩 채워진다. 그래서 당신은 0.001초마다 A물통의 물을 B물통(currentTime)에 채운다. B물통의 관점에 본다면 0.001초마다 물이 채워지고 있고, 눈금 '1'에 다다를 동안 A물통은 1000번 움직인다. 그리고 B물통의 눈금이 점차 올라갈 때마다 index값은 바뀐다.
"B물통에 채워진 물의 양을 index공식에 넣어서,
정수값(0,1,2 ...)이 되면 책장을 한장 넘겨라"
const dt = (now - this.lastTime) / 1000.0;
3이동거리
(안 보일시 F5 새로고침)
4 Duration(반복주기)
5결론
|
Delta |
FPS |
Duration |
증가 | 반복속도 증가 이동속도 증가 |
반복속도 증가 |
반복속도 감소 |
감소 | 반복속도 감소 이동속도 감소 |
반복속도 감소 |
반복속도 증가 |
'웹개발 자료실 > 웹게임제작 Code' 카테고리의 다른 글
html5 캔버스 『마우스에 반응하는 이미지 만들기』 (0) | 2020.02.13 |
---|---|
캔버스 루프 애니메이션 4편 『최종정리』 (0) | 2020.02.06 |
캔버스 루프 애니메이팅 2편 『canvas 좌표축 이해』 (1) | 2020.02.04 |
캔버스 루프 애니메이팅 1편 『설계 및 최소구현』 (0) | 2020.01.31 |
캔버스 게임만들기 3편『state구현하기』 (0) | 2019.11.04 |
댓글