From 30135b1e207a6869ce97145e03362203c318a44c Mon Sep 17 00:00:00 2001 From: Joey Wunderlich Date: Thu, 21 Jan 2021 16:25:30 -0800 Subject: [PATCH 1/3] clean up conditional / scope of a few vars --- libs/game/physics.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libs/game/physics.ts b/libs/game/physics.ts index d495fbc3d..2da18aa2b 100644 --- a/libs/game/physics.ts +++ b/libs/game/physics.ts @@ -350,27 +350,25 @@ class ArcadePhysicsEngine extends PhysicsEngine { const s = movingSprite.sprite; // if the sprite is already clipping into a wall, // allow free movement rather than randomly 'fixing' it - if (s.flags & sprites.Flag.IsClipping) { - if (!tm.isOnWall(s)) { - s.flags &= ~sprites.Flag.IsClipping; - } + if ((s.flags & sprites.Flag.IsClipping) && !tm.isOnWall(s)) { + s.flags &= ~sprites.Flag.IsClipping; } if (!s.isStatic()) s.setHitbox(); const hbox = s._hitbox; const tileScale = tm.scale; const tileSize = 1 << tileScale; - const xDiff = Fx.sub( - s._x, - s._lastX - ); + if (!(s.flags & SPRITE_NO_WALL_COLLISION)) { + const xDiff = Fx.sub( + s._x, + s._lastX + ); - const yDiff = Fx.sub( - s._y, - s._lastY - ); + const yDiff = Fx.sub( + s._y, + s._lastY + ); - if (!(s.flags & SPRITE_NO_WALL_COLLISION)) { if (xDiff !== Fx.zeroFx8) { const right = xDiff > Fx.zeroFx8; const x0 = Fx.toIntShifted( From 50fc09e81fcebffba7d5bcb9935da45f8fdfb531 Mon Sep 17 00:00:00 2001 From: Joey Wunderlich Date: Thu, 21 Jan 2021 16:39:57 -0800 Subject: [PATCH 2/3] move clipping check to tilemap --- libs/game/physics.ts | 80 +----------------------------------------- libs/game/tilemap.ts | 83 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 79 deletions(-) diff --git a/libs/game/physics.ts b/libs/game/physics.ts index 2da18aa2b..0c706103e 100644 --- a/libs/game/physics.ts +++ b/libs/game/physics.ts @@ -638,90 +638,12 @@ class ArcadePhysicsEngine extends PhysicsEngine { ); this.tilemapCollisions(ms, tm); // otherwise, accept movement... - } else if (tm.isOnWall(s) && !this.canResolveClipping(s, tm)) { - // if no luck, flag as clipping into a wall - s.flags |= sprites.Flag.IsClipping; } else { - // or clear clipping if no longer clipping - s.flags &= ~sprites.Flag.IsClipping; + tm._checkClipping(s, this.maxStep); } } } - // Attempt to resolve clipping by moving the sprite slightly up / down / left / right - protected canResolveClipping(s: Sprite, tm: tiles.TileMap) { - if (!s.isStatic()) s.setHitbox(); - const hbox = s._hitbox; - const sz = 1 << tm.scale; - const maxMove = this.maxStep; - const origY = s._y; - const origX = s._x; - const l = Fx.toInt(hbox.left); - const r = Fx.toInt(hbox.right); - const t = Fx.toInt(hbox.top); - const b = Fx.toInt(hbox.bottom); - - { // bump up and test; - const offset = (b + 1) % sz; - if (offset <= maxMove) { - s._y = Fx.sub( - s._y, - Fx8(offset) - ); - if (!tm.isOnWall(s)) { - return true; - } else { - s._y = origY; - } - } - } - { // bump down and test; - const offset = (Math.floor(t / sz) + 1) * sz - t; - if (offset <= maxMove) { - s._y = Fx.add( - s._y, - Fx8(offset) - ); - if (!tm.isOnWall(s)) { - return true; - } else { - s._y = origY; - } - } - } - { // bump left and test; - const offset = (r + 1) % sz; - if (offset <= maxMove) { - s._x = Fx.sub( - s._x, - Fx8(offset) - ); - if (!tm.isOnWall(s)) { - return true; - } else { - s._x = origX; - } - } - } - { // bump right and test; - const offset = (Math.floor(l / sz) + 1) * sz - l; - if (offset <= maxMove) { - s._x = Fx.add( - s._x, - Fx8(offset) - ); - if (!tm.isOnWall(s)) { - return true; - } else { - s._x = origX; - } - } - } - - // no trivial adjustment worked; it's going to clip for now - return false; - } - private constrain(v: Fx8) { return Fx.max( Fx.min( diff --git a/libs/game/tilemap.ts b/libs/game/tilemap.ts index 29d63fb8a..cfe845e73 100644 --- a/libs/game/tilemap.ts +++ b/libs/game/tilemap.ts @@ -421,6 +421,89 @@ namespace tiles { ); } + public _checkClipping(s: Sprite, maxStep = 2) { + if (this.isOnWall(s) && !this.canResolveClipping(s, maxStep)) { + // if no luck, flag as clipping into a wall + s.flags |= sprites.Flag.IsClipping; + } else { + // or clear clipping if no longer clipping + s.flags &= ~sprites.Flag.IsClipping; + } + } + + // Attempt to resolve clipping by moving the sprite slightly up / down / left / right + protected canResolveClipping(s: Sprite, maxStep: number) { + if (!s.isStatic()) s.setHitbox(); + const hbox = s._hitbox; + const sz = 1 << this.scale; + const origY = s._y; + const origX = s._x; + const l = Fx.toInt(hbox.left); + const r = Fx.toInt(hbox.right); + const t = Fx.toInt(hbox.top); + const b = Fx.toInt(hbox.bottom); + + { // bump up and test; + const offset = (b + 1) % sz; + if (offset <= maxStep) { + s._y = Fx.sub( + s._y, + Fx8(offset) + ); + if (!this.isOnWall(s)) { + return true; + } else { + s._y = origY; + } + } + } + { // bump down and test; + const offset = (Math.floor(t / sz) + 1) * sz - t; + if (offset <= maxStep) { + s._y = Fx.add( + s._y, + Fx8(offset) + ); + if (!this.isOnWall(s)) { + return true; + } else { + s._y = origY; + } + } + } + { // bump left and test; + const offset = (r + 1) % sz; + if (offset <= maxStep) { + s._x = Fx.sub( + s._x, + Fx8(offset) + ); + if (!this.isOnWall(s)) { + return true; + } else { + s._x = origX; + } + } + } + { // bump right and test; + const offset = (Math.floor(l / sz) + 1) * sz - l; + if (offset <= maxStep) { + s._x = Fx.add( + s._x, + Fx8(offset) + ); + if (!this.isOnWall(s)) { + return true; + } else { + s._x = origX; + } + } + } + + // no trivial adjustment worked; it's going to clip for now + return false; + } + public isOnWall(s: Sprite) { const hbox = s._hitbox; From 6295f13120047437a1a4cf7e88149f84eedfe580 Mon Sep 17 00:00:00 2001 From: Joey Wunderlich Date: Thu, 21 Jan 2021 16:55:07 -0800 Subject: [PATCH 3/3] check for collisions on wall change --- libs/game/physics.ts | 8 ++++++++ libs/game/tilemap.ts | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libs/game/physics.ts b/libs/game/physics.ts index 0c706103e..f56743fb7 100644 --- a/libs/game/physics.ts +++ b/libs/game/physics.ts @@ -10,6 +10,10 @@ class PhysicsEngine { removeSprite(sprite: Sprite) { } + _allSprites(): Sprite[] { + return null; + } + /** move a single sprite **/ moveSprite(s: Sprite, dx: Fx8, dy: Fx8) { } @@ -102,6 +106,10 @@ class ArcadePhysicsEngine extends PhysicsEngine { } } + _allSprites(): Sprite[] { + return this.sprites; + } + removeSprite(sprite: Sprite) { this.sprites.removeElement(sprite); } diff --git a/libs/game/tilemap.ts b/libs/game/tilemap.ts index cfe845e73..985906686 100644 --- a/libs/game/tilemap.ts +++ b/libs/game/tilemap.ts @@ -265,6 +265,7 @@ namespace tiles { setData(map: TileMapData) { this._map = map; + this.checkForNewClipping(); } public getTile(col: number, row: number): Location { @@ -296,8 +297,13 @@ namespace tiles { } public setWallAt(col: number, row: number, on: boolean): void { - if (!this._map.isOutsideMap(col, row)) + if (!this._map.isOutsideMap(col, row)) { this._map.setWall(col, row, on); + + if (on) { + this.checkForNewClipping(); + } + } } public getTilesByType(index: number): Location[] { @@ -421,6 +427,17 @@ namespace tiles { ); } + protected checkForNewClipping() { + const p = game.currentScene().physicsEngine; + const allSprites = p._allSprites() || []; + + for (const s of allSprites) { + if (!(s.flags & SPRITE_NO_WALL_COLLISION)) { + this._checkClipping(s, 2); + } + } + } + public _checkClipping(s: Sprite, maxStep = 2) { if (this.isOnWall(s) && !this.canResolveClipping(s, maxStep)) { // if no luck, flag as clipping into a wall