자바스크립트를 이용하여
자스스톤 게임을 구현하는 예제(ver.1)입니다.
- 카드 세팅, 팩토리, 생성자 패턴, cloneNode() -
자스스톤 게임을 구현하는 예제(ver.1)입니다.
- 카드 세팅, 팩토리, 생성자 패턴, cloneNode() -
예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.
구현 내용
1 | 위쪽: 상대편, 아래쪽: 내편 | |
2 | 상대편과 내편 각각 덱에 일반 카드 5개와 영웅 카드 1개씩 세팅 | 팩토리 패턴, 생성자 |
3 | 카드 속성: 공격력(att)과 체력(hp), 코스트(cost) | |
4 | 영웅카드: 공격력 낮고, 체력만 높고, 코스트는 없음 | |
5 | 중복되는 부분 팩토리 패턴 함수로 처리 | 리팩토링 |
구현 화면
html 코드
<div id="rival">
<div>코스트:<span id="rival-cost">10</span>/<span>10</span></div>
<div id="rival-hero"></div>
<div id="rival-cards" style="height: 100px">
</div>
</div>
<div id="rival-deck"></div>
<hr />
<button id="turn-btn">턴 교체</button>
<div class="turn-box">현재 턴: <span id="turn-type">나의 턴</span></div>
<div id="my">
<div id="my-cards" style="height: 100px"></div>
<div id="my-hero"></div>
<div>코스트:<span id="my-cost">10</span>/<span>10</span></div>
</div>
<div id="my-deck"></div>
<div class="card-hidden">
<div class="card">
<div class="card-cost"></div>
<div class="card-att"></div>
<div class="card-hp"></div>
</div>
</div>
css 코드
#my,
#rival {
display: inline-block;
vertical-align: top;
margin-right: 50px;
}
#my {
margin-bottom: 10px;
}
#rival {
vertical-align: bottom;
margin-top: 10px;
}
#my-deck,
#rival-deck {
display: inline-block;
vertical-align: top;
width: 200px;
background-color: antiquewhite;
}
#rival-deck,
#rival-hero,
#rival-cards,
#my-cards,
#my-deck,
#my-hero {
text-align: center;
}
#rival-cards>.card,
#my-cards .card {
width: 40px;
height: 55px;
}
.card {
width: 50px;
height: 75px;
display: inline-block;
position: relative;
border: 1px solid #dedede;
margin: 10px 0;
font-size: 12px;
margin-right: 10px;
background-color: aliceblue;
}
.card-att,
.card-hp,
.card-cost {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
bottom: 0;
border: 1px solid #828282;
font-size: 12px;
line-height: 15px;
text-align: center;
font-weight: bold;
}
.card-cost {
bottom: auto;
right: 0;
background-color: burlywood;
}
.card-att {
left: 0;
background-color: coral;
}
.card-hp {
right: 0;
background-color: darkseagreen;
}
.card-hidden {
display: none;
}
#turn-btn {
float: right;
position: relative;
top: -20px;
}
.turn-box {
text-align: center;
margin: 15px 0;
font-weight: bold;
}
script 코드
덱의 일반카드 세팅(영웅카드 세팅 전)
· 생성자 패턴을 이용하여 일반 카드를 세팅한다.
· 공격력, 체력, 코스트를 Math.random()을 이용하여 임의로 값을 부여한다.
· 데이터를 따로 분리하여 관리한다.
· cloneNode로 html에 이미 만들어 놓은 카드 형태를 복사하고, 데이터 값을 화면에 출력한다.
const 상대영웅 = document.getElementById('rival-hero');
const 내영웅 = document.getElementById('my-hero');
const 상대덱 = document.getElementById('rival-deck');
const 내덱 = document.getElementById('my-deck');
//가상의 데이터 저장
//데이터와 화면을 따로 분리하여 관리
let 상대덱data = [];
let 내덱data = [];
let 상대영웅data;
let 내영웅data;
function 상대덱생성(개수) {
for (let i = 0; i < 개수; i++) {
//카드공장에서 생성한 객체->data 변수에 담아줌
상대덱data.push(카드공장());
}
console.log(상대덱data);
//중요. 상대덱data 카드를 하나씩 화면에 출력하기
상대덱data.forEach(function(data) { //data는 카드공장에서 생성한 객체
//cloneNode로 card 형태 복사하여 apppendChild로 출력
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
//textContect로 data의 값 넣어줘야함
카드.querySelector('.card-cost').textContent = data.cost;
카드.querySelector('.card-att').textContent = data.att;
카드.querySelector('.card-hp').textContent = data.hp;
상대덱.appendChild(카드);
})
};
function 내덱생성(개수) {
for (let i = 0; i < 개수; i++) {
내덱data.push(카드공장());
}
내덱data.forEach(function(data) { //반복문 사용
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
카드.querySelector('.card-cost').textContent = data.cost;
카드.querySelector('.card-att').textContent = data.att;
카드.querySelector('.card-hp').textContent = data.hp;
내덱.appendChild(카드);
});
};
function 내영웅생성() {
내영웅data = 카드공장();
};
function 상대영웅생성() {
상대영웅data = 카드공장();
};
function 초기세팅() {
상대덱생성(5);
내덱생성(5);
내영웅생성();
상대영웅생성();
}
function Card() { //카드 세팅 생성자 패턴
this.att = Math.ceil(Math.random() * 5);
this.hp = Math.ceil(Math.random() * 5);
this.cost = Math.floor((this.att + this.hp) / 2);
}
function 카드공장() {
return new Card();
}
초기세팅();
cloneNode()
· cloneNode() 로 기존 html 태그, 아이디, 클래스 속성까지 그대로 복사 가능합니다.
· 매개변수에 true를 추가하면 내부, 자식까지 모두 복사됩니다.
· cloneNode를 활용하여 dom 출력에 필요한 createElement(), className()로 일일이 코드를 만들 필요가 없습니다.
영웅카드 세팅 후 코드 추가 및 변경
· 영웅카드 조건: 공격력 낮음/체력은 높음/코스트 없음
· 기존의 생성자 new 함수로 만든 것에서 영웅카드를 추가하기 위하여 변형함
· 매개변수가 영웅일 경우, 분기 처리함, 영웅 아닐 경우 원래 일반 카드
function 내영웅생성() {
내영웅data = 카드공장(true);
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
카드.querySelector('.card-cost').textContent = 내영웅data.cost;
카드.querySelector('.card-att').textContent = 내영웅data.att;
카드.querySelector('.card-hp').textContent = 내영웅data.hp;
내영웅.appendChild(카드);
};
function 상대영웅생성() {
상대영웅data = 카드공장(true);
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
카드.querySelector('.card-cost').textContent = 상대영웅data.cost;
카드.querySelector('.card-att').textContent = 상대영웅data.att;
카드.querySelector('.card-hp').textContent = 상대영웅data.hp;
상대영웅.appendChild(카드);
};
function 초기세팅() {
상대덱생성(5);
내덱생성(5);
내영웅생성();
상대영웅생성();
}
//영웅카드를 별도로 추가(공격력 낮고, 체력만 높임, 코스트 없음)
function Card(영웅) {
if (영웅) { //영웅카드
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5) + 25;
this.hero = true;
} else { //일반카드
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5);
this.cost = Math.floor((this.att + this.hp) / 2);
}
}
function 카드공장(영웅) {
return new Card(영웅);
}
초기세팅();
리팩토링
중복되는 부분이 많아 팩토리 패턴을 이용한 함수를 만들어 제거합니다.
리팩토링 후 전체 코드
const 상대영웅 = document.getElementById('rival-hero');
const 내영웅 = document.getElementById('my-hero');
const 상대덱 = document.getElementById('rival-deck');
const 내덱 = document.getElementById('my-deck');
//가상의 데이터 저장
let 상대덱data = [];
let 내덱data = [];
let 상대영웅data;
let 내영웅data;
function 카드돔연결(데이터, 돔, 영웅) {
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
카드.querySelector('.card-cost').textContent = 데이터.cost;
카드.querySelector('.card-att').textContent = 데이터.att;
카드.querySelector('.card-hp').textContent = 데이터.hp;
//영웅일때 cost 감추기
if (영웅) {
카드.querySelector('.card-cost').style.display = 'none';
let 이름 = document.createElement('div');
이름.textContent = '영웅',
카드.appendChild(이름);
}
돔.appendChild(카드);
}
function 상대덱생성(개수) {
for (let i = 0; i < 개수; i++) {
상대덱data.push(카드공장());
}
상대덱data.forEach(function(data) {
카드돔연결(data, 상대덱);
})
};
function 내덱생성(개수) {
for (let i = 0; i < 개수; i++) {
내덱data.push(카드공장());
}
내덱data.forEach(function(data) {
카드돔연결(data, 내덱);
});
};
function 내영웅생성() {
내영웅data = 카드공장(true);
카드돔연결(내영웅data, 내영웅, true);
};
function 상대영웅생성() {
상대영웅data = 카드공장(true);
카드돔연결(상대영웅data, 상대영웅, true);
};
function 초기세팅() {
상대덱생성(5);
내덱생성(5);
내영웅생성();
상대영웅생성();
}
function Card(영웅) {
if (영웅) {
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5) + 25;
this.hero = true;
} else {
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5);
this.cost = Math.floor((this.att + this.hp) / 2);
}
}
function 카드공장(영웅) {
return new Card(영웅);
}
초기세팅();
반응형
'개발 > Javascript' 카테고리의 다른 글
[js] 카드세팅 리팩토링 딕셔너리 구조 (ft. 자바스크립트로 자스스톤 게임 구현 ver.3) (0) | 2021.03.02 |
---|---|
[js] 생성자, 카드세팅 (ft. 자바스크립트로 자스스톤 게임 구현 ver.2) (0) | 2021.03.02 |
[js] 생성자 패턴/인스턴스(ft. this, 팩토리 패턴과의 비교) (0) | 2021.02.26 |
[js] 팩토리 패턴(ft. 프로토 타입, Object.create(), 코드 중복 방지 방법) (0) | 2021.02.23 |
[js] 자주 쓰이는 정규식(regular expression) 모음 (ft. 정규표현식) (0) | 2021.02.19 |
댓글