This commit is contained in:
Evelyn Sucitro 2025-12-01 11:53:50 +07:00
commit dcb69e9dc5
6 changed files with 846 additions and 285 deletions

View File

@ -15,7 +15,6 @@
<div class="starfield" aria-hidden="true"></div>
<div class="cursor-light" aria-hidden="true"></div>
<!-- SOUND CONTROLS - KIRI ATAS -->
<!-- SOUND CONTROL - KIRI ATAS -->
<div class="sound-control-container">
<!-- Main Sound Button -->

View File

@ -14,7 +14,7 @@ let mergesInCurrentMove = 0;
Audio Setup
------------------------ */
const audio = {
bg: new Audio("Bgmusic.mp3"),
bg: new Audio("Background_Music.mp3"),
pop: new Audio("Pop.mp3"),
merge: new Audio("Merge.mp3")
};

File diff suppressed because it is too large Load Diff

View File

@ -3,44 +3,32 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048</title>
<title>Homepage - 2048</title>
<link rel="stylesheet" href="Homepage.css">
</head>
<body>
<div class="container">
<div class="header">
<h1>2048</h1>
</div>
<!-- Neon Particles Background -->
<div id="particles"></div>
<div class="score-container">
<div class="score-box">
<div class="score-label">Score</div>
<div class="score-value" id="score">0</div>
</div>
<div class="score-box">
<div class="score-label">High</div>
<div class="score-value" id="high">0</div>
</div>
<!-- Header -->
<header>
<div class="logo">2048</div>
<div class="nav-buttons">
<a href="Login.html" class="btn btn-secondary">Login</a>
</div>
</header>
<div class="controls">
<button class="btn" id="newGameBtn">New Game</button>
<button class="btn" id="undoBtn">Undo</button>
<!-- Hero Section -->
<section class="hero">
<div class="hero-title">2048</div>
<p class="hero-subtitle">Join the tiles, reach 2048</p>
<div class="cta-buttons">
<a href="2048.html" class="btn btn-cta btn-play">Play</a>
<a href="leaderboard.html" class="btn btn-cta btn-leaderboard">🏆 Leaderboard</a>
</div>
</section>
<div class="game-board" id="gameBoard"></div>
<div class="instructions">
<h3>How to Play</h3>
<p>Use arrow keys (↑ ↓ ← →) or swipe to move tiles. When two tiles with the same number touch, they merge into one! Join the numbers to reach the <strong>2048 tile</strong>!</p>
</div>
</div>
<div class="game-over" id="gameOver">
<div class="game-over-content">
<h2 id="gameOverTitle">Game Over!</h2>
<p id="gameOverMessage">Your score: <span id="finalScore">0</span></p>
<button class="btn" id="tryAgainBtn">Try Again</button>
</div>
</div>
<script src="Animation_Homepage.js"></script>
</body>
</html>

View File

@ -0,0 +1,233 @@
(function() {
'use strict';
// ==================== DOM ELEMENTS ====================
const elements = {
logo: null,
loginBtn: null,
playBtn: null,
leaderboardBtn: null,
heroTitle: null,
heroSubtitle: null
};
// ==================== INITIALIZE ====================
function init() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAll);
} else {
initAll();
}
}
function initAll() {
try {
// Cache DOM elements
cacheElements();
// Validate elements
if (!validateElements()) {
console.error('Some required elements are missing');
return;
}
// Setup event listeners
setupEventListeners();
// Initialize smooth scroll
initSmoothScroll();
console.log('✅ Homepage initialized successfully');
} catch (error) {
console.error('Error initializing homepage:', error);
}
}
// ==================== CACHE ELEMENTS ====================
function cacheElements() {
elements.logo = document.querySelector('.logo');
elements.loginBtn = document.querySelector('a[href="Login.html"]');
elements.playBtn = document.querySelector('a[href="2048.html"]');
elements.leaderboardBtn = document.querySelector('a[href="leaderboard.html"]');
elements.heroTitle = document.querySelector('.hero-title');
elements.heroSubtitle = document.querySelector('.hero-subtitle');
}
// ==================== VALIDATE ELEMENTS ====================
function validateElements() {
const requiredElements = ['logo', 'playBtn'];
const missingElements = requiredElements.filter(key => !elements[key]);
if (missingElements.length > 0) {
console.warn('Missing elements:', missingElements);
return false;
}
return true;
}
// ==================== EVENT LISTENERS ====================
function setupEventListeners() {
// Logo click - reload page
if (elements.logo) {
elements.logo.addEventListener('click', handleLogoClick);
}
// Login button
if (elements.loginBtn) {
elements.loginBtn.addEventListener('click', handleLoginClick);
}
// Play button
if (elements.playBtn) {
elements.playBtn.addEventListener('click', handlePlayClick);
}
// Leaderboard button
if (elements.leaderboardBtn) {
elements.leaderboardBtn.addEventListener('click', handleLeaderboardClick);
}
// Keyboard shortcuts
document.addEventListener('keydown', handleKeyPress);
// Window events
window.addEventListener('resize', handleResize);
window.addEventListener('beforeunload', handleBeforeUnload);
}
// ==================== EVENT HANDLERS ====================
function handleLogoClick(e) {
e.preventDefault();
window.location.href = 'index.html';
}
function handleLoginClick(e) {
// Allow default behavior (navigate to Login.html)
console.log('Navigating to Login page...');
}
function handlePlayClick(e) {
// Allow default behavior (navigate to 2048.html)
console.log('Starting game...');
}
function handleLeaderboardClick(e) {
// Allow default behavior (navigate to leaderboard.html)
console.log('Opening leaderboard...');
}
function handleKeyPress(e) {
// Press 'P' to play
if (e.key === 'p' || e.key === 'P') {
if (elements.playBtn) {
elements.playBtn.click();
}
}
// Press 'L' to login
if (e.key === 'l' || e.key === 'L') {
if (elements.loginBtn) {
elements.loginBtn.click();
}
}
// Press 'B' for leaderboard
if (e.key === 'b' || e.key === 'B') {
if (elements.leaderboardBtn) {
elements.leaderboardBtn.click();
}
}
}
function handleResize() {
// Handle responsive behavior if needed
const width = window.innerWidth;
if (width < 768) {
console.log('Mobile view');
} else if (width < 1024) {
console.log('Tablet view');
} else {
console.log('Desktop view');
}
}
function handleBeforeUnload(e) {
// Cleanup before page unload
console.log('Page unloading...');
}
// ==================== SMOOTH SCROLL ====================
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href === '#' || !href) return;
e.preventDefault();
const target = document.querySelector(href);
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
// ==================== UTILITY FUNCTIONS ====================
function checkBrowserSupport() {
const features = {
localStorage: typeof(Storage) !== 'undefined',
flexbox: CSS.supports('display', 'flex'),
grid: CSS.supports('display', 'grid')
};
console.log('Browser support:', features);
return features;
}
function isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
// ==================== PUBLIC API ====================
window.Homepage = {
init: initAll,
isMobile: isMobile,
checkSupport: checkBrowserSupport
};
// ==================== CLEANUP ====================
window.cleanupHomepage = function() {
// Remove event listeners
if (elements.logo) {
elements.logo.removeEventListener('click', handleLogoClick);
}
if (elements.loginBtn) {
elements.loginBtn.removeEventListener('click', handleLoginClick);
}
if (elements.playBtn) {
elements.playBtn.removeEventListener('click', handlePlayClick);
}
if (elements.leaderboardBtn) {
elements.leaderboardBtn.removeEventListener('click', handleLeaderboardClick);
}
document.removeEventListener('keydown', handleKeyPress);
window.removeEventListener('resize', handleResize);
window.removeEventListener('beforeunload', handleBeforeUnload);
console.log('Homepage cleaned up');
};
// Start initialization
init();
})();