터치팡팡(a.k.a개미잡기) 개발강좌(6) - 캔버스에 개미를 곡선으로 움직여 보자1

3 minute read

html5의 캔버스(canvas)를 이용하여 터치팡팡게임을 만드는 과정을 소개합니다. a.k.a 개미잡기
완성된 게임은 터치팡팡 <- 링크를 통해 확인할수 있다.




캔버스위에 개미를 곡선으로 움직여 보자1

저번시간에는 개미가 오른쪽 방향으로 움직이는거까지 진행을 해 보았다. 개미는 일직선으로 움직이지 않는다. 좀더 개미답게 움직이게 하기 위해서 곡선으로 움직이게 하려고 한다.

곡선그리기

일단 포토샵을 조금 다뤄본 사람이라면 베지어 곡선을 들어 봤을것이다.

베이어 곡선은 캔버스로 간단하게 그릴수 있다.

코드펜을 보자
(화면이 안나온다면 오측 하단에 return 버튼을 눌러보자)

See the Pen canvas 010 by mnmsoft (@mnmsoft) on CodePen.

ctx.bezierCurveTo(50, 5, 70, 130, 300, 100)

새로운 코드는 이거 한줄이다. canvas 는 곡선을 그리는 베지어 함수를 제공한다.

매개변수는(첫번째제어점X,첫번째제어점Y,두번째제어점X,두번째제어점Y,종료점X,종료점Y) 이다

베지어 곡선의 대한 정확한 원리를 알려주는 좋은 유투브 정보를 알고 있어서 링크로 공유한다.

우리는 개미를 저 선에 따라 움직이게 할 예정이다.

곡선을 점으로 그리기

안탑깝게도 저 베이저 곡선을 따라 움직이게 하는 방법을 필자는 찾지 못하였다.
그리하여 수동으로 베지어 곡선을 그리고 그 좌표를 얻어내어서 개미를 각 좌표로 옮길 예정이다.

영상을 보고 오면 알겠지만 한점과 다른점의 사이의 을 선으로 그었을때 특점비율의 위치를 알아낼 필요가 있다.

필자는 이렇게 구현하였다.

function diffPos(point1,point2,ratio){
	let rPoint = [];
	rPoint[0] = point1[0] + ((point2[0] - point1[0]) * ratio);
	rPoint[1] = point1[1] + ((point2[1] - point1[1]) * ratio);
	return rPoint;
}

[x좌표,y좌표]로 구선된 1차원 배열을 만들어서 다루는게 생각하기도 사용하기도 쉬워서 그렇게 사용한다.

두개의 점을 매개변수로 받은다음 각 x,y좌표에 대하여 원점의 x좌표를 다른한점의 x좌표에서 뺀후 원하는 비율만큼 곱한값을 원점에 곱한다.

예를 들면 원점(1,1) 다른점(3,3) 이고 두점의 10% 위치를 구하려면

먼저 두 점의 차를 구하고 (3-1) 이건 두점과 점사이의 거리가 된다. (값은 2)
여기에 원하는 비율의 위치를 구하기 위해 10%인 0.1을 곱한다. (값은 0.2)
구해진 값을 원점좌표인 1에서 더한다. (1 + 0.2) 이러면
두점사이의 10%프로 해당하는 좌표를 구할수 있다.

위 예제로 함수로 호출하면 이렇게 될것이다.

diffPos([1,1],[3,3],0.1)

이러허게 만들어진 함수를이용하여 베지어좌표를 구하는 또 다른 함수를 구현해보자.

function drawBezier(point1,control1,control2,point2,ratio){
	const q1 = diffPos(point1,control1,ratio);
	const q2 = diffPos(control1,control2,ratio);
	const q3 = diffPos(control2,point2,ratio);

	const r1 = diffPos(q1,q2,ratio);
	const r2 = diffPos(q2,q3,ratio);

	const s1 = diffPos(r1,r2,ratio);
	return s1;
}

함수를 설명하면..

베지어 곡선을 구현하기 위한 좌표는 총 4개이다 시작점,제어점1,제어점2,끝점

함수는 이 4개의 점을 매개변수로 받고 추가로 점과 점사이의 어느 위치인지를 나타내는 비율의 값을을 받는다.

그리고 이 점들 (시작점과 제어점1 , 제어점1과 제어점2, 제어점2와 끝점)의 사이의 특정위치의 점을 구하면 3개의 점이 나온다. 소스에서는 q1,q2,q3이란 변수에 담았다.

이어서 3개의 점을 기준으로 (q1과q2사이의 점,q2와q3사이의 점) 을 구하면 2개 소스에서 이점을 r1 , r2란 변수에 담았다.

마지막으로 r1와 r2 사이의 특정위치의 점을 구하여 s1에 담았다.

이런 함수가 있다면 위 코드펜 소스가 사용했던 좌표를 넣어서 10%로의 위치의 좌표를 알수 있다.

drawBezier([0,0],[50,5],[70,130],[300,100],0.1)

반복문을 사용하면 이렇게 구현할수 있을것이다.

for(let i=0;i<=1;i+=0.01){
	drawBezier([0,0],[50,5],[70,130],[300,100],i)	
}

점들사이의 특정위치를 가르키는 마지막 매개변수를 0부터 0.01씩 1이 될때 까지 증가시킨다.

그렇게 얻어지는 점을 화면에 그려보자.

(화면이 안나온다면 오측 하단에 return 버튼을 눌러보자)

See the Pen canvas 010 by mnmsoft (@mnmsoft) on CodePen.

위에서 그려진 곡선이 점으로 100개로 나뉘어진 점으로 표현된것을 볼수 있다.

드디어 준비는 끝났다.

구해진 점에 개미 그리기!

이제 저 점위치에 개미를 그려보자!

(화면이 안나온다면 오측 하단에 return 버튼을 눌러보자)

See the Pen canvas 010 by mnmsoft (@mnmsoft) on CodePen.

이전에 구현했던 오른쪽 방향으로 가는 개미를 이번에 구한 베지어 곡선을 따라 움직이게 해보았다.

거의 된거 같지만 여전희 문제가 있다 개미는 오른쪽으로만 움직이는게 아니라 곡선을 따라 움직이는데 머리방향은 오른쪽만 바라보고 있다.

다음시간에는 베지어 곡선에 따라 움직이는 방향에 맞게 머리방향을 틀는 시간을 가져보겠다.

다음에 또 만나요~!

Leave a comment