코딩/1-JavaScript

04_캔버스충돌처리

tree0505 2025. 6. 12. 15:44
반응형
  • 04_캔버스충돌처리

  • _01_원과점충돌

  • 물리가 많이 있지만 그중 가장 기초적인 충돌
  • 충돌 
    • 원과 점 충돌 
    • 원과 원 충돌 
    • 원과 네모 충돌 
    • 네모와 네모 충돌 

  • 원과 점 충돌 
    • 내가 클릭할 수 있느냐. 
    • 원이 있으면 클릭할 수 있나 
    • 여기도 삼각함수가 들어간다. 
  • 원안에 점이 있다. 중심점과 마우스가 있다.
    • 마우스가 밖에 있나. 
    • 마우스가 원 안에 있나. 
    • 점이
    • 어떻게 측정을 하나. 
      • 점과 점을 삼각형을 그리면 된다. 
        • 점과 점 사이의 길이를 알면 된다. 
        • 이 길이가 원의 반지름 보다 작으면 원 안에 있는거고. 
        • 길이가 원의 반지름 보다 크면 원 밖에 있는거다. 
      • 대각선의 길이를 어떻게 구하나. 
        • X(제곱2)  Y(제곱2) Z(제곱2) 
          • 직각삼각형인 경우 
        • 가로와 세로는 알고 있는데. 대각선을 모른다. 

  • 어제 아날로그 시계는 뭐냐? 
    • 어제는 선과 각을 알고 있는데 
    • X와 Y를 구하고 싶은거고 
    • Y = Z * 코싸인 
    • X = Z * 싸인 
  • 오늘은 반대이다. 
    • X와 Y는 알고 있는데 
    • Z를 구하고 싶은것 
    • X(제곱) + Y(제곱)  = Z(제곱) 
      • Z(제곱)에 루트를 씌우면 Z를 구할 수 있다. 


  • X = 4 
  • Y = 3 
  • Z = 5 (이걸 모른다고 했을때)

 

  • X = 4 * 4 (제곱) = 16 
  • Y = 3 * 3 (제곱) = 9 
  • X(제곱) + Y(제곱) = Z(제곱)
  • X(제곱) 16 + Y(제곱) 9 = Z(제곱) = 25 
  • Z = 5이다. 루트를 씌우면 


  • _01_원과점충돌

  • arcAndPoint.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>원을 클릭하세요.</h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="arcAndPoint.js"></script>
    </body>
    </html>

  • arcAndPoint.js
    function draw() {
        // 캔버스를 지운다.
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 캔버스를 다시 그린다.
        drawArc();
    }
    //---------------------------------------
    //이 함수는 원을 그리는 함수입니다.
    // 조건에 따라 원의 색을 파란색 또는 빨간색으로 칠합니다.
    function drawArc(){
        ctx.beginPath();

        ctx.arc(x, y, radius, 0, angle);
        //ctx.arc() 함수는 원을 그리는 명령
        if(check){
            ctx.fillStyle = "red"; //충돌이 났으면 RED
        }else{
            ctx.fillStyle = "blue";
        }

        ctx.fill();
        ctx.closePath();
    }
    //-----------------------------------------------
    //함수 전체 목적
        // 원의 중심 좌표 (x, y)와
        // 마우스로 클릭한 좌표 (mx, my)를 비교해서
        // 클릭한 지점이 원의 안에 있는지를 true 또는 false로 리턴합니다.
    function getPointiInArc(x, y, mx, my) {
        //총 4개의 매개변수를 받습니다:
            // x, y: 원의 중심 좌표
            // mx, my: 마우스로 클릭한 위치
        /*
            제곱근을 구하는 함수
            Math.sqrt()
           
            절대값을 구하는 함수
            Math.abs()
        */

        let hypotenusePow = Math.abs((x - mx) * (x - mx) + (y - my) * (y - my));
        //abs => 절댓값을 썼다. 음수가 나올 수도 있으니까.
        //hypotenusePow =>Z(제곱)를 구한것
        //x - mx => 뺀 이유??
        //피타고라스의 정리를 이용해서 거리의 제곱을 계산합니다.
            //수학공식 : 거리(제곱) = (x - mx)(제곱) + (y-my)(제곱)  

        let hypotenuse = Math.sqrt(hypotenusePow);
        //sqrt => 제곱근 . 루트이다.
        //위에서 구한 거리의 제곱을 √로 계산하여 실제 거리를 구합니다.
            // 이 값은 클릭 지점과 원 중심 사이의 거리입니다

        console.log(x , " ", y, " ", mx, " ", my);
        console.log(hypotenuse, " ", radius);
        //hypotenuse => 루트를 씌우면 길이가 나온다.
        //radius => 반지름
        if(hypotenuse <= radius){
            //반지름보다 작으면
            return true; //충돌이 된것
            //거리 hypotenuse가 원의 반지름보다 작거나 같으면 → 클릭한 위치는 원 안에 있습니다.
                // 이 경우 true를 반환합니다.
        }
        return false;
    }
    //----------------------------------------------------
    //- `window` 전체에 클릭 이벤트를 감지합니다.  
        // 사용자가 **마우스로 클릭할 때마다** 이 콜백 함수가 실행됩니다.
        // `event`는 클릭 이벤트 객체이며, 클릭된 위치 정보 등을 담고 있습니다.
    window.addEventListener("click", (event) => {
        let mx = event.clientX - ctx.canvas.offsetLeft;
        let my = event.clientY - ctx.canvas.offsetTop;

        check = getPointiInArc(x, y, mx, my);
       
    });
    //-------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");
    //getContext("2d")는 2차원 그래픽을 그릴 수 있는 ctx라는 객체를 반환합니다

    let x = 300;        // 원의 중앙 x좌표
    //원의 중심의 x좌표입니다.
    // 캔버스 위의 가로 방향 기준으로, 중심이 300픽셀 떨어진 위치에 그리겠다는 뜻입니다.



    let y = 300;        // 원의 중앙 y좌표
    let radius = 150;
    let angle = Math.PI * 2;
    //원을 그릴 때 필요한 호의 각도입니다.
    // Math.PI * 2는 360도(=2π 라디안)입니다.
    // 즉, 전체 원을 그릴 수 있도록 설정해 둔 거예요.

    let check = false;
    //클릭했는지 여부를 나타내는 논리 변수입니다.
    // 나중에 이 값이 true가 되면 원의 색을 바꾸거나, 어떤 조건에 따라 다르게 행동하도록 만들 수 있습니다.

    setInterval(draw, 10);

 

 


  • _02_원과원충돌

  • 원과 원 충돌도 점 충돌이다. 
    • 원도 점이 2개가 있는거다. 
    • 충돌이 됬을때. 
      • 작은 원의 점과. 큰원의 점을 삼각형을 그린다. 
      • 작은원의 반지름과. 큰 원의 반지름을 더하면 
        • 이것보다 길면 충돌 X
        • 작으면 충돌 


  • arcAndArc.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1> 이동키 : A S D W </h1>
        <h1> 작은원을 이동시켜 큰원과 충돌시켜보세요. </h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="arcAndArc.js"></script>
    </body>
    </html>

  • arcAndArc.js
  • function draw() {

        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 그리는 순서에 따라 먼저 그려진다.
        // targetArc를 먼저 그렸기 때문에
        // 서로 겹쳤을 때, myArc가 위로 그려진다.
        drawArc(targetArc);
        drawArc(myArc);
        moveArc(myArc);

        getArcInArc(myArc, targetArc);
    }

    function getArcInArc(arc1, arc2){
        let x1 = arc1.x;
        let y1 = arc1.y;
        let radius1 = arc1.radius;

        let x2 = arc2.x;
        let y2 = arc2.y;
        let radius2 = arc2.radius;

        let hypotenusePow = Math.abs((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));
        let hypotenuse = Math.sqrt(hypotenusePow);
        let totalRadius = radius1 + radius2;
       
        if(hypotenuse <= totalRadius){
            arc1.color = "red"
        }else{
            arc1.color = "blue"
        }
    }

    function drawArc(arc){
        ctx.beginPath();
        ctx.arc(arc.x, arc.y, arc.radius, 0, Math.PI * 2);
        ctx.fillStyle = arc.color;
        ctx.fill();
        ctx.closePath();
    }

    function moveArc(arc){
        if(getKeyStay("left")){
            arc.x -= arc.speed;
        }
        if(getKeyStay("right")){
            arc.x += arc.speed;
        }
        if(getKeyStay("up")){
            arc.y -= arc.speed;
        }
        if(getKeyStay("down")){
            arc.y += arc.speed;
        }
       
    }

    //-------------------------------------------------

    function getKeyStay(key){
        return keyStay[key];
    }

    window.addEventListener("keydown", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = true;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = true;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = true;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = true;
        }

    });

    window.addEventListener("keyup", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = false;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = false;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = false;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = false;
        }

    });

    //----------------------------------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");

    let keyStay = {"right" : false, "left" : false, "up" : false, "down" : false};

    let myArc = {
        "x" : 100,
        "y" : 100,
        "radius" : 40,
        "speed" : 2,
        "color" : "blue"
    };

    let targetArc = {
        "x" : 300,
        "y" : 300,
        "radius" : 60,
        "color" : "green"
    };

    setInterval(draw, 10);

  • _03_네모와네모충돌

  • 파란 네모의 모서리가 초록 네모의 안에 있는지 검사 
  • 네모와 점 충돌과 같다. 

  • 만약 파란 네모가 초록네모 보다 크면? 
    • 클때는 안된다. 



  •    if(left1 < right2 && right1 > left2 && top1 < bottom2 && bottom1 > top2){
            return true;
        }
        return false;

  • _03_네모와네모충돌

  • rectAndRect.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1> 이동키 : A S D W </h1>
        <h1> 작은네모를 이동시켜 큰 네모와 충돌시켜보세요. </h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="rectAndRect.js"></script>
        <div class="testText"></div>

        <!--
        -->
    </body>
    </html>

  • rectAndRect.js
  • function draw(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);
       
        drawRect(targetRect)
        drawRect(myRect);
        moveRect(myRect);

        let check = getRectInRect(myRect, targetRect);
        if(check){
            myRect.color = "red";
        }else{
            myRect.color = "blue";
        }
    }

    function drawRect(rect){
        ctx.beginPath();
        ctx.rect(rect.x, rect.y, rect.width, rect.height);
        ctx.fillStyle = rect.color;
        ctx.fill();
        ctx.closePath();
    }

    function moveRect(rect){
        if(getKeyStay("left")){
            rect.x -= rect.speed;
        }
        if(getKeyStay("right")){
            rect.x += rect.speed;
        }
        if(getKeyStay("up")){
            rect.y -= rect.speed;
        }
        if(getKeyStay("down")){
            rect.y += rect.speed;
        }
    }

    function getRectInRect(r1, r2){
        let left1 = r1.x;
        let right1 = r1.x + r1.width;
        let top1 = r1.y;
        let bottom1 = r1.y + r1.height;

        let left2 = r2.x;
        let right2 = r2.x + r2.width;
        let top2 = r2.y;
        let bottom2 = r2.y + r2.height;

        //점 충돌보다 더 정확한 충돌  
        if(left1 < right2 && right1 > left2 && top1 < bottom2 && bottom1 > top2){
            return true;
        }
        return false;
    }

    //-------------------------------------------------

    function getKeyStay(key){
        return keyStay[key];
    }

    window.addEventListener("keydown", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = true;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = true;
        }
        if(e.code == 'KeyW') {  
            keyStay.up = true;
        }
        if(e.code == 'KeyS') {
            keyStay.down = true;
        }
     
    });

    window.addEventListener("keyup", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = false;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = false;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = false;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = false;
        }
       
    });

    //----------------------------------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");

    let keyStay = {"right" : false , "left" : false, "up" : false, "down" : false};

    let myRect = {
        "x" : 100,
        "y" : 100,
        "width" : 50,
        "height" : 50,
        "speed" : 2,
        "color" : "blue"
    };

    let targetRect = {
        "x" : 180,
        "y" : 180,
        "width" : 80,
        "height" : 80,
        "color" : "green"
    };

    setInterval(draw, 10);

  • _04_네모와원충돌

  • 네모와 원 충돌 
    • 1. 네모에다가 원 반지름 만큼. 더 큰 네모를 만든다. 
      • 원의 점이 네모 안에 있으면 충돌 
      • 충돌이 2개 필요하다. 
      • 피타고라스로 구할 수 있다. 
    • 2. 네모의 꼭짓점이 원 안에 있으면 충돌 


  • 충돌을 마스터 할려면 미적분을 마스터 해야한다. 

  • _04_네모와원충돌

  • rectAndArc.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1> 이동키 : A S D W </h1>
        <h1> 작은네모를 이동시켜 큰 원과 충돌시켜보세요. </h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="rectAndArc.js"></script>
        <div class="testText"></div>
    </body>
    </html>

  • rectAndArc.js
  • function draw(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        drawArc(targetArc)
        drawRect(myRect);
        moveRect(myRect);

        let check = collisionRectAndArc(myRect, targetArc);
        if(check){
            myRect.color = "red";
        }else{
            myRect.color = "blue";
        }

        //-------------------------------------------------------
       
        // 이해를 돕기 위해 원의 중앙 점을 노란색으로 표시
        ctx.beginPath();
        ctx.arc(targetArc.x, targetArc.y, 2, 0, Math.PI * 2);
        ctx.fillStyle = "yellow";
        ctx.fill();
        ctx.closePath();
        // 이해를 돕기 위해 사각형 가이드 선 표시
        let tempRect = {
            x : myRect.x - targetArc.radius,
            y : myRect.y - targetArc.radius,
            width : myRect.width + targetArc.radius * 2,
            height : myRect.height + targetArc.radius * 2
        };
        ctx.beginPath();
        ctx.rect(tempRect.x, tempRect.y, tempRect.width, tempRect.height);
        ctx.stroke();
        ctx.closePath();
       
    }

    function drawArc(arc){
        ctx.beginPath();
        ctx.arc(arc.x, arc.y, arc.radius, 0, Math.PI * 2);
        ctx.fillStyle = arc.color;
        ctx.fill();
        ctx.closePath();
    }

    function drawRect(rect){
        ctx.beginPath();
        ctx.rect(rect.x, rect.y, rect.width, rect.height);
        ctx.fillStyle = rect.color;
        ctx.fill();
        ctx.closePath();
    }

    function moveRect(rect){
        if(getKeyStay("left")){
            rect.x -= rect.speed;
        }
        if(getKeyStay("right")){
            rect.x += rect.speed;
        }
        if(getKeyStay("up")){
            rect.y -= rect.speed;
        }
        if(getKeyStay("down")){
            rect.y += rect.speed;
        }
    }

    function getPointInRect(arcX, arcY, rect){
        let left = rect.x;
        let right = rect.x + rect.width;
        let top = rect.y;
        let bottom = rect.y + rect.height;
     
        if(left < arcX && arcX < right && top < arcY && arcY < bottom ){
            return true;
        }
        return false;
    }

    function getPointInArc(x, y, arc){
       
        let hypotenusePow = Math.abs((x - arc.x) * (x - arc.x) + (y - arc.y) * (y -arc.y));
        let hypotenuse = Math.sqrt(hypotenusePow);
        if(hypotenuse <= arc.radius){
            return true;
        }
        return false;
    }

    function collisionRectAndArc(rect, arc){
        // [조건1] 원의 반지름 만큼 사각형을 네방향으로 확장한 후,
        // 원의 중심점이 그 사각형 안에 있다면 충돌
        let tempRect = {        // 가이드 사각형 크기설정
            x : rect.x - arc.radius,
            y : rect.y - arc.radius,
            width : rect.width + arc.radius * 2,
            height : rect.height + arc.radius * 2
        };

        // 원의 중앙점이 가이드 사각형의 1, 3번 안에 있는지 확인
        if((rect.x < arc.x && arc.x < rect.x + rect.width)
            // 또는 원의 중앙점이 가이드 사각형의 2, 4번 안에 있는지 확인
            || (rect.y < arc.y && arc.y < rect.y + rect.height)) {
            // 원의 중앙점이 1, 2, 3, 4번에 있는지 확인
            if(getPointInRect(arc.x, arc.y, tempRect)){
                return true;
            }
        }

        // [조건2] 예외적으로 대각선 쪽으로 왔을땐 사각형 꼭지점들이
        // 원 안에 있는지 확인(점-원 충돌)
        if(getPointInArc(rect.x, rect.y, arc)){
            return true;
        }

        if(getPointInArc(rect.x + rect.width, rect.y, arc)){
            return true;
        }

        if(getPointInArc(rect.x, rect.y + rect.height, arc)){
            return true;
        }

        if(getPointInArc(rect.x + rect.width, rect.y + rect.height, arc)){
            return true;
        }

        // 찾는 값이 있으면 화면에 띄우면서 찾는다.
        $testText = document.querySelector(".testText");
        let temp = `체크 사각형 : ${tempRect.x} , ${tempRect.y} , ${tempRect.width} , ${tempRect.height} <br><br>`;
        temp += `원본 사각형 : ${rect.x} , ${rect.y} , ${rect.width} , ${rect.height} <br><br>`;
        temp += `원 : ${arc.x} , ${arc.y}, ${arc.radius} <br><br>`;
        $testText.innerHTML = temp;

        return false;
    }
    //----------------------------------------------------------------

    function getKeyStay(key){
        return keyStay[key];
    }

    window.addEventListener("keydown", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = true;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = true;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = true;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = true;
        }
    });

    window.addEventListener("keyup", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = false;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = false;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = false;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = false;
        }
    });

    //----------------------------------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");

    let keyStay = {"right" : false, "left" : false, "up" : false, "down" : false};

    let myRect = {
        "x" : 80,
        "y" : 80,
        "width" : 50,
        "height" : 50,
        "speed" : 2,
        "color" : "blue"
    };

    let targetArc = {
        "x" : 200,
        "y" : 200,
        "radius" : 80,
        "color" : "green"
    };

    setInterval(draw, 10);

  • _05_원과원리스트충돌
    • 배열 쓰면 된다. 

  • arcAndArcList.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1> 이동키 : A S D W </h1>
        <h1>작은 원을 큰원들과 충돌시켜보세요.</h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="arcAndArcList.js"></script>
        <div class="testText"></div>
    </body>
    </html>

  • arcAndArcList.js
  • function init(size){
        for(let i = 0; i < size; i++){

            let originx = 100;
            let originy = 300;
            let gap = 100;
            let radius = 50;

            let startx = originx + i * radius + i * gap;

            let targetArc = {
                "x" : startx,
                "y" : originy ,
                "radius" : radius,
                "color" : "green"
            };

            targetList.push(targetArc);
        }
    }

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 그리는 순서에 따라 먼저 그려진다.
        for(let v of targetList){
            drawArc(v);
        }

        drawArc(myArc);
        moveArc(myArc);
        collisionList(myArc, targetList);
       
        $testText = document.querySelector(".testText");
        let temp = `${myArc.x} , ${myArc.y} <br><br>`;
        for(v of targetList){
           temp += `${v.x} , ${v.y} <br>`;
        }
        $testText.innerHTML = temp;
    }

    function drawArc(arc){
        ctx.beginPath();
        ctx.arc(arc.x, arc.y, arc.radius, 0, Math.PI * 2);
        ctx.fillStyle = arc.color;
        ctx.fill();
        ctx.closePath();
    }

    function moveArc(arc){
        if(getKeyStay("left")){
            arc.x -= arc.speed;
        }
        if(getKeyStay("right")){
            arc.x += arc.speed;
        }
        if(getKeyStay("up")){
            arc.y -= arc.speed;
        }
        if(getKeyStay("down")){
            arc.y += arc.speed;
        }
    }

    function collisionList(arc, arcList){
        let count = 0;
        for(let v of arcList){
            count += getArcInArc(myArc, v);
        }
        if(count == targetList.length){
            arc.color = "blue";
        }else{
            arc.color = "red";
        }
    }

    function getArcInArc(arc1, arc2){
        let x1 = arc1.x;
        let y1 = arc1.y;
        let radius1 = arc1.radius;

        let x2 = arc2.x;
        let y2 = arc2.y;
        let radius2 = arc2.radius;

        let hypotenusePow = Math.abs((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));
        let hypotenuse = Math.sqrt(hypotenusePow);
        let totalRadius = radius1 + radius2;

        if(hypotenuse <= totalRadius){
            return 0;
        }
        return 1;
    }

    //-------------------------------------------------

    function getKeyStay(key){
        return keyStay[key];
    }

    window.addEventListener("keydown", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = true;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = true;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = true;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = true;
        }

    });

    window.addEventListener("keyup", (e) => {
        if(e.code == 'KeyD') {        
            keyStay.right = false;
        }
        if(e.code == 'KeyA') {  
            keyStay.left = false;
        }
        if(e.code == 'KeyW') {    
            keyStay.up = false;
        }
        if(e.code == 'KeyS') {  
            keyStay.down = false;
        }

    });

    //----------------------------------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");

    let keyStay = {"right" : false, "left" : false, "up" : false, "down" : false};
    let myArc = {
        "x" : 100,
        "y" : 100,
        "radius" : 40,
        "speed" : 2,
        "color" : "blue"
    };

    let targetList = []
    init(5);
    setInterval(draw, 10);



  • _06_네모클릭이동

  • rectClickMove.html
  • <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>네모를 클릭후 마우스버튼을 때지말고 이동시켜보세요.</h1>
        <canvas id="myCanvas" width="800" height="600" style="border: 1px solid black;">
        </canvas>
        <script src="rectClickMove.js"></script>
        <div class="testText"></div>
    </body>
    </html>

  • rectClickMove.js
  • function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawRect(myRect);
        changeColor(myRect);
    }

    function drawRect(rect){
        ctx.beginPath();
        ctx.rect(rect.x, rect.y, rect.width, rect.height);
        ctx.fillStyle = rect.color;
        ctx.fill();
        ctx.closePath();
    }

    function getPointInRect(x, y, rc){
        let left = rc.x;
        let right = rc.x + rc.width;
        let top = rc.y;
        let bottom = rc.y + rc.height;
        if(left < x && x < right && top < y && y < bottom){
            return true;
        }
        return false;
    }

    function changeColor(rect){
        if(rect.state == "none"){
            rect.color = "blue";
        }else if(rect.state == "over"){
            rect.color = "red";
        }else if(rect.state == "click"){
            rect.color = "green"
        }
    }

    //-------------------------------------------------
    /*
        mousedown : 마우스 클릭할 때
        mousemove : 마우스가 움직일 때
        mouseup : 마우에서 손을 뗄 때
    */

    window.addEventListener("mousedown", (event) => {
        let mx = event.clientX - ctx.canvas.offsetLeft;
        let my = event.clientY - ctx.canvas.offsetTop;
        if(getPointInRect(mx, my, myRect)){
            myRect.state = "click";
            myRect.gapX = mx - myRect.x;
            myRect.gapY = my - myRect.y;
        }
    });

    window.addEventListener("mousemove", (event) =>{
        let mx = event.clientX - ctx.canvas.offsetLeft;
        let my = event.clientY - ctx.canvas.offsetTop;
        if(myRect.state == "click"){
            myRect.x = mx - myRect.gapX;
            myRect.y = my - myRect.gapY;
            return;
        }
       
        if(getPointInRect(mx, my, myRect)){
            myRect.state = "over";
        }else{
            myRect.state = "none";
        }
    });

    window.addEventListener("mouseup", (event) => {
        let mx = event.clientX - ctx.canvas.offsetLeft;
        let my = event.clientY - ctx.canvas.offsetTop;
        if(getPointInRect(mx, my, myRect)){
            myRect.state = "over";
        }else{
            myRect.state = "none";
        }
    });

    //----------------------------------------------------------------------------
    let canvas = document.getElementById("myCanvas");
    let ctx = canvas.getContext("2d");

    let myRect = {
        "x" : 100,
        "y" : 100,
        "width" : 150,
        "height" : 150,
        "color" : "blue",
        "state" : "none", // none, over, click
        "gapX" : 0,
        "gapY" : 0
    };

    setInterval(draw, 10);



 

반응형

'코딩 > 1-JavaScript' 카테고리의 다른 글

E02_애니메이션 => 01단계_타이틀  (0) 2025.06.13
05_게임_오목  (0) 2025.06.12
03_캔버스키보드  (2) 2025.06.12
_05_버튼이미지 ~ _09_삼각함수 ( 4 ~ 7 )  (0) 2025.06.11
_05_버튼이미지 ~ _09_삼각함수 ( 1 ~ 3 )  (1) 2025.06.11