벽돌깨기게임 마우스 패들 캔버스에 가두기

이명진·2021년 2월 25일
0

들어가기 전에..

벽돌깨기 플래시 게임을 이전에 만들어둔게 있었는데 좌우로 이동하면 패들의 반이 밖으로 이동한다. 그 당시에는 만드는데 급급하였기 때문에 넘어갔지만 문제점을 듣고 발견하게 되어서 고민을 해보게 되었다.
혼자 공부하고 이해했기 때문에 맞는 내 생각이 맞는건지 모르겠다.
제 생각 대한 비판이나 이견이 있으신 분들은 댓글로 달아주시면 저의 문제해결에 큰 도움이 될것입니다.

벽돌깨기 패들 수정

마우스 움직임에 따라 패들 이동 하기

function mouseMoveHandler(e) {
    var relativeX = e.clientX - canvas.offsetLeft;
    if(relativeX > 0 && relativeX < canvas.width) {
        paddleX = relativeX - paddleWidth/2;
    }
}

문제의 코드 ..

https://developer.mozilla.org/ko/docs/Games/Tutorials/순수한자바스크립트를이용한2D벽돌깨기게임/Mouse_controls#마우스움직임에따라패들이동하기

지금 다시 찾아보니 글작성자는 "Exercise: 패들이 캔버스 양쪽 가장자리에서 반만 잘려나가 보일 것 입니다. 패들 이동 제한 경계를 조정해 보세요." 라는 과제를 남겼다.

문제처럼 벽돌 게임을 실행하면 패들의 반은 잘려나간다.
아래는 제가 만든 게임이니 한번 시도해보시길 바랍니다 .
https://leemj0948.github.io/FlashGame/

플레이 안해보시는분들을 위해 사진을 첨부합니다.

패들 반이 잘려나갑니다.

이론의 글작성자는 코드와 함께 해설을 남겨두었습니다.
하지만 한글로 번역해서 그런지.. 공부를 덜해서 그런지 해설도 어려웠습니다.

이 함수에서 우리는 먼저 상대적인 relativeX 를 구합니다. 이 값은 뷰포트(e.clientX)와 캔버스 왼쪽 가장자리 (canvas.offsetLeft) 사이의 거리에 마우스 위치를 뺀 값입니다. 상대적인 X 포인터 위치가 0보다 크고 캔버스 폭보다 적으면 포인터가 경계 내에 있게 되고, paddleX의 위치(패들 왼쪽 가장자리에 배치되어 있다)는 패들 width의 반을 뺀 relativeX의 값으로 설정되므로 이동은 실제로 패들 가운데 상대적으로 이동이 됩니다.

설명을 해주었지만뷰포트?도 무엇인지 몰랐고 왜 마우스 위치를 빼야 하는지도 몰랐다. 그래서 직접 실험을 해보며 코드를 수정하게 되었고 왼쪽을 밖으로 안나가지는 경우와 오른쪽 밖으로 안나가지는 경우를 발견하게 되었습니다.

case study

function mouseMoveHandler(event){
    let relativeX = event.clientX - MC.offsetLeft ;
  
    if(relativeX > 0 ){ //왼쪽을 막는다. relativeX < 0 
      paddleX = relativeX 
    }
}

이 코드를 사용하면 왼쪽으로 패들이 나가지 않는다.

function mouseMoveHandler(event){
    let relativeX = event.clientX - MC.offsetLeft ;
 
    
   
    if(relativeX > 0 &&relativeX < MC.width ){ //오른쪽을 막는다. relativeX < 0 
      paddleX = relativeX - paddleWeight
    }
}

이 코드를 사용하면 오른쪽으로 패들이 나가지 않는다.

두가지 조건을 발견하였고 이 두가지를 조합해보면 가능하지 않을까 생각하며 else if 절을 이용하여 조합해보았지만 실패하였습니다.
몇번의 조합을 해본 결과 약간 부족한 성공에 도달할수 있었고 그 성공 코드는 마지막에 올리겠습니다.

제가 이해한 코드 해설은 이렇습니다.

let relativeX = event.clientX - MC.offsetLeft ;

e.clientX는 가로축으로 움직이는 값을 나타내는걸로 MDN에서 찾을수 있었습니다. 또한 canvas.offsetLeft는 캔버스가 시작되는 x값 좌측의 여백을 의미한다고 합니다.
그래서 결과적으로는 relativeX값은 MC.offsetLeft값을 뺀 값이기에 캔버스 왼쪽을 0값으로 만들어 줍니다.

그래서 아래의 코드를 분석 하면

if(relativeX > 0 ){ //왼쪽을 막는다. relativeX < 0 
      paddleX = relativeX 
    }
}

if절의 안의 paddlexX값은 패들 안의 마우스의 위치값으로 이해했습니다.
조건 절의 값은 0보다 큰 값이기 때문에 캔버스 왼쪽이 0값이기 때문에 왼쪽으로 갈수 가 없고 0부터 시작하여 오른쪽으로 진행합니다.
paddleX = event.clientX - MC.offsetLeft 이 값이기 때문에 패들 안 마우스는 맨 왼쪽에 위치하고 마우스는 0값을 벗어나지 못하기에 왼쪽을 벗어나지 않습니다.

이와 반대의 경우인 paddleX = relativeX - paddleWeight는 paddle weidgh를 뺀값이기 때문에 패들 안 마우스 위치는 패들의 오른쪽끝에 가있습니다. 그래서 오른쪽을 벗어나지 않게 된다고 이해하게 되었습니다.

아래는 제가 발견하게된 임시 성공 코드입니다.

function mouseMoveHandler(event){
    let relativeX = event.clientX - MC.offsetLeft ;
    let relativeY = event.clientX * 0;
    
    if(relativeX < 0 ){ //왼쪽을 막는다. relativeX < 0 
        paddleX = relativeY
    
    // paddleX = relativeX - paddleWeight/2   relativeX > 0 && relativeX < MC.width
    }
    else if( relativeX > 0 &&relativeX < MC.width) { // 오른쪽을 막는다. 
        paddleX = relativeX  - paddleWeight
    }
    
}

패들안 마우스 값을 오른쪽으로 설정하였고 마우스가 0값부터 캔버스 너비 안에 있을 경우에는 오른쪽을 막다가 실제 마우스가 캔버스 왼쪽 끝에 도달하면 패들 마우스 값은 맨 오른쪽 값이기 때문에 패들이 오른쪽만 빼고 사라지집니다. 하지만 오른쪽 끝이 0값이하에 도달하는 순간 (패들 오른쪽 끝이 왼쪽 끝에 닿게 되는 순간) 위치 좌표를 0값을 주게되어서 나가는 순간 왼쪽으로 패들이 다시 리스폰되어 왼쪽이 막히는 현상을 줄수 있습니다.

아직까지는 임시 방편이지만 완벽하게 좌우로 나가지 않게 막기위해서 더 연구해봐야 할것 같습니다. 정리를 하면서도 이해하기 어려웠는데 제가 이해한 방향이 맞는지도 애매합니다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글