export class Player extends Phaser.GameObjects.Sprite { constructor(scene, x, y, texture, frame) { super(scene, x, y, 'player-tiles'); scene.add.existing(this); scene.physics.world.enable(this); this.body.setSize(50,100); // Initialize variables this.pauseMove = false; this.isTakingDamage = false; this.showHealth = false; this.healthText; this.healthImages; this.numHearts = 3; this.maxHearts = 3; this.normalVelocityX = 260; this.inventory = []; this.facing = 'south'; this.isAttacking = false; this.isFiring = false; this.axe; this.bullet; this.texturePlus = 24; // Create animations this.anims.create({ key: 'north', frames: this.anims.generateFrameNumbers('player-tiles', { start: 0+this.texturePlus, end: 1+this.texturePlus }), frameRate: 5, repeat: -1 }); this.anims.create({ key: 'side', frames: this.anims.generateFrameNumbers('player-tiles', { start: 8+this.texturePlus, end: 9+this.texturePlus }), frameRate: 5, repeat: -1 }); this.anims.create({ key: 'south', frames: this.anims.generateFrameNumbers('player-tiles', { start: 16+this.texturePlus, end: 17+this.texturePlus }), frameRate: 5, repeat: -1 }); this.anims.create({ key: 'death', frames: [ { key: 'player-tiles', frame: 3+this.texturePlus } ], frameRate: 5, duration: 1500, repeat: -1 }); this.anims.create({ key: 'death2', frames: [ { key: 'player-tiles', frame: 4+this.texturePlus } ], frameRate: 5, duration: 1500, repeat: -1 }); this.scene.input.keyboard.on('keydown-A', this.attack, this); } update() { // Movement Debug: // console.log(this.body.x + " " + this.body.y); if (this.pauseMove === true) { this.body.setVelocity(0); } else { // Movement: Left/Right: if (this.scene.cursors.left.isDown) { this.body.setVelocityX(-200); this.setFlipX(false); this.anims.play('side', true); this.facing = 'west'; } else if (this.scene.cursors.right.isDown) { this.body.setVelocityX(200); this.setFlipX(true); this.anims.play('side', true); this.facing = 'east'; } else { this.body.setVelocityX(0); } // Movement: Up/Down: if (this.scene.cursors.up.isDown) { this.body.setVelocityY(-200); this.anims.play('south', true); this.facing = 'south'; } else if (this.scene.cursors.down.isDown) { this.body.setVelocityY(200); this.anims.play('north', true); this.facing = 'north'; } else { this.body.setVelocityY(0); } } } attack() { if (this.isAttacking === true) { return; } this.isAttacking = true; this.pauseMove = true; // Determine the direction the player is facing let offsetX = 0; let offsetY = 0; let flip = false; let rotate = 0; let direction = 360; let velocX = 0; let velocY = 0; if (this.facing === 'west') { offsetX = -100; flip = true; direction = -360; velocX = -1500; } else if (this.facing === 'east') { offsetX = +100; velocX = 1500; } else if (this.facing === 'north') { offsetY = +100; rotate = 90; velocY = 1500; } else if (this.facing === 'south') { offsetY = -100; rotate = 270; velocY = -1500; } // Create a rectangle for the attack area in front of the player const attackArea = new Phaser.Geom.Rectangle( this.x + offsetX, this.y + offsetY, 100, // width 100 // height ); // Add Axe this.axe = this.scene.physics.add.sprite(attackArea.x, attackArea.y, 'player-tiles', 2); this.scene.axes.add(this.axe); this.axe.setFlipX(flip); this.axe.setAngle(rotate); this.axe.setVelocity(velocX / 4, velocY / 4); this.scene.tweens.add({ targets: this.axe, scale: 1, // 110% of original size angle: direction+rotate, // Spin clockwise once (360 degrees) duration: 1000, ease: 'Power2' }); this.scene.sound.play('axeThrow'); // Add Bullet if hearts are full if (this.numHearts >= 3 && this.isFiring === false) { this.bullet = this.scene.physics.add.sprite(attackArea.x, attackArea.y, 'player-tiles', 10); this.scene.bullets.add(this.bullet) this.bullet.setFlip(flip); this.bullet.setAngle(rotate); this.bullet.setVelocity(velocX, velocY); this.scene.sound.play('gunShot'); this.isFiring = true; this.scene.physics.world.enable(this.bullet); } // Reset attack ability after a delay this.scene.time.delayedCall(500, () => { this.pauseMove = false; this.axe.destroy(); this.isAttacking = false; if (this.bullet) { this.bullet.destroy(); } }); if (this.isFiring === true) { this.scene.time.delayedCall(2000, () => { this.isFiring = false; }); } } healthBars(showHealth, Hearts, Lives) { this.showHealth = showHealth; if (this.showHealth === true) { this.healthText = this.scene.add.text(16, 16, 'Health: ', { fontSize: '36px', fill: '#FFF' }) .setShadow(3,3, '#333', 5) .setScrollFactor(0); this.updateHealth(); this.livesText = this.scene.add.text(16, 64, 'Lives:', { fontSize: '36px', fill: '#FFF' }) .setShadow(3,3, '#333', 5) .setScrollFactor(0); } } takeDamage(fromObject) { if (this.isTakingDamage) { return; } this.isTakingDamage = true; this.scene.sound.play('player-damage'); this.scene.tweens.add({ targets: this, tint: 0xaaaaff, duration: 1000, repeat: 0, yoyo: true, ease: 'Power1' }); this.numHearts -= 1; if (this.numHearts > 0) { this.updateHealth(); } else { this.updateHealth(); this.pauseMove = true; this.anims.play('death'); this.body.enable = false; this.scene.tweens.add({ targets: this, angle: 720, // Spin clockwise once (360 degrees) duration: 1500, ease: 'Power2', onComplete: () => { this.anims.play('death2'); // Add animation to lower player by 20px this.scene.tweens.add({ targets: this, y: '+=20', duration: 1000, ease: 'Power1' }); // Fade out the camera and restart the scene this.scene.cameras.main.fade(1500, 0, 0, 0, true); this.scene.time.delayedCall(1500, () => { this.scene.bgMusic.stop(); this.scene.scene.restart(); }); } }); } // Knockback // Reset taking damage state after a delay this.scene.time.delayedCall(500, () => { this.isTakingDamage = false; this.pauseMove = false; }); } addHealth(amount) { if (this.numHearts < 3) { this.numHearts += 1; this.updateHealth(); this.scene.sound.play('health-pickup'); } } updateHealth() { if (!this.showHealth) { return; } if (this.healthImages) { this.healthImages.destroy(true); } if (this.lifeImages) { this.lifeImages.destroy(true); } this.healthImages = this.scene.add.group(); this.lifeImages = this.scene.add.group(); let startX = 170; let startLivesX = 165 // Add full hearts for (let i = 0; i < this.numHearts; i++) { this.healthImages.add(this.scene.add.image(startX, 15, 'heart-full').setOrigin(0, 0).setScale(.5).setScrollFactor(0)); startX += 48; } // Add empty hearts for the remaining slots for (let i = this.numHearts; i < 3; i++) { this.healthImages.add(this.scene.add.image(startX, 15, 'heart-empty').setOrigin(0, 0).setScale(.5).setScrollFactor(0)); startX += 48; } // Add Lives for (let i = 0; i < this.numLives; i++) { this.lifeImages.add(this.scene.add.image(startLivesX, 64, 'life').setOrigin(0, 0).setScale(.5).setScrollFactor(0)); startLivesX += 48; } } addItemToInventory(itemKey) { if (!this.inventory[itemKey]) { this.inventory[itemKey] = 1; // Create the item with a quantity of 1 } else { this.inventory[itemKey]++; // Increment the quantity if it already exists } } removeItemFromInventory(itemKey) { if (this.inventory[itemKey]) { this.inventory[itemKey]--; if (this.inventory[itemKey] <= 0) { delete this.inventory[itemKey]; // Remove the item if its quantity is zero or less } } } hasItem(itemKey) { return this.inventory[itemKey] && this.inventory[itemKey] > 0; } getInventory() { return this.inventory; // Return a copy of the inventory to prevent direct modification } }