Added a Song duration bar. Contains the song name, song duration and duration bar. Song duration acts as a countdown timer, same as the duration bar. Styling for mobile may need to be adjusted. Name/Duration/Timer updates correctly when the song changes.

This commit is contained in:
Jamon 2024-08-11 13:54:38 +12:00
parent a553fdd46a
commit b240756a64
4 changed files with 150 additions and 11 deletions

View File

@ -180,8 +180,8 @@ class SynthCoin:
self.x = x self.x = x
self.y = y self.y = y
self.radius = 5 self.radius = 5
self.follow_radius = 100 self.follow_radius = 200
self.follow_speed = 2 self.follow_speed = 5
self.created_at = time.time() self.created_at = time.time()
def update(self, players): def update(self, players):
@ -1482,6 +1482,7 @@ def game_loop():
'action': 'change', 'action': 'change',
'song': f"/{music_player.get_current_song()}", 'song': f"/{music_player.get_current_song()}",
'startTime': music_player.start_time, 'startTime': music_player.start_time,
'serverTime': time.time(),
'songDuration': music_player.get_current_song_duration() 'songDuration': music_player.get_current_song_duration()
}, room=main_room) }, room=main_room)
@ -1551,6 +1552,7 @@ def start_music():
'action': 'start', 'action': 'start',
'song': music_player.get_current_song(), 'song': music_player.get_current_song(),
'startTime': music_player.start_time, 'startTime': music_player.start_time,
'serverTime': time.time(),
'songDuration': music_player.get_current_song_duration() 'songDuration': music_player.get_current_song_duration()
}, room=main_room) }, room=main_room)
@ -1564,6 +1566,7 @@ def change_song():
'action': 'change', 'action': 'change',
'song': new_song, 'song': new_song,
'startTime': music_player.start_time, 'startTime': music_player.start_time,
'serverTime': time.time(),
'songDuration': music_player.get_current_song_duration() 'songDuration': music_player.get_current_song_duration()
}, room=main_room) }, room=main_room)
@ -1649,8 +1652,19 @@ class MusicPlayer:
self.current_song_index = (self.current_song_index + 1) % len(self.playlist) self.current_song_index = (self.current_song_index + 1) % len(self.playlist)
self.start_time = time.time() self.start_time = time.time()
self.load_current_song() self.load_current_song()
send_discord_alert(f"🎵 Now playing: {self.get_current_song()}") new_song = self.get_current_song()
return self.get_current_song() send_discord_alert(f"🎵 Now playing: {new_song}")
# Emit updated music sync information
socketio.emit('music_control', {
'action': 'change',
'song': new_song,
'startTime': self.start_time,
'serverTime': time.time(),
'songDuration': self.get_current_song_duration()
}, room=main_room)
return new_song
@ -1864,6 +1878,7 @@ class AdminConsole(cmd.Cmd):
'action': 'change', 'action': 'change',
'song': new_song, 'song': new_song,
'startTime': music_player.start_time, 'startTime': music_player.start_time,
'serverTime': time.time(),
'songDuration': music_player.get_current_song_duration() 'songDuration': music_player.get_current_song_duration()
}, room=main_room) }, room=main_room)
@ -1889,6 +1904,7 @@ class AdminConsole(cmd.Cmd):
'action': 'change', 'action': 'change',
'song': new_song, 'song': new_song,
'startTime': music_player.start_time, 'startTime': music_player.start_time,
'serverTime': time.time(),
'songDuration': music_player.get_current_song_duration() 'songDuration': music_player.get_current_song_duration()
}, room=main_room) }, room=main_room)

View File

@ -183,5 +183,15 @@
</div> </div>
<button class="close-button">Close</button> <button class="close-button">Close</button>
</div> </div>
<div id="songDurationBar" class="song-duration-bar">
<div id="songDurationFill" class="song-duration-fill"></div>
<div class="song-info">
<div id="songName"><div class="scrolling-text"></div></div>
<div id="songTimer"></div>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -30,7 +30,8 @@ let gameStarted = false;
let joystick = { active: false, startX: 0, startY: 0, endX: 0, endY: 0 }; let joystick = { active: false, startX: 0, startY: 0, endX: 0, endY: 0 };
let isDebugging = document.getElementById('debugCheckbox').checked; let isDebugging = document.getElementById('debugCheckbox').checked;
let socket; let socket;
let currentSongDuration = 180; // Default to 3 minutes let currentSongDuration = 0;
let songStartTime = 0;
let backgroundCanvas, backgroundCtx; let backgroundCanvas, backgroundCtx;
let uiButton, uiWidget, menuButton; let uiButton, uiWidget, menuButton;
let isWidgetVisible = false; let isWidgetVisible = false;
@ -72,6 +73,7 @@ let shootingJoystick = {
}; };
let lastUpdateTime = Date.now(); let lastUpdateTime = Date.now();
let impactEffects = []; let impactEffects = [];
let currentSongName = '';
@ -2188,6 +2190,15 @@ function startGame() {
}); });
}); });
socket.on('server_restart', (data) => {
notificationSystem.showNotification(data.message);
// Optionally, you could implement a reconnection attempt after a short delay
setTimeout(() => {
location.reload();
}, 5000); // Wait for 5 seconds before reloading the page
});
socket.on('achievement_unlocked', handleAchievementUnlock); socket.on('achievement_unlocked', handleAchievementUnlock);
@ -2232,8 +2243,13 @@ function startGame() {
if (gameStarted) { if (gameStarted) {
const serverClientTimeDiff = Date.now() / 1000 - data.serverTime; const serverClientTimeDiff = Date.now() / 1000 - data.serverTime;
currentSongDuration = data.songDuration || 180; // Use the provided duration or default to 3 minutes currentSongDuration = data.songDuration || 180; // Use the provided duration or default to 3 minutes
songStartTime = data.startTime + serverClientTimeDiff;
const songPosition = (Date.now() / 1000 - data.startTime - serverClientTimeDiff) % currentSongDuration; const songPosition = (Date.now() / 1000 - data.startTime - serverClientTimeDiff) % currentSongDuration;
setupAudio(data.song, songPosition); setupAudio(data.song, songPosition);
currentSongName = data.song.split('/').pop();
updateSongDurationBar();
} }
}); });
@ -2527,10 +2543,14 @@ socket.on('bullet_impact', (data) => {
switch(data.action) { switch(data.action) {
case 'start': case 'start':
case 'change': case 'change':
const currentTime = Date.now() / 1000; const serverClientTimeDiff = Date.now() / 1000 - data.serverTime;
const elapsedTime = currentTime - data.startTime;
currentSongDuration = data.songDuration || 180; // Use the provided duration or default to 3 minutes currentSongDuration = data.songDuration || 180; // Use the provided duration or default to 3 minutes
setupAudio(data.song, elapsedTime % currentSongDuration); songStartTime = data.startTime + serverClientTimeDiff;
const songPosition = 0; // Start from the beginning for 'change' action
setupAudio(data.song, songPosition);
currentSongName = data.song.split('/').pop();
updateSongDurationBar();
break; break;
case 'stop': case 'stop':
if (audioElement) { if (audioElement) {
@ -2539,7 +2559,7 @@ socket.on('bullet_impact', (data) => {
break; break;
} }
}); });
socket.on('skin_update', (data) => { socket.on('skin_update', (data) => {
const { player_id, skin_data } = data; const { player_id, skin_data } = data;
if (player_id === socket.id) { if (player_id === socket.id) {
@ -2550,7 +2570,7 @@ socket.on('bullet_impact', (data) => {
otherPlayers[player_id].setSkin(skin_data); otherPlayers[player_id].setSkin(skin_data);
} }
}); });
showSongDurationBar();
} }
function hideShopButton() { function hideShopButton() {
@ -3179,6 +3199,9 @@ function update() {
if (gameStarted) { if (gameStarted) {
alertSystem.draw(ctx); alertSystem.draw(ctx);
} }
if (gameStarted) {
updateSongDurationBar();
}
requestAnimationFrame(update); requestAnimationFrame(update);
debugLog('Player position:', player.x, player.y); debugLog('Player position:', player.x, player.y);
debugLog('Number of enemies:', serverEnemies.length); debugLog('Number of enemies:', serverEnemies.length);
@ -3798,6 +3821,34 @@ class ImpactEffect {
} }
} }
function updateSongDurationBar() {
const now = Date.now() / 1000;
const elapsed = now - songStartTime;
const remaining = Math.max(0, currentSongDuration - elapsed);
const progress = Math.min(1, elapsed / currentSongDuration);
const fillElement = document.getElementById('songDurationFill');
const timerElement = document.getElementById('songTimer');
const songNameElement = document.querySelector('#songName .scrolling-text');
fillElement.style.width = `${(1 - progress) * 100}%`;
timerElement.textContent = formatTime(remaining);
songNameElement.textContent = `Now playing: ${currentSongName}`;
}
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.floor(seconds % 60);
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
}
function showSongDurationBar() {
document.getElementById('songDurationBar').style.display = 'block';
}
function hideSongDurationBar() {
document.getElementById('songDurationBar').style.display = 'none';
}
init(); init();

View File

@ -548,6 +548,68 @@ body {
} }
} }
.song-duration-bar {
position: fixed;
top: 10px;
left: 50%;
transform: translateX(-50%);
width: 300px;
height: 30px;
background-color: rgba(0, 0, 0, 0.5);
border: 2px solid #00ffff;
border-radius: 15px;
overflow: hidden;
display: none;
align-items: center;
}
.song-duration-fill {
height: 100%;
background-color: rgba(0, 255, 255, 0.3);
transition: width 1s linear;
}
.song-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
font-family: 'Orbitron', sans-serif;
font-size: 14px;
color: #00ffff;
}
#songName {
flex-grow: 1;
overflow: hidden;
white-space: nowrap;
}
#songName .scrolling-text {
display: inline-block;
padding-left: 100%;
animation: scroll 15s linear infinite;
}
@keyframes scroll {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-100%, 0);
}
}
#songTimer {
flex-shrink: 0;
}
.skin-option.glow-effect { .skin-option.glow-effect {
box-shadow: 0 0 10px 3px currentColor; box-shadow: 0 0 10px 3px currentColor;
animation: glow 1.5s ease-in-out infinite alternate; animation: glow 1.5s ease-in-out infinite alternate;