| | |
| | class PenaltyProGame { |
| | constructor() { |
| | this.playerStats = { |
| | name: "Marco Rodriguez", |
| | level: 1, |
| | xp: 60, |
| | xpToNextLevel: 1000, |
| | coins: 90, |
| | wins: 2, |
| | losses: 4, |
| | goals: 0, |
| | streak: 0, |
| | power: 82, |
| | speed: 78, |
| | acceleration: 74 |
| | }; |
| | } |
| |
|
| | addCoins(amount) { |
| | this.playerStats.coins += amount; |
| | this.updateUI(); |
| | this.showRewardNotification(`+${amount} coins`); |
| | } |
| |
|
| | addXP(amount) { |
| | this.playerStats.xp += amount; |
| | if (this.playerStats.xp >= this.playerStats.xpToNextLevel) { |
| | this.levelUp(); |
| | } |
| | this.updateUI(); |
| | this.showRewardNotification(`+${amount} XP`); |
| | } |
| |
|
| | levelUp() { |
| | this.playerStats.level += 1; |
| | this.playerStats.xp -= this.playerStats.xpToNextLevel; |
| | this.playerStats.xpToNextLevel = Math.floor(this.playerStats.xpToNextLevel * 1.2); |
| | this.showLevelUpNotification(); |
| | } |
| |
|
| | showRewardNotification(message) { |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed bottom-4 right-4 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg flex items-center'; |
| | notification.innerHTML = ` |
| | <i data-feather="award" class="mr-2"></i> |
| | <span>${message}</span> |
| | `; |
| | document.body.appendChild(notification); |
| | feather.replace(); |
| | |
| | setTimeout(() => { |
| | notification.classList.add('fade-out'); |
| | setTimeout(() => notification.remove(), 500); |
| | }, 3000); |
| | } |
| |
|
| | showLevelUpNotification() { |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed inset-0 flex items-center justify-center bg-black bg-opacity-70 z-50'; |
| | notification.innerHTML = ` |
| | <div class="bg-gradient-to-br from-green-600 to-blue-600 p-8 rounded-xl text-center max-w-md mx-4"> |
| | <i data-feather="star" class="w-16 h-16 text-yellow-300 mx-auto mb-4"></i> |
| | <h3 class="text-2xl font-bold mb-2">LEVEL UP!</h3> |
| | <p class="text-xl mb-4">You are now level ${this.playerStats.level}</p> |
| | <p class="mb-4">Unlock new abilities and rewards</p> |
| | <button class="bg-white text-gray-900 px-6 py-2 rounded-lg font-bold"> |
| | Continue |
| | </button> |
| | </div> |
| | `; |
| | document.body.appendChild(notification); |
| | feather.replace(); |
| | |
| | notification.querySelector('button').addEventListener('click', () => { |
| | notification.remove(); |
| | }); |
| | } |
| |
|
| | updateUI() { |
| | |
| | const elements = { |
| | '.player-name': this.playerStats.name, |
| | '.player-level': this.playerStats.level, |
| | '.player-xp': `${this.playerStats.xp}/${this.playerStats.xpToNextLevel}`, |
| | '.player-coins': this.playerStats.coins, |
| | '.player-wins': this.playerStats.wins, |
| | '.player-losses': this.playerStats.losses, |
| | '.player-goals': this.playerStats.goals, |
| | '.player-streak': this.playerStats.streak, |
| | '.pwr-stat': this.playerStats.power, |
| | '.spd-stat': this.playerStats.speed, |
| | '.acc-stat': this.playerStats.acceleration, |
| | '.xp-bar': `${(this.playerStats.xp / this.playerStats.xpToNextLevel) * 100}%`, |
| | '.pwr-bar': `${this.playerStats.power}%`, |
| | '.spd-bar': `${this.playerStats.speed}%`, |
| | '.acc-bar': `${this.playerStats.acceleration}%` |
| | }; |
| |
|
| | for (const [selector, value] of Object.entries(elements)) { |
| | document.querySelectorAll(selector).forEach(el => { |
| | if (selector.includes('-bar')) { |
| | el.style.width = value; |
| | } else { |
| | el.textContent = value; |
| | } |
| | }); |
| | } |
| | } |
| | } |
| |
|
| | |
| | const game = new PenaltyProGame(); |
| | |
| | document.addEventListener('DOMContentLoaded', () => { |
| | |
| | game.updateUI(); |
| | |
| | |
| | document.addEventListener('gameAction', (e) => { |
| | const { type, success, coins, xp } = e.detail; |
| | |
| | if (success) { |
| | game.addCoins(coins); |
| | game.addXP(xp); |
| | } |
| | }); |
| |
|
| | |
| | document.querySelectorAll('[data-game-mode]').forEach(card => { |
| | card.addEventListener('click', (e) => { |
| | const gameMode = card.getAttribute('data-game-mode'); |
| | const difficulty = card.getAttribute('data-difficulty'); |
| | |
| | switch(gameMode) { |
| | case 'quick-match': |
| | startQuickMatch(difficulty); |
| | break; |
| | case 'daily-challenge': |
| | startDailyChallenge(); |
| | break; |
| | case 'training': |
| | startTraining(); |
| | break; |
| | } |
| | }); |
| | }); |
| | }); |
| | function startQuickMatch(difficulty) { |
| | |
| | let coins = 0; |
| | let xp = 0; |
| | |
| | switch(difficulty) { |
| | case 'easy': |
| | coins = 15; |
| | xp = 50; |
| | break; |
| | case 'medium': |
| | coins = 20; |
| | xp = 75; |
| | break; |
| | case 'hard': |
| | coins = 25; |
| | xp = 100; |
| | break; |
| | } |
| | |
| | |
| | const isWin = Math.random() > 0.4; |
| | |
| | if (isWin) { |
| | game.playerStats.wins += 1; |
| | game.playerStats.streak += 1; |
| | game.playerStats.goals += Math.floor(Math.random() * 5) + 1; |
| | } else { |
| | game.playerStats.losses += 1; |
| | game.playerStats.streak = 0; |
| | } |
| | |
| | game.addCoins(coins); |
| | game.addXP(xp); |
| | |
| | |
| | showMatchResult(isWin, coins, xp); |
| | } |
| |
|
| | function startDailyChallenge() { |
| | |
| | const coins = 50; |
| | const xp = 150; |
| | const isWin = Math.random() > 0.3; |
| | |
| | if (isWin) { |
| | game.playerStats.wins += 1; |
| | game.playerStats.streak += 1; |
| | game.playerStats.goals += Math.floor(Math.random() * 7) + 1; |
| | } else { |
| | game.playerStats.losses += 1; |
| | game.playerStats.streak = 0; |
| | } |
| | |
| | game.addCoins(coins); |
| | game.addXP(xp); |
| | showMatchResult(isWin, coins, xp); |
| | } |
| |
|
| | function startTraining() { |
| | |
| | game.playerStats.goals += Math.floor(Math.random() * 10); |
| | game.updateUI(); |
| | |
| | |
| | const notification = document.createElement('div'); |
| | notification.className = 'fixed bottom-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg'; |
| | notification.textContent = 'Training completed! Your accuracy improved.'; |
| | document.body.appendChild(notification); |
| | |
| | setTimeout(() => { |
| | notification.classList.add('fade-out'); |
| | setTimeout(() => notification.remove(), 500); |
| | }, 3000); |
| | } |
| |
|
| | function showMatchResult(isWin, coins, xp) { |
| | const resultEl = document.createElement('div'); |
| | resultEl.className = 'fixed inset-0 flex items-center justify-center bg-black bg-opacity-70 z-50'; |
| | resultEl.innerHTML = ` |
| | <div class="bg-gray-800 p-8 rounded-xl text-center max-w-md mx-4 border-4 ${isWin ? 'border-green-500' : 'border-red-500'}"> |
| | <h3 class="text-3xl font-bold mb-4">${isWin ? 'VICTORY!' : 'DEFEAT'}</h3> |
| | <div class="grid grid-cols-2 gap-4 mb-6"> |
| | <div class="bg-gray-700 p-3 rounded-lg"> |
| | <div class="text-yellow-400 font-bold">+${coins}</div> |
| | <div class="text-sm text-gray-400">Coins</div> |
| | </div> |
| | <div class="bg-gray-700 p-3 rounded-lg"> |
| | <div class="text-green-400 font-bold">+${xp}</div> |
| | <div class="text-sm text-gray-400">XP</div> |
| | </div> |
| | </div> |
| | <div class="mb-6"> |
| | <div class="text-xl font-bold mb-2">${isWin ? 'You scored!' : 'Better luck next time'}</div> |
| | <p class="text-gray-400">Current streak: ${game.playerStats.streak}</p> |
| | </div> |
| | <button class="bg-green-600 hover:bg-green-700 px-6 py-2 rounded-lg font-bold transition-all"> |
| | Continue |
| | </button> |
| | </div> |
| | `; |
| | |
| | document.body.appendChild(resultEl); |
| | |
| | resultEl.querySelector('button').addEventListener('click', () => { |
| | resultEl.remove(); |
| | }); |
| | } |