// Phaser is loaded from CDN, so we don't need to import it as a module /** * Main game configuration and initialization */ const config = { type: Phaser.AUTO, width: 1600, height: 900, parent: 'game-container', scene: { preload: preload, create: create, update: update }, scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH }, physics: { default: 'arcade', arcade: { gravity: { y: 0 }, debug: false } } }; /** * Game instance */ let game; /** * Preload function - load all assets before the game starts */ function preload() { console.log('Preloading game assets...'); // Create a simple loading bar const progressBar = this.add.graphics(); const progressBox = this.add.graphics(); progressBox.fillStyle(0x242424, 0.8); progressBox.fillRect(700, 430, 200, 50); const width = this.cameras.main.width; const height = this.cameras.main.height; const loadingText = this.make.text({ x: width / 2, y: height / 2 - 50, text: 'Loading...', style: { font: '20px monospace', fill: '#ffffff' } }); loadingText.setOrigin(0.5, 0.5); const percentText = this.make.text({ x: width / 2, y: height / 2 - 5, text: '0%', style: { font: '18px monospace', fill: '#ffffff' } }); percentText.setOrigin(0.5, 0.5); const assetText = this.make.text({ x: width / 2, y: height / 2 + 50, text: '', style: { font: '18px monospace', fill: '#ffffff' } }); assetText.setOrigin(0.5, 0.5); // Update loading progress this.load.on('progress', (value) => { percentText.setText(parseInt(value * 100) + '%'); progressBar.clear(); progressBar.fillStyle(0xffffff, 1); progressBar.fillRect(700, 430, 200 * value, 50); }); this.load.on('fileprogress', (file) => { assetText.setText('Loading asset: ' + file.key); }); this.load.on('complete', () => { progressBar.destroy(); progressBox.destroy(); loadingText.destroy(); percentText.destroy(); assetText.destroy(); }); } /** * Create function - setup the game world and initial state */ function create() { console.log('Creating game scene...'); // Set background color this.cameras.main.setBackgroundColor('#2d5a8c'); // Add a simple title text const title = this.add.text(800, 100, 'Deck Building Card Battle', { fontSize: '32px', fill: '#ffffff', align: 'center' }); title.setOrigin(0.5); // Create a basic game area const gameArea = this.add.rectangle(800, 450, 1400, 700, 0x3a7c2d); gameArea.setOrigin(0.5); // Add some instructions const instructions = this.add.text(800, 850, 'Use mouse to play cards and build your deck', { fontSize: '16px', fill: '#ffffff', align: 'center' }); instructions.setOrigin(0.5); // Initialize game state this.gameState = { playerDeck: [], opponentDeck: [], playerHand: [], opponentHand: [], playerField: [], opponentField: [], selectedCard: null, turnPhase: 'draw', currentPlayer: 'player' }; // Create a 10-card deck with numbers 1-10 this.gameState.playerDeck = []; for (let i = 1; i <= 10; i++) { this.gameState.playerDeck.push({ id: i, number: i, type: 'creature', // placeholder type attack: Math.floor(Math.random() * 5) + 1, // random attack value health: Math.floor(Math.random() * 5) + 1 // random health value }); } // Shuffle the deck using Fisher-Yates algorithm (using Phaser's scope) shuffleDeck(this.gameState.playerDeck); // Deal 3 cards to player's hand this.gameState.playerHand = this.gameState.playerDeck.splice(0, 3); // Display the player's hand at the bottom of the screen displayPlayerHand.call(this); console.log('Game scene created successfully'); } /** * Shuffle an array using Fisher-Yates algorithm */ function shuffleDeck(deck) { for (let i = deck.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [deck[i], deck[j]] = [deck[j], deck[i]]; } } /** * Display the player's hand at the bottom of the screen */ function displayPlayerHand() { const cardWidth = 100; const cardHeight = 140; const spacing = 20; // Calculate total width needed for all cards const totalWidth = (this.gameState.playerHand.length * cardWidth) + ((this.gameState.playerHand.length - 1) * spacing); // Starting x position to center the hand const startX = (1600 - totalWidth) / 2; // Position cards at the bottom of the screen const yPosition = 850; this.gameState.playerHand.forEach((card, index) => { const xPosition = startX + (index * (cardWidth + spacing)); // Create a simple card placeholder with number const cardSprite = this.add.rectangle(xPosition, yPosition, cardWidth, cardHeight, 0x8B4513); cardSprite.setOrigin(0.5); // Add the number to the card const numberText = this.add.text(xPosition, yPosition - 20, `${card.number}`, { fontSize: '24px', fill: '#ffffff' }); numberText.setOrigin(0.5); // Store card data with sprite reference card.sprite = cardSprite; card.text = numberText; // Add hover events for the card addInteractiveCard.call(this, card, xPosition, yPosition, cardWidth, cardHeight); }); } /** * Make a single card interactive with hover effects */ function addInteractiveCard(card, xPosition, yPosition, width, height) { const originalY = yPosition; // Create a transparent hit area for the card that matches its dimensions const hitArea = this.add.rectangle(xPosition, yPosition + 70, width - 10, height - 10); hitArea.setOrigin(0.5); hitArea.setInteractive(); // Add event listeners for hover effects hitArea.on('pointerover', () => { // Raise the card up to full view (move it up by 30 pixels) if (card.sprite) { card.sprite.setY(originalY - 30); } if (card.text) { card.text.setY(originalY - 50); } }); hitArea.on('pointerout', () => { // Return the card to its original position if (card.sprite) { card.sprite.setY(originalY); } if (card.text) { card.text.setY(originalY - 20); } }); } /** * Update function - called every frame */ function update() { // Game logic updates go here } /** * Initialize the game when the page loads */ document.addEventListener('DOMContentLoaded', () => { console.log('Initializing Phaser 3 card battle game...'); // Create the game instance game = new Phaser.Game(config); console.log('Phaser 3 card battle game initialized'); }); // Export for potential module usage (not needed when using CDN) // export { config, game };