긴 추석 연휴동안 무엇을 해볼까 고민하던 중,
우연히도 "항해 플러스 코육대"라는 게시글을 보게 되었다.
https://hanghaeplus-coyukdae.oopy.io/
그림과 같이 다양한 종복이 존재했고, 처음엔 테트리스에 도전해보려고 하다가 산소도 가야하고 전도 부쳐야하고 바쁜 일정들 사이에서 잠깐 잠깐 하기에는 행맨 게임이 제일 간단해보여 행맨 게임으로 도전해 보게 되었다.
리액트로 시작하려하다가, 평가하시는 분들이 편하게 평가하려면 그냥 html 만 열어도 바로 평가 되게끔 html, js 만 이용해서 간단하게 만들기로 했다.
예전에 어쩌다가 html의 canvas를 알게 되었는데, 생각보다 쉽고 간편해서 이걸로 한 번 도전해 보기로 했다. 그런데 canvas를 쓰니까 뭔가 이쁜 맛이 없어서 후회 중이다....
대충 화면은 이렇다... 초간단 초심플...
디자인적 감각이 없는 사람인지라 어쩔 수가 없다...
여러번 실패하면 이렇게 그림이 하나하나 생기면서 행맨이 그려진다. 이 부분에서 canvas를 사용했다.
var hangman = {
canvas : document.getElementById("canvas"),
x : 150,
y : 50,
r : 30,
setBase : function() {
ctx = canvas.getContext("2d");
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x, this.y + 250);
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + 100, this.y);
ctx.moveTo(this.x - 20, this.y + 250);
ctx.lineTo(this.x + 50, this.y + 250);
ctx.stroke();
},
setRope : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(this.x + 100, this.y);
ctx.lineTo(this.x + 100, this.y + 50);
ctx.moveTo(this.x + 50, this.y);
ctx.lineTo(this.x, this.y + 50);
ctx.stroke();
},
setHead : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.arc(this.x + 100, this.y + 50 + this.r, this.r, 0, 360);
ctx.stroke();
},
setBody : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(this.x + 100, this.y + 50 + this.r * 2);
ctx.lineTo(this.x + 100, this.y + 50 + this.r * 2 + 50);
ctx.stroke();
},
setArms : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(this.x + 100, this.y + 50 + this.r * 2 + 10);
ctx.lineTo(this.x + 50, this.y + 50 + this.r * 2 - 10);
ctx.moveTo(this.x + 100, this.y + 50 + this.r * 2 + 10);
ctx.lineTo(this.x + 150, this.y + 50 + this.r * 2 - 10);
ctx.stroke();
},
setLegs : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(this.x + 100, this.y + 50 + this.r * 2 + 50);
ctx.lineTo(this.x + 50, this.y + 50 + this.r * 2 + 95);
ctx.moveTo(this.x + 100, this.y + 50 + this.r * 2 + 50);
ctx.lineTo(this.x + 150, this.y + 50 + this.r * 2 + 95);
ctx.stroke();
},
setHands : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.arc(this.x + 50, this.y + 50 + this.r * 2 - 10, 5, 0, 360);
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x + 150, this.y + 50 + this.r * 2 - 10, 5, 0, 360);
ctx.stroke();
},
setFeet : function() {
ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(this.x + 50 + 10, this.y + 50 + this.r * 2 + 95 + 5);
ctx.lineTo(this.x + 50 - 10, this.y + 50 + this.r * 2 + 95 - 10);
ctx.moveTo(this.x + 150 - 10, this.y + 50 + this.r * 2 + 95 + 5);
ctx.lineTo(this.x + 150 + 10, this.y + 50 + this.r * 2 + 95 - 10);
ctx.stroke();
}
}
위치를 쉽게 바꿀 수 있게 하기 위해서 시작 좌표 x, y 를 제일 처음 지정해주고,
각각 부위마다 함수를 따로 구현해 줬다.
그래서 실패할 때마다 아래와 같이 특정 부위 함수를 호출한다.
switch(counts) {
case 1:
hangman.setBase();
break;
case 2:
hangman.setRope();
break;
case 3:
hangman.setHead();
break;
case 4:
hangman.setBody();
break;
case 5:
hangman.setArms();
break;
case 6:
hangman.setHands();
break;
case 7:
hangman.setLegs();
break;
case 8:
hangman.setFeet();
game.failGame();
}
성공하거나 실패했을 시, 알파벳 카드를 사용하지 못하게 막거나
Restart 를 눌렀을 시 다시 카드를 사용할 수 있게 원상태로 돌려놔야 하기 때문에 아래와 같은 함수를 사용했다.
reverseAllCards : function(isBack) {
blanksDivs = document.getElementsByClassName("cards");
for(var i = 0; i < blanksDivs.length; i++) {
blanksDivs[i].disabled = isBack;
}
}
isBack이 true일 경우 뒤집어 졌다는 의미로 클릭이 불가능하고,
false일 경우 뒤집어 지지 않았다는 의미로 클릭이 가능하다.
단어 같은 경우, 내가 만든 것에는 따로 갯수 제한이 없지만 항해 플러스 문제에서는 10자 이하의 단어만 허용했었다.
words 라는 변수에 단어를 추가로 넣어주기만 하면 랜덤으로 뽑아서 제출해준다.
const words = [
"apple",
"banana",
"umbrella",
"triangle",
"cave",
"sunglass",
"chair",
"legal",
"illegal",
"valuable",
"chemical",
"delicious",
"active",
"creative",
"actual",
"wonderful",
"slim",
"fat",
"stupid",
"actual",
"double",
"creative",
"show",
"eternal",
"exalt",
"exert",
"exploit",
"explicit",
"revolve",
"ethereal",
"give",
"get",
"grain",
"great",
"bad",
"goverment",
"trim"
];
// 랜덤으로 단어를 하나 추출
word = words[Math.floor(Math.random() * words.length)]
특정 알파벳 카드를 선택했을 때, 문제 제출된 단어에 포함된 단어인지 확인하는 로직은 아래와 같다.
onClickCard : function(btn) {
// _ _ _ _ _ 와 같이 알파벳이 들어나는 elements
blanksDivs = document.getElementsByClassName("blanks_cards");
isCorrect = false;
// 클릭한 알파벳은 사용하지 못하게 막아준다.
btn.disabled = true;
// 문제 단어 글자수 만큼 for 문을 돌면서 알파벳을 비교한다.
for(var i = 0; i < word.length; i++) {
if(word[i].toUpperCase() == btn.innerText.toUpperCase()) {
blanksDivs[i].innerText = word.charAt(i).toUpperCase();
isCorrect = true;
// correctCounts가 문제 단어 글자수와 같아지면 성공으로 처리하기 위해, 증가시켜준다.
correctCounts++;
}
}
if(!isCorrect) {
counts++;
switch(counts) {
case 1:
hangman.setBase();
break;
case 2:
hangman.setRope();
break;
case 3:
hangman.setHead();
break;
case 4:
hangman.setBody();
break;
case 5:
hangman.setArms();
break;
case 6:
hangman.setHands();
break;
case 7:
hangman.setLegs();
break;
case 8:
hangman.setFeet();
game.failGame();
}
}else {
if(correctCounts == word.length) {
game.successGame();
}
}
}
처음에는 이미지를 내가 그려놓고 하나씩 보여줄까 했는데, 그림 그리는게 귀찮았다...
그래서 그냥 타이핑으로 모든 것을 해결하겠다는, 정말 무의미한 의지로 ㅋㅋㅋ canvas를 이용해보았다.
완성하고 보니 너무 허접해 보여서 후회중.. 그냥 그림그릴걸...
그래도 추석동안 뭔가 하나 해봤다는게 나에게 큰 의미로 다가온 것 같다.
이 시기를 기점으로 앞으로 뭔가 작은 것 하나라도 해서 velog나 git에 꾸준히 올려야겠다는 의지를 다잡으려고 한다. (사실 저번주부터 올리고 있었는데, 깃 계정을 잘못 등록해서 이상한데에 잔디가 심어졌다...ㅠㅠ)
끝-*