윷짝놀이 : 게임 로직 hook으로 분리하기

J·2023년 5월 25일

프로젝트

목록 보기
7/14

게임 로직 구현에서 게임 진행의 흐름을 action의 값을 바꾸면서 구현하기로 했었는데

이것들을 hook의 형태로 분리해서 hook의 흐름이 필요한 컴포넌트에서 불러다 쓸 수 있도록 했다.

로직 분리하기

나는 크게 4가지로 분리했다.

useGameAction()    //action 관리
useGameTurn()      //게임 시작하기, 차례 돌릴때 필요한 작업
usePieceMove()     //윷 말을 선택하고 움직이기  
useYutThrow()     //윷을 던지고 결과 저장, 사용

위의 링크로 들어가면 useGameReset이란 hook도 있는데 게임이 끝나고 새로운 게임을 할때는 관련 변수를 초기화해야 게임을 정상적으로 즐길 수 있기 때문에 hook으로 분리해두었다.

📌 주의!
각 hook의 구조를 구경하기 전에 주의할점은
react hook이나 recoil hook을 구조만 간단하게 보기 위해서
관련 변수, react hook 같은 부수적인 부분은 모두 지웠다는거 기억해주시길!

useGameAction()

action의 값만 바꾸어주면되는데 왜 hook으로까지 적었을까?

//useGameAction.tsx
const useGameAction = () => {
  const [action, setAction] = useRecoilState(GameActionState);
  
  const startGame = () => {
    setAction("Started");
  };

  const turnStart = () => {
    setAction("TurnStart");
  };
  
  //...

}

useGameAction은 단순히 action의 값을 수정하는 기능밖에 없다.
하지만 이를 메소드화한다면 다음과 같은 효과를 얻을 수 있다.

//before
const nextTurn = useCallback(
  (userId: string) => {
    setNowTurnPlayerId(userId);
    startTurn();
    setAction("TurnStart");
  },
  [playerTurnList]
);


//after
const nextTurn = useCallback(
  (userId: string) => {
    setNowTurnPlayerId(userId);
    startTurn();
    turnStart();
  },
  [playerTurnList]
);

before와 after를 비교해봤을때 after가 확실히 코드의 흐름을 읽기가 편해졌다.
이런 효과를 얻고 싶어서 useGameAction을 만들었다

useGameTurn()

useGameTurn에서는 게임 시작, turn 시작, turn 종료처럼
turn 관련된 작업으로 구성했다.

상세한 코드를 첨부하기에는 꽤 길기 때문에 어떤 메소드가 있는지 확인해보자


const useGameTurn = () => {
  // 게임 시작시 관려 변수 셋팅
  const initPlayerTurn = (turnInfoList: Array<string>) => {}
  
  // 차례 시작때 필요한 작업
  const startTurn = () => {};
  
  // 다음 차례는 누구인지 계산해보기
  const getNextPlayerId = () : string => {};
    
  // 다음 턴이 누군지 전역 변수 갱신
  const nextTurn = (userId: string) =>{};
  
  // 다음 차례가 내 차례면 소켓으로 broadcast
  const ifNextTurnIsMe = () => {};
  
  //action에 따른 흐름 분기
  useEffect(() => {
    if (action === "None") return;

    switch (action) {
      case "Started":
      case "TurnStart":
      case "ThrowYut":
      case "TurnEnd":
      }
    }, [action]);
}

usePieceMove()

윷 말을 움직이는것과 관련된 기능을 모아놨다.

const usePieceMove = () => {
  //말을 업은 경우 움직일 말을 찾아서 셋팅
  const pieceMove = (userId: string,
                     pieceIdList: Array<number>,
                     movePath: Array<number>,
                     moveType: PieceMoveType) => {
  	setMoveInfo()
  };
  
  //pieceMove에 필요한 변수를 저장
  const setMoveInfo = (userId: string, 
                       pieceIndex: number, 
                       movePath: Array<number>) => {};
  
  //윷 말 움직이기 실행
  const doPieceMove = (movePieceIndex: number, 
                       pointIndex: number) => {};
  
  // 도개걸윷모를 int 값으로 변환
  const convertThrowResultToInt = (type: ThrowResultType) => {}
  
  //말 선택
  const selectPiece = (userId: string, pieceId: number) => {};
  
  //모서리 분기점 선택 (leftTop에서 ⬇로 갈지 ↘ 으로 갈지 등등)
  const selectArrow = (arrowType: number, position: number) => {};
  
    //말 동내기
  const pieceOver = () => {};

  //말 합칠때 필요한 값 계산, 셋팅
  const appendPiece = () => {
  	appendAToB()
  };
  
  //a와 b를 합침
  const appendAToB = (userId: string,
                      movePieceIndex: number, //움직여서 합칠 말
                      targetPieceIndex: number //원래 말 판에 있던 말
      ) => {};
  
  //윷 말을 잡을때 필요한 값 저장
  const saveCatchInfo = (catchedUserId: string,
                         catchedPieceList: Array<number>) => {}

  //상대방 윷 말 잡기
  const catchPiece = () => {};
  
  //윷 판의 모서리 비활성화
  const clearActiveCornerArrow = () => {};
  
  //서버에 event 카드 요청
  const getEvent = () => {};

  
  //윷 말 움직이기 action 흐름 분기
  useEffect(() => {
    let i = 0;
    const timer = setInterval(() => {
      if (윷 말을 다 움직였다면) {
        clearInterval(timer);

        // move가 끝나면 추가 동작
        switch (moveType) {
          case "Append":
          case "Over":
          case "Catch":
          case "Event":
          case "End":
        }

        if (더 쓸 결과가 없다면) {
          turnEnd();
          return;
        }
        //더 쓸 결과가 있으면 윷 말 선택
        selectPieceStart();
        return;
      }
      //실제로 윷 말 움직이를 실행함
      doPieceMove(movePieceIndex, movePathList[i++]);
    }, animationSeconds * 1000);
  }, [movePathList]);
};

useYutThrow()

const useYutThrow = () => {
  //내가 윷을 던져도 되는지 계산
  const canIThrow = () : boolean=> {};

  //사용할 결과가 없는지
  const isResultEmpty = () : boolean=> {}
  
  // 윷 던지기
  const throwYut = () => {};

  // 서버에서 받아온 윷 던지기 결과 저장
  const saveThrowResult = () => {};

  // 사용할 윷 던지기 결과
  const getYutThrowResultForUse = () : ThrowResultType => {};

  // 
  const popYutThrowResultForUse = () => {};

  //
  const resetThrowResultList = () => {};
  
  //윷 던지기 component controll
  useEffect(() => {
    if (윷 던지는 타이밍이 아닐때) {
      //윷 던지기 비활성화
      return;
    }
    // 윷 던질때이고
    if (현재 내 차례일 때는) {
      //윷 던지기 활성화
    }
  }, [action]);
};

리뷰

로직을 분리해서 윷 던지기 컴포넌트, 윷 말 컴포넌트 등에서 필요한 로직을 가져다 쓸 수 있어서 좋았다.

하지만 메소드명이 중구난방이라서 다른 팀원들이 읽기에는 많이 헷갈렸을거 같다.

hook 폴더 - github

profile
꾸준한 노력파 개발자의 이모저모

0개의 댓글