[로데시] 개발
[대학전쟁3] 양면빙고 웹 개발 09 - UI/UX 개선 및 기능 보완 본문
반응형

0️⃣ 지난 번까지..
지난 글에서는 2인이 play할 수 있는 기능을 구현했다.1️⃣ 게임 전 - 대기 및 설정 (Setup)
📌 메인 화면 CSS 적용
2️⃣ 게임 중 - 진행 단계 (In-Game)
📌 시간 set
- if (roomDoc.status === "playing" && !roomDoc.winner) {
- setTimeLeft(TURN_LIMIT);
- }
🌟 roomService.js
export async function handleTurnTimeout({ roomId, timedOutUid }) {
if (!roomId) throw new Error("roomId required");
if (!timedOutUid) throw new Error("timedOutUid required");
const roomRef = doc(db, "rooms", roomId);
try {
const result = await runTransaction(db, async (tx) => {
const snap = await tx.get(roomRef);
if (!snap.exists()) return { updated: false, reason: "ROOM_NOT_FOUND" };
const room = snap.data();
// 상태/승자 검증
if (room.status !== "playing") return { updated: false, reason: "NOT_PLAYING" };
if (room.winner) return { updated: false, reason: "ALREADY_ENDED" };
// 현재 턴 확인 (중복/경합 방지)
if (room.currentTurn !== timedOutUid) return { updated: false, reason: "TURN_CHANGED" };
const players = room.players || {};
const playerUids = Object.keys(players);
if (playerUids.length < 1) return { updated: false, reason: "NO_PLAYERS" };
// turn 넘기기
const nextUid = getNextTurnUid(players, timedOutUid);
if (!nextUid) return { updated: false, reason: "NO_OTHER_PLAYER" };
// DB 업데이트 - turnCount 증가 X
const updateData = {
currentTurn: nextUid,
lastAction: {
type: "TIMEOUT",
actorUid: timedOutUid,
ts: serverTimestamp(),
},
lastTimeoutAt: serverTimestamp(),
};
tx.update(roomRef, updateData);
return { updated: true, newTurn: nextUid };
});
return result;
} catch (err) {
console.error("handleTurnTimeout transaction failed:", err);
throw err;
}
}
ㆍ 트랜잭션 내에서 현재 룸 상태 검증:
🌟 Game.js
setTimeLeft((prev) => {
if (prev <= 1) {
// 타임아웃 시도는 currentTurn이 내 uid일 때만 실행
if (currentTurn === myUid && !timeoutCallingRef.current) {
timeoutCallingRef.current = true;
(async () => {
try {
const res = await handleTurnTimeout({ roomId, timedOutUid: currentTurn });
setTimeLeft(TURN_LIMIT);
} catch (err) {
console.error("handleTurnTimeout failed", err);
// 실패 시 안전하게 리셋
setTimeLeft(TURN_LIMIT);
} finally {
timeoutCallingRef.current = false;
}
})();
} else {
setTimeLeft(TURN_LIMIT);
}
return TURN_LIMIT; // 현재 20초 제한 (추후 수정)
}
return prev - 1;
});
ㆍ 로컬 타이머가 0이 되었을 때 오직 현재 턴을 가진 플레이어의 클라이언트만 서버에 handleTurnTimeout 호출을 시도 (동시 호출이 발생하더라도 서버 트랜잭션으로 안전하게 보호됨)
3️⃣ 게임 후 - 결과 및 피드백 (Outcome)
📌 빙고 완성// 승자 set
if (!serverWinner && uidWithColor) setServerWinner(uidWithColor);
// 빙고 line set
setWinningLine(found);
if (uidWithColor) {
setWinningLine(found); // 빙고 line set
}
const hostUid = room.hostUid || playerUids[0];
const otherUid = playerUids.find(u => u !== hostUid) || hostUid;
const updatedPlayers = assignRandomColors(newPlayers, hostUid, otherUid); // random으로 색 다시 배정
4️⃣ 시스템(System) 및 공통 로직
📌라우팅(Routing) 분리5️⃣ 앞으로...
이제 자잘한 오류들을 거의 다 잡았다.. 끝이 보이는데 끝이 보이질 않는다. 3월 되기전에는 끝ㄴ내야지
반응형
'개인 개발 > 대학전쟁' 카테고리의 다른 글
| [대학전쟁3] 양면빙고 웹 개발 08 - 2인 play (0) | 2026.02.08 |
|---|---|
| [대학전쟁3] 양면빙고 웹 개발 07 - timer, highlight, restart (0) | 2026.01.31 |
| [대학전쟁3] 양면빙고 웹 개발 06 - 직전 타일 이동, 뒤집기 제한 (0) | 2026.01.23 |
| [대학전쟁] 양면빙고 웹 개발 05 - 빙고 판단, player 2명 (0) | 2026.01.20 |
| [대학전쟁] 양면빙고 웹 개발 04 - 타일 뒤집기 (flip), 이동 (move) (1) | 2026.01.18 |