웹 블록 회피 게임 만들기

JavaScriptBeginner
지금 연습하기

소개

이 프로젝트에서는 HTML, CSS, JavaScript 를 사용하여 재미있고 간단한 블록 회피 게임을 만들어 볼 것입니다. 이 게임은 플레이어가 검은색 블록을 클릭하여 점수를 얻고 흰색 블록을 클릭하지 않도록 하는 블록 이동 게임입니다. 단계별로 만들어 봅시다!

👀 미리보기

block avoidance game preview

🎯 과제

이 프로젝트에서 다음을 배우게 됩니다.

  • HTML 을 사용하여 게임 레이아웃을 디자인하는 방법
  • CSS 를 사용하여 게임에 스타일을 추가하는 방법
  • JavaScript 를 사용하여 기본적인 게임 로직을 구현하는 방법
  • 게임을 초기화하고 초기 블록 세트를 만드는 방법
  • 블록 클릭 감지, 게임 오버 시나리오, 블록 생성 및 이동을 포함한 게임 플레이 기능을 구현하는 방법
  • 게임 점수 및 속도 관리를 마무리하는 방법

🏆 성과

이 프로젝트를 완료하면 다음을 수행할 수 있습니다.

  • HTML 을 사용하여 웹 레이아웃을 디자인
  • CSS 를 사용하여 스타일링 기법 적용
  • JavaScript 를 사용하여 게임 로직 구현
  • Document Object Model (DOM) 조작
  • 이벤트 및 사용자 상호 작용 처리
  • 게임 상태 변수 생성 및 관리
  • 게임 디스플레이를 동적으로 수정 및 업데이트
  • 게임 구현 테스트 및 디버깅

HTML 로 게임 레이아웃 디자인하기

요구 사항:

  • index.html 파일을 엽니다.
  • HTML 태그 및 구조에 대한 이해가 필요합니다.

기능:

  • 메인 게임 컨테이너 레이아웃.
  • 게임 점수 표시.
  • 게임을 시작하는 시작 버튼 제공.

단계:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Avoid the white block</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <h2>score</h2>
    <h2 id="score">0</h2>
    <div id="main">
      <div id="con"></div>
      <!-- Game container -->
    </div>
    <div class="btn">
      <button class="start" onclick="start()">Start</button>
      <!-- Start button -->
    </div>
  </body>
  <script src="script.js"></script>
</html>

위 코드에서 우리는 게임을 위한 기본적인 HTML 구조를 만들었습니다. id="main"을 가진 div가 있는데, 이것이 우리의 게임 컨테이너가 될 것입니다. 게임 컨테이너 내부에는 id="con"을 가진 또 다른 div가 있는데, 이것이 플레이어가 될 것입니다. 또한 게임을 시작하는 데 사용될 class="start"를 가진 button을 만들었습니다.

✨ 솔루션 확인 및 연습

게임에 스타일 추가하기

요구 사항:

  • styles.css 파일을 엽니다.
  • CSS 속성 및 선택자에 대한 기본적인 지식.
  • 반응형 디자인을 위한 스타일링 기법에 대한 이해.

기능:

  • 게임의 시각적 매력 향상.
  • 다양한 화면 크기에 맞춰 게임 인터페이스를 반응형으로 만듭니다.

단계:

body {
  background-color: #f0f0f0;
  font-family: "Arial", sans-serif;
}
h2 {
  text-align: center;
  color: #333;
  margin-bottom: 8px;
}
#main {
  width: 408px;
  height: 408px;
  background: white;
  border: 8px solid #ccc;
  border-radius: 10px;
  /* Added border-radius for a softer look */
  margin: 20px auto;
  overflow: hidden;
  position: relative;
  /* Added relative positioning for child positioning */
}
#con {
  width: 100%;
  height: 400px;
  position: absolute;
  /* Changed to absolute */
  top: -408px;
}
.row {
  height: 100px;
  width: 100%;
}
.cell {
  height: 100px;
  width: 100px;
  float: left;
  border-bottom: rgb(200, 200, 200) 1px solid;
  /* Lighter border color */
}
.black {
  background: #444;
  /* Dark grey instead of black for a softer look */
}
.btn {
  width: 100%;
  text-align: center;
  margin-top: 20px;
}
.start {
  margin: 20px auto;
  width: 150px;
  height: 50px;
  border-radius: 25px;
  /* Increased border-radius for a pill shape */
  background: #4caf50;
  /* Green button */
  color: #fff;
  font-size: 16px;
  /* Increased font size */
  border: none;
  /* Remove default border */
  cursor: pointer;
  /* Cursor effect */
  transition: background 0.3s;
  /* Transition effect */
}
.start:hover {
  background: #45a049;
  /* Darker green on hover */
}

위 코드에서 우리는 게임에 몇 가지 기본적인 스타일을 추가했습니다. body에 배경색을 추가하고 텍스트에 글꼴을 추가했습니다. 또한 게임 컨테이너에 부드러운 모양을 만들기 위해 border-radius 를 추가했습니다. 게임 컨테이너에 position: relative를 추가하고 플레이어에 position: absolute를 추가했습니다. 이렇게 하면 게임 컨테이너 내부에 플레이어를 배치할 수 있습니다. 또한 시작 버튼에 전환 효과를 추가했습니다.

✨ 솔루션 확인 및 연습

기본 게임 로직 구현하기

요구 사항:

  • script.js 파일을 엽니다.
  • JavaScript 기본 사항에 대한 예비 지식.
  • Document Object Model (DOM) 의 개념 이해.

기능:

  • 필수 유틸리티 함수 설정.
  • 중요한 게임 상태 변수 초기화.

단계:

// Utility functions and initial variable setup
// Get an element by its id
function $(id) {
  return document.getElementById(id);
}

// Create a div element with a given class name
function creatediv(className) {
  var div = document.createElement("div");
  div.className = className;
  return div;
}
// Set an interval id as null initially
var clock = null;
// State of the game (0 means stopped and 1 means started)
var state = 0;
// Speed of the game blocks movement
var speed = 6;
// Flag to check if the game has started or not
var flag = false;

위 코드에서 우리는 두 개의 유틸리티 함수를 만들었습니다. 첫 번째 함수 $(id)는 id 로 요소를 가져오는 데 사용됩니다. 두 번째 함수 creatediv(className)은 주어진 클래스 이름을 가진 div 요소를 만드는 데 사용됩니다. 또한 게임에서 나중에 사용될 몇 가지 변수를 초기화했습니다.

✨ 솔루션 확인 및 연습

게임 초기화

요구 사항:

  • JavaScript 함수를 작성할 수 있는 능력.
  • JavaScript 이벤트 리스너에 대한 숙지.

기능:

  • 게임을 시작할 준비를 합니다.
  • 게임의 초기 블록 세트를 생성합니다.

단계:

// Clicking the start game button to start the game
function start() {
  if (!flag) {
    init();
  } else {
    alert("The game has already started! No need to click again!");
  }
}

// Initialization (init) function
function init() {
  flag = true;
  for (var i = 0; i < 4; i++) {
    createrow();
  }

  // Adding event listeners with addEventListener
  $("main").addEventListener("click", function (ev) {
    judge(ev);
  });

  // Timer call move() every 30 milliseconds
  clock = setInterval(move, 30);
}

위 코드에서 우리는 시작 버튼을 클릭했을 때 호출될 start() 함수를 만들었습니다. start() 함수 내부에서 게임을 초기화하는 init() 함수를 호출했습니다. init() 함수 내부에서 게임이 시작되었는지 확인하는 데 사용될 flag 변수를 true로 설정했습니다. 또한 createrow() 함수를 사용하여 네 개의 블록 행을 생성했습니다. 또한 게임 컨테이너에 클릭 이벤트를 감지하는 데 사용될 이벤트 리스너를 추가했습니다. 또한 30 밀리초마다 move() 함수를 호출하는 타이머를 설정했습니다.

✨ 솔루션 확인 및 연습

게임 플레이 기능 구현

요구 사항:

  • JavaScript 루프 및 조건문에 대한 숙련도.
  • JavaScript 를 사용하여 DOM 을 조작하는 방법.

기능:

  • 핵심 게임 역학을 구현합니다.
  • 게임 오버 시나리오를 설계합니다.
  • 블록 생성 및 이동 메커니즘을 구현합니다.

단계:

  1. 플레이어가 검은색 블록 또는 흰색 블록을 클릭했는지 확인합니다. 플레이어의 클릭에 따라 게임 상태를 업데이트합니다.
// Determine whether to click on a black or white block
function judge(ev) {
  if (
    ev.target.className.indexOf("black") == -1 &&
    ev.target.className.indexOf("cell") !== -1
  ) {
    ev.target.parentNode.pass1 = 1; // Defines the pass attribute, which indicates that the white block of this row has been clicked
  }

  if (ev.target.className.indexOf("black") !== -1) {
    // Clicking a target with black in the class name is a black block
    ev.target.className = "cell";
    ev.target.parentNode.pass = 1; // Defines the pass attribute, indicating the black block in this row was clicked
    score();
  }
}
  1. 플레이어 상호 작용을 기반으로 게임이 종료되는 시점을 결정합니다. 게임이 종료되면 게임 종료 작업을 트리거합니다.
// Check if the game is over
function over() {
  var rows = con.childNodes;
  if (rows.length == 5 && rows[rows.length - 1].pass !== 1) {
    fail();
  }
  for (let i = 0; i < rows.length; i++) {
    if (rows[i].pass1 == 1) {
      fail();
    }
  }
}

// Game Over
function fail() {
  clearInterval(clock);
  flag = false;
  confirm("The final score is " + parseInt($("score").innerHTML));
  var con = $("con");
  con.innerHTML = "";
  $("score").innerHTML = 0;
  con.style.top = "-408px";
}
  1. 게임 플레이를 위해 블록 행을 생성합니다. 다른 블록들 중에서 "black" 블록을 무작위로 배치합니다.
// Create a <div class="row"> with four children <div class="cell">
function createrow() {
  var con = $("con");
  var row = creatediv("row"); // Create div: className=row
  var arr = createcell(); // Define the class name of the div cell, one of which is cell black

  con.appendChild(row); // Add child node with row as con

  for (var i = 0; i < 4; i++) {
    row.appendChild(creatediv(arr[i])); // Add child nodes of row cell
  }

  if (con.firstChild == null) {
    con.appendChild(row);
  } else {
    con.insertBefore(row, con.firstChild);
  }
}

// Create an array of class names; one of them is "cell black", others are "cell"
function createcell() {
  var temp = ["cell", "cell", "cell", "cell"];
  var i = Math.floor(Math.random() * 4); // Randomly generate the position of the black block Math.random() function parameters 0~1 random number
  temp[i] = "cell black";
  return temp;
}
  1. 블록이 지속적으로 아래로 이동하도록 합니다. 화면에서 벗어나는 오래된 행을 삭제합니다.
// Move the black blocks down
function move() {
  var con = $("con");
  var top = parseInt(window.getComputedStyle(con, null)["top"]);

  if (speed + top > 0) {
    top = 0;
  } else {
    top += speed;
  }
  con.style.top = top + "px"; // Keep moving the top value so it moves
  over();
  if (top == 0) {
    createrow();
    con.style.top = "-102px";
    delrow();
  }
}

// Delete a row
function delrow() {
  var con = $("con");
  if (con.childNodes.length == 6) {
    con.removeChild(con.lastChild);
  }
}
✨ 솔루션 확인 및 연습

게임 점수 및 속도 관리 최종 구현

요구 사항:

  • JavaScript 변수 및 산술 연산에 대한 이해.
  • JavaScript 로 복잡한 게임 로직을 작성할 수 있는 능력.

기능:

  • 보상 시스템을 구축합니다.
  • 게임의 난이도를 점진적으로 높이는 시스템을 만듭니다.

단계:

// Acceleration function, increases the speed
function speedup() {
  speed += 2;
  if (speed == 20) {
    alert("That's awesome!");
  }
}
// Scoring
function score() {
  var newscore = parseInt($("score").innerHTML) + 1; // point plus one
  $("score").innerHTML = newscore; // Modify Score
  if (newscore % 10 == 0) {
    // Use the acceleration function when the fraction is a multiple of 10, it gets faster and faster
    speedup();
  }
}

위 코드에서 우리는 게임의 속도를 증가시키는 데 사용될 speedup() 함수를 만들었습니다. 또한 게임의 점수를 증가시키는 데 사용될 score() 함수를 만들었습니다. 또한 score() 함수에 점수가 10 의 배수일 때 speedup() 함수를 호출하는 조건을 추가했습니다.

✨ 솔루션 확인 및 연습

게임 테스트 실행

  • 웹 브라우저에서 index.html을 엽니다.

    open web
  • 게임을 플레이하여 모든 기능이 예상대로 작동하는지 확인합니다.

  • 페이지의 효과는 다음과 같습니다.

    gameplay demonstration animation
✨ 솔루션 확인 및 연습

요약

훌륭합니다! HTML, CSS 및 JavaScript 를 사용하여 처음부터 간단하지만 재미있는 블록 회피 게임을 만들었습니다. 이 프로젝트는 사용자 상호 작용, 게임 로직 및 게임 상태 변경에 따른 동적 CSS 스타일링을 처리하는 방법을 소개했습니다. 레벨, 시간 제한 또는 다양한 난이도 모드와 같은 더 많은 기능으로 이 기본 게임을 확장할 수 있습니다. 새로운 게임을 즐겁게 실험해 보세요!