Skip to content

Commit

Permalink
Merge branch 'main' into leebang
Browse files Browse the repository at this point in the history
  • Loading branch information
themerous authored Sep 10, 2024
2 parents 2df981e + 281ca8c commit 0d8125f
Show file tree
Hide file tree
Showing 27 changed files with 763 additions and 125 deletions.
4 changes: 2 additions & 2 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const config = {
},
{
source: '/nws/:path*',
destination: 'http://localhost:4000/nws/:path*',
destination: 'http://localhost:4000/nws/?:path*',
},
{
source: '/socket.io/:path*',
destination: 'http://localhost:4000/socket.io/:path*',
destination: 'http://localhost:4000/socket.io/?:path*',
},
]
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"react-apexcharts": "1.4.1",
"react-dom": "18.3.1",
"react-hook-form": "7.52.0",
"react-transition-group": "^4.4.5",
"socket.io-client": "^4.7.5",
"sockjs-client": "^1.6.1",
"yup": "^1.4.0",
Expand Down
9 changes: 6 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src/app/mini-game/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import Stack from '@mui/material/Stack';

import { config } from '@/config';
import Lobby from "@/components/game/Lobby";
import App from "@/components/mini-game/App";
import App from "@/components/mini-game/snake/App";
import useWindowSizeCustom from "@/hooks/useWindowSizeCustom";
import GameMap from "@/components/mini-game/snake/components/GameMap";



Expand All @@ -22,7 +23,7 @@ export default function Page(): React.JSX.Element {
// scale: 0.3,
// width: windowSizeCustom.width / ,
}}>
<App/>
<GameMap roomId={11} />
</div>


Expand Down
3 changes: 1 addition & 2 deletions src/components/friend-list/FriendList.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export default function FriendList() {
if (oneFriend && oneFriend.chatRoomId) {
loadMessages(oneFriend.chatRoomId);
}

}
};

Expand Down Expand Up @@ -179,9 +180,7 @@ export default function FriendList() {
...prevMessages,
{ senderId: userData.user_id, content: messageContent, timestamp: new Date().toISOString() }
]);

}

}

// 초대 수락 핸들러
Expand Down
8 changes: 5 additions & 3 deletions src/components/game/InviteModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, G
import Button from "@mui/material/Button";
import apiAxiosInstance from "@/hooks/apiAxiosInstance";

const InviteModal = ({ open, onClose, userId, client, roomId }) => {
const jwt = localStorage.getItem('custom-auth-token');
const InviteModal = ({open, onClose, userId, client, roomId}) => {
const [jwt, setJwt] = useState(null);
useEffect(() => {
setJwt(localStorage.getItem('custom-auth-token'));
}, [jwt]);
const [userData, setUserData] = useState(null);
const [friendList, setFriendList] = useState([]);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -60,7 +63,6 @@ const InviteModal = ({ open, onClose, userId, client, roomId }) => {
};



return (
<Dialog
open={open}
Expand Down
14 changes: 2 additions & 12 deletions src/components/game/Lobby.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
box-shadow: 5px 4px 8px rgba(0, 0, 0, 0.3);
font-family: 'Press Start 2P', cursive;
border-radius: 15px;
display: flex;
justify-content: center;
}

.titleStyle h1 {
Expand Down Expand Up @@ -206,18 +208,6 @@
color: white;
}

.game-container {
width: 500px;
height: 445px;
padding: 20px;
background-color: white;
border-radius: 10px;
color: black;
text-align: center;
position: absolute;
right: 5%;
box-shadow: 5px 5px 5px gray;
}

.character-selection {
display: grid;
Expand Down
85 changes: 55 additions & 30 deletions src/components/game/Lobby.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import RankAnimation from "@/components/game/RankAnimation";
import Modal from "@/components/game/Modal";
import InviteModal from "@/components/game/InviteModal";
import apiAxiosInstance from "@/hooks/apiAxiosInstance";
import {useParams} from "next/navigation";
import FriendFrom from "@/components/game/FriendFrom";
import InforModal from "@/components/game/InforModal";
import FriendTo from "@/components/game/FriendTo";
import FriendFrom from "@/components/game/FriendFrom";

const characters = [
{id: 1, src: '/image/character/bear.png', alt: 'Character 1'},
Expand Down Expand Up @@ -49,7 +50,6 @@ const Lobby = () => {
const chatMessagesRef = useRef(null);
const [input, setInput] = useState('');
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const [roomId, setRoomId] = useState('');
const [balloons, setBalloons] = useState({});
const [showOptions, setShowOptions] = useState(false);
const [visibleOptions, setVisibleOptions] = useState({});
Expand All @@ -70,7 +70,7 @@ const Lobby = () => {
const [isFriendToModalOpen, setIsFriendToModalOpen] = useState(false); // 친구 요청 받은 모달 상태
const [receiver, setReciver] = useState(''); // 친구 요청을 보낸 유저 닉네임
const [sender, setSender] = useState(''); // 친구 요청을 보낸 유저 닉네임

const {roomId} = useParams();

async function getUserData(jwt) {
try {
Expand All @@ -91,15 +91,18 @@ const Lobby = () => {
}
}, []);

//roomId
//방 제목
useEffect(() => {
if (typeof window !== 'undefined') {
const urlPath = window.location.pathname;
const pathSegments = urlPath.split('/');
const lastSegment = pathSegments[pathSegments.length - 1];
setRoomId(lastSegment);
const fetchRoomName = async () => {
const response = await apiAxiosInstance.get(`/roomName/${roomId}`);
setRoomName(response.data); // 서버에서 반환된 roomName 설정
};

if (roomId) {
fetchRoomName();
}
}, []);
}, [roomId]);


//방 제목
useEffect(() => {
Expand Down Expand Up @@ -188,7 +191,7 @@ const Lobby = () => {
}, [players, userData]);

const checkAllReady = () => {
if (players.length > 1 && players.slice(1).every(player => player.ready)) {
if (players.length === 4 && players.slice(1).every(player => player.ready)) {
setAllReady(true);
} else {
setAllReady(false);
Expand All @@ -197,14 +200,18 @@ const Lobby = () => {

const handleReadyClick = (player) => {
if (player?.user_id == userData?.user_id) {
if (client && client.connected) {
const updatedReadyState = !player.ready;
client.send(`/app/chat.ready/${roomId}`, {}, JSON.stringify({
sender: player.user_id,
type: 'READY',
ready: updatedReadyState,
roomId
}));
if (player.characterSrc.startsWith('/image')) {
if (client && client.connected) {
const updatedReadyState = !player.ready;
client.send(`/app/chat.ready/${roomId}`, {}, JSON.stringify({
sender: player.user_id,
type: 'READY',
ready: updatedReadyState,
roomId
}));
}
} else {
alert("캐릭터 선택을 해주십시오.")
}
}
};
Expand Down Expand Up @@ -369,6 +376,11 @@ const Lobby = () => {
}, [messages]);

const handleStartGame = () => {
if (players.some(player => !player.characterSrc.startsWith("/image"))) {
alert("캐릭터 선택을 해야 시작 가능합니다.");
return;
}

if (client && client.connected) {
// 현재 사용자가 선택한 캐릭터 이미지를 가져옴
const selectedCharacterSrc = players.find(player => player.name === userData.nickname)?.characterSrc;
Expand Down Expand Up @@ -494,19 +506,20 @@ const Lobby = () => {
const playersData = [];

gameInfo.forEach(line => {
const match = line.match(/^(.+?):\s(.+?),\sSpeed:\s(\d+)$/);
if (match) {
const playerName = match[1].trim();
const characterSrc = match[2].trim();
const speed = parseInt(match[3], 10);

playersData.push({user_id: playerName, characterSrc: characterSrc, speed: speed});
const match = line.split("|");
if (match.length === 4) {
let [user_id, characterSrc, speed, nickname] = line.split("|");
speed = parseInt(speed, 10);
playersData.push({user_id: user_id, characterSrc: characterSrc, speed: speed, nickname: nickname});
}
});
console.log('playersData', playersData);

// 순서를 유지한 채로 playersData를 사용
setOrder(playersData); // 순서대로 저장된 정보를 그대로 사용
setShowGameResult(true); // 결과 화면 표시
} else if (message.type === 'END_GAME') {
location.href = `/game/${roomId}`;
}
};

Expand All @@ -515,15 +528,15 @@ const Lobby = () => {
if (showGameResult) {
console.log('Order updated:', order); // 디버깅용

let delay = 1000; // 각 순위가 나타나는 시간 간격 (밀리초)
let delay = 100; // 각 순위가 나타나는 시간 간격 (밀리초)

// 순번을 순차적으로 추가
const tempOrder = [];
order.forEach((player, index) => {
setTimeout(() => {
tempOrder.push(player);
setOrder([...tempOrder]); // 새로운 배열로 설정하여 재렌더링
}, delay * (index + 1));
}, delay + (index + 100));
});
}
}, [showGameResult]); // order가 아니라 showGameResult가 변경될 때만 실행되도록 수정
Expand All @@ -534,7 +547,7 @@ const Lobby = () => {
{showYutPan ? (
<YutPan roomId={roomId}/>
) : showGameResult ? (
<RankAnimation players={order} userData={userData}/>
<RankAnimation players={order} userData={userData} client={client}/>
) : (
<>
<Modal open={isModalOpen} onClose={handleCloseModal}/>
Expand Down Expand Up @@ -721,7 +734,18 @@ const Lobby = () => {
</div>
</>
)}
<div className="game-container">
<div style={{
width: "500px",
height: "445px",
padding: "20px",
backgroundColor: "white",
borderRadius: "10px",
color: "black",
textAlign: "center",
position: "absolute",
right: "5%",
boxShadow: "5px 5px 5px gray"
}}>
<b style={{fontSize: '20px'}}>Select&nbsp;Character</b>

<div className="character-selection">
Expand All @@ -732,6 +756,7 @@ const Lobby = () => {
alt={character.alt}
className={`character ${selectedCharacter === character.id ? 'selected' : ''}`}
onClick={() => {
//캐릭터 선택
if (selectedCharacter === character.id) {
handleCharacterDeselect(character.id);
} else if (!selectedCharacters.includes(character.src)) {
Expand Down
33 changes: 22 additions & 11 deletions src/components/game/RankAnimation.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState, useEffect } from 'react';
import Race from './Race';
import React, {useEffect, useState} from 'react';
import Race from './Race'; // Race 컴포넌트를 가져옵니다.
import './RankAnimation.css';
import Button from "@mui/material/Button";
import {useParams} from "next/navigation";

const RankAnimation = ({ players, roomId, stompClient }) => {
const RankAnimation = ({players, userData, client}) => {
const [currentRank, setCurrentRank] = useState(0);
const [displayedPlayers, setDisplayedPlayers] = useState([]);
const [sortedPlayers, setSortedPlayers] = useState([]);
Expand Down Expand Up @@ -46,31 +47,41 @@ const RankAnimation = ({ players, roomId, stompClient }) => {
}
}, [currentRank, sortedPlayers, stompClient, roomId]);



const isHost = players.length > 0 && players[0].isHost;
// userData와 players가 모두 존재하고 players 배열이 비어있지 않은 경우만 isHost를 계산
const isHost = players[0]?.user_id == userData?.user_id;

if (!players || players.length === 0) {
return null;
}

const {roomId} = useParams();

const mainGameStart = () => {
if (displayedPlayers != null) {
client.send(`/app/chat.mainGameStart/${roomId}`, {}, JSON.stringify({
displayedPlayers
}));
}
}

return (
<div className="rank-animation-container">
<div className="ball-mixing-container">
<Race players={players} />
{/* 입장 순서대로 레이스 컴포넌트에 원래의 players 전달 */}
<Race players={players}/>
</div>
<div className="rank-display-container">
{displayedPlayers.map((player, index) => (
<div key={index} className="rank-ball" style={{ animation: `reveal 1s ease-in-out ${index * 2}s forwards` }}>
<span className="rank-text">{index + 1}위: {player.name}</span>
<div key={index} className="rank-ball" style={{animation: `reveal 1s ease-in-out ${index * 2}s forwards`}}>
<span className="rank-text">{index + 1}위: {player.nickname}</span>
</div>
))}
</div>
<br /><br />
{isHost && (
<Button
style={{ backgroundColor: '#007bff', color: 'black', boxShadow: '3px 3px 3px gray', width: '100px' }}
onClick={() => console.log('Game Start!')}
style={{backgroundColor: '#007bff', color: 'black', boxShadow: '3px 3px 3px gray', width: '100px'}}
onClick={mainGameStart}
>
시작
</Button>
Expand Down
Loading

0 comments on commit 0d8125f

Please sign in to comment.