Skip to content

Commit

Permalink
Merge pull request #80 from 5wonju/feat/#68-game-result-modal
Browse files Browse the repository at this point in the history
Feat/#68 game result modal
  • Loading branch information
3o14 authored May 13, 2024
2 parents 55ec352 + 2af1f95 commit 5ba5518
Show file tree
Hide file tree
Showing 24 changed files with 116,067 additions and 123,195 deletions.
53 changes: 27 additions & 26 deletions frontend/app/(page)/(needProtection)/game/component/Character.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
// @ts-nocheck
'use client'

import { Html, useAnimations, useGLTF } from '@react-three/drei'
import { Html, Text, useAnimations, useGLTF } from '@react-three/drei'
import React, { useEffect, useRef } from 'react'
import { useCharacterSelectStore, useModalStore, usePlayerStore } from '../lib/store'
import { teamEnum } from '../lib/store-type'
import { useAuth } from '@/app/hooks/useAuth'
import { useFrame, useThree } from '@react-three/fiber'

const pathObj = {
0: '/models/custom/custom-model0.gltf',
1: '/models/custom/custom-model1.gltf',
2: '/models/custom/custom-model2.gltf',
3: '/models/custom/custom-model3.gltf',
4: '/models/custom/custom-model4.gltf',
5: '/models/custom/custom-model5.gltf',
}
export default function Character({ pos }) {
const groupRef = useRef()
const { userInfo } = useAuth()
Expand All @@ -33,7 +26,7 @@ export default function Character({ pos }) {

// ์บ๋ฆญํ„ฐ์— ๊ทธ๋ฆผ์ž ํšจ๊ณผ
scene.traverse((child) => {
if (child.isMesh) {
if (child.amIMesh) {
child.castShadow = true
}
})
Expand All @@ -42,32 +35,40 @@ export default function Character({ pos }) {
useEffect(() => {
if (!actions) return

actions[playerMoveState].reset().fadeIn(0.2).play( )
actions[playerMoveState].reset().fadeIn(0.2).play()
return () => {
if (!actions[playerMoveState]) return
actions[playerMoveState].fadeOut(0.2)
}
}, [playerMoveState])

const textRef = useRef()
const { camera } = useThree()

useFrame(() => {
if (textRef.current) {
// ํ…์ŠคํŠธ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์นด๋ฉ”๋ผ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „
textRef.current.lookAt(camera.position)
// Y ์ถ•์„ ๊ณ ์ •ํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๋กœ ์กฐ์ •
textRef.current.rotation.z = 0
textRef.current.rotation.y = 0 // Y ์ถ• ํšŒ์ „ ์ œ๊ฑฐ
}
})

return (
<group ref={groupRef} scale={1}>
<primitive object={nodes} />
<primitive object={scene} />
{pos && (
<Html position={[0, 3, 0]} className={`${isModalOpen ? 'hidden' : ''}`}>
<div
className={`text-sm w-20 overflow-hidden whitespace-nowrap select-none truncate ${
playerTeamState === teamEnum.BLUE
? 'text-blue-400'
: playerTeamState === teamEnum.RED
? 'text-red-400'
: 'text-neutral-700'
}`}
>
{userInfo && userInfo.nickname}
</div>
</Html>
)}
<Text
ref={textRef}
position={[0, 3, 0]} // ์บ๋ฆญํ„ฐ์˜ ๋จธ๋ฆฌ ์œ„ ์ ์ ˆํ•œ ์œ„์น˜์— ๋‹‰๋„ค์ž„์„ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
fontSize={0.5} // ํฐํŠธ ํฌ๊ธฐ๋ฅผ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.
color="black" // ํ…์ŠคํŠธ ์ƒ‰์ƒ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
anchorX="center" // ํ…์ŠคํŠธ๋ฅผ ์ค‘์•™ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.
anchorY="bottom" // ํ…์ŠคํŠธ์˜ ํ•˜๋‹จ์„ ๊ธฐ์ค€์œผ๋กœ ์œ„์น˜๋ฅผ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
>
{userInfo && userInfo.nickname}
</Text>
</group>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function Character({ pos }) {

// ์บ๋ฆญํ„ฐ์— ๊ทธ๋ฆผ์ž ํšจ๊ณผ
scene.traverse((child) => {
if (child.isMesh) {
if (child.amIMesh) {
child.castShadow = true
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const GameBoard = () => {
countdownGame: state.countdownGame,
}))

useEffect(() => {
countdownGame()
}, [])
// useEffect(() => {
// countdownGame()
// }, [])

const getCurrentContent = () => {
switch (gameState) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import { rankList, teamColorToCss } from '../../lib/util'
import { rankList, teamColorToCssText } from '../../lib/util'
import { wonUserList } from '../../lib/dummy'
import { teamEnum } from '../../lib/store-type'

Expand Down Expand Up @@ -61,7 +61,7 @@ const QuizResult = () => {
<span className="font-normal text-xs text-darkGray3 h-3">{wonUser.time}์ดˆ</span>
<span
className={`${
teamColorToCss[wonUser.team as teamEnum]
teamColorToCssText[wonUser.team as teamEnum]
} font-medium text-xl overflow-hidden w-24 select-none truncate`}
>
{wonUser.nickname}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { ITeamInfoProps } from '../../lib/type'
import { teamEnum } from '../../lib/store-type'
import { teamColorToCss } from '../../lib/util'
import { teamColorToCssText } from '../../lib/util'

const TeamInfo = ({
teamName,
Expand All @@ -18,9 +18,9 @@ const TeamInfo = ({
}`}
>
<div>
<h2 className={`${teamColorToCss[teamColor as teamEnum]} font-bold`}>{teamName}</h2>
<h2 className={`${teamColorToCssText[teamColor as teamEnum]} font-bold`}>{teamName}</h2>
{teamColor !== teamEnum.NONE && (
<p className={`${teamColorToCss[teamColor as teamEnum]}`}>ํŒ€ ์ ์ˆ˜ {teamScore}</p>
<p className={`${teamColorToCssText[teamColor as teamEnum]}`}>ํŒ€ ์ ์ˆ˜ {teamScore}</p>
)}
</div>
<ul>
Expand All @@ -31,12 +31,10 @@ const TeamInfo = ({
className="flex items-center justify-between gap-2 text-sm"
>
<div className="flex items-end gap-2">
<span className={`${teamColorToCss[teamColor as teamEnum]}`}>
<span className={`${teamColorToCssText[teamColor as teamEnum]}`}>
{user.nickname}
</span>
<span className="text-darkGray1 font-light text-xs">
{user.point}
</span>
<span className="text-darkGray1 font-light text-xs">{user.point}</span>
</div>
</li>
))
Expand All @@ -49,7 +47,7 @@ const TeamInfo = ({
className="flex items-center justify-between gap-2 text-sm"
>
<div className="flex items-end gap-2">
<span className={`${teamColorToCss[teamColor as teamEnum]}`}>
<span className={`${teamColorToCssText[teamColor as teamEnum]}`}>
{user.userNickname}
</span>
<span className="text-darkGray1 font-light text-xs">{user.userScore}</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { useGameResultStore, useGameRoomStore } from '../../lib/store'
import { gameStateEnum, teamEnum } from '../../lib/store-type'
import { IGameResult } from '../../lib/type'
import TeamResult from './TeamResult'

const GameResult = () => {
const { gameState } = useGameRoomStore((state) => ({
gameState: state.gameState,
}))
// const { gameResult } = useGameResultStore()
// ๋”๋ฏธ ๋ฐ์ดํ„ฐ
const gameResult: IGameResult = {
winTeam: 'RED',
redTeamTotalPoint: 151000,
blueTeamTotalPoint: 121200,
redTeam: [
{
userId: 1,
username: 'red1',
earnPoint: 10,
amIMe: true,
},
{
userId: 2,
username: 'red2',
earnPoint: 20,
amIMe: false,
},
{
userId: 3,
username: 'red3',
earnPoint: 30,
amIMe: false,
},
],
blueTeam: [
{
userId: 4,
username: 'blue1',
earnPoint: 40,
amIMe: false,
},
{
userId: 5,
username: 'blue2',
earnPoint: 50,
amIMe: false,
},
{
userId: 6,
username: 'blue3',
earnPoint: 60,
amIMe: false,
},
],
}

return (
<div
className={`${
gameState === gameStateEnum.DONE ? 'visible' : 'hidden'
} fixed top-0 left-0 z-20 w-full h-full bg-black bg-opacity-20 flex items-center justify-center`}
>
<div className="bg-white z-30 inset-32 flex flex-col gap-10 justify-center items-center bg-opacity-60 backdrop-filter backdrop-blur-md shadow-lg border border-white border-opacity-60 fixed rounded-3xl p-4">
<div className="flex items-center gap-2 font-bold text-7xl animate-floating">
<span className={`text-red-400`}>{gameResult.winTeam}</span>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Star.png"
alt="Star"
className=" size-6"
/>
<span className="flex items-center gap-1 text-yellow-400">WIN</span>
</div>

<fieldset className="flex justify-around w-full *:w-5/12 items-center mt-4">
<section>
<TeamResult
team={teamEnum.RED}
isWin={gameResult.winTeam === teamEnum.RED}
teamPoint={gameResult.redTeamTotalPoint}
teamResult={gameResult.redTeam}
/>
</section>
<section>
<TeamResult
team={teamEnum.BLUE}
isWin={gameResult.winTeam === teamEnum.BLUE}
teamPoint={gameResult.blueTeamTotalPoint}
teamResult={gameResult.blueTeam}
/>
</section>
</fieldset>
</div>
</div>
)
}

export default GameResult
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* eslint-disable @next/next/no-img-element */
import { teamEnum } from '../../lib/store-type'
import { IUserResult, TeamResultProps } from '../../lib/type'
import { teamColorToCssBg, teamColorToCssText } from '../../lib/util'

const emojis = [
<img
key={1}
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Keycap%20Digit%20One.png"
alt="Keycap Digit One"
className="size-10"
/>,
<img
key={2}
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Keycap%20Digit%20Two.png"
alt="Keycap Digit Two"
className="size-10"
/>,
<img
key={3}
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Keycap%20Digit%20Three.png"
alt="Keycap Digit Three"
className="size-10"
/>,
<img
key={4}
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Keycap%20Digit%20Four.png"
alt="Keycap Digit Four"
className="size-10"
/>,
<img
key={5}
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Keycap%20Digit%20Five.png"
alt="Keycap Digit Five"
className="size-10"
/>,
]

const TeamResult = ({ team, isWin, teamPoint, teamResult }: TeamResultProps) => {
return (
<section className={`w-full h-full ${isWin ? 'scale-105' : 'scale-90'}`}>
<fieldset className="flex items-center gap-4 h-28">
<h3 className={`${teamColorToCssText[team as teamEnum]} font-bold text-5xl`}>
<span
className={`${team === teamEnum.RED ? 'redTeam' : 'blueTeam'} px-3`}
>
{team}
</span>
<span className="px-3 font-semibold text-3xl">{teamPoint}์ </span>
</h3>
<h3 className="py-2">
{isWin ? (
<img
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Smilies/Beaming%20Face%20with%20Smiling%20Eyes.png"
alt="Beaming Face with Smiling Eyes"
className="h-20"
/>
) : (
<img
src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Smilies/Crying%20Face.png"
alt="Crying Face"
className="h-20"
/>
)}
</h3>
</fieldset>
<ul className="flex flex-col gap-4 w-full h-4/5 pt-8">
{teamResult.map((user: IUserResult, index) => (
<li
key={user.userId}
className={`flex justify-between gap-5 *:text-3xl glass ${
isWin ? 'text-black' : 'text-darkGray1 bg-neutral-600 bg-opacity-25'
} px-4 py-4 pr-6 ${user.amIMe ? 'bg-yellow-400 bg-opacity-50' : ''}`}
>
<span>{emojis[index]}</span>
<span className="font-medium">{user.username}</span>
<span className="font-semibold">{user.earnPoint}</span>
</li>
))}
</ul>
</section>
)
}

export default TeamResult
9 changes: 7 additions & 2 deletions frontend/app/(page)/(needProtection)/game/lib/store-type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IRoomInfo } from '../../lobby/lib/type'
import { IGameScore, IQuiz, IUserInfo } from './type'
import { IGameResult, IGameScore, IQuiz, IUserInfo } from './type'

// :: ๊ฒŒ์ž„ ์ƒํƒœ
export enum gameStateEnum {
Expand Down Expand Up @@ -29,7 +29,7 @@ export enum AnswerEnum {
C = 'C',
D = 'D',
B = 'B',
NONE = 'none',
NONE = 'none', // none -> N์œผ๋กœ ์ˆ˜์ •ํ•˜๊ธฐ
}

// ------------------------------------------------
Expand Down Expand Up @@ -97,3 +97,8 @@ export interface IGameScoreState {
gameScore: IGameScore | null
setGameScore: (gameScore: IGameScore) => void
}

export interface IGameResultState {
gameResult: IGameResult | null
setGameResult: (gameResult: IGameResult) => void
}
Loading

0 comments on commit 5ba5518

Please sign in to comment.