Refactor game state management with GlobalState class; implement score display via Interface; adjust enemy points (100 for boss, 10 for regular); add heart upgrade item in Gulch

This commit is contained in:
Brian Fertig 2025-07-30 19:48:25 -06:00
parent 1a7ed865c8
commit 6680df14f8
8 changed files with 100 additions and 18 deletions

View File

@ -21,8 +21,8 @@
"scale": 0.5, "scale": 0.5,
"selectedLayer": 1, "selectedLayer": 1,
"viewCenter": { "viewCenter": {
"x": 2369, "x": 3252,
"y": 1644 "y": 2399
} }
}, },
"NNDungeon.tmx#99boy-tiles": { "NNDungeon.tmx#99boy-tiles": {

View File

@ -115,9 +115,10 @@ export class NNBoy extends Phaser.GameObjects.Sprite {
}); });
if (this.health === 1) { if (this.health === 1) {
if (this.boss === true) { if (this.boss === true) {
//BOSS DEFEAT //BOSS DEFEAT
this.scene.game.globalState.addScore(100);
this.scene.interface.showScore();
this.shoots = false; this.shoots = false;
this.garbage = false; this.garbage = false;
this.onPatrol = false; this.onPatrol = false;
@ -155,7 +156,8 @@ export class NNBoy extends Phaser.GameObjects.Sprite {
} }
}); });
} else { } else {
this.scene.game.playerData.score += 1; this.scene.game.globalState.addScore(10);
this.scene.interface.showScore();
//REGULAR ENEMY DEFEAT //REGULAR ENEMY DEFEAT
let dropHeart = Math.floor(Math.random() * this.dropHeartOneIn); let dropHeart = Math.floor(Math.random() * this.dropHeartOneIn);
if (dropHeart === 1) { if (dropHeart === 1) {

View File

@ -12,8 +12,8 @@ export class Player extends Phaser.GameObjects.Sprite {
this.showHealth = false; this.showHealth = false;
this.healthText; this.healthText;
this.healthImages; this.healthImages;
this.numHearts = 3; this.numHearts = scene.game.globalState.hearts;
this.maxHearts = scene.game.playerData.maxHearts; this.maxHearts = scene.game.globalState.maxHearts;
this.normalVelocityX = 260; this.normalVelocityX = 260;
this.inventory = []; this.inventory = [];
this.facing = 'south'; this.facing = 'south';
@ -217,9 +217,7 @@ export class Player extends Phaser.GameObjects.Sprite {
.setShadow(3,3, '#333', 5) .setShadow(3,3, '#333', 5)
.setScrollFactor(0); .setScrollFactor(0);
this.updateHealth(); this.updateHealth();
this.livesText = this.scene.add.text(16, 64, 'Score: '+this.scene.game.playerData.score, { fontSize: '36px', fill: '#FFF' })
.setShadow(3,3, '#333', 5)
.setScrollFactor(0);
} }
} }

View File

@ -5,7 +5,9 @@ export class GlobalState {
maxHearts: 3, maxHearts: 3,
score: 0, score: 0,
inventory: [], inventory: [],
upgrades: [] upgrades: [],
startGulchX: 950,
startGulchY: 4250,
}; };
} }
@ -45,6 +47,20 @@ export class GlobalState {
this.playerData.inventory = value; this.playerData.inventory = value;
} }
// Add item(s) to inventory (handles positive counts only)
addToInventory(itemName, count = 1) {
if (count < 0) throw new Error("Cannot add negative count to inventory");
if (count === 0) return;
// Create new array with existing items + added items
this.inventory = [...this.inventory, ...Array(count).fill(itemName)];
}
// Return count of item in inventory (including 0 for missing items)
hasInventory(itemName) {
return this.inventory.filter(item => item === itemName).length;
}
get upgrades() { get upgrades() {
return [...this.playerData.upgrades]; // Return a copy return [...this.playerData.upgrades]; // Return a copy
} }
@ -53,4 +69,26 @@ export class GlobalState {
if (!Array.isArray(value)) throw new Error("Upgrades must be an array"); if (!Array.isArray(value)) throw new Error("Upgrades must be an array");
this.playerData.upgrades = value; this.playerData.upgrades = value;
} }
get startGulchX() {
return this.playerData.startGulchX;
}
set startGulchX(value) {
this.playerData.startGulchX = value;
}
get startGulchY() {
return this.playerData.startGulchY;
}
set startGulchY(value) {
this.playerData.startGulchY = value;
}
// Add safe score increment method (replaces manual score updates)
addScore(amount) {
if (amount < 0) throw new Error("Cannot add negative score");
this.score += amount;
}
} }

16
src/interface.js Normal file
View File

@ -0,0 +1,16 @@
export class Interface {
constructor(scene) {
this.scene = scene;
}
showScore() {
if (this.scoreText) {
this.scoreText.destroy();
}
// Add Score
this.scoreText = this.scene.add.text(16, 64, 'Score: '+this.scene.game.globalState.score, { fontSize: '36px', fill: '#FFF' })
.setShadow(3,3, '#333', 5)
.setScrollFactor(0);
}
}

View File

@ -1,6 +1,7 @@
import { MenuScene } from './scenes/MenuScene.js'; import { MenuScene } from './scenes/MenuScene.js';
import { Gulch } from './scenes/gulch.js'; import { Gulch } from './scenes/gulch.js';
import { NNDungeon } from './scenes/NNDungeon.js'; import { NNDungeon } from './scenes/NNDungeon.js';
import { GlobalState } from './globalState.js';
const config = { const config = {
type: Phaser.AUTO, type: Phaser.AUTO,
@ -26,9 +27,11 @@ const config = {
const game = new Phaser.Game(config); const game = new Phaser.Game(config);
game.playerData = { game.globalState = new GlobalState();
score: 0,
maxHearts: 3, // game.playerData = {
startGulchX: 950, // score: 0,
startGulchY: 4250, // maxHearts: 3,
} // startGulchX: 950,
// startGulchY: 4250,
// }

View File

@ -1,6 +1,7 @@
import { Player } from '../characters/player.js'; import { Player } from '../characters/player.js';
import { Camera } from '../misc/cameras.js'; import { Camera } from '../misc/cameras.js';
import { NNBoy } from '../characters/99boy.js'; import { NNBoy } from '../characters/99boy.js';
import { Interface } from '../interface.js';
export class NNDungeon extends Phaser.Scene { export class NNDungeon extends Phaser.Scene {
@ -61,6 +62,10 @@ export class NNDungeon extends Phaser.Scene {
const interactiveLayer = NNDungeonMap.getObjectLayer('interactive'); const interactiveLayer = NNDungeonMap.getObjectLayer('interactive');
//const zoneLayer = gulchMap.getObjectLayer('zone'); //const zoneLayer = gulchMap.getObjectLayer('zone');
// Show Score
this.interface = new Interface(this);
this.interface.showScore();
// Add a player // Add a player
this.player = new Player(this, 2400, 3450); this.player = new Player(this, 2400, 3450);
//this.player = new Player(this, 3550, 350); //this.player = new Player(this, 3550, 350);

View File

@ -1,6 +1,7 @@
import { Player } from '../characters/player.js'; import { Player } from '../characters/player.js';
import { Camera } from '../misc/cameras.js'; import { Camera } from '../misc/cameras.js';
import { NNBoy } from '../characters/99boy.js'; import { NNBoy } from '../characters/99boy.js';
import { Interface } from '../interface.js';
export class Gulch extends Phaser.Scene { export class Gulch extends Phaser.Scene {
@ -19,7 +20,8 @@ export class Gulch extends Phaser.Scene {
preload() { preload() {
this.load.image('gulch-tiles', 'assets/gulch-tiles.png'); this.load.image('gulch-tiles', 'assets/gulch-tiles.png');
this.load.image('heart-full', 'assets/heart-full.png'); this.load.image('heart-full', 'assets/heart-full.png');
this.load.image('heart-empty', 'assets/heart-empty.png'); this.load.image('heart-empty', 'assets/heart-empty.png');
this.load.image('heart-upgrade', 'assets/heart-upgrade.png');
this.load.tilemapTiledJSON('gulchMap', 'assets/gulch.json'); this.load.tilemapTiledJSON('gulchMap', 'assets/gulch.json');
this.load.spritesheet('player-tiles', 'assets/player-tiles.png', { this.load.spritesheet('player-tiles', 'assets/player-tiles.png', {
frameWidth: 100, frameWidth: 100,
@ -52,8 +54,12 @@ export class Gulch extends Phaser.Scene {
const enemiesLayer = gulchMap.getObjectLayer('enemies'); const enemiesLayer = gulchMap.getObjectLayer('enemies');
const zoneLayer = gulchMap.getObjectLayer('zone'); const zoneLayer = gulchMap.getObjectLayer('zone');
// Show Score
this.interface = new Interface(this);
this.interface.showScore();
// Add a player // Add a player
this.player = new Player(this, this.game.playerData.startGulchX, this.game.playerData.startGulchY); this.player = new Player(this, this.game.globalState.startGulchX, this.game.globalState.startGulchY);
this.player.healthBars(true, 1, 3); this.player.healthBars(true, 1, 3);
zoneLayer.objects.forEach(object => { zoneLayer.objects.forEach(object => {
@ -150,6 +156,20 @@ export class Gulch extends Phaser.Scene {
heart.destroy(); heart.destroy();
}); });
// Add level heart upgrade
if (this.game.globalState.hasInventory('gulch-heart') === 0) {
this.upgrade = this.physics.add.image(5200, 5800, 'heart-upgrade').setScale(0.2);
this.physics.add.collider(this.player, this.upgrade, (player, upgrade) => {
this.game.globalState.addToInventory('gulch-heart', 1);
this.player.maxHearts ++;
this.player.numHearts ++;
this.game.globalState.maxHearts = this.player.maxHearts;
this.game.globalState.hearts = this.player.numHearts;
this.player.updateHealth();
upgrade.destroy();
});
}
//this.cameras.main.setScroll(800, 1100); //this.cameras.main.setScroll(800, 1100);
this.cameras.main.setBounds(0, 3600, 1600, 900); this.cameras.main.setBounds(0, 3600, 1600, 900);