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

3 minute read

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




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

저번시간에는 개미가 곡선을 따라 움직이게 하였다. 정확히는 곡선의 좌표를 구한뒤에 각 좌표에 맞게 움직이게 하였다. 하지만 개미는 항상 오른쪽을 바라보고 있다. 개미가 곡선에 따라 정면을 바라보게 해보자.

어떻게 하면 개미가 곡선에 따라 움직일때 자연스럽게 정면을 바라 볼수 있을까? 필자는 이렇게 생각했다.

좌표에 개미를 그릴때 이전 좌표의 정보와 비교하여 진행방향으로 머리의 방향을 정하자! 예를 들면 지금 그리는 좌표가 [3,3] 이고 이전에 그려진 좌표가 [2,2] 라면 x좌표가 커졌으니 오른쪽 방향 y좌표도 커졌으니 아래방향 으로 합쳐서 오른쪽 아래방향으로 머리를 그려야 한다.

만약 현재좌표가 [3,3] 이고 이전 좌표가 [2,0] 이라면 x좌표가 커지고 y좌표가 커졌으니 오른쪽 아래방향으로 머리를 그려야 한다. 그러나 커진 정도가 x좌표는 1만큼, y좌표는 3만큼 커졌기 때문에 좀더 아래방향으로 틀어지게 그려야 한다.

이걸 수식으로 생각하여 공식화 해야 한다.

더 좋은 방법이 있을것이라고 생각하지만 필자는 이렇게 구했다. 다시 한번 말하지만 더 좋은 방법이 있을것이다. 이 소스는 원하는 답을 주긴 하지만 자신이 없다. 구현을 목적으로 실시간으로 답은 찾고.. 리팩토링 하지 않은 코드이기 때문이다.. 그치만 소스를 살펴보자.

function getHeadAngle(point1,point2){
	let x , y;

	x = point2[0] - point1[0];
	y = point2[1] - point1[1];
	returnAngle = 0;

	//console.log(x,y,tempNum);

	
	if(x == y){

	}else if(x >= 0 && y < 0){ // 0~90
		x = Math.abs(x);
		y = Math.abs(y);
		if(x == y){
			returnAngle = 45;
		}else if(x <= y){
			returnAngle = 0;
			returnAngle += 45*x/y
		}else{
			returnAngle = 90;
			returnAngle -= 45*y/x
		}
		//console.log(returnAngle);
		return returnAngle
	}else if(x >= 0 && y >= 0){ //90~180
		x = Math.abs(x);
		y = Math.abs(y);
		if(x == y){
			returnAngle = 90 + 45;
		}else if(x <= y){
			returnAngle = 180;
			returnAngle -= 45*x/y
		}else{
			returnAngle = 90;
			returnAngle += 45*y/x
		}
		//console.log(returnAngle);
		return returnAngle

	}else if(x < 0 && y >= 0){ //180~270
		x = Math.abs(x);
		y = Math.abs(y);
		returnAngle = 180;
		if(x == y){
			returnAngle = 180 + 45;
		}else if(x <= y){
			returnAngle = 180;
			returnAngle += 45*x/y
		}else{
			returnAngle = 270;
			returnAngle -= 45*y/x
		}
		//console.log(returnAngle);
		return returnAngle

	}else if(x < 0 && y < 0){ //270~360
		x = Math.abs(x);
		y = Math.abs(y);
		returnAngle = 270;
		if(x == y){
			returnAngle = 270 + 45;
		}else if(x <= y){
			returnAngle = 360;
			returnAngle -= 45*x/y
		}else{
			returnAngle = 270;
			returnAngle += 45*y/x
		}
		//console.log(returnAngle);
		return returnAngle
	}	
}

머리 방향을 구하는것이기에 getHeadAngle 라는 함수를 만들고
파라미터로 (이전좌표,현재좌표)를 받았다.

x가 켜졌는지 작아졌는지 y가 켜졌는지 작아졌는지에 따라 4가지 방향으로 큰 제어문을 잡았다.
(오른쪽아래,오른쪽위,왼쪽아래,왼쪽위)

네가지 제어분기 중에 한가지만 살펴보자. x는 커지고 y는 작아진 구간이다! x는 커지고 y는 작아진 구간

머리의 방향은 0도에서 90도 사이가 될것이다.

if(x >= 0 && y < 0){
	x = Math.abs(x);
	y = Math.abs(y);
	if(x == y){
		returnAngle = 45;
	}else if(x <= y){
		returnAngle = 0;
		returnAngle += 45*x/y
	}else{
		returnAngle = 90;
		returnAngle -= 45*y/x
	}
	//console.log(returnAngle);
	return returnAngle
}
x = Math.abs(x);
y = Math.abs(y);

이미 구간의 선택은 끝났기에 계산을 쉽게 하기 위해 모두 절대값을 구하였다.

if(x == y){
	returnAngle = 45;
}

x의 변화와 y의 변화가 같으면 45가 된다.

if(x <= y){
	returnAngle = 0;
	returnAngle += 45*x/y
}

y의 변화가 x의 변화보다 크다면 0~45도 사이가 될것이다. 기본으로 returnAngle 를 0으로 잡고

y의 변화가 크면 클수롤 0도에 가까워지고
그렇치 않으면 45에 가까워 질것이다.

그렇게 하기 위해 x를 y로 나눈 값을 45에 곱하였고. 그값을 0에서 더하였다.

else{
		returnAngle = 90;
		returnAngle -= 45*y/x
	}

반대로 y의 변화보다 x의 변화가 크면
45~90도 사이가 될것이다. x의 변화가 크면 클수록 90에 가까울것이다.

그렇게 하기 위해 y를 x로 나눈값을 -45에 곱하였고 그값을 90에 더하였다 (-값을 더함)

그렇게 해서 방향에 따른 개미의 머리 방향을 정하였다.

자 이걸 코드에 적용하여 정상적으로 작동하는지 보자!

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

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

getHeadAngle 함수와

  let tempCalcPoint;

이전좌표를 담기 위한 변수를 선언하고

  let calcPoint = drawBezier([0,0],[50,5],[70,130],[300,100],i);    
  let angle = 90;
  if(tempCalcPoint){
    angle = getHeadAngle(tempCalcPoint,calcPoint)
  }
  angleDrawImg(ctx,angle,img,calcPoint[0],calcPoint[1],img.width,img.height);

개미를 그리는 위치에 해당함수를 호출하여 리턴되는 각도값을 넣어주었다.

잘동작한다~~~~!

다음에 또 봐요~!

Leave a comment