Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/images/stage1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
173 changes: 150 additions & 23 deletions src/game/stage1.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,32 @@ import { useNavigate, useLocation } from 'react-router-dom';
const Stage1 = () => {
const navigate = useNavigate();
const location = useLocation();
const { stageIndex } = location.state; // stageIndex 가져오기
const { stageIndex } = location.state;

const [answer, setAnswer] = useState('');
const [feedback, setFeedback] = useState('');
const [draggingCard, setDraggingCard] = useState(null); // 드래그 중인 카드 ID
const [offset, setOffset] = useState({ x: 0, y: 0 }); // 드래그 시작 위치와 마우스 간 거리
const [hint, setHint] = useState('');
const [hint1Used, setHint1Used] = useState(false);
const [hint2Used, setHint2Used] = useState(false);

const cardData = [
{ id: 1, text: 'ㅅ', width: 100, height: 100 },
{ id: 2, text: 'ㅗ', width: 100, height: 100 },
{ id: 3, text: 'ㄹ', width: 100, height: 100 },
{ id: 4, text: 'ㅣ', width: 100, height: 100 },
{ id: 5, text: 'ㄱ', width: 100, height: 100 },
{ id: 6, text: 'ㅡ', width: 100, height: 100 },
{ id: 7, text: 'ㄹ', width: 100, height: 100 },
{ id: 8, text: 'ㅈ', width: 100, height: 100 },
{ id: 9, text: 'ㅏ', width: 100, height: 100 },
{ id: 1, text: 'ㅅ', width: 100, height: 100, left: 100, top: 100 },
{ id: 2, text: 'ㅗ', width: 100, height: 100, left: 300, top: 100 },
{ id: 3, text: 'ㄹ', width: 100, height: 100, left: 500, top: 100 },
{ id: 4, text: 'ㅣ', width: 100, height: 100, left: 700, top: 100 },
{ id: 5, text: 'ㄱ', width: 100, height: 100, left: 900, top: 100 },
{ id: 6, text: 'ㅡ', width: 100, height: 100, left: 1100, top: 100 },
{ id: 7, text: 'ㄹ', width: 100, height: 100, left: 1300, top: 100 },
{ id: 8, text: 'ㅈ', width: 100, height: 100, left: 1500, top: 100 },
{ id: 9, text: 'ㅏ', width: 100, height: 100, left: 1700, top: 100 },
];

const [cards, setCards] = useState(cardData);

useEffect(() => {
handleReset(); // 컴포넌트가 렌더링될 때 카드 초기화
handleReset();
}, []);

const handleReset = () => {
Expand All @@ -38,26 +43,86 @@ const Stage1 = () => {
);
setAnswer('');
setFeedback('');
setHint('');
setHint1Used(false);
setHint2Used(false);
};

const handleSubmit = () => {
const correctAnswer = "소리글자";
const correctAnswer = '소리글자';
if (answer === correctAnswer) {
setFeedback("정답입니다! 🎉");
setFeedback('정답입니다! 🎉');
setTimeout(() => {
navigate("/map", { state: { startIndex: 0, solved: true } }); // stage1 완료 후 map1로
navigate('/map', { state: { startIndex: 0, solved: true } });
}, 1000);
} else {
setFeedback("틀렸습니다. 다시 시도하세요.");
setFeedback('틀렸습니다. 다시 시도하세요.');
}
};


const handleHint = (hintNumber) => {
if (hintNumber === 1) {
setHint('음성에 대응하는 문자를 가리키는 말');
setHint1Used(true);
} else if (hintNumber === 2) {
setHint('초성: ㅅㄹㄱㅈ');
setHint2Used(true);
} else if (hintNumber === 3) {
setHint('소리글자');
}
};

const handleCloseHint = () => {
setHint('');
};

const handleGoBack = () => {
navigate("/map"); // `/map`으로 돌아가기
};

navigate('/map');
};

// 드래그 시작
const handleMouseDown = (e, cardId) => {
const card = cards.find((c) => c.id === cardId);
if (card) {
setDraggingCard(cardId);
setOffset({ x: e.clientX - card.left, y: e.clientY - card.top });
}
};

// 드래그 중
const handleMouseMove = (e) => {
if (draggingCard) {
setCards((prevCards) =>
prevCards.map((card) =>
card.id === draggingCard
? {
...card,
left: Math.min(
Math.max(0, e.clientX - offset.x), // x 경계
1500 - card.width // 최대 x
),
top: Math.min(
Math.max(0, e.clientY - offset.y), // y 경계
800 - card.height // 최대 y
),
}
: card
)
);
}
};

// 드래그 종료
const handleMouseUp = () => {
setDraggingCard(null);
};

return (
<div className="stage-container">
<div
className="stage-container"
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
>
<header>
<h1>훈민정음 맞추기 게임</h1>
<p>전통 문화를 느끼며 단어를 맞춰보세요!</p>
Expand All @@ -69,6 +134,9 @@ const Stage1 = () => {
width: '1500px',
height: '800px',
border: '2px dashed #000',
backgroundImage: 'url(/images/stage1.png)',
backgroundSize: 'cover', // 이미지를 영역에 맞게 조정
backgroundPosition: 'center', // 이미지를 중앙에 배치
}}
>
{cards.map((card) => (
Expand All @@ -84,9 +152,13 @@ const Stage1 = () => {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#bebebe',
borderRadius: '5px',
backgroundColor: '#ffe9b9c5',
borderRadius: '20px',
cursor: 'pointer',
fontSize: '24px',
fontWeight: 'bold',
}}
onMouseDown={(e) => handleMouseDown(e, card.id)}
>
{card.text}
</div>
Expand All @@ -102,9 +174,64 @@ const Stage1 = () => {
/>
<button onClick={handleSubmit}>제출</button>
<button onClick={handleReset}>리셋</button>
<button onClick={handleGoBack}>돌아가기</button> {/* 돌아가기 버튼 추가 */}
<button onClick={handleGoBack}>돌아가기</button>
<button onClick={() => handleHint(1)}>힌트1</button>
<button
onClick={() => handleHint(2)}
disabled={!hint1Used}
style={{
backgroundColor: hint1Used ? '#007bff' : '#ccc',
cursor: hint1Used ? 'pointer' : 'not-allowed',
}}
>
힌트2
</button>
<button
onClick={() => handleHint(3)}
disabled={!hint2Used}
style={{
backgroundColor: hint2Used ? '#28a745' : '#ccc',
cursor: hint2Used ? 'pointer' : 'not-allowed',
}}
>
정답
</button>
{feedback && <p>{feedback}</p>}
</div>

{hint && (
<div
className="hint-modal"
style={{
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '400px',
backgroundColor: 'white',
padding: '20px',
boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.2)',
borderRadius: '8px',
zIndex: 1000,
}}
>
<p>{hint}</p>
<button
onClick={handleCloseHint}
style={{
position: 'absolute',
top: '10px',
right: '10px',
background: 'transparent',
border: 'none',
fontSize: '18px',
cursor: 'pointer',
}}
>
</button>
</div>
)}
</div>
);
};
Expand Down
71 changes: 68 additions & 3 deletions src/game/stage2.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ p, h2 {
}


.button-container {
.button-container2 {
display: flex;
justify-content: center;
gap: 5px;
margin-top: 10px;
}

button {
.stage2btn {
padding: 10px 15px;
font-size: 16px;
background-color: #8B4513;
Expand All @@ -102,7 +102,7 @@ button {
transition: background-color 0.3s;
}

button:hover {
.stage2btn:hover {
background-color: #A0522D;
}

Expand Down Expand Up @@ -130,3 +130,68 @@ button:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
overflow: auto;
}
.hint-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.hint-box {
background-color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
position: relative;
width: 50%;
}

.close-btn {
position: absolute;
top: 10px;
right: 15px;
font-size: 18px;
border: none;
background: none;
cursor: pointer;

}


.hint-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.hint-content {
background: white;
padding: 20px;
border-radius: 8px;
text-align: center;
position: relative;
}

.close-hint {
position: absolute;
top: 10px;
right: 10px;
border: none;
background: none;
font-size: 20px;
cursor: pointer;
}

Loading