Project

  • commandplusK
  • /
  • CtrlplusK
notion image

Driving Practice Game

깃허브

🚗 Experience Driving Practice on the Web!
Experience the thrill of driving in this immersive Three.js NEXT game. Enhance your driving skills while emphasizing the value of safe and meaningful journeys. Join us in promoting the importance of driving for connectivity and safety
🚗 Experience Driving Practice on the Web!
https://car-drive-practice.vercel.app/

✅ 개발 설명

  • Next.js 프레임워크로 작업 되었습니다. (R3f, Drei), [react-next-three] 공식 보일러 플레이트를 참고함.
  • cannon으로 물리엔진을 추가 하였습니다. 엑셀, 브레이크를 통해 차량의 스피드를 제어할 수 있습니다.
    • <Physics broadphase="SAP" gravity={[0, -9.6, 0]} allowSleep>
         <DebugWrapper>
          //world
         </DebugWrapper>
      </Physics>
  • firebase로 구글 회원가입, 로그인을 구현하였습니다. [공식독스] 및 공식 유튜브 참조
    • const firebaseConfig = {
      	//설정
      }
      
      const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
      const db = getFirestore(app);
      const auth = getAuth(app);
      
      export { app, auth, db };
  • 저장 데이터를 LocalStorage와 firebase 클라우드에 저장 하였습니다.
  • scss로 스타일링을 주었습니다. framer-motion으로 애니메이션을 주었습니다.
  • zustand로 전역값 관리를 합니다. ex( 게임 오버, 성공, 준비를 관리 합니다.)
    • type GameState = "READY" | "START" | "SUCCESS" | "GAMEOVER"
      
      //game store 일부
      const useGameStore = create<GameStore>((set) => ({
          gameState: "READY",
          setGameState: (value: GameState) => set({ gameState: value}),
 

notion image

✅ 자동차 주차 연습 게임

  • 카메라 화면이 3개로 이루어져 있어서 전환을 할 수 있습니다.
    • type CameraType = "FOCUS" | "ALL" | "VIEW"
      //타입에 따라 카메라 포지션 정하기
  • X 축을 체크하여 핸들과 앞바퀴 방향을 정합니다.
    • const bind:any = useGesture({
      	onDragStart: () => {
      		setStartRotation(rotation);
      	},
      	//x 포지션에 따라 newRotation을 만듬.
      	onDrag: ({ movement: [x], dragging }) => {
      		const newRotation = Math.max(-0.35, Math.min(0.35, startRotation + x / 300));
      		setRotation(newRotation);
      	}
      }
  • 엑셀, 브레이크를 통해 차량의 스피드를 제어할 수 있습니다.
    • //엑셀 제어 함수 중 일부
      const onHandleAccel = ()=> {
      	vehicleApi.applyEngineForce(engineForce, 2);
        vehicleApi.applyEngineForce(engineForce, 3);
      }
  • 기어를 통해 자동차와 같은 조작을 합니다.
    • //carStore의 일부
      const useCarStore = create<CarStoreState>((set) => ({
          selectedGearState: 'D',
          setSelectedGearState: (value: 'D' | 'P' | 'R') => set({ selectedGearState: value }),
      }));
  • 주차를 120초 이내에 클리어하면 “성공” 입니다.
    • // 데이터의 모든 quest가 true면 성공!
      const check = stageData[stageNumber].quest.every((el)=> el.clear)
      if(check) setGameState("SUCCESS")
  • 클리어한 시간에 따라 별 점수가 있습니다.
    • // 별 수 나누기
      const calculateStarScore = (clearTimer: number): StarScore => {
      	if (clearTimer <= 0) {
      	  return 0;
        } else if (clearTimer <= 10) {
      	  return 0;
        } else if (clearTimer <= 30) {
      	  return 1;
        } else if (clearTimer <= 80) {
      		return 2;
        } else {
      	  return 3;
        }
      };
  • 벽이나 다른 차량에 부딪히면 “실패” 입니다.
    • //물체의 이름이 chassisBody면으로 체크
       const onCollide = (e) => {
      	 const { body } = e;
         if (body.name === "chassisBody") {
           checkCarCollide(true)
      	   setTimeout(()=> setGameState("GAMEOVER"),500)
         }
       }