Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pnpm run lint
pnpm run test
#pnpm run test
4 changes: 0 additions & 4 deletions packages/nf-acceleration-2d.component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,13 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
type: "number",
name: "x",
description: "Horizontal acceleration in px/s²",
example: 4.2,
default: 0,
optional: true,
},
{
type: "number",
name: "y",
description: "Vertical acceleration in px/s²",
example: 67,
default: 0,
optional: true,
},
],
};
54 changes: 54 additions & 0 deletions packages/nf-apply-damage-2d.system/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { type EditorSystemManifest, type Entity, type Registry } from "@nanoforge-dev/ecs-lib";

import { DamageDealer } from "../components/nf-damage-dealer.component";
import { DrawableCircle2D } from "../components/nf-drawable-circle-2d.component";
import { DrawableRect2D } from "../components/nf-drawable-rect-2d.component";
import { DrawableText2D } from "../components/nf-drawable-text-2d.component";
import { Health } from "../components/nf-health.component";
import { HitboxCircle2D } from "../components/nf-hitbox-circle-2d.component";
import { HitboxRectangle2D } from "../components/nf-hitbox-rectangle-2d.component";
import { Owner } from "../components/nf-owner.component";

export function applyDamge2D(registry: Registry) {
const entities = [
...registry.getIndexedZipper([DamageDealer, HitboxCircle2D]),
...registry.getIndexedZipper([DamageDealer, HitboxRectangle2D]),
];

const entityToKill: Entity[] = [];
entities.forEach(({ id, DamageDealer, HitboxCircle2D, HitboxRectangle2D }) => {
(HitboxCircle2D ?? HitboxRectangle2D).entitiesColliding.forEach((e: number) => {
const owner = registry.getEntityComponent(registry.entityFromIndex(id), Owner);
if (owner && owner.owner.getId() === e) return;
const health = registry.getEntityComponent(registry.entityFromIndex(e), Health);
if (health) {
health.currentHealth -= DamageDealer.damage;
if (health.currentHealth <= 0) entityToKill.push(registry.entityFromIndex(e));
}
});
});
entityToKill.forEach((e) => {
registry.getEntityComponent(e, DrawableCircle2D)?.shape.destroy();
registry.getEntityComponent(e, DrawableRect2D)?.shape.destroy();
registry.getEntityComponent(e, DrawableText2D)?.shape.destroy();
registry.killEntity(e);
});
}
// * Required to generate code
export default applyDamge2D.name;

// * Required for the editor to display the system and generate code
export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
name: "applyDamge2D",
description: "Apply damage to entity that have health and delete dead entities",
dependencies: [
"DamageDealer",
"HitboxCircle2D",
"HitboxRectangle2D",
"Health",
"Owner",
"DrawableCircle2D",
"DrawableRect2D",
"DrawableText2D",
],
};
14 changes: 14 additions & 0 deletions packages/nf-apply-damage-2d.system/nanoforge.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "nf/apply-damage-2d",
"type": "system",
"description": "Apply damage to entity that have health and delete dead entities",
"tags": ["base", "health"],
"dependencies": [
"nf/damage-dealer-2d",
"nf/hitbox-circle-2d",
"nf/hitbox-rectangle-2d",
"nf/health",
"nf/owner",
"nf/drawable-text-2d"
]
}
75 changes: 75 additions & 0 deletions packages/nf-collision-2d.system/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib";

import { Position2D } from "../components/nf-position-2d.component";
import { HitboxRectangle2D } from "../components/nf-hitbox-rectangle-2d.component";
import { HitboxCircle2D } from "../components/nf-hitbox-circle-2d.component";

function checkRectangleRectangleCollision(r1: HitboxRectangle2D, p1: Position2D, r2: HitboxRectangle2D, p2: Position2D): boolean {
return p1.x < p2.x + r2.width &&
p1.x + r1.width > p2.x &&
p1.y < p2.y + r2.height &&
p1.y + r1.height > p2.y;
}

function checkCircleCircleCollision(c1: HitboxCircle2D, p1: Position2D, c2: HitboxCircle2D, p2: Position2D): boolean {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)) <= c1.radius + c2.radius
}

function checkRectangleCircleCollision(r: HitboxRectangle2D, pr: Position2D, c: HitboxCircle2D, pc: Position2D): boolean {
let edgeX = pc.x;
let edgeY = pc.y;

if (pc.x < pr.x) edgeX = pr.x;
else if (pc.x > pr.x + r.width) edgeX = pr.x + r.width;
if (pc.y < pr.y) edgeY = pr.y;
else if (pc.y > pr.y + r.height) edgeY = pr.y + r.height;
return Math.sqrt(Math.pow(pc.x - edgeX, 2) + Math.pow(pc.y - edgeY, 2)) <= c.radius;
}


export function hitboxCollinding2D(registry: Registry) {
const rectangles = registry.getIndexedZipper([Position2D, HitboxRectangle2D]);
const circles = registry.getIndexedZipper([Position2D, HitboxCircle2D]);


rectangles.forEach((ent: any) => {
ent.HitboxRectangle2D.entitiesColliding.length = 0;
});
circles.forEach((ent: any) => {
ent.HitboxCircle2D.entitiesColliding.length = 0;
});
for (let i = 0; i < rectangles.length; i++) {
for (let k = i + 1; k < rectangles.length; k++) {
if (checkRectangleRectangleCollision(rectangles[i].HitboxRectangle2D, rectangles[i].Position2D, rectangles[k].HitboxRectangle2D, rectangles[k].Position2D)) {
rectangles[i].HitboxRectangle2D.entitiesColliding.push(rectangles[k].id)
rectangles[k].HitboxRectangle2D.entitiesColliding.push(rectangles[i].id)
}
}
}
for (let i = 0; i < circles.length; i++) {
for (let k = i + 1; k < circles.length; k++) {
if (checkCircleCircleCollision(circles[i].HitboxCircle2D, circles[i].Position2D, circles[k].HitboxCircle2D, circles[k].Position2D)) {
circles[i].HitboxCircle2D.entitiesColliding.push(circles[k].id)
circles[k].HitboxCircle2D.entitiesColliding.push(circles[i].id)
}
}
}
rectangles.forEach(({ id: rectangleId, Position2D: rectanglePostion, HitboxRectangle2D }) => {
circles.forEach(({ id: circleId, Position2D: circlePostion, HitboxCircle2D }) => {
if (circleId !== rectangleId && checkRectangleCircleCollision(HitboxRectangle2D, rectanglePostion, HitboxCircle2D, circlePostion)) {
HitboxRectangle2D.entitiesColliding.push(circleId)
HitboxCircle2D.entitiesColliding.push(rectangleId)
}
});
});
}

// * Required to generate code
export default hitboxCollinding2D.name;

// * Required for the editor to display the system and generate code
export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
name: "hitboxCollinding2D",
description: "Detect collisions between hitbox components and populate entitiesColliding lists",
dependencies: ["Position2D", "HitboxRectangle2D", "HitboxCircle2D"],
};
7 changes: 7 additions & 0 deletions packages/nf-collision-2d.system/nanoforge.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "nf/collision-2d",
"type": "system",
"description": "Detect collisions between hitbox components and populate entitiesColliding lists",
"tags": ["base"],
"dependencies": ["nf/position-2d", "nf/hitbox-rectangle-2d", "nf/hitbox-circle-2d"]
}
27 changes: 27 additions & 0 deletions packages/nf-damage-dealer.component/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib";

export class DamageDealer {
name = this.constructor.name;

constructor(
public damage: number,
) {}
}

// * Required to generate code
export default DamageDealer.name;

// * Required for the editor to display the component and generate code
export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
name: "DamageDealer",
description: "Damage dealer at collision",
params: [
{
type: "number",
name: "damage",
description: "Number of damage inflicted at collision",
example: 10,
default: 10,
},
],
};
6 changes: 6 additions & 0 deletions packages/nf-damage-dealer.component/nanoforge.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "nf/damage-dealer-2d",
"type": "component",
"description": "Damage dealer at collision",
"tags": ["base", "health"]
}
33 changes: 33 additions & 0 deletions packages/nf-destroy-on-hit-2d.component/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib";

export class DestroyOnHit2D {
name = this.constructor.name;

constructor(
public destroyOnOwner: boolean,
public destroyOnStaticBody: boolean,
) {}
}

// * Required to generate code
export default DestroyOnHit2D.name;

// * Required for the editor to display the component and generate code
export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
name: "DestroyOnHit2D",
description: "Destroy the entity at collision",
params: [
{
type: "boolean",
name: "destroyOnOwner",
description: "Should the entity destroy on hit with the owner",
default: false,
},
{
type: "boolean",
name: "destroyOnStaticBody",
description: "Should the entity destroy on hit with static bodys",
default: true,
},
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "nf/destroy-on-hit-2d",
"type": "component",
"description": "Destroy the entity at collision",
"tags": ["base"]
}
54 changes: 54 additions & 0 deletions packages/nf-destroyer-on-hit-2d.system/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { type EditorSystemManifest, type Registry, Entity } from "@nanoforge-dev/ecs-lib";

import { DestroyOnHit2D } from "../components/nf-destroy-on-hit-2d.component";
import { HitboxCircle2D } from "../components/nf-hitbox-circle-2d.component";
import { HitboxRectangle2D } from "../components/nf-hitbox-rectangle-2d.component";
import { Owner } from "../components/nf-owner.component";
import { StaticBody2D } from "../components/nf-static-body-2d.component";
import { DrawableCircle2D } from "../components/nf-drawable-circle-2d.component";
import { DrawableRect2D } from "../components/nf-drawable-rect-2d.component";
import { DrawableText2D } from "../components/nf-drawable-text-2d.component";

export function destroyOnHit2D(registry: Registry) {
const entities = [
...registry.getIndexedZipper([DestroyOnHit2D, HitboxCircle2D]),
...registry.getIndexedZipper([DestroyOnHit2D, HitboxRectangle2D])
];

const entityToKill: Entity[] = [];
entities.forEach(({ id, DestroyOnHit2D, HitboxCircle2D, HitboxRectangle2D }) => {
(HitboxCircle2D ?? HitboxRectangle2D).entitiesColliding.forEach(e => {
const owner = registry.getEntityComponent(registry.entityFromIndex(id), Owner);
if (owner && !DestroyOnHit2D.destroyOnOwner && owner.owner.getId() === e) {
return
}
if (!DestroyOnHit2D.destroyOnStaticBody && registry.getEntityComponent(registry.entityFromIndex(e), StaticBody2D))
return;
entityToKill.push(registry.entityFromIndex(id))
})
});
entityToKill.forEach(e => {
registry.getEntityComponent(e, DrawableCircle2D)?.shape.destroy()
registry.getEntityComponent(e, DrawableRect2D)?.shape.destroy()
registry.getEntityComponent(e, DrawableText2D)?.shape.destroy()
registry.killEntity(e)
})
}
// * Required to generate code
export default destroyOnHit2D.name;

// * Required for the editor to display the system and generate code
export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
name: "destroyOnHit2D",
description: "Destroy entities with DestroyOnHit2D when they collide with other entities",
dependencies: [
"DestroyOnHit2D",
"HitboxCircle2D",
"HitboxRectangle2D",
"Owner",
"StaticBody2D",
"DrawableCircle2D",
"DrawableRect2D",
"DrawableText2D",
],
};
16 changes: 16 additions & 0 deletions packages/nf-destroyer-on-hit-2d.system/nanoforge.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "nf/destroyer-on-hit-2d",
"type": "system",
"description": "Destroy entities with DestroyOnHit2D when they collide with other entities",
"tags": ["base"],
"dependencies": [
"nf/destroy-on-hit-2d",
"nf/hitbox-circle-2d",
"nf/hitbox-rectangle-2d",
"nf/owner",
"nf/static-body-2d",
"nf/drawable-circle-2d",
"nf/drawable-rect-2d",
"nf/drawable-text-2d"
]
}
2 changes: 1 addition & 1 deletion packages/nf-drawable-circle-2d.component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,4 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
optional: true,
},
],
};
};
2 changes: 1 addition & 1 deletion packages/nf-drawable-rect-2d.component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,4 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
optional: true,
},
],
};
};
26 changes: 26 additions & 0 deletions packages/nf-gravity-2d.system/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib";

import { Acceleration2D } from "../components/nf-acceleration-2d.component";
import { Grounded } from "../components/nf-grounded.component";
import { RigidBody2D } from "../components/nf-rigid-body-2d.component";

export function gravity2D(registry: Registry) {
const entities = registry.getZipper([Acceleration2D, Grounded, RigidBody2D]);

entities.forEach(({ Acceleration2D, Grounded, RigidBody2D }) => {
if (Grounded.grounded) {
Acceleration2D.y = 0
return
}
Acceleration2D.y = RigidBody2D.gravityStrength
});
}
// * Required to generate code
export default gravity2D.name;

// * Required for the editor to display the system and generate code
export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
name: "gravity2D",
description: "Apply gravity acceleration to rigid bodies that are not grounded",
dependencies: ["Acceleration2D", "Grounded", "RigidBody2D"],
};
7 changes: 7 additions & 0 deletions packages/nf-gravity-2d.system/nanoforge.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "nf/gravity-2d",
"type": "system",
"description": "Apply gravity acceleration to rigid bodies that are not grounded",
"tags": ["base", "mouvement"],
"dependencies": ["nf/acceleration-2d", "nf/grounded", "nf/rigid-body-2d"]
}
Loading
Loading