diff --git a/app/Game/Client/GameController.js b/app/Game/Client/GameController.js index 18a6497..03c3144 100755 --- a/app/Game/Client/GameController.js +++ b/app/Game/Client/GameController.js @@ -32,6 +32,11 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, nc, reque Parent.call(this, options); + // Set reference to this GameController in the physics engine for camera access + if (this.physicsEngine && this.physicsEngine.setGameController) { + this.physicsEngine.setGameController(this); + } + this.ncTokens = this.ncTokens.concat([ nc.on(nc.ns.client.game.gameStats.toggle, this.toggleGameStats, this) ]); diff --git a/app/Game/Client/Physics/Engine.js b/app/Game/Client/Physics/Engine.js index 9dc6e2c..bca83a5 100755 --- a/app/Game/Client/Physics/Engine.js +++ b/app/Game/Client/Physics/Engine.js @@ -52,15 +52,59 @@ function (Parent, Settings, domController, Box2D, nc, PlanckDebugDraw, debugLaye Engine.prototype.renderDebug = function () { if (this.debugDraw) { this.debugDraw.clear(); + + // Get camera position from the game view + var cameraPos = this.getCameraPosition(); + var zoom = this.getCameraZoom(); + + // Apply camera transformations to debug draw + this.debugDraw.setTransform(cameraPos, zoom); this.debugDraw.drawWorld(this.world); } }; + Engine.prototype.getCameraPosition = function() { + // Get camera position from the view system + // This needs to match the layer positioning logic + if (this.gameController && this.gameController.view && this.gameController.view.layerManager) { + var layerManager = this.gameController.view.layerManager; + var tileLayer = layerManager.getLayerById('tile'); // Use tile layer as reference + + if (tileLayer) { + return { + x: tileLayer.position.current.x, + y: tileLayer.position.current.y, + zoom: tileLayer.zoom.current + }; + } + } + + // Fallback to default position + return { x: 0, y: 0, zoom: 1 }; + }; + + Engine.prototype.getCameraZoom = function() { + if (this.gameController && this.gameController.view && this.gameController.view.layerManager) { + var layerManager = this.gameController.view.layerManager; + var tileLayer = layerManager.getLayerById('tile'); + + if (tileLayer) { + return tileLayer.zoom.current; + } + } + + return 1; + }; + + Engine.prototype.setGameController = function(gameController) { + this.gameController = gameController; + }; + Engine.prototype.update = function () { Parent.prototype.update.call(this); - if(this.debugMode) { - this.world.DrawDebugData(); + if(this.debugMode && this.debugDraw) { + this.debugDraw.drawWorld(this.world); } }; diff --git a/app/Game/Client/View/Pixi/PlanckDebugDraw.js b/app/Game/Client/View/Pixi/PlanckDebugDraw.js index ce6f7e7..79a021a 100644 --- a/app/Game/Client/View/Pixi/PlanckDebugDraw.js +++ b/app/Game/Client/View/Pixi/PlanckDebugDraw.js @@ -10,6 +10,8 @@ function (Settings) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.scale = Settings.RATIO; + this.cameraPos = { x: 0, y: 0 }; + this.cameraZoom = 1; this.flags = { shapes: true, joints: false, @@ -23,12 +25,23 @@ function (Settings) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); }; + PlanckDebugDraw.prototype.setTransform = function(cameraPos, zoom) { + this.cameraPos = cameraPos; + this.cameraZoom = zoom || 1; + }; + PlanckDebugDraw.prototype.drawWorld = function(world) { if (!this.flags.shapes) return; this.ctx.save(); - this.ctx.scale(this.scale, this.scale); - this.ctx.lineWidth = 1 / this.scale; + + // Apply camera transformations like the game layers do + var transformedX = this.cameraPos.x * this.cameraZoom + Settings.STAGE_WIDTH / 2; + var transformedY = this.cameraPos.y * this.cameraZoom + Settings.STAGE_HEIGHT / 2; + + this.ctx.translate(transformedX, transformedY); + this.ctx.scale(this.scale * this.cameraZoom, this.scale * this.cameraZoom); + this.ctx.lineWidth = 0.5 / this.scale; // Iterate through all bodies for (var body = world.getBodyList(); body; body = body.getNext()) { @@ -38,6 +51,11 @@ function (Settings) { for (var fixture = body.getFixtureList(); fixture; fixture = fixture.getNext()) { var shape = fixture.getShape(); + // Skip sensor fixtures to match old Box2D behavior + if (fixture.isSensor()) { + continue; + } + if (body.isDynamic()) { this.ctx.strokeStyle = '#ff0000'; // Red for dynamic bodies this.ctx.fillStyle = 'rgba(255, 0, 0, 0.1)'; diff --git a/app/Game/Config/Settings.js b/app/Game/Config/Settings.js index 10cf76f..6cbcd08 100755 --- a/app/Game/Config/Settings.js +++ b/app/Game/Config/Settings.js @@ -39,7 +39,7 @@ function () { VIEW_CONTROLLER: 0 ? "Three" : "Pixi", ARROW_GLIDE: 30, // % of the way per frame SHOW_LAYER_INFO: false, - ENABLE_POINTER_LOCK_FILTER: true, + ENABLE_POINTER_LOCK_FILTER: false, // GAME PLAY WALK_SPEED: 4, diff --git a/app/Game/Core/Collision/Detector.js b/app/Game/Core/Collision/Detector.js index b353b16..1684229 100755 --- a/app/Game/Core/Collision/Detector.js +++ b/app/Game/Core/Collision/Detector.js @@ -32,6 +32,20 @@ function (Planck) { var userDataA = contact.getFixtureA().getUserData(); var userDataB = contact.getFixtureB().getUserData(); + // Check if this is a foot sensor collision + var isFootSensorCollision = false; + var footSensorUserData = null; + + if (userDataA && userDataA.isFootSensor) { + isFootSensorCollision = true; + footSensorUserData = userDataA; + } + + if (userDataB && userDataB.isFootSensor) { + isFootSensorCollision = true; + footSensorUserData = userDataB; + } + if (userDataA && userDataA.onCollisionChange) { userDataA.onCollisionChange(isColliding, contact.getFixtureB()); } diff --git a/app/Game/Core/GameObjects/Doll.js b/app/Game/Core/GameObjects/Doll.js index 0cf2706..1f036fd 100755 --- a/app/Game/Core/GameObjects/Doll.js +++ b/app/Game/Core/GameObjects/Doll.js @@ -105,20 +105,26 @@ function (Parent, Exception, planck, Settings, CollisionDetector, Item, nc, Asse this.legs = this.body.createFixture(fixtureDef); - fixtureDef.density = 0; + // Create a fresh fixture definition for the foot sensor + var footSensorDef = { + shape: null, + density: 0, + friction: 0, + restitution: 0, + isSensor: true, + userData: { + onCollisionChange: this.onFootSensorDetection.bind(this), + isFootSensor: true + } + }; var feetShape = planck.Circle( (this.width - 1) / 2 / Settings.RATIO, // the -1 one prevents collisions with walls - planck.Vec2(0, 2 / Settings.RATIO) // 2 is offset into ground + planck.Vec2(0, -20 / Settings.RATIO) // 20 pixels down from center (dramatic test) ); - fixtureDef.shape = feetShape; - fixtureDef.isSensor = true; + footSensorDef.shape = feetShape; - fixtureDef.userData = { - onCollisionChange: this.onFootSensorDetection.bind(this) - }; - - this.footSensor = this.body.createFixture(fixtureDef); + this.footSensor = this.body.createFixture(footSensorDef); var grabSensorLeftShape = planck.Box( this.reachDistance / 2 / Settings.RATIO, @@ -312,7 +318,11 @@ function (Parent, Exception, planck, Settings, CollisionDetector, Item, nc, Asse }; Doll.prototype.setStanding = function (isStanding) { - if (this.standing == isStanding) return; + if (this.standing == isStanding) { + console.log('setStanding called but no change needed, already:', isStanding); + return; + } + console.log('*** STANDING STATE CHANGE: ', this.standing, '->', isStanding, '***'); this.standing = isStanding; if(isStanding) this.setActionState("stand"); }; @@ -394,23 +404,23 @@ function (Parent, Exception, planck, Settings, CollisionDetector, Item, nc, Asse return this.nearbyDolls.length > 0; }; - Doll.prototype.onFootSensorDetection = function(isColliding, fixture) { // jshint unused:false - + Doll.prototype.onFootSensorDetection = function(isColliding, fixture) { var self = this; var hasJumpStartVelocity = this.body.getLinearVelocity().y < -Settings.JUMP_SPEED; + var currentVelocity = this.body.getLinearVelocity(); if(isColliding) { if(!hasJumpStartVelocity) { this.setStanding(true); } } else { - var contactCount = 0; var edge = self.body.getContactList(); while (edge) { var contact = edge.contact; + if(!contact.isTouching()) { edge = edge.next; continue;