Skip to content

Commit

Permalink
style: Create force folder to keep different types of forces
Browse files Browse the repository at this point in the history
  • Loading branch information
NriotHrreion committed Nov 10, 2024
1 parent d33621b commit 0b103ed
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 18 deletions.
24 changes: 19 additions & 5 deletions src/simulator/force.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { CanvasObject } from "./object";

import { gravity as g } from "@/common/global";

import { Vector, type IVector } from "./vector";

interface IForce extends IVector {
export interface IForce extends IVector {
getAccelerate(mass: number): Vector
setSize(size: number): void
setToZero(): void
update(self: CanvasObject): void
}

export class Force extends Vector implements IForce {
Expand All @@ -28,9 +30,7 @@ export class Force extends Vector implements IForce {
this.y = size * sin;
}

public setToZero() {
this.x = this.y = 0;
}
public update(_self: CanvasObject) { }

public static gravity(mass: number): Force {
return new Force(0, -mass * g);
Expand Down Expand Up @@ -62,6 +62,7 @@ interface IForceCollection {
get(key: string): Force
set(key: string, force: Force): void
remove(key: string): void
removeForce(force: Force): void
clear(): void
getSum(): Force
getComponent(n: Vector): Force
Expand Down Expand Up @@ -99,6 +100,15 @@ export class ForceCollection implements IForceCollection {
this._map.delete(key);
}

public removeForce(target: Force) {
for(const [key, force] of this) {
if(target === force) {
this.remove(key);
return;
}
}
}

public clear() {
this._map.clear();
}
Expand All @@ -116,4 +126,8 @@ export class ForceCollection implements IForceCollection {
public getComponent(n: Vector) {
return this.getSum().getComponent(n) as Force;
}

*[Symbol.iterator](): Iterator<[string, Force]> {
for(const item of this._map) yield item;
}
}
36 changes: 36 additions & 0 deletions src/simulator/forces/frictionForce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { CanvasObject } from "@/simulator/object";
import type { SupportForce } from "./supportForce";

import { Force, type IForce } from "@/simulator/force";

interface IFrictionForce extends IForce {
origin: CanvasObject
}

export class FrictionForce extends Force implements IFrictionForce {
public origin: CanvasObject;

private readonly _maxStaticFrictionSize: number;

private constructor(support: SupportForce, private readonly friction: number) {
super(0, 0);

this.origin = support.origin;
this._maxStaticFrictionSize = support.length * this.friction;
}

public override update(self: CanvasObject) {
super.update(self);

/** @todo */
}

/** @deprecated */
public static override from(_arg: never): never {
throw new Error("Cannot create a friction force via from().");
}

public static create(support: SupportForce, friction: number): FrictionForce {
return new FrictionForce(support, friction);
}
}
38 changes: 38 additions & 0 deletions src/simulator/forces/supportForce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Vector } from "@/simulator/vector";
import type { CanvasObject } from "@/simulator/object";

import { Force, type IForce } from "@/simulator/force";
import { Ground } from "@/simulator/objects/ground";
import { Ball } from "@/simulator/objects/ball";
import { Block } from "@/simulator/objects/block";

interface ISupportForce extends IForce {
origin: CanvasObject
}

export class SupportForce extends Force implements ISupportForce {

private constructor(x: number, y: number, public origin: CanvasObject) {
super(x, y);
}

public override update(self: CanvasObject) {
super.update(self);

if(self instanceof Ball) {
if(this.origin instanceof Ground && self.obj.y < self.render.canvas.height - Ground.GROUND_HEIGHT - self.radius) {
self.forces.removeForce(this);
}
} else if(self instanceof Block) {
if(this.origin instanceof Ground && self.obj.y < self.render.canvas.height - Ground.GROUND_HEIGHT - self.size) {
self.forces.removeForce(this);
}
}
}

public static override from(vector: Force | Vector, origin?: CanvasObject): SupportForce {
if(!origin) throw new Error("Cannot create a support force without providing the origin object.");

return new SupportForce(vector.x, vector.y, origin);
}
}
4 changes: 4 additions & 0 deletions src/simulator/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ export class CanvasObject<H extends Hitbox = Hitbox> extends Disposable implemen

public update(delta: number) {
if(!this._isHeld) {
for(const [, force] of this.forces) {
force.update(this);
}

const sumForce = this.forces.getSum();
const accelerate = sumForce.getAccelerate(this.mass);

Expand Down
6 changes: 0 additions & 6 deletions src/simulator/objects/ball.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { colors } from "@/simulator/render/colors";
import { Vector } from "@/simulator/vector";
import { RoundHitbox } from "@/simulator/hitboxes/roundHitbox";

import { Ground } from "./ground";

export class Ball extends CanvasObject<RoundHitbox> {
public static readonly id = "ball";

Expand Down Expand Up @@ -131,10 +129,6 @@ export class Ball extends CanvasObject<RoundHitbox> {
public override update(delta: number) {
super.update(delta);

if(this.obj.y < this.render.canvas.height - Ground.GROUND_HEIGHT - this.radius) {
this.forces.remove("ground.support");
}

this._drawName(0, 0);
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/simulator/objects/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { colors } from "@/simulator/render/colors";
import { Vector } from "@/simulator/vector";
import { ConvexHitbox } from "@/simulator/hitboxes/convexHitbox";

import { Ground } from "./ground";
import { Ball } from "./ball";

export class Block extends CanvasObject<ConvexHitbox> {
Expand Down Expand Up @@ -132,10 +131,6 @@ export class Block extends CanvasObject<ConvexHitbox> {
public override update(delta: number) {
super.update(delta);

if(this.obj.y < this.render.canvas.height - Ground.GROUND_HEIGHT - this.size) {
this.forces.remove("ground.support");
}

this._drawName(this.size / 2, this.size / 2);
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/simulator/objects/ground.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { colors } from "@/simulator/render/colors";
import { Vector } from "@/simulator/vector";
import { GroundHitbox } from "@/simulator/hitboxes/groundHitbox";
import { Force } from "@/simulator/force";
import { SupportForce } from "@/simulator/forces/supportForce";

import { Ball } from "./ball";
import { Block } from "./block";
Expand All @@ -16,6 +17,7 @@ export class Ground extends CanvasObject<GroundHitbox> {

public static readonly GROUND_HEIGHT = 25;
public static readonly DAMPING = .9;
public static readonly FRICTION = .5; // mu
public static readonly STABLE_VELOCITY = 5;

public readonly normalVector: Vector = new Vector(0, 1);
Expand Down Expand Up @@ -46,7 +48,7 @@ export class Ground extends CanvasObject<GroundHitbox> {
obj.reverseVelocity("y", Ground.DAMPING);
} else {
obj.velocity.y = 0;
obj.forces.set("ground.support", Force.reverse(obj.forces.getComponent(new Vector(0, 1))));
obj.forces.set("ground.support", SupportForce.from(Force.reverse(obj.forces.getComponent(new Vector(0, 1))), this));
}

} else if(obj instanceof Block) {
Expand All @@ -56,7 +58,7 @@ export class Ground extends CanvasObject<GroundHitbox> {
obj.updateHitboxAnchor();

obj.velocity.y = 0;
obj.forces.set("ground.support", Force.reverse(obj.forces.getComponent(new Vector(0, 1))));
obj.forces.set("ground.support", SupportForce.from(Force.reverse(obj.forces.getComponent(new Vector(0, 1))), this));

}
}));
Expand Down

0 comments on commit 0b103ed

Please sign in to comment.