Make guessing phase while hearing
All checks were successful
Publish Docker image / Push Docker image to Docker Hub (push) Successful in 1m55s
All checks were successful
Publish Docker image / Push Docker image to Docker Hub (push) Successful in 1m55s
This commit is contained in:
@ -149,6 +149,10 @@ export const Game = () => {
|
|||||||
return prevMsg;
|
return prevMsg;
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
"song-options": (data) => {
|
||||||
|
console.log("Received song options early:", data);
|
||||||
|
setSongOptions(data.songOptions || []);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanupFunctions = Object.entries(eventHandlers).map(
|
const cleanupFunctions = Object.entries(eventHandlers).map(
|
||||||
@ -320,11 +324,38 @@ export const Game = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{role === "guesser" && (
|
{role === "guesser" && (
|
||||||
|
<div className="guessing-display">
|
||||||
<div className="listening-display">
|
<div className="listening-display">
|
||||||
<div className="listening-icon">
|
<div className="listening-icon">
|
||||||
<FontAwesomeIcon icon={faHeadphones} size="4x" />
|
<FontAwesomeIcon icon={faHeadphones} size="4x" />
|
||||||
</div>
|
</div>
|
||||||
<p className="instruction">Höre genau zu und versuche, den Song zu erkennen!</p>
|
<p className="instruction">Listen carefully and think about which song it might be!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{songOptions.length > 0 && (
|
||||||
|
<div className="song-grid early-preview">
|
||||||
|
{songOptions.map(song => (
|
||||||
|
<div
|
||||||
|
key={song.id}
|
||||||
|
className={`song-option ${selectedSong?.id === song.id ? 'selected' : ''}`}
|
||||||
|
onClick={() => handleSongSelect(song)}
|
||||||
|
>
|
||||||
|
<div className="song-image">
|
||||||
|
<img src={song.coverUrl} alt={song.title} />
|
||||||
|
{selectedSong?.id === song.id && (
|
||||||
|
<div className="selection-indicator">
|
||||||
|
<FontAwesomeIcon icon={faCheckCircle} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="song-details">
|
||||||
|
<div className="song-title">{song.title}</div>
|
||||||
|
<div className="song-artist">{song.artist}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -334,8 +365,8 @@ export const Game = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="guessing-phase">
|
<div className="guessing-phase">
|
||||||
<div className="phase-header">
|
<div className="phase-header">
|
||||||
<h3>Runde {round}: Song erraten</h3>
|
<h3>Final Answer Time!</h3>
|
||||||
<div className="timer">
|
<div className="timer urgent">
|
||||||
<FontAwesomeIcon icon={faClock} /> {timeLeft}s
|
<FontAwesomeIcon icon={faClock} /> {timeLeft}s
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -597,6 +597,26 @@
|
|||||||
opacity: 0.8
|
opacity: 0.8
|
||||||
animation: pulse 1.5s infinite ease-in-out
|
animation: pulse 1.5s infinite ease-in-out
|
||||||
|
|
||||||
|
.guessing-display
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
gap: 20px
|
||||||
|
margin-top: 20px
|
||||||
|
|
||||||
|
.early-preview
|
||||||
|
opacity: 0.8
|
||||||
|
transition: opacity 0.3s ease
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
.song-grid
|
||||||
|
margin-top: 10px
|
||||||
|
|
||||||
|
.timer.urgent
|
||||||
|
animation: urgent-pulse 1s infinite
|
||||||
|
background: rgba(255, 100, 100, 0.2)
|
||||||
|
|
||||||
@keyframes subtle-text-glow
|
@keyframes subtle-text-glow
|
||||||
0%, 100%
|
0%, 100%
|
||||||
text-shadow: 0 0 10px rgba(255, 255, 255, 0.4)
|
text-shadow: 0 0 10px rgba(255, 255, 255, 0.4)
|
||||||
@ -1046,3 +1066,11 @@
|
|||||||
50%
|
50%
|
||||||
transform: scale(1.1)
|
transform: scale(1.1)
|
||||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 0, 0.6)
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 0, 0.6)
|
||||||
|
|
||||||
|
@keyframes urgent-pulse
|
||||||
|
0%, 100%
|
||||||
|
transform: scale(1)
|
||||||
|
background: rgba(255, 100, 100, 0.2)
|
||||||
|
50%
|
||||||
|
transform: scale(1.05)
|
||||||
|
background: rgba(255, 100, 100, 0.3)
|
@ -26,7 +26,7 @@ const initializeGameState = (roomId) => {
|
|||||||
roundStartTime: null,
|
roundStartTime: null,
|
||||||
phaseTimeLimit: {
|
phaseTimeLimit: {
|
||||||
composing: 30,
|
composing: 30,
|
||||||
guessing: 30
|
guessing: 10
|
||||||
},
|
},
|
||||||
lastFrequency: 440,
|
lastFrequency: 440,
|
||||||
};
|
};
|
||||||
@ -55,11 +55,14 @@ const startNewRound = async (roomId) => {
|
|||||||
|
|
||||||
gameState.currentComposer = determineNextComposer(roomId, gameState, users);
|
gameState.currentComposer = determineNextComposer(roomId, gameState, users);
|
||||||
|
|
||||||
|
const success = await selectSongAndOptions(gameState);
|
||||||
|
if (!success) return false;
|
||||||
|
|
||||||
users.forEach(user => {
|
users.forEach(user => {
|
||||||
gameState.roles[user.id] = user.id === gameState.currentComposer ? 'composer' : 'guesser';
|
gameState.roles[user.id] = user.id === gameState.currentComposer ? 'composer' : 'guesser';
|
||||||
});
|
});
|
||||||
|
|
||||||
return await selectSongAndOptions(gameState);
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const determineNextComposer = (roomId, gameState, users) => {
|
const determineNextComposer = (roomId, gameState, users) => {
|
||||||
|
@ -55,18 +55,22 @@ module.exports = (io) => (socket) => {
|
|||||||
const roles = gameController.getRoles(roomId);
|
const roles = gameController.getRoles(roomId);
|
||||||
const selectedSong = gameController.getSelectedSong(roomId);
|
const selectedSong = gameController.getSelectedSong(roomId);
|
||||||
const timeLeft = gameController.getTimeRemaining(roomId);
|
const timeLeft = gameController.getTimeRemaining(roomId);
|
||||||
|
const songOptions = gameController.getSongOptions(roomId);
|
||||||
|
|
||||||
io.to(roomId).emit('roles-assigned', roles);
|
io.to(roomId).emit('roles-assigned', roles);
|
||||||
|
|
||||||
Object.entries(roles).forEach(([userId, role]) => {
|
Object.entries(roles).forEach(([userId, role]) => {
|
||||||
if (role === 'composer') {
|
if (role === 'composer') {
|
||||||
io.to(userId).emit('song-selected', selectedSong);
|
io.to(userId).emit('song-selected', selectedSong);
|
||||||
|
} else {
|
||||||
|
io.to(userId).emit('song-options', { songOptions });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
io.to(roomId).emit('round-started', {
|
io.to(roomId).emit('round-started', {
|
||||||
round: gameController.getRoundResults(roomId).round,
|
round: gameController.getRoundResults(roomId).round,
|
||||||
timeRemaining: timeLeft
|
timeRemaining: timeLeft,
|
||||||
|
phase: 'composing'
|
||||||
});
|
});
|
||||||
|
|
||||||
startPhaseTimer(roomId);
|
startPhaseTimer(roomId);
|
||||||
@ -84,7 +88,8 @@ module.exports = (io) => (socket) => {
|
|||||||
|
|
||||||
io.to(roomId).emit('phase-changed', {
|
io.to(roomId).emit('phase-changed', {
|
||||||
phase: 'guessing',
|
phase: 'guessing',
|
||||||
timeRemaining: timeLeft
|
timeRemaining: timeLeft,
|
||||||
|
message: 'Time to submit your final answer!'
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(roles).forEach(([userId, role]) => {
|
Object.entries(roles).forEach(([userId, role]) => {
|
||||||
|
Reference in New Issue
Block a user