Add background video support to Quick Play
- Added video mode selection (none, background, popup, multi-screen) - Implemented BaseVideoPlayer integration for background videos - Added video opacity, sound, and control options - Enhanced video library initialization for Quick Play mode - Added user-friendly notifications when no videos are available - Improved video container styling with proper layering - Added automatic random video loading and rotation - Enhanced task display readability over background video
This commit is contained in:
parent
a10a6bafef
commit
8fb373afdb
517
quick-play.html
517
quick-play.html
|
|
@ -127,6 +127,47 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Video Settings -->
|
||||
<div class="setting-group">
|
||||
<h3>🎬 Video Experience</h3>
|
||||
<div class="video-settings">
|
||||
<div class="setting-row">
|
||||
<label for="video-mode">Video Mode:</label>
|
||||
<select id="video-mode">
|
||||
<option value="none">None - Focus Mode</option>
|
||||
<option value="background" selected>Background Video</option>
|
||||
<option value="popup">Popup Rewards</option>
|
||||
<option value="multi-screen">Multi-Screen (Advanced)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="video-options" id="video-options">
|
||||
<div class="video-option">
|
||||
<input type="checkbox" id="enable-video-sound" checked>
|
||||
<label for="enable-video-sound">
|
||||
<span class="option-icon">🔊</span>
|
||||
<span class="option-text">Video Audio</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="video-option">
|
||||
<input type="checkbox" id="enable-video-controls">
|
||||
<label for="enable-video-controls">
|
||||
<span class="option-icon">🎛️</span>
|
||||
<span class="option-text">Show Video Controls</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label for="video-opacity">Video Opacity:</label>
|
||||
<select id="video-opacity">
|
||||
<option value="0.3">30% - Subtle</option>
|
||||
<option value="0.5">50% - Balanced</option>
|
||||
<option value="0.7" selected>70% - Prominent</option>
|
||||
<option value="1.0">100% - Full</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visual Settings -->
|
||||
<div class="setting-group">
|
||||
<h3>🖼️ Visual Experience</h3>
|
||||
|
|
@ -287,6 +328,10 @@
|
|||
<script src="src/features/ui/flashMessageManager.js"></script>
|
||||
<script src="src/features/images/popupImageManager.js"></script>
|
||||
<script src="src/features/audio/audioManager.js"></script>
|
||||
<script src="src/features/media/baseVideoPlayer.js"></script>
|
||||
<script src="src/features/media/overlayVideoPlayer.js"></script>
|
||||
<script src="src/features/media/quadVideoPlayer.js"></script>
|
||||
<script src="src/features/media/videoLibrary.js"></script>
|
||||
<script src="src/features/video/videoPlayerManager.js"></script>
|
||||
<script src="src/features/webcam/webcamManager.js"></script>
|
||||
<script src="src/features/tasks/aiTaskManager.js"></script>
|
||||
|
|
@ -307,11 +352,17 @@
|
|||
enableFlashMessages: true,
|
||||
difficulty: 'medium',
|
||||
includeStandardTasks: true,
|
||||
includeScenarioTasks: false // Scenarios disabled by default
|
||||
includeScenarioTasks: false, // Scenarios disabled by default
|
||||
// Video settings
|
||||
videoMode: 'background',
|
||||
enableVideoSound: true,
|
||||
enableVideoControls: false,
|
||||
videoOpacity: 0.7
|
||||
};
|
||||
|
||||
let gameInstance = null;
|
||||
let isGameRunning = false;
|
||||
let backgroundVideoPlayer = null;
|
||||
|
||||
// Initialize Quick Play when page loads
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
|
|
@ -419,6 +470,12 @@
|
|||
document.getElementById('enable-ambient-audio').checked = quickPlaySettings.enableAmbientAudio;
|
||||
document.getElementById('enable-voice-commands').checked = quickPlaySettings.enableVoiceCommands;
|
||||
|
||||
// Apply video settings
|
||||
document.getElementById('video-mode').value = quickPlaySettings.videoMode;
|
||||
document.getElementById('enable-video-sound').checked = quickPlaySettings.enableVideoSound;
|
||||
document.getElementById('enable-video-controls').checked = quickPlaySettings.enableVideoControls;
|
||||
document.getElementById('video-opacity').value = quickPlaySettings.videoOpacity;
|
||||
|
||||
// Apply task type settings
|
||||
document.getElementById('include-standard-tasks').checked = quickPlaySettings.includeStandardTasks;
|
||||
document.getElementById('include-scenario-tasks').checked = quickPlaySettings.includeScenarioTasks;
|
||||
|
|
@ -435,6 +492,220 @@
|
|||
preset.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Show/hide video options based on mode
|
||||
updateVideoOptionsVisibility();
|
||||
}
|
||||
|
||||
|
||||
async function initializeBackgroundVideo() {
|
||||
try {
|
||||
console.log('🎬 Initializing background video player...');
|
||||
|
||||
// Create BaseVideoPlayer instance for background video
|
||||
backgroundVideoPlayer = new BaseVideoPlayer('#background-video-container', {
|
||||
showControls: quickPlaySettings.enableVideoControls,
|
||||
autoHide: true,
|
||||
showProgress: false,
|
||||
showVolume: true,
|
||||
showFullscreen: false,
|
||||
showQuality: false,
|
||||
showSpeed: false,
|
||||
keyboardShortcuts: false, // Disable to avoid conflicts with game controls
|
||||
minimal: !quickPlaySettings.enableVideoControls
|
||||
});
|
||||
|
||||
// Set initial volume based on settings
|
||||
backgroundVideoPlayer.setVolume(quickPlaySettings.enableVideoSound ? 0.3 : 0);
|
||||
|
||||
// Set video opacity
|
||||
const videoElement = backgroundVideoPlayer.videoElement;
|
||||
if (videoElement) {
|
||||
videoElement.style.opacity = quickPlaySettings.videoOpacity;
|
||||
}
|
||||
|
||||
// Setup background video specific event listeners
|
||||
setupBackgroundVideoListeners();
|
||||
|
||||
// Load random video
|
||||
await loadRandomBackgroundVideo();
|
||||
|
||||
console.log('✅ Background video player initialized');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error initializing background video:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadRandomBackgroundVideo() {
|
||||
try {
|
||||
// Get all available videos using the same logic as other video players
|
||||
let allVideos = [];
|
||||
|
||||
// First check if we have a video library instance
|
||||
if (window.videoLibrary && typeof window.videoLibrary.getAllVideos === 'function') {
|
||||
allVideos = window.videoLibrary.getAllVideos();
|
||||
console.log(`🎬 Got ${allVideos.length} videos from VideoLibrary instance`);
|
||||
}
|
||||
|
||||
// Try desktop file manager
|
||||
if (allVideos.length === 0 && window.desktopFileManager) {
|
||||
allVideos = window.desktopFileManager.getAllVideos();
|
||||
console.log(`🎬 Got ${allVideos.length} videos from DesktopFileManager`);
|
||||
}
|
||||
|
||||
// Fallback to unified storage
|
||||
if (allVideos.length === 0) {
|
||||
const unifiedData = JSON.parse(localStorage.getItem('unifiedVideoLibrary') || '{}');
|
||||
allVideos = unifiedData.allVideos || [];
|
||||
console.log(`🎬 Got ${allVideos.length} videos from unified storage`);
|
||||
}
|
||||
|
||||
// Fallback to legacy storage
|
||||
if (allVideos.length === 0) {
|
||||
const storedVideos = JSON.parse(localStorage.getItem('videoFiles') || '{}');
|
||||
allVideos = Object.values(storedVideos).flat();
|
||||
console.log(`🎬 Got ${allVideos.length} videos from legacy storage`);
|
||||
}
|
||||
|
||||
// If still no videos, try to initialize video library
|
||||
if (allVideos.length === 0) {
|
||||
console.log('🎬 No videos found, attempting to initialize video library...');
|
||||
await initializeVideoLibrary();
|
||||
|
||||
// Try again after initialization
|
||||
const unifiedData = JSON.parse(localStorage.getItem('unifiedVideoLibrary') || '{}');
|
||||
allVideos = unifiedData.allVideos || [];
|
||||
console.log(`🎬 After initialization: ${allVideos.length} videos available`);
|
||||
}
|
||||
|
||||
if (allVideos.length === 0) {
|
||||
console.warn('⚠️ No videos available for background playback');
|
||||
showVideoSetupNotification();
|
||||
return;
|
||||
}
|
||||
|
||||
// Select random video
|
||||
const randomIndex = Math.floor(Math.random() * allVideos.length);
|
||||
const randomVideo = allVideos[randomIndex];
|
||||
|
||||
console.log(`🎬 Loading background video: ${randomVideo.name || randomVideo.title}`);
|
||||
|
||||
// Load video without autoplay initially
|
||||
backgroundVideoPlayer.loadVideo(randomVideo.path || randomVideo.filePath, false);
|
||||
|
||||
// Start playing after a short delay to ensure task focus isn't disrupted
|
||||
setTimeout(() => {
|
||||
if (backgroundVideoPlayer && backgroundVideoPlayer.videoElement) {
|
||||
backgroundVideoPlayer.play();
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading background video:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function setupBackgroundVideoListeners() {
|
||||
if (!backgroundVideoPlayer) return;
|
||||
|
||||
// Random video button
|
||||
const randomBtn = document.querySelector('.random-video-btn');
|
||||
if (randomBtn) {
|
||||
randomBtn.addEventListener('click', () => {
|
||||
loadRandomBackgroundVideo();
|
||||
});
|
||||
}
|
||||
|
||||
// Video ended - load next random video
|
||||
if (backgroundVideoPlayer.videoElement) {
|
||||
backgroundVideoPlayer.videoElement.addEventListener('ended', () => {
|
||||
setTimeout(() => {
|
||||
loadRandomBackgroundVideo();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Handle video errors
|
||||
backgroundVideoPlayer.videoElement.addEventListener('error', () => {
|
||||
console.warn('Background video error, loading new video...');
|
||||
setTimeout(() => {
|
||||
loadRandomBackgroundVideo();
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateVideoOptionsVisibility() {
|
||||
const videoOptions = document.getElementById('video-options');
|
||||
const videoMode = document.getElementById('video-mode').value;
|
||||
|
||||
if (videoMode === 'none') {
|
||||
videoOptions.style.display = 'none';
|
||||
} else {
|
||||
videoOptions.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function initializeVideoLibrary() {
|
||||
try {
|
||||
console.log('🎬 Attempting to initialize video library for Quick Play...');
|
||||
|
||||
// Check if we have linked video directories
|
||||
const linkedDirs = JSON.parse(localStorage.getItem('linkedVideoDirectories') || '[]');
|
||||
if (linkedDirs.length > 0) {
|
||||
console.log(`🎬 Found ${linkedDirs.length} linked directories, scanning...`);
|
||||
|
||||
// Initialize VideoLibrary to scan directories
|
||||
if (typeof VideoLibrary !== 'undefined') {
|
||||
const tempVideoLibrary = new VideoLibrary({
|
||||
videoContainer: document.createElement('div')
|
||||
});
|
||||
await tempVideoLibrary.loadVideoLibrary();
|
||||
window.videoLibrary = tempVideoLibrary;
|
||||
console.log('🎬 VideoLibrary initialized successfully');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log('🎬 No linked directories found');
|
||||
return false;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error initializing video library:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function showVideoSetupNotification() {
|
||||
// Show a user-friendly notification about setting up videos
|
||||
const taskTitle = document.getElementById('task-title');
|
||||
const taskText = document.getElementById('task-text');
|
||||
|
||||
if (taskTitle && taskText) {
|
||||
// Temporarily show setup message
|
||||
const originalTitle = taskTitle.textContent;
|
||||
const originalText = taskText.textContent;
|
||||
|
||||
taskTitle.textContent = '🎬 Background Video Setup';
|
||||
taskText.innerHTML = `
|
||||
No videos found for background playback.<br>
|
||||
To enable background videos:<br>
|
||||
1. Go to the main menu → Porn Cinema<br>
|
||||
2. Add video directories or files<br>
|
||||
3. Return to Quick Play<br><br>
|
||||
<small>Continuing without background video...</small>
|
||||
`;
|
||||
|
||||
// Restore original content after 8 seconds
|
||||
setTimeout(() => {
|
||||
if (taskTitle && taskText) {
|
||||
taskTitle.textContent = originalTitle;
|
||||
taskText.textContent = originalText;
|
||||
}
|
||||
}, 8000);
|
||||
}
|
||||
|
||||
console.log('📋 Video setup notification shown to user');
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
|
|
@ -550,6 +821,21 @@
|
|||
quickPlaySettings.enableVoiceCommands = e.target.checked;
|
||||
});
|
||||
|
||||
// Video settings
|
||||
document.getElementById('video-mode').addEventListener('change', (e) => {
|
||||
quickPlaySettings.videoMode = e.target.value;
|
||||
updateVideoOptionsVisibility();
|
||||
});
|
||||
document.getElementById('enable-video-sound').addEventListener('change', (e) => {
|
||||
quickPlaySettings.enableVideoSound = e.target.checked;
|
||||
});
|
||||
document.getElementById('enable-video-controls').addEventListener('change', (e) => {
|
||||
quickPlaySettings.enableVideoControls = e.target.checked;
|
||||
});
|
||||
document.getElementById('video-opacity').addEventListener('change', (e) => {
|
||||
quickPlaySettings.videoOpacity = parseFloat(e.target.value);
|
||||
});
|
||||
|
||||
// Task type checkboxes
|
||||
document.getElementById('include-standard-tasks').addEventListener('change', (e) => {
|
||||
quickPlaySettings.includeStandardTasks = e.target.checked;
|
||||
|
|
@ -614,9 +900,39 @@
|
|||
function initializeGameInstance() {
|
||||
const gameContainer = document.getElementById('game-container-wrapper');
|
||||
|
||||
// Create the game interface structure
|
||||
// Create the game interface structure with optional background video
|
||||
const hasBackgroundVideo = quickPlaySettings.videoMode === 'background';
|
||||
|
||||
gameContainer.innerHTML = `
|
||||
<div class="game-container">
|
||||
${hasBackgroundVideo ? `
|
||||
<!-- Background Video Container -->
|
||||
<div id="background-video-container" class="background-video-container">
|
||||
<video id="background-video" class="background-video" preload="metadata" loop>
|
||||
<source id="background-video-source" src="" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
<!-- Video Controls (optional) -->
|
||||
<div class="video-controls background-video-controls" style="display: ${quickPlaySettings.enableVideoControls ? 'flex' : 'none'};">
|
||||
<div class="controls-row">
|
||||
<button class="control-btn play-pause-btn" title="Play/Pause">▶</button>
|
||||
<div class="volume-control">
|
||||
<button class="control-btn mute-btn" title="Mute">🔊</button>
|
||||
<input type="range" class="volume-slider" min="0" max="100" value="70">
|
||||
</div>
|
||||
<button class="control-btn random-video-btn" title="Random Video">🎲</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Video Loading Indicator -->
|
||||
<div class="video-loading" id="background-video-loading" style="display: none;">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>Loading video...</p>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<!-- Include main game interface elements here -->
|
||||
<div class="game-content">
|
||||
<div class="main-content-area">
|
||||
|
|
@ -648,6 +964,15 @@
|
|||
console.log('Game button listeners set up after DOM creation');
|
||||
}, 100);
|
||||
|
||||
// Initialize background video if enabled
|
||||
if (hasBackgroundVideo) {
|
||||
setTimeout(() => {
|
||||
initializeBackgroundVideo();
|
||||
}, 200);
|
||||
} else {
|
||||
console.log('🎬 Background video disabled - video mode:', quickPlaySettings.videoMode);
|
||||
}
|
||||
|
||||
// Initialize the game instance with Quick Play specific settings
|
||||
setTimeout(() => {
|
||||
initializeFullGame();
|
||||
|
|
@ -974,6 +1299,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Clean up background video
|
||||
if (backgroundVideoPlayer) {
|
||||
console.log('Stopping background video');
|
||||
try {
|
||||
backgroundVideoPlayer.pause();
|
||||
if (backgroundVideoPlayer.destroy) {
|
||||
backgroundVideoPlayer.destroy();
|
||||
}
|
||||
backgroundVideoPlayer = null;
|
||||
} catch (videoError) {
|
||||
console.warn('Error stopping background video:', videoError);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect results
|
||||
const timer = document.getElementById('game-timer');
|
||||
const tasksElement = document.getElementById('tasks-completed');
|
||||
|
|
@ -2075,6 +2414,180 @@
|
|||
padding: 20px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Background Video Styles */
|
||||
.background-video-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.background-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.background-video-controls {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 20px;
|
||||
padding: 8px 16px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.background-video-container:hover .background-video-controls {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.background-video-controls .controls-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.background-video-controls .control-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.background-video-controls .control-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.background-video-controls .volume-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.background-video-controls .volume-slider {
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.background-video-controls .volume-slider::-webkit-slider-thumb {
|
||||
appearance: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: #00d4ff;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.background-video-controls .volume-slider::-moz-range-thumb {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: #00d4ff;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Ensure game content appears above background video */
|
||||
.game-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: rgba(0, 0, 0, 0.1); /* Slight overlay for better text readability */
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
/* Enhance task display container for better visibility over video */
|
||||
.task-display-container {
|
||||
background: rgba(0, 0, 0, 0.7) !important;
|
||||
backdrop-filter: blur(5px);
|
||||
border: 2px solid rgba(0, 212, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
.control-sidebar {
|
||||
background: rgba(0, 0, 0, 0.8) !important;
|
||||
backdrop-filter: blur(5px);
|
||||
border: 1px solid rgba(0, 212, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Video mode selection styles */
|
||||
.video-settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.video-options {
|
||||
margin-left: 20px;
|
||||
padding: 15px;
|
||||
background: rgba(0, 212, 255, 0.05);
|
||||
border: 1px solid rgba(0, 212, 255, 0.2);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.video-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.video-option label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Mobile adjustments for background video */
|
||||
@media (max-width: 768px) {
|
||||
.background-video-controls {
|
||||
bottom: 5px;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.background-video-controls .control-btn {
|
||||
font-size: 12px;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
|
||||
.background-video-controls .volume-slider {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.game-content {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.task-display-container {
|
||||
background: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
.control-sidebar {
|
||||
background: rgba(0, 0, 0, 0.9) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue