// at top of Player.update(): this.prevX = this.x; this.prevY = this.y; // ... your movement math ... // precise land-from-above collision this.grounded = false; const cand = getNearbyPlatforms(this.x, this.y); // uses the grid (added below) const bottom = this.y + this.size / 2; const prevBottom = this.prevY + this.size / 2; for (const p of cand) { // horizontal overlap first const leftHit = this.x + this.size/2 > p.x; const rightHit = this.x - this.size/2 < p.x + p.w; if (!leftHit || !rightHit) continue; // must be moving downward and crossing the top surface const crossingTop = this.vy >= 0 && prevBottom <= p.y && bottom >= p.y; if (!crossingTop) continue; // snap onto the top face this.y = p.y - this.size / 2; this.vy = 0; this.grounded = true; }