Skip to content

Commit

Permalink
feat: Add wall mode and wall test
Browse files Browse the repository at this point in the history
  • Loading branch information
NriotHrreion committed Nov 3, 2024
1 parent 0f02bb2 commit 68f9f6d
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/simulator/hitbox.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Canvas } from "@/ui/canvas/canvas";
import type { CanvasObject } from "./object";
import type { Point } from "./render/render";

Expand All @@ -18,6 +19,7 @@ export interface IHitbox extends IDisposable {
* @param obj A target object to test
*/
test(obj: CanvasObject): void
testWall(canvas: Canvas): "x" | "y" | null
/**
* Set a new anchor for the hitbox
*
Expand Down Expand Up @@ -47,6 +49,7 @@ export abstract class Hitbox extends Disposable implements IHitbox {
}

public abstract test(obj: CanvasObject): void;
public abstract testWall(canvas: Canvas): "x" | "y" | null;

public setAnchor(anchor: Point) {
this.anchor = anchor;
Expand Down
22 changes: 15 additions & 7 deletions src/simulator/hitboxes/convexHitbox.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import type { Point } from "@/simulator/render/render";
import type { CanvasObject } from "@/simulator/object";
import type { Canvas } from "@/ui/canvas/canvas";

import { Hitbox, type IHitbox } from "@/simulator/hitbox";
import { type Vector, VectorCollection } from "@/simulator/vector";

import { RoundHitbox } from "./roundHitbox";

interface IConvexHitbox extends IHitbox {
boundaries: VectorCollection
boundaries: Vector[]
}

export class ConvexHitbox extends Hitbox implements IConvexHitbox {
public boundaries: VectorCollection;

public constructor(boundaryVectors: Vector[], anchor: Point) {

public constructor(public boundaries: Vector[], anchor: Point) {
super(anchor);

this.boundaries = new VectorCollection(boundaryVectors);

if(this.boundaries.getSum().length !== 0) {
if(new VectorCollection(boundaries).getSum().length !== 0) {
throw new Error("The sum of the boundary vectors must be 0.");
}
}
Expand All @@ -37,4 +35,14 @@ export class ConvexHitbox extends Hitbox implements IConvexHitbox {
return false;
}
}

public testWall(canvas: Canvas) {
if(this.anchor.y <= 0) {
return "y";
} else if(this.anchor.x <= 0 || this.anchor.x + this.boundaries[0].x >= canvas.width) {
return "x";
}

return null;
}
}
4 changes: 4 additions & 0 deletions src/simulator/hitboxes/groundHitbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ export class GroundHitbox extends Hitbox implements IGroundHitbox {
}
}
}

public testWall(): null {
return null;
}
}
11 changes: 11 additions & 0 deletions src/simulator/hitboxes/roundHitbox.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Point } from "@/simulator/render/render";
import type { CanvasObject } from "@/simulator/object";
import type { Canvas } from "@/ui/canvas/canvas";

import { Hitbox, type IHitbox } from "@/simulator/hitbox";
import { getPointDistance } from "@/common/utils/utils";
Expand Down Expand Up @@ -38,4 +39,14 @@ export class RoundHitbox extends Hitbox implements IRoundHitbox {
}
}
}

public testWall(canvas: Canvas) {
if(this.anchor.y <= 0) {
return "y";
} else if(this.anchor.x <= 0 || this.anchor.x + 2 * this.radius >= canvas.width) {
return "x";
}

return null;
}
}
12 changes: 12 additions & 0 deletions src/simulator/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ interface ICanvasObject extends Renderable {
* Clear all forces from the object
*/
clearForces(): void
reverseVelocity(direction: "x" | "y", damping?: number): void
/**
* Update the anchor point of the hitbox,
* so that it matches the current position of the object.
Expand Down Expand Up @@ -224,6 +225,17 @@ export class CanvasObject<H extends Hitbox = Hitbox> extends Disposable implemen
this._forces.clear();
}

public reverseVelocity(direction: "x" | "y", damping: number = 1) {
const n = new Vector(0, 1);

const vy = this.velocity.getComponent(n);
const vx = Vector.sub(this.velocity, vy);

direction === "y"
? this.velocity = Vector.add(vx, Vector.multiplyScalar(Vector.reverse(vy), damping))
: this.velocity = Vector.add(vy, Vector.multiplyScalar(Vector.reverse(vx), damping));
}

public updateHitboxAnchor(): void {
const bound = this.obj.getBounds();
this.hitbox.setAnchor({
Expand Down
5 changes: 2 additions & 3 deletions src/simulator/objects/ground.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class Ground extends CanvasObject<GroundHitbox> {
public static readonly id = "ground";

public static readonly GROUND_HEIGHT = 50;
public static readonly DAMPING = 1;
public static readonly DAMPING = .9;
public static readonly STABLE_VELOCITY = 5;

public readonly normalVector: Vector = new Vector(0, 1);
Expand All @@ -41,10 +41,9 @@ export class Ground extends CanvasObject<GroundHitbox> {
obj.updateHitboxAnchor();

const vy = obj.velocity.getComponent(this.normalVector);
const vx = Vector.sub(obj.velocity, vy);

if(vy.length > Ground.STABLE_VELOCITY) {
obj.velocity = Vector.add(vx, Vector.multiplyScalar(Vector.reverse(vy), Ground.DAMPING));
obj.reverseVelocity("y", Ground.DAMPING);
} else {
obj.velocity.y = 0;
obj.applyForce("ground.support", Force.reverse(Force.gravity(obj.mass)));
Expand Down
20 changes: 20 additions & 0 deletions src/simulator/render/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ interface IRender extends Renderable, IDisposable {
* @param enabled Is the mouse mode enabled
*/
setMouseMode(enabled: boolean): void
/**
* Toggle the wall mode (on / off)
*
* @param enabled Is the wall mode enabled
*/
setWallMode(enabled: boolean): void

onRender: Event<OnRenderListenerData>
}
Expand All @@ -96,6 +102,7 @@ export class Render extends Disposable implements IRender {

public isPaused: boolean = false;
public isMouseMode: boolean = false;
public isWallMode: boolean = true;

public constructor(public canvas: Canvas) {
super();
Expand Down Expand Up @@ -157,6 +164,14 @@ export class Render extends Disposable implements IRender {
obj.hitbox.test(_obj);
}
}

// Test wall
if(!this.isWallMode) return;

const hitDirection = obj.hitbox.testWall(this.canvas);
if(hitDirection) {
obj.reverseVelocity(hitDirection);
}
}
}

Expand Down Expand Up @@ -223,6 +238,10 @@ export class Render extends Disposable implements IRender {
this.isMouseMode = enabled;
}

public setWallMode(enabled: boolean) {
this.isWallMode = enabled;
}

public update(delta: number) {
// Pre-rendering stage
if(!this._prerenderObjects.isEmpty()) {
Expand All @@ -244,6 +263,7 @@ export class Render extends Disposable implements IRender {

infoList.push(`Objects: ${this._objects.length}`);
if(this.isMouseMode) infoList.push("MouseMode");
if(this.isWallMode) infoList.push("WallMode");

for(let i = 0; i < infoList.length; i++) {
this.container.addChild(this.createText(infoList[i], 10, 10 + i * 20));
Expand Down
2 changes: 2 additions & 0 deletions src/ui/panel/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { ObjectNameMap } from "@/simulator/object";
import {
type IconNode,
Box,
BrickWall,
Info,
MousePointer2,
Pause,
Expand Down Expand Up @@ -73,6 +74,7 @@ export class Panel extends Component<HTMLDivElement, PanelOptions> implements IP
toolbarLeftGroup.addButton({ icon: Settings, tooltip: "设置" }, () => modalProvider.open("settings"));
toolbarLeftGroup.addButton({ icon: Box, tooltip: "管理" }, () => modalProvider.open("manager"));
toolbarLeftGroup.addSwitcher({ icon: MousePointer2, tooltip: "鼠标模式" }, ({ isActive }) => this._renderer.setMouseMode(isActive));
toolbarLeftGroup.addSwitcher({ icon: BrickWall, tooltip: "边界墙", defaultValue: true }, ({ isActive }) => this._renderer.setWallMode(isActive));
this._refreshButton = toolbarLeftGroup.addButton({ icon: RotateCw, tooltip: "刷新" });
this._pauseSwitcher = toolbarLeftGroup.addSwitcher({ icon: Pause, tooltip: "暂停" }, ({ isActive }) => {
isActive ? this._pauseRenderer() : this._unpauseRenderer();
Expand Down

0 comments on commit 68f9f6d

Please sign in to comment.