Notice
Recent Posts
Recent Comments
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Today
Total
관리 메뉴

만재송

[Cocos Creator] lerp (Linear Interpolation) 본문

프로그래밍/COCOS Creator

[Cocos Creator] lerp (Linear Interpolation)

만재송 2018. 2. 4. 13:59

lerp (Linear Interpolation)



lerp 는 한국말로 선형 보간법이라고 하고 그 뜻은 두점이 주어졌을 때 그 사이에 위치한 값을 추정하기 위하여 직선 거리에 따라 선형적으로 계산하는 방법이다. 뭔가 수학적인 방법을 어떻게 게임에서 사용하지? 하는 생각이 들수도 있다. 하지만 이미 유니티에서는 굉장히 자주 쓰이고 있고 앞으로 게임을 만들기 위해 없어서는 안될 방법이다. 


그러면 lerp는 어디서 사용이 될까? 쉽게 설명하면 "어떤 수치에서 어떤 수치로 값이 변경되는 데 한번에 변경되지 않고 부드럽게 변경하고 싶을 때" 사용한다. 유니티에서는 보통 어떤 오브젝트를 부드럽게 이동하거나 회전시킬 때, 카메라를 부드럽게 이동시킬 때 사용한다. 


유니티에서도 자주 사용하는데 cocos creator 라고 사용하지 말라는 법이 어디있나! cocos creator 의 lerp를 한번 파헤쳐보자.


Cocos2d (Cocos Creator) lerp


cocos2d (cocos creator) 도 lerp 를 사용할 수 있게 구현이 되어있다. cocos2d 의 내부 로직을 보면 다음과 같다.

 * @param {Number} a number A
* @param {Number} b number B
* @param {Number} r ratio between 0 and 1
* @function
* @example
* cc.lerp(2,10,0.5)//returns 6<br/>
* cc.lerp(2,10,0.2)//returns 3.6
*/
cc.lerp = function (a, b, r) {
return a + (b - a) * r;
};

첫번째 인자 a 는 첫번째 끝점 이고 보통 시작점을 의미한다. 


두번째 인자 b 는 두번째 끝점 이고 보통 도착점을 의미한다. 


세번째 인자 r 은 거리비율이고 0와 1사이 값을 넣을 수 있다. 거리비율이란건 첫번째 끝점 a를 시작점으로해서 b 점까지를 직선으로 연결했을 때 r이 0.1이라고 하면 직선에서 10% 되는 부분의 지점이란 것이다.


예로들어 a = 0, b = 10, r = 0.5 일때 좌표에 0 과 10 사이를 직선으로 연결하고 그 직선의 중간값 (0.5) 인 5를 반환한다는 뜻이다. r 이 0.2 라면 2를 반환하는 것이다. 


아직까지는 lerp 로 어떻게 물체를 이동시키고 카메라를 이동시키는지 모를수도있다. 예제를 통해서 어떻게 쓰이는지 한번 알아보자.



오브젝트 이동


위에서 배운 lerp를 통해 오브젝트를 이동시켜 보자. 프로젝트를 생성하고 Sprite Node를 Node Tree에 붙이자. 



다음으로 스크립트를 생성하자. 그리고 lerp를 사용하기 위해 update 메서드를 만들자. 


cc.Class({
extends: cc.Component,

onLoad : function () {
},

update : function (dt) {

}
});


이제 update와 lerp를 이용하여 해당 물체를 이동시킬것이다. update 문에 아래와 같이 코드를 작성하자.


update : function (dt) {
let posX = this.node.x
this.node.x = cc.lerp(this.node.x, 150, dt);
}


위의 코드는 현재 물체의 위치에서 x 값 150 의 위치로 이동시키는 코드이다. 


기본적으로 update 메서드는 1프레임에 1번 호출되는 메서드다. update의 파라미터 값인 dt (deltaTime) 은 update 메서드 호출 사이의 시간 이다. 그래서 lerp 의 3번째 인자에 dt를 넣어주면 update 가 실행될 때 마다 물체의 기존위치에서 (150 - 기존위치) * dt 까지 이동이 된다.


이해가 잘 안갈 수 있다. 예를 들어 현재 물체의 위치가 0이고 도달위치가 10, 프레임이 10 (dt = 0.1) 이라고 가정했을 때, 


1번째 update 실행 => 물체의 위치 = 0 + (10 - 0) * 0.1 = 1

2번째 update 실행 => 물체의 위치 = 1 + (10 - 1) * 0.1 = 1.9

3번째 update 실행 => 물체의 위치 = 1.9 + (10 - 1.9) * 0.1 = 2.71

...

...

n번째 update 실행 => 물체의 위치 = 10


점점 작은 수치만큼 증가하다가 결국 물체의 위치가 10이 된다. 움직이는 속도를 변경하고 싶으면 dt 값에 어떤값을 곱하거나 나누면 속도를 변경할 수 있다.


이렇듯, 위 의 코드를 실행하면 물체의위치가 처음 posX 부터 시작해서 150까지 부드럽게 이동하는 모습을 볼 수 있다.



물체를 일정한속도로 이동하고싶을때는 어떻게 할까? 위의 코드에서 조금만 변경해주면 된다. 아래의 코드를 보자.


cc.Class({
extends: cc.Component,

onLoad : function () {
this.posX = this.node.x;
this.time = 0;
},

update : function (dt) {
this.time += this.time > 1 ? 0 : dt;
this.node.x = cc.lerp(this.posX, 150, this.time);
}
});


onLoad 에서 물체의 시작지점을 posX 프로퍼티 에 저장하고 time 프로퍼티를 생성한다. update 에서는 time 의 값을 update 가 실행될때마다 dt 를 더해준다. lerp 의 3번째 인자인 r 은 1을 넘기면 안되기 때문에 1 이상일때는 time의 값은 고정해준다. 이렇게 되면 time 의 값은 프레임이 일정하다는 가정하에 1초가 되면 1이 될것이다. (update 는 1초에 프레임 값만큼 호출된다.)


다음 lerp 를 수정하자. 첫번째 인자에 최초 물체의 위치값을 넣고 2번째 인자는 도착위치, 3번째 인자에 time 프로퍼티를 넣고 실행해보자. 1초동안 물체가 150의 위치로 일정한 속도로 이동하는 모습을 볼 수 있다. 만약 1초가아닌 2초 3초 등등 다른 시간을 넣고싶다면 그만큼 dt 를 곱하거나 나누면 된다.




카메라 이동


이번엔 lerp를 사용하여 물체를 1박자 느리게 따라가는 카메라를 구현해보자. cocos creator 는 카메라 기능을 하는 컴포넌트가 있다. 먼저 Node Tree 에 빈 Node를 생성하여 Camera 컴포넌트를 추가하자. 그리고 Targets 프로퍼티 값을 1로 하고 카메라 영향을 받을 물체의 Node 를 추가하자.


테스트를 더 확실히하기 위해서 긴 배경도 추가하자. background Node 에 긴배경을 하나 추가하고 카메라 컴포넌트에 추가하자. (이부분은 없으면 건너 뛰어도 상관없다.)


다음 스크립트 2개를 생성한다. 카메라에 붙일 Camera 스크립트 와 물체에 붙일 Target 스크립트를 만든다. 간단하게 물체의 스크립트는 move Action 으로 이동하는 간단한 코드를 작성한다.


// Target.js
cc.Class({
extends: cc.Component,

onLoad: function () {
this.node.runAction(cc.moveBy(3, 1000, 0));
}
});


다음으로 타겟을 따라가기 위해서 카메라를 lerp 를 이용하여 이동시킨다.


// Camera.js
cc.Class({
extends: cc.Component,

properties: {
target: cc.Node
},

onLoad: function () {
},

update : function (dt) {
this.node.x = cc.lerp(this.node.x, this.target.x, dt);
}
});


properties 에 물체의 Node 를 저장시키고 update 에서 현재 카메라의 위치에서 물체의 x 값까지 lerp 를 이용하여 dt 퍼센트 만큼 카메라를 이동시킨다. 


이렇게 구현하면 카메라는 update 문으로 현재 물체의 위치를 확인하고 물체의 경로를 뒤따라서 가게 된다. Editor 로 가서 스크립트를 각각의 Node 에 추가하고 실행해보자. 3 초간 빠르게 이동하는 물체를 힘겹게 따라잡으려고 하는 카메라의 끈기를 볼 수 있을것이다.






참고



Comments