Javascript Study 5주차 toy project
Space Invaders tutorial
addEventListener
를 사용해야 한다.
DOMContentLoaded
- 브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생한다.
- 이미지 파일이나 스타일시트 등의 기타 자원은 기다리지 않는다.
keydown
- 키가 눌렸을 때 이벤트 발생
- 어떤 키가 눌렸는지 나타내는 코드를 제공
KeyboardEvent.key
contains("class")
add("class")
remove("class")
alienInvaders.forEach( invader => squares[currentInvaderIndex + invader].classList.add('invader'))
// shooter 움직이기
function moveShooter(e) {
// 예전 위치는 지우기
squares[currentShooterIndex].classList.remove('shooter')
// 이벤트 요소의 키값 비교하기
switch(e.key) {
case 'ArrowLeft':
// 인덱스 범위 안에서만 움직이게 하기
if (currentShooterIndex % width !== 0) currentShooterIndex -= 1
break
case 'ArrowRight':
// 인덱스 범위 안에서만 움직이게 하기
if (currentShooterIndex % width < width - 1) currentShooterIndex += 1
break
}
squares[currentShooterIndex].classList.add('shooter')
}
document.addEventListener('keydown', moveShooter)
setInterval(함수, 시간)
: "시간(ms)"을 간격으로 "함수"를 반복 호출 하는 함수clearInterval(변수)
: 반복을 중단하는 함수// setInterval()함수의 반환값을 변수에 할당하여 반복 시작
let 변수 = setInterval(함수, 시간);
// 변수에 담은 것을 호출하여 반복 중단
clearInterval(변수);
// 반복을 재시작 하려면 재할당하면 된다.
변수 = setInterval(함수, 시간);
setInterval()
함수의 return값으로 고유한 interval ID를 갖는다
이를 통해 clearInterval()
로 해당 interval ID를 제거해서 반복 호출을 중단시킬 수 있다.
<!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>Space Invaders</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Score: <span id="result"></span></h2>
<div class="grid">
<!-- <div class="laser"></div> -->
</div>
<script src="app.js" charset="utf-8"></script>
</body>
</html>
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin: 0;
}
.grid {
display: flex;
flex-wrap: wrap;
border: solid 1px;
width: 600px;
height: 600px;
}
.grid div {
width: 40px;
height: 40px;
box-sizing: border-box;
position: relative;
}
.shooter {
background-image: url(images/shooter.png);
background-size: cover;
}
.invader {
background-image: url(images/invader.png);
background-size: cover;
}
.boom {
background-color: red;
border-radius: 20px;
}
.laser {
border-left: solid 5px orange;
position: absolute;
left: 15px;
}
// 15 x 15칸 만들기
for (let i = 0; i < 255; i++) {
// div 요소 생성
const divElement = document.createElement("div");
// grid에 div 요소 추가
const grid = document.querySelector(".grid");
grid.appendChild(divElement);
}
// 브라우저가 HTML을 전부 읽고 DOM 트리를 완성하자마자 발생하는 이벤트
document.addEventListener("DOMContentLoaded", () => {
const squares = document.querySelectorAll(".grid div");
const resultDisplay = document.querySelector("#result");
let width = 15;
let currentShooterIndex = 202;
let currentInvaderIndex = 0;
let alienInvadersTakenDown = [];
let result = 0;
let direction = 1;
let invaderId;
// invaders 정의하기, 15 x 15칸에 0부터 시작하는 30개 뭉치
const alienInvaders = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39,
];
// invaders 그리기, 모든 칸이 들어있는 배열 squares에서 invader에 해당하는 칸만 style 적용
alienInvaders.forEach((invader) =>
squares[currentInvaderIndex + invader].classList.add("invader")
);
// shooter 그리기
squares[currentShooterIndex].classList.add("shooter");
// shooter 움직이기
function moveShooter(e) {
// 예전 위치 지우기
squares[currentShooterIndex].classList.remove("shooter");
// 이벤트 요소의 키값 비교하기
switch (e.key) {
case "ArrowLeft":
// 인덱스 범위 안에서만 움직이게 하기
if (currentShooterIndex % width !== 0) currentShooterIndex -= 1;
break;
case "ArrowRight":
// 인덱스 범위 안에서만 움직이게 하기
if (currentShooterIndex % width < width - 1) currentShooterIndex += 1;
break;
}
squares[currentShooterIndex].classList.add("shooter");
}
document.addEventListener("keydown", moveShooter);
// invaders 움직이기
function moveInvaders() {
const leftEdge = alienInvaders[0] % width === 0;
const rightEdge = alienInvaders[alienInvaders.length - 1] % width === width - 1;
// 왼쪽 벽이면서 왼쪽으로 가려할 때, 혹은 오른쪽 벽이면서 오른쪽으로 가려할 때
if ((leftEdge && direction === -1) || (rightEdge && direction === 1)) {
// invaders 전체를 밑으로 내려주기
direction = width
} else if (direction === width) {
if (leftEdge) direction = 1
else direction = -1
}
for (let i = 0; i <= alienInvaders.length - 1; i++) {
squares[alienInvaders[i]].classList.remove('invader')
}
for (let i = 0; i <= alienInvaders.length - 1; i++) {
alienInvaders[i] += direction
}
for (let i = 0; i <= alienInvaders.length - 1; i++) {
// 레이저에 맞지 않았다면
if (!alienInvadersTakenDown.includes(i)) {
squares[alienInvaders[i]].classList.add('invader')
}
}
// game over 정의하기
// shooter가 있는 인덱스에 클래스가 invader, shooter 둘다 있다면 game over
if (squares[currentShooterIndex].classList.contains('invader', 'shooter')) {
resultDisplay.textContent = 'Game Over'
squares[currentShooterIndex].classList.add('boom')
clearInterval(invaderId)
}
for (let i = 0; i <= alienInvaders.length -1; i++) {
// invaders의 인덱스가 grid의 마지막 줄보다 크다면 game over
if (alienInvaders[i] > (squares.length - (width - 1))) {
resultDisplay.textContent = 'Game Over'
clearInterval(invaderId)
}
}
// 이겼을 때
if (alienInvadersTakenDown.length === alienInvaders.length) {
resultDisplay.textContent = 'You Win'
clearInterval(invaderId)
}
}
invaderId = setInterval(moveInvaders, 500)
// invader에게 레이저 쏘기
function shoot(e) {
let laserId
let currentLaserIndex = currentShooterIndex
// shooter에서부터 레이저 나가기
function moveLaser() {
squares[currentLaserIndex].classList.remove('laser')
// 레이저의 행 이동
currentLaserIndex -= width
squares[currentLaserIndex].classList.add('laser')
// 만약 invader가 레이저에 맞았다면
if (squares[currentLaserIndex].classList.contains('invader')) {
squares[currentLaserIndex].classList.remove('laser')
squares[currentLaserIndex].classList.remove('invader')
squares[currentLaserIndex].classList.add('boom')
setTimeout(() => squares[currentLaserIndex].classList.remove('boom'), 250)
clearInterval(laserId)
// invaders 배열에 레이저 인덱스가 있다면 alienInvadersTakenDown에 추가하기
const alienTakenDown = alienInvaders.indexOf(currentLaserIndex)
alienInvadersTakenDown.push(alienTakenDown)
result++
resultDisplay.textContent = result
}
// 레이저는 빠르게 사라지기
if (currentLaserIndex < width) {
clearInterval(laserId)
setTimeout(() => squares[currentLaserIndex].classList.remove('laser'), 100)
}
}
switch(e.code) {
case 'Space':
laserId = setInterval(moveLaser, 100)
break
}
}
document.addEventListener('keydown', shoot)
});
Ethan, a college student with a passion for strategy games, decided to try his hand at an online poker tournament that promised both excitement and a sizable prize pool. Although he had some basic poker knowledge, this tournament was https://azurcasino-france.com his first serious foray into competitive poker. The tournament’s structure was intricate, with multiple rounds and a diverse pool of competitors, making it both thrilling and daunting for Ethan.