방 기능

준비/시작 기능

  • 현재 방에 입장해 두 명이 준비되면 게임이 시작될 수 있도록 수정해야겠다
/*클라이언트*/
// 준비완료/취소 보내기
export const ready = (roomId) => {
    socket.emit("ready", {
        userId,
        token,
        handlerId,
        clientVersion: CLIENT_VERSION,
        roomId
    })
}
  • 서버에서도 이를 확인하여 값을 전달!
/*서버*/
// 방 상태 확인
export const gameReady = (gameId, userId) => {
    const roomIdx = gameRooms.findIndex((e) => e.gameId === gameId)
    // 방이 서버에 있는 확인
    if (roomIdx === -1) return false

   // 참가자가 준비완료/취소 했을 경우
    if (gameRooms[roomIdx].userId2 === userId) {
        gameRooms[roomIdx].ready = !gameRooms[roomIdx].ready
        return "ready"
    // 호스트의 시작이 성공했을 경우
    } else if (gameRooms[roomIdx].userId1 === userId && gameRooms[roomIdx].ready) return "start"

    return "notReady"
}
// 방 상태에 따라 준비상태 반환
export const ready = (socket, data) => {
    // 기본 검증
    if (!Auth(data)) return

    const status = gameReady(data.roomId, data.userId)
    
    switch (status) {
        case false:
            socket.emit('ready', {
                status: "fail",
                message: "Room not found"
            })
            return
        case "ready":
            socket.emit('ready', {
                status: "ready",
                message: "Ready to go"
            })
            return
        case "notReady":
            socket.to(data.roomId).emit('ready', {
                status: "fail",
                message: "Not all players are ready"
            })
            return
        case "start":
            socket.to(data.roomId).emit('ready', {
                status: "start",
                message: "The game starts"
            })
            return
        default:
            socket.emit('ready', {
                status: "fail",
                message: "Error"
            })
            return;
    }
} 
  • 받아온 값이 시작이면 화면에 게임을 불러오도록 설정!
/* 클라이언트 socket.js*/
socket.on("ready", (data) => {
    alert(data.message)
    if (data.status === "start") gameStart ()
})
/* 클라이언트 lobby.js*/
export const gameStart = () => {
    waitRoom.hide()
    // 원래는 game.html 을 불러오는 형식이였지만, 
    // js 세션 유지를 위해 game.js를 불러와 실행하도록 바꾸었다
    import("./src/game.js")
    gameFrame.style.display = "block"
}

나가기 기능

  • 방을 나가면 방에서 제외되며 호스트가 나가면 방이 폭파되도록 설계한다!
// 클라이언트의 나가기 이벤트
exitButton.addEventListener('click', function () {
    await sendEvent(1003, {roomId})
});
// 서버에서 매칭되는 함수
export const exitRoom = (userId, payload, socket, io) => {
    const room = leaveRoom(payload.roomId, userId)
    if (room) {
        // 업뎃 정보 공유
        socket.to(payload.roomId).emit('room', { room })
        // 참가자가 나갔을 시 참가자만 제외
        socket.leave(payload.roomId)
    // 호스트가 나갈 시 인원 전부 삭제하도록 요구
    } else io.to(payload.roomId).emit('leaveRoom', { roomId: payload.roomId })

    return { status: "success" }
}
// 내부 함수
export const leaveRoom = (gameId, userId) => {
    const roomIdx = gameRooms.findIndex((e) => e.gameId === gameId)
    // 방이 서버에 있는 확인
    if (roomIdx === -1) return false
    // 호스트가 나갈 시 방 삭제
    if (gameRooms[roomIdx].userId1 === userId) {
        gameRooms.splice(roomIdx,1)
    // 참가자가 나갈 시 userId2를 비움
    } else if (gameRooms[roomIdx].userId2 === userId) {
        gameRooms[roomIdx].userId2 = null
    } else return false 
    // 나가는게 성공적으로 마쳐지면 방 정보를 반환
    return gameRooms[roomIdx]
}
  • leaveRoom 채널을 이용해 서버에서 join()된 roomId를 초기화 해준다
// 클라이언트에서 이 파괴되었을 시 
socket.on('leaveRoom',(data) => {
  // 클라이언트에서 사용자에게 보여지는 부분을 조정
  exitRoom()
  // 방 ID를 재전달하여 참가 방을 떠나게 함 
  socket.emit('leaveRoom',{ roomId: data.roomId })
})
// 서버에서 적용되는 곳
// 삭제된 방에서 일괄 나가기
socket.on('leaveRoom', (data) => socket.leave(data.roomId))

강퇴 기능

  • 기존에 만든 나가기 기능을 응용하여 간단하게 구현하였다
// 서버에서 요청을 받을 시 일어나는 상황
export const kickUser = (userId, payload, socket) => {
    const room = kick(payload.roomId)
    // 참가자에게 방을 나가도록 요구
    socket.to(payload.roomId).emit('leaveRoom', { roomId: payload.roomId })
    // 업데이트된 값 적용
    socket.emit('room', { room })

    return { status: "success" }
}
export const kick = (gameId) => {
    const roomIdx = gameRooms.findIndex((e) => e.gameId === gameId)
    // 방이 서버에 있는 확인
    if (roomIdx === -1) return false
    // 서버에서 유저(참가자) 삭제
    gameRooms[roomIdx].userId2 = null
    
    return gameRooms[roomIdx]
}

한줄 평 + 개선점

  • 오늘 주로 진행된 과정은 개인적 부분보다 팀 프로젝트적 부분이 많았다.

  • 병합하는 과정에서 발생한 오류들을 수정하며 원인분석을 많이 했었는데 이를 제대로 기록하지 못해서 아쉬웠다