From 3844363b150c0b36cb8505229b6d695724e473d0 Mon Sep 17 00:00:00 2001 From: Marc Flerackers Date: Mon, 27 May 2024 19:00:44 +0900 Subject: [PATCH] Added gravity vector, modified all logic to support up/down correctly with any direction --- CHANGELOG.md | 1 + src/components/physics/body.ts | 43 ++++++++++++++++++++++------------ src/kaboom.ts | 24 +++++++++++++------ src/types.ts | 8 +++++++ 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f2071c6..4ea4206c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - added support for texture larger than 2048x2048 - added `chooseMultiple()` and `shuffle()` helper functions - added `getSceneName()` to get the current scene name +- added support for gravity direction ### v3000.1.17 diff --git a/src/components/physics/body.ts b/src/components/physics/body.ts index ef45130e..511aaec9 100644 --- a/src/components/physics/body.ts +++ b/src/components/physics/body.ts @@ -91,7 +91,9 @@ export function body(opt: BodyCompOpt = {}): BodyComp { this.onPhysicsResolve((col) => { if (internal.game.gravity) { if (col.isBottom() && this.isFalling()) { - this.vel.y = 0; + this.vel = this.vel.reject( + internal.game.gravity.unit(), + ); curPlatform = col.target as GameObj< PosComp | BodyComp | AreaComp >; @@ -102,7 +104,9 @@ export function body(opt: BodyCompOpt = {}): BodyComp { this.trigger("ground", curPlatform); } } else if (col.isTop() && this.isJumping()) { - this.vel.y = 0; + this.vel = this.vel.reject( + internal.game.gravity.unit(), + ); this.trigger("headbutt", col.target); } } @@ -119,7 +123,7 @@ export function body(opt: BodyCompOpt = {}): BodyComp { willFall = false; } - let updateY = true; + let addGravity = true; if (curPlatform) { if ( @@ -139,21 +143,28 @@ export function body(opt: BodyCompOpt = {}): BodyComp { ); } lastPlatformPos = curPlatform.pos; - updateY = false; + addGravity = false; } } - if (updateY) { - const prevVelY = this.vel.y; + if (addGravity) { + const prevVel = this.vel.clone(); - this.vel.y += internal.game.gravity * this.gravityScale - * k.dt(); - this.vel.y = Math.min( - this.vel.y, - opt.maxVelocity ?? MAX_VEL, + // Apply gravity + this.vel = this.vel.add( + internal.game.gravity.scale(this.gravityScale * k.dt()), ); - if (prevVelY < 0 && this.vel.y >= 0) { + // Clamp velocity + const maxVel = opt.maxVelocity ?? MAX_VEL; + if (this.vel.slen() > maxVel * maxVel) { + this.vel = this.vel.unit().scale(maxVel); + } + + if ( + prevVel.dot(internal.game.gravity) < 0 + && this.vel.dot(internal.game.gravity) >= 0 + ) { this.trigger("fall"); } } @@ -182,17 +193,19 @@ export function body(opt: BodyCompOpt = {}): BodyComp { }, isFalling(): boolean { - return this.vel.y > 0; + return this.vel.dot(internal.game.gravity) > 0; }, isJumping(): boolean { - return this.vel.y < 0; + return this.vel.dot(internal.game.gravity) < 0; }, jump(force: number) { curPlatform = null; lastPlatformPos = null; - this.vel.y = -force || -this.jumpForce; + this.vel = internal.game.gravity.unit().scale( + -force || -this.jumpForce, + ); }, onGround(this: GameObj, action: () => void): EventController { diff --git a/src/kaboom.ts b/src/kaboom.ts index a11e46a9..b2267bf4 100644 --- a/src/kaboom.ts +++ b/src/kaboom.ts @@ -705,7 +705,7 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => { root: make([]), // misc - gravity: 0, + gravity: vec2(0, 1), scenes: {}, currentScene: null, @@ -3370,11 +3370,19 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => { } function setGravity(g: number) { - game.gravity = g; + game.gravity = game.gravity.unit().scale(g); } function getGravity() { - return game.gravity; + return game.gravity.len(); + } + + function setGravityDirection(d: Vec2) { + game.gravity = d.unit().scale(game.gravity.len()); + } + + function getGravityDirection() { + return game.gravity.unit(); } function setBackground(...args) { @@ -4249,16 +4257,16 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => { return !this.displacement.isZero(); } isLeft() { - return this.displacement.x > 0; + return this.displacement.cross(game.gravity) > 0; } isRight() { - return this.displacement.x < 0; + return this.displacement.cross(game.gravity) < 0; } isTop() { - return this.displacement.y > 0; + return this.displacement.dot(game.gravity) > 0; } isBottom() { - return this.displacement.y < 0; + return this.displacement.dot(game.gravity) < 0; } preventResolution() { this.resolved = true; @@ -4983,6 +4991,8 @@ export default (gopt: KaboomOpt = {}): KaboomCtx => { toWorld, setGravity, getGravity, + setGravityDirection, + getGravityDirection, setBackground, getBackground, getGamepads: app.getGamepads, diff --git a/src/types.ts b/src/types.ts index 9fd99ad6..9dacdc54 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1903,6 +1903,14 @@ export interface KaboomCtx { * @group Info */ getGravity(): number; + /** + * Set gravity direction. + */ + setGravityDirection(d: Vec2): void; + /** + * Get gravity direction. + */ + getGravityDirection(): Vec2; /** * Set background color. *