diff --git a/index.html b/index.html
index 0cc5dd6..ad29eb8 100644
--- a/index.html
+++ b/index.html
@@ -1716,6 +1716,7 @@
this.load.image('room_ceo_l', 'assets/rooms/room_ceo_l.png');
this.load.image('room_spooky_basement_l', 'assets/rooms/room_spooky_basement_l.png');
this.load.image('door', 'assets/tiles/door.png');
+
// Load object sprites
this.load.image('pc', 'assets/objects/pc.png');
this.load.image('key', 'assets/objects/key.png');
@@ -1734,6 +1735,12 @@
this.load.image('lockpick', 'assets/objects/lockpick.png');
this.load.image('spoofing_kit', 'assets/objects/spoofing_kit.png');
+ // Load character sprite sheet instead of single image
+ this.load.spritesheet('hacker', 'assets/characters/hacker.png', {
+ frameWidth: 64,
+ frameHeight: 64
+ });
+
// Get scenario from URL parameter or use default
const urlParams = new URLSearchParams(window.location.search);
const scenarioFile = urlParams.get('scenario') || 'assets/scenarios/ceo_exfil.json';
@@ -1790,17 +1797,104 @@
worldBounds.height
);
- // Create player first
- player = this.add.rectangle(400, 300, 32, 32, 0xff0000);
+ // Create player as sprite
+ player = this.add.sprite(400, 300, 'hacker', 0);
this.physics.add.existing(player);
- player.body.setSize(16, 16);
- player.body.setOffset(8, 8);
+
+ // Scale the character up by 25%
+ player.setScale(1.25);
+
+ // Set smaller collision box at the feet
+ player.body.setSize(15, 10);
+ player.body.setOffset(25, 50); // Adjusted offset to account for scaling
+
player.body.setCollideWorldBounds(true);
player.body.setBounce(0);
player.body.setDrag(0);
player.body.setFriction(0);
+
+ // Enable physics debug to see the collision box
+ this.physics.world.debugGraphic.clear();
+ this.physics.world.drawDebug = true;
+
+ // Force debug display to be visible and on top
+ this.physics.world.debugGraphic.setVisible(true);
+ this.physics.world.debugGraphic.setDepth(9999);
+
+ // Set player depth to ensure it renders above most objects
+ player.setDepth(2000);
+
+ // Track player direction and movement state
+ player.direction = 'down'; // Initial direction
+ player.isMoving = false;
+ player.lastDirection = 'down';
- player.setDepth(1000);
+ // Create animations for each direction
+ this.anims.create({
+ key: 'walk-right',
+ frames: this.anims.generateFrameNumbers('hacker', { start: 1, end: 4 }),
+ frameRate: 8,
+ repeat: -1
+ });
+
+ this.anims.create({
+ key: 'walk-down',
+ frames: this.anims.generateFrameNumbers('hacker', { start: 6, end: 9 }),
+ frameRate: 8,
+ repeat: -1
+ });
+
+ this.anims.create({
+ key: 'walk-up',
+ frames: this.anims.generateFrameNumbers('hacker', { start: 11, end: 14 }),
+ frameRate: 8,
+ repeat: -1
+ });
+
+ this.anims.create({
+ key: 'walk-up-right',
+ frames: this.anims.generateFrameNumbers('hacker', { start: 16, end: 19 }),
+ frameRate: 8,
+ repeat: -1
+ });
+
+ this.anims.create({
+ key: 'walk-down-right',
+ frames: this.anims.generateFrameNumbers('hacker', { start: 21, end: 24 }),
+ frameRate: 8,
+ repeat: -1
+ });
+
+ // Create idle frames (first frame of each row)
+ this.anims.create({
+ key: 'idle-right',
+ frames: [{ key: 'hacker', frame: 0 }],
+ frameRate: 1
+ });
+
+ this.anims.create({
+ key: 'idle-down',
+ frames: [{ key: 'hacker', frame: 5 }],
+ frameRate: 1
+ });
+
+ this.anims.create({
+ key: 'idle-up',
+ frames: [{ key: 'hacker', frame: 10 }],
+ frameRate: 1
+ });
+
+ this.anims.create({
+ key: 'idle-up-right',
+ frames: [{ key: 'hacker', frame: 15 }],
+ frameRate: 1
+ });
+
+ this.anims.create({
+ key: 'idle-down-right',
+ frames: [{ key: 'hacker', frame: 20 }],
+ frameRate: 1
+ });
// Initialize room layout after player creation
initializeRooms.call(this);
@@ -1913,6 +2007,9 @@
}
function update() {
+ // Make sure debug is always enabled
+ this.physics.world.drawDebug = true;
+
// updates the player's movement
updatePlayerMovement.call(this);
@@ -2342,6 +2439,10 @@
if (!isMoving || !targetPoint) {
if (player.body.velocity.x !== 0 || player.body.velocity.y !== 0) {
player.body.setVelocity(0, 0);
+ player.isMoving = false;
+
+ // Play idle animation based on last direction
+ player.anims.play(`idle-${player.direction}`, true);
}
return;
}
@@ -2359,6 +2460,10 @@
if (distanceSq < ARRIVAL_THRESHOLD * ARRIVAL_THRESHOLD) {
isMoving = false;
player.body.setVelocity(0, 0);
+ player.isMoving = false;
+
+ // Play idle animation based on last direction
+ player.anims.play(`idle-${player.direction}`, true);
return;
}
@@ -2377,20 +2482,45 @@
const velocityX = (dx / distance) * MOVEMENT_SPEED;
const velocityY = (dy / distance) * MOVEMENT_SPEED;
- // Only update velocity if it changed significantly
- const currentVX = player.body.velocity.x;
- const currentVY = player.body.velocity.y;
- const velocityDiffX = Math.abs(currentVX - velocityX);
- const velocityDiffY = Math.abs(currentVY - velocityY);
-
- if (velocityDiffX > 1 || velocityDiffY > 1) {
- player.body.setVelocity(velocityX, velocityY);
+ // Set velocity directly without checking for changes
+ player.body.setVelocity(velocityX, velocityY);
+
+ // Determine direction based on velocity
+ const absVX = Math.abs(velocityX);
+ const absVY = Math.abs(velocityY);
+
+ // Set player direction and animation
+ if (absVX > absVY * 2) {
+ // Mostly horizontal movement
+ player.direction = velocityX > 0 ? 'right' : 'right'; // Use right animation but flip
+ player.setFlipX(velocityX < 0); // Flip sprite horizontally if moving left
+ } else if (absVY > absVX * 2) {
+ // Mostly vertical movement
+ player.direction = velocityY > 0 ? 'down' : 'up';
+ player.setFlipX(false);
+ } else {
+ // Diagonal movement
+ if (velocityY > 0) {
+ player.direction = 'down-right';
+ } else {
+ player.direction = 'up-right';
+ }
+ player.setFlipX(velocityX < 0); // Flip sprite horizontally if moving left
+ }
+
+ // Play appropriate animation if not already playing
+ if (!player.isMoving || player.lastDirection !== player.direction) {
+ player.anims.play(`walk-${player.direction}`, true);
+ player.isMoving = true;
+ player.lastDirection = player.direction;
}
// Stop if collision detected
if (player.body.blocked.none === false) {
isMoving = false;
player.body.setVelocity(0, 0);
+ player.isMoving = false;
+ player.anims.play(`idle-${player.direction}`, true);
}
}
@@ -2784,13 +2914,33 @@
// checks if the player is in bounds
function isPlayerInBounds(bounds) {
- const buffer = 0; // Changed from TILE_SIZE (48) to 0
- return (
- player.x >= bounds.x - buffer &&
- player.x <= bounds.x + bounds.width + buffer &&
- player.y >= bounds.y - buffer &&
- player.y <= bounds.y + bounds.height + buffer
- );
+ // Use the player's physics body bounds for more precise detection
+ const playerBody = player.body;
+ const playerBounds = {
+ left: playerBody.x,
+ right: playerBody.x + playerBody.width,
+ top: playerBody.y,
+ bottom: playerBody.y + playerBody.height
+ };
+
+ // Calculate the overlap area between player and room
+ const overlapWidth = Math.min(playerBounds.right, bounds.x + bounds.width) -
+ Math.max(playerBounds.left, bounds.x);
+ const overlapHeight = Math.min(playerBounds.bottom, bounds.y + bounds.height) -
+ Math.max(playerBounds.top, bounds.y);
+
+ // Require a minimum overlap percentage (e.g., 50% of player width/height)
+ const minOverlapPercent = 0.5;
+ const playerWidth = playerBounds.right - playerBounds.left;
+ const playerHeight = playerBounds.bottom - playerBounds.top;
+
+ const widthOverlapPercent = overlapWidth / playerWidth;
+ const heightOverlapPercent = overlapHeight / playerHeight;
+
+ return overlapWidth > 0 &&
+ overlapHeight > 0 &&
+ widthOverlapPercent >= minOverlapPercent &&
+ heightOverlapPercent >= minOverlapPercent;
}
// handles room changes