23.01.17(Js)

MH S·2023년 1월 17일

Js

목록 보기
2/5

게임 만들기

<!DOCTYPE html>
<html lang="en">
  <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>
    <div id="btn">커스텀 버튼</div>
    <div id="content">내용</div>
  </body>
  <script>
    // const func = () => console.log("함수");
    // func();

    // (() => {
    //   console.log("함수");
    // })();

    const btn = document.getElementById("btn");
    // btn.onclick = () => {
    //   const content = document.getElementById("content");
    //   if (content.style.display == "none") {
    //     content.style.display = "block";
    //   } else {
    //     content.style.display = "none";
    //   }
    //   /// console.log(content.style.display);
    // };

    btn.addEventListener("click", () => {
      const content = document.getElementById("content");
      if (content.style.display == "none") {
        content.style.display = "block";
      } else {
        content.style.display = "none";
      }
    });
  </script>
</html>
<버튼 추가 3가지 방식>
1. 보통 html 안에 버튼 선언을 많이함 ex) div id="btn"
2. script 안에 함수를 선언
3. script 안에 addEventListener 를 선언
총 3가지 방식을 사용.

<!DOCTYPE html>
<html lang="en">
  <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>
    <canvas id="myCanvas"></canvas>
  </body>
  <script>
    //그림판
    /** @type {HTMLCanvasElement} */
    const myCanvas = document.getElementById("myCanvas");
    myCanvas.width = 500;
    myCanvas.height = 300;
    myCanvas.style.backgroundColor = "gray";

    //그림 그리는 역할
    /** @type {CanvasRenderingContext2D} */
    const context = myCanvas.getContext("2d");

    //도형 그리기 시작
    context.beginPath();
    //동그라미 그리기
    context.arc(50, 50, 50, 0, 2 * Math.PI);
    //동그라미 색상
    context.fillStyle = "blue";
    //그리기 완료
    context.fill();

    context.fillStyle = "red";
    //사각형 그리기
    context.fillRect(200, 50, 100, 50);

    //글쓰기
    context.font = "30px Arial";
    context.fillStyle = "black";
    context.fillText("안녕하세요", 300, 50);
  </script>
</html>

<배경에 동그라미, 사각형 그리기 예제>
<!DOCTYPE html>
<html lang="en">
  <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>
    <canvas id="myCanvas"></canvas>
  </body>
  <script>
    let circleX = 50;
    let circleY = 50;

    // 그림판
    /** @type {HTMLCanvasElement} */
    const myCanvas = document.getElementById("myCanvas");
    myCanvas.width = 500;
    myCanvas.height = 300;
    myCanvas.style.backgroundColor = "gray";

    // 그림 그리는 역할
    /** @type {CanvasRenderingContext2D} */
    const context = myCanvas.getContext("2d");

    // 도형 그리기 시작
    context.beginPath();
    // 동그라미
    context.arc(circleX, circleY, 10, 0, 2 * Math.PI);
    // 색깔
    context.fillStyle = "blue";
    // 그리기 완료
    context.fill();

    document.onkeyup = (event) => {
      console.log(event);
      if (event.keyCode == 39) {
        context.clearRect(0, 0, myCanvas.width, myCanvas.height);
        circleX = circleX + 25;
        context.beginPath();
        context.arc(circleX, circleY, 10, 0, 2 * Math.PI);
        context.fillStyle = "blue";
        context.fill();
      } else if (event.keyCode == 40) {
        context.clearRect(0, 0, myCanvas.width, myCanvas.height);
        circleY = circleY + 25;
        context.beginPath();
        context.arc(circleX, circleY, 10, 0, 2 * Math.PI);
        context.fillStyle = "blue";
        context.fill();
      }
    };
  </script>
</html>

<동그라미 방향키로 이동하는 예제>
<!DOCTYPE html>
<html lang="en">
  <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>
    <canvas id="myCanvas"></canvas>
  </body>
  <script>
    let circleX = 50;
    let circleY = 50;
    let rightKeyPressed = false;
    let leftKeyPressed = false;

    // 그림판
    /** @type {HTMLCanvasElement} */
    const myCanvas = document.getElementById("myCanvas");
    myCanvas.width = 500;
    myCanvas.height = 300;
    myCanvas.style.backgroundColor = "gray";

    // 그림 그리는 역할
    /** @type {CanvasRenderingContext2D} */
    const context = myCanvas.getContext("2d");

    const draw = () => {
      if (rightKeyPressed) {
        circleX = circleX + 1;
      } else if (leftKeyPressed) {
        circleY = circleY + 1;
      }
      context.clearRect(0, 0, myCanvas.width, myCanvas.height);
      context.beginPath();
      context.arc(circleX, circleY, 10, 0, 2 * Math.PI);
      context.fillStyle = "blue";
      context.fill();
    };

    document.onkeydown = (event) => {
      if (event.keyCode == 39) {
        rightKeyPressed = true;
      } else if (event.keyCode == 40) {
        leftKeyPressed = true;
      }
    };
    document.onkeyup = (event) => {
      if (event.keyCode == 39) {
        rightKeyPressed = false;
      } else if (event.keyCode == 40) {
        leftKeyPressed = false;
      }
    };

    // document.onkeyup = (event) => {
    //   console.log(event);
    //   if (event.keyCode == 39) {
    //     circleX = circleX + 25;
    //   } else if (event.keyCode == 40) {
    //     circleY = circleY + 25;
    //   } else if (event.keyCode == 37) {
    //     circleX = circleX - 25;
    //   } else if (event.keyCode == 38) {
    //     circleY = circleY - 25;
    //   }
    // };

    setInterval(draw, 100);
  </script>
</html>
<동그라미 방향키 누를시 쭉 이동하는 예제>
<!DOCTYPE html>
<html lang="en">
  <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>
    <canvas id="myCanvas"></canvas>
  </body>
  <script>
    //그림판
    /** @type {HTMLCanvasElement} */
    const myCanvas = document.getElementById("myCanvas");
    myCanvas.width = 500;
    myCanvas.height = 300;
    myCanvas.style.backgroundColor = "gray";

    //그림 그리는 역할
    /** @type {CanvasRenderingContext2D} */
    const context = myCanvas.getContext("2d");

    //도형 그리기 시작
    context.beginPath();
    //동그라미 그리기
    context.arc(50, 50, 50, 0, 2 * Math.PI);
    //동그라미 색상
    context.fillStyle = "blue";
    //그리기 완료
    context.fill();

    context.fillStyle = "red";
    //사각형 그리기
    context.fillRect(200, 50, 100, 50);

    //글쓰기
    context.font = "30px Arial";
    context.fillStyle = "black";
    context.fillText("안녕하세요", 300, 50);

    const image = new Image();
    image.src = "./asset/img/mole.png";
    image.onload = () => {
      //이미지 로딩이 되면 실행
      context.drawImage(image, 100, 100, 100, 100);
    };
  </script>
</html>

<그림 넣는 예제>

두더지 게임

<!DOCTYPE html>
<html lang="en">
  <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>
    <canvas id="moleGame"></canvas>
  </body>
  <script>
    // 두더지
    class Mole {
      constructor(game, index, x, y) {
        this.idx = index;
        this.x = x;
        this.y = y;
        this.attacked = false;

        setTimeout(() => {
          // 두더지 사라짐
          game.moleArray[this.idx] = null;
          if (!this.attacked) {
            // fail점수 상승
            game.fail++;
          }
        }, 1500);
      }
    }

    // 두더지 게임
    class MoleGame {
      constructor(canvas) {
        // 게임 설정 데이터
        this.gameWidth = 350;
        this.gameHeight = 700;
        this.gameLevel = 1;
        this.genMole = 2;
        this.moleArray = new Array(9).fill(null);
        this.score = 0;
        this.fail = 0;
        this.moleInterval = null;
        this.renderInterval = null;

        // 캔버스
        /** @type {HTMLCanvasElement} */
        this.canvas = canvas;
        this.canvas.width = this.gameWidth;
        this.canvas.height = this.gameHeight;

        // 컨텍스트
        /** @type {CanvasRenderingContext2D} */
        this.ctx = this.canvas.getContext("2d");

        // 배경 이미지
        this.bgImage = new Image();
        this.bgImage.src = "./asset/img/bg.jpg";

        // 두더지 이미지
        this.moleImage = new Image();
        this.moleImage.src = "./asset/img/mole_r.png";

        // 공격 이펙트 이미지
        this.boomImage = new Image();
        this.boomImage.src = "./asset/img/boom.png";

        // 에셋 로딩 예시
        // const imgArray = [this.bgImage, this.moleImage, this.boomImage];
        // imgArray.length;
        // imgArray.filter((value) => value.complete).length;

        // 공격
        this.canvas.onmousedown = (event) => {
          this.moleArray.forEach((mole) => {
            // mole이 null이 아니고
            // 공격당한 mole이 아니고
            // mole 이미지가 있는 범위 안
            if (
              mole != null &&
              !mole.attacked &&
              event.clientX > mole.x &&
              event.clientX < mole.x + 85 &&
              event.clientY > mole.y &&
              event.clientY < mole.y + 96
            ) {
              mole.attacked = true;
              this.score++;
            }
          });
        };

        // 두더지 생성
        this.moleInterval = setInterval(() => {
          // 2마리 카운트
          // 랜덤 위치 정해주기
          // 생성해서 배열에 넣기
          // 9마리가 꽉 차면 생성하지 않기
          let count = this.genMole;
          while (count > 0) {
            if (this.moleArray.some((mole) => mole == null)) {
              const tempIndex = Math.floor(Math.random() * 9);
              if (this.moleArray[tempIndex] == null) {
                this.moleArray[tempIndex] = new Mole(
                  this,
                  tempIndex,
                  (tempIndex % 3) * 107 + 20, //x좌표
                  Math.floor(tempIndex / 3) * 143 + 200 //y좌표
                );
                count = count - 1;
              }
            } else {
              break;
            }
          }
        }, 1000 / this.gameLevel);

        // 화면 그리기
        this.render();
      }

      render() {
        this.renderInterval = setInterval(() => {
          // 게임 종료 조건
          if (this.fail > this.genMole * 2.5) {
            this.over();
          }
          // 화면 클리어
          this.ctx.clearRect(0, 0, this.gameWidth, this.gameHeight);

          // 배경그리기
          this.ctx.drawImage(
            this.bgImage,
            0,
            0,
            this.gameWidth,
            this.gameHeight
          );

          // 두더지 그리기
          this.moleArray.forEach((mole) => {
            if (mole == null) return;
            this.ctx.drawImage(this.moleImage, mole.x, mole.y, 85, 96);
            if (mole.attacked) {
              this.ctx.drawImage(this.boomImage, mole.x, mole.y, 85, 96);
            }
          });

          // 점수 / 실패
          this.ctx.font = "30px Arial";
          this.ctx.fillText(`score: ${this.score}`, 20, 30);
          this.ctx.fillText(`fail: ${this.fail}`, 160, 30);
        }, 100);
      }

      over() {
        // interval 멈추기
        clearInterval(this.moleInterval);
        clearInterval(this.renderInterval);
        alert("게임오버");
      }
    }

    alert("게임시작");

    new MoleGame(document.getElementById("moleGame"));
  </script>
</html>

<두더지 게임 결과>

JSON

  • 객체를 문자로 만드는 것 JSON
  • 통신 데이터는 모두 문자열로 이루어지기 때문에 JSON을 통해 문자열 변환

https://www.data.go.kr/index.do
(공공데이터포털 - api활용)

API 통신

공공데이터를 활용한 api 연동

  1. 크롬 확장 프로그램 JSON Formatter 다운

  2. 공공데이터포털에서 api 승인 이후 다음 그림과 같이 선택

  3. json으로 연 웹페이지 주소 복사

  1. 다음 예제 코드를 통해 api 연동 및 수정

UC_SEQ, MAIN_TITLE 과 같은 상수를 활용해 ${value. } 를 통해 활용해 코드 작성

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Bootstrap Example</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <nav class="navbar navbar-expand-sm navbar-dark bg-dark">
      <div class="container-fluid">
        <a class="navbar-brand" href="javascript:void(0)">Logo</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#mynavbar"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="mynavbar">
          <ul class="navbar-nav me-auto">
            <li class="nav-item">
              <a class="nav-link" href="javascript:void(0)">Link</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="javascript:void(0)">Link</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="javascript:void(0)">Link</a>
            </li>
          </ul>
          <form class="d-flex">
            <input class="form-control me-2" type="text" placeholder="Search" />
            <button class="btn btn-primary" type="button">Search</button>
          </form>
        </div>
      </div>
    </nav>
    <div class="container">
      <div
        id="cardGroup"
        class="card-group row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4 row-cols-xxl-5"
      ></div>
      <!--창크기에 따라 카드가 1,2,3,4,5열씩 나열-->
    </div>
  </body>
  <script>
    fetch(
      "https://apis.data.go.kr/6260000/AttractionService/getAttractionKr?serviceKey=KmPzcGQ5PCcraF4sRF2nw3lzJFd%2FO32LKptEAZtAFZXe8y8cBaNU8xo5HXLMQhmQvo0hbUPQawobLltt%2FX25YQ%3D%3D&pageNo=1&numOfRows=10&resultType=json"
    ) //공공데이터에 가져온 api 링크 추가
      .then((res) => res.json()) //json 형식으로 변환
      .then((response) => {
        const cards = response.getAttractionKr.item; //api 데이터 변환

        const cardGroup = document.getElementById("cardGroup");

        cards.forEach((value, index) => {
          //col m-3 -> 카드 사이 넓이 3 으로 고정
          cardGroup.insertAdjacentHTML(
            "beforeend",
            `<div class="col "> 
          <div class="card m-3">
            <img
              src="${value.MAIN_IMG_THUMB}"
              class="card-img-top"
              alt="..."
            />
            <div class="card-body">
              <h5 class="card-title">
                <a href="${value.HOMEPAGE_URL}" target="_blank">${value.MAIN_TITLE}</a>
                </h5>
              <p class="card-text">
                ${value.TITLE}, ${value.SUBTITLE}
              </p>
              <p class="card-text">
                <small class="text-muted">${value.CNTCT_TEL}</small>
              </p>
            </div>
          </div>
        </div>`
          );
        });
      });

    // const cards = [0, 0, 0, 0, 0, 0, 0];
    const cards = new Array(7).fill(0);
    /*
    const cardGroup = document.getElementById("cardGroup");

    cards.forEach((value, index) => {
      //col m-3 -> 카드 사이 넓이 3 으로 고정
      cardGroup.insertAdjacentHTML(
        "beforeend",
        `<div class="col "> 
          <div class="card m-3">
            <img
              src="https://w.namu.la/s/dc42bb0527e08b0d65f370f3a8ad1c471ccbd90a5f01b85343e6471c7f4100486b9be8514d380c33651c70fdc1c7da610cd2effaa9696b1226d29082faa22131e41b8bd7a75491abd0819c4789a517c0f34511a2defbefe71296ccb382a08b337ae0c3be5daae0f3da9ad3fb8934625c"
              class="card-img-top"
              alt="..."
            />
            <div class="card-body">
              <h5 class="card-title">Card title ${index}</h5>
              <p class="card-text">
                This is a wider card with supporting text below as a natural
                lead-in to additional content. This content is a little bit
                longer.
              </p>
              <p class="card-text">
                <small class="text-muted">Last updated 3 mins ago</small>
              </p>
            </div>
          </div>
        </div>`
      );
    });*/
  </script>
</html>

<결과 화면>

0개의 댓글