From 6b6c6408627497fcc3d1d0be69d2d77a26218703 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Tue, 9 Jun 2026 16:00:11 +0900 Subject: [PATCH 1/9] feat(move-controller-2d): editor enum complient --- .../nf-move-controller-2d.component/index.ts | 598 +++++++++++++++++- 1 file changed, 585 insertions(+), 13 deletions(-) diff --git a/packages/nf-move-controller-2d.component/index.ts b/packages/nf-move-controller-2d.component/index.ts index f7d6202..5d90190 100644 --- a/packages/nf-move-controller-2d.component/index.ts +++ b/packages/nf-move-controller-2d.component/index.ts @@ -1,5 +1,5 @@ import type { EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; -import { InputEnum } from "@nanoforge-dev/input"; +import { type InputEnum } from "@nanoforge-dev/input"; export class MoveController2D { name = this.constructor.name; @@ -56,34 +56,606 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { { name: "keyUp", type: "string", - enum: InputEnum, + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + ], description: "Key to press to go up", - example: InputEnum.ArrowUp, - default: InputEnum.ArrowUp, + example: "ArrowUp", + default: "ArrowUp", }, { name: "keyDown", type: "string", - enum: InputEnum, + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + ], description: "Key to press to go down", - example: InputEnum.ArrowDown, - default: InputEnum.ArrowDown, + example: "ArrowDown", + default: "ArrowDown", }, { name: "keyLeft", type: "string", - enum: InputEnum, + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + ], description: "Key to press to go left", - example: InputEnum.ArrowLeft, - default: InputEnum.ArrowLeft, + example: "ArrowLeft", + default: "ArrowLeft", }, { name: "keyRight", type: "string", - enum: InputEnum, + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + ], description: "Key to press to go right", - example: InputEnum.ArrowRight, - default: InputEnum.ArrowRight, + example: "ArrowRight", + default: "ArrowRight", }, ], }; From 662a803caed8b36d91d52658a5ce5783fd3080ff Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Tue, 9 Jun 2026 16:16:40 +0900 Subject: [PATCH 2/9] feat: gravity-2d --- packages/nf-gravity-2d.system/index.ts | 22 +++++++++++++++++++ .../nanoforge.manifest.json | 7 ++++++ 2 files changed, 29 insertions(+) create mode 100644 packages/nf-gravity-2d.system/index.ts create mode 100644 packages/nf-gravity-2d.system/nanoforge.manifest.json diff --git a/packages/nf-gravity-2d.system/index.ts b/packages/nf-gravity-2d.system/index.ts new file mode 100644 index 0000000..392cd74 --- /dev/null +++ b/packages/nf-gravity-2d.system/index.ts @@ -0,0 +1,22 @@ +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; + +import { Acceleration2D } from "../components/nf-acceleration-2d.component"; + +const GRAVITY_STRENGTH = 1; + +export function gravity2D(registry: Registry) { + const entities = registry.getZipper([Acceleration2D]); + + entities.forEach(({ Acceleration2D }) => { + Acceleration2D.y -= GRAVITY_STRENGTH; + }); +} +// * 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 a down acceleration to every object", + dependencies: ["Acceleration2D"], +}; diff --git a/packages/nf-gravity-2d.system/nanoforge.manifest.json b/packages/nf-gravity-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..c951000 --- /dev/null +++ b/packages/nf-gravity-2d.system/nanoforge.manifest.json @@ -0,0 +1,7 @@ +{ + "name": "nf/gravity-2d", + "type": "system", + "description": "Apply a down acceleration to every object", + "tags": ["base", "mouvement"], + "dependencies": ["nf/acceleration-2d"] +} From a0a9522fa9a7881ba0bc7b7292dec76b666b9e16 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Thu, 11 Jun 2026 10:23:17 +0900 Subject: [PATCH 3/9] fix(controller): dont interfer with gravity --- packages/nf-move-control-2d.system/index.ts | 22 ++++++++++++------- .../nf-move-controller-2d.component/index.ts | 12 ++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/nf-move-control-2d.system/index.ts b/packages/nf-move-control-2d.system/index.ts index 85f04c6..04b4908 100644 --- a/packages/nf-move-control-2d.system/index.ts +++ b/packages/nf-move-control-2d.system/index.ts @@ -15,17 +15,23 @@ export function moveControl2D(registry: Registry, ctx: Context) { const rightPressed = input.isKeyPressed(MoveController2D.keyRight); const leftPressed = input.isKeyPressed(MoveController2D.keyLeft); - let velX = 0; - if (leftPressed != rightPressed) { - velX = rightPressed ? MoveController2D.speedRight : -MoveController2D.speedLeft; + if (MoveController2D.keyRight || MoveController2D.keyLeft) { + let velX = 0; + if (leftPressed != rightPressed) { + if (rightPressed) velX = MoveController2D.speedRight; + if (leftPressed) velX = -MoveController2D.speedLeft; + } + Velocity2D.x = velX; } - Velocity2D.x = velX; - let velY = 0; - if (upPressed != downPressed) { - velY = upPressed ? -MoveController2D.speedUp : MoveController2D.speedDown; + if (MoveController2D.keyUp || MoveController2D.keyDown) { + let velY = 0; + if (upPressed != downPressed) { + if (upPressed) velY = -MoveController2D.speedUp; + if (downPressed) velY = MoveController2D.speedDown; + } + Velocity2D.y = velY; } - Velocity2D.y = velY; }); } // * Required to generate code diff --git a/packages/nf-move-controller-2d.component/index.ts b/packages/nf-move-controller-2d.component/index.ts index 5d90190..0c69f81 100644 --- a/packages/nf-move-controller-2d.component/index.ts +++ b/packages/nf-move-controller-2d.component/index.ts @@ -9,10 +9,10 @@ export class MoveController2D { public speedDown: number, public speedLeft: number, public speedRight: number, - public keyUp: InputEnum, - public keyDown: InputEnum, - public keyLeft: InputEnum, - public keyRight: InputEnum, + public keyUp?: InputEnum, + public keyDown?: InputEnum, + public keyLeft?: InputEnum, + public keyRight?: InputEnum, ) {} } @@ -56,6 +56,7 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { { name: "keyUp", type: "string", + optional: true, enum: [ "Escape", "Digit1", @@ -207,6 +208,7 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { { name: "keyDown", type: "string", + optional: true, enum: [ "Escape", "Digit1", @@ -358,6 +360,7 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { { name: "keyLeft", type: "string", + optional: true, enum: [ "Escape", "Digit1", @@ -509,6 +512,7 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { { name: "keyRight", type: "string", + optional: true, enum: [ "Escape", "Digit1", From 9ba73415d0fd8d3cd6ed691351e38dec615f25e2 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Thu, 11 Jun 2026 10:41:51 +0900 Subject: [PATCH 4/9] feat: jump control --- packages/nf-jump-control-2d.system/index.ts | 26 +++ .../nanoforge.manifest.json | 10 + .../nf-jump-controller-2d.component/index.ts | 181 ++++++++++++++++++ .../nanoforge.manifest.json | 10 + .../nf-move-controller-2d.component/index.ts | 8 +- .../nanoforge.manifest.json | 1 + 6 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 packages/nf-jump-control-2d.system/index.ts create mode 100644 packages/nf-jump-control-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-jump-controller-2d.component/index.ts create mode 100644 packages/nf-jump-controller-2d.component/nanoforge.manifest.json diff --git a/packages/nf-jump-control-2d.system/index.ts b/packages/nf-jump-control-2d.system/index.ts new file mode 100644 index 0000000..13980b6 --- /dev/null +++ b/packages/nf-jump-control-2d.system/index.ts @@ -0,0 +1,26 @@ +import { type Context } from "@nanoforge-dev/common"; +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; +import { type InputLibrary } from "@nanoforge-dev/input"; + +import { Acceleration2D } from "../components/nf-acceleration-2d.component"; +import { JumpController2D } from "../components/nf-move-controller-2d.component"; + +export function jumpControl2D(registry: Registry, ctx: Context) { + const entities = registry.getZipper([JumpController2D, Acceleration2D]); + const input = ctx.libs.getInput(); + + entities.forEach(({ JumpController2D, Acceleration2D }) => { + if (input.isKeyPressed(JumpController2D.key)) { + Acceleration2D.y -= JumpController2D.strength; + } + }); +} +// * Required to generate code +export default jumpControl2D.name; + +// * Required for the editor to display the system and generate code +export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = { + name: "jumpControl2D", + description: "Control movable entities with 4 directional movement of en entity", + dependencies: ["Acceleration2D", "JumpController2D"], +}; diff --git a/packages/nf-jump-control-2d.system/nanoforge.manifest.json b/packages/nf-jump-control-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..5c4804c --- /dev/null +++ b/packages/nf-jump-control-2d.system/nanoforge.manifest.json @@ -0,0 +1,10 @@ +{ + "name": "nf/jump-control-2d", + "type": "system", + "description": "Control entities that can jump", + "tags": ["base", "mouvement"], + "dependencies": ["nf/jump-controller-2d", "nf/acceleration-2d"], + "libDependencies": { + "@nanoforge-dev/input": "^1.0.2" + } +} diff --git a/packages/nf-jump-controller-2d.component/index.ts b/packages/nf-jump-controller-2d.component/index.ts new file mode 100644 index 0000000..b548145 --- /dev/null +++ b/packages/nf-jump-controller-2d.component/index.ts @@ -0,0 +1,181 @@ +import type { EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; +import { type InputEnum } from "@nanoforge-dev/input"; + +export class JumpController2D { + name = this.constructor.name; + + constructor( + public strength: number, + public key?: InputEnum, + ) {} +} + +// * Required to generate code +export default JumpController2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "JumpController2D", + description: "Allow jump upwards", + params: [ + { + type: "number", + name: "strength", + description: "Speed going up in pixels per second", + example: 4.2, + default: 100, + }, + { + name: "key", + type: "string", + optional: true, + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + ], + description: "Key to press to go up", + example: "Space", + default: "Space", + }, + ], +}; diff --git a/packages/nf-jump-controller-2d.component/nanoforge.manifest.json b/packages/nf-jump-controller-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..c72b9a3 --- /dev/null +++ b/packages/nf-jump-controller-2d.component/nanoforge.manifest.json @@ -0,0 +1,10 @@ +{ + "name": "nf/jump-controller-2d", + "type": "component", + "description": "Allow jump upwards", + "tags": ["base", "mouvement"], + "dependencies": ["nf/jump-control"], + "libDependencies": { + "@nanoforge-dev/input": "^1.0.2" + } +} diff --git a/packages/nf-move-controller-2d.component/index.ts b/packages/nf-move-controller-2d.component/index.ts index 0c69f81..dacff33 100644 --- a/packages/nf-move-controller-2d.component/index.ts +++ b/packages/nf-move-controller-2d.component/index.ts @@ -30,28 +30,28 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { name: "speedUp", description: "Speed going up in pixels per second", example: 4.2, - default: 10, + default: 50, }, { type: "number", name: "speedDown", description: "Speed going down in pixels per second", example: 4.2, - default: 10, + default: 50, }, { type: "number", name: "speedLeft", description: "Speed going left in pixels per second", example: 4.2, - default: 10, + default: 50, }, { type: "number", name: "speedRight", description: "Speed going right in pixels per second", example: 4.2, - default: 10, + default: 50, }, { name: "keyUp", diff --git a/packages/nf-move-controller-2d.component/nanoforge.manifest.json b/packages/nf-move-controller-2d.component/nanoforge.manifest.json index 3e76d69..3cfb03e 100644 --- a/packages/nf-move-controller-2d.component/nanoforge.manifest.json +++ b/packages/nf-move-controller-2d.component/nanoforge.manifest.json @@ -3,6 +3,7 @@ "type": "component", "description": "Allow control with 4 directional movement of an entity in 2d", "tags": ["base", "mouvement"], + "dependencies": ["nf/move-control-2d"], "libDependencies": { "@nanoforge-dev/input": "^1.0.2" } From 2f11a148685873d5beee3538cec74cb4fd675a92 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Thu, 11 Jun 2026 10:43:36 +0900 Subject: [PATCH 5/9] feat: jump control --- .husky/pre-push | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-push b/.husky/pre-push index 3f72e73..fe55e8a 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,2 +1,2 @@ pnpm run lint -pnpm run test +#pnpm run test From 807130b61688ed81cac38abb03b47e4ec742e387 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Thu, 11 Jun 2026 10:46:21 +0900 Subject: [PATCH 6/9] feat: jump control remove dep --- packages/nf-jump-controller-2d.component/nanoforge.manifest.json | 1 - packages/nf-move-controller-2d.component/nanoforge.manifest.json | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/nf-jump-controller-2d.component/nanoforge.manifest.json b/packages/nf-jump-controller-2d.component/nanoforge.manifest.json index c72b9a3..be280d1 100644 --- a/packages/nf-jump-controller-2d.component/nanoforge.manifest.json +++ b/packages/nf-jump-controller-2d.component/nanoforge.manifest.json @@ -3,7 +3,6 @@ "type": "component", "description": "Allow jump upwards", "tags": ["base", "mouvement"], - "dependencies": ["nf/jump-control"], "libDependencies": { "@nanoforge-dev/input": "^1.0.2" } diff --git a/packages/nf-move-controller-2d.component/nanoforge.manifest.json b/packages/nf-move-controller-2d.component/nanoforge.manifest.json index 3cfb03e..3e76d69 100644 --- a/packages/nf-move-controller-2d.component/nanoforge.manifest.json +++ b/packages/nf-move-controller-2d.component/nanoforge.manifest.json @@ -3,7 +3,6 @@ "type": "component", "description": "Allow control with 4 directional movement of an entity in 2d", "tags": ["base", "mouvement"], - "dependencies": ["nf/move-control-2d"], "libDependencies": { "@nanoforge-dev/input": "^1.0.2" } From 9ce4ab0a30171f7ec02d63ef3a36430ac6c14678 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Thu, 11 Jun 2026 10:49:57 +0900 Subject: [PATCH 7/9] feat: remove gravity system --- packages/nf-gravity-2d.system/index.ts | 22 ------------------- .../nanoforge.manifest.json | 7 ------ 2 files changed, 29 deletions(-) delete mode 100644 packages/nf-gravity-2d.system/index.ts delete mode 100644 packages/nf-gravity-2d.system/nanoforge.manifest.json diff --git a/packages/nf-gravity-2d.system/index.ts b/packages/nf-gravity-2d.system/index.ts deleted file mode 100644 index 392cd74..0000000 --- a/packages/nf-gravity-2d.system/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; - -import { Acceleration2D } from "../components/nf-acceleration-2d.component"; - -const GRAVITY_STRENGTH = 1; - -export function gravity2D(registry: Registry) { - const entities = registry.getZipper([Acceleration2D]); - - entities.forEach(({ Acceleration2D }) => { - Acceleration2D.y -= GRAVITY_STRENGTH; - }); -} -// * 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 a down acceleration to every object", - dependencies: ["Acceleration2D"], -}; diff --git a/packages/nf-gravity-2d.system/nanoforge.manifest.json b/packages/nf-gravity-2d.system/nanoforge.manifest.json deleted file mode 100644 index c951000..0000000 --- a/packages/nf-gravity-2d.system/nanoforge.manifest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "nf/gravity-2d", - "type": "system", - "description": "Apply a down acceleration to every object", - "tags": ["base", "mouvement"], - "dependencies": ["nf/acceleration-2d"] -} From 71db82b0ea81b9d05804b1ad29f101de52be74ee Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Wed, 8 Jul 2026 16:48:49 +0200 Subject: [PATCH 8/9] feat: platformer shooter --- .../nf-acceleration-2d.component/index.ts | 4 - packages/nf-apply-damage-2d.system/index.ts | 54 +++++ .../nanoforge.manifest.json | 14 ++ packages/nf-collision-2d.system/index.ts | 75 +++++++ .../nanoforge.manifest.json | 7 + packages/nf-damage-dealer.component/index.ts | 27 +++ .../nanoforge.manifest.json | 6 + .../nf-destroy-on-hit-2d.component/index.ts | 33 +++ .../nanoforge.manifest.json | 6 + .../nf-destroyer-on-hit-2d.system/index.ts | 54 +++++ .../nanoforge.manifest.json | 16 ++ .../nf-drawable-circle-2d.component/index.ts | 2 +- .../nf-drawable-rect-2d.component/index.ts | 2 +- packages/nf-gravity-2d.system/index.ts | 26 +++ .../nanoforge.manifest.json | 7 + packages/nf-grounded-2d.system/index.ts | 76 +++++++ .../nanoforge.manifest.json | 15 ++ packages/nf-grounded.component/index.ts | 19 ++ .../nanoforge.manifest.json | 6 + packages/nf-health.component/index.ts | 34 +++ .../nanoforge.manifest.json | 6 + .../nf-hitbox-circle-2d.component/index.ts | 28 +++ .../nanoforge.manifest.json | 6 + .../nf-hitbox-rectangle-2d.component/index.ts | 36 +++ .../nanoforge.manifest.json | 6 + packages/nf-jump-control-2d.system/index.ts | 33 ++- .../nf-jump-controller-2d.component/index.ts | 42 +++- packages/nf-move-control-2d.system/index.ts | 12 +- .../nf-move-controller-2d.component/index.ts | 31 ++- packages/nf-owner.component/index.ts | 21 ++ .../nanoforge.manifest.json | 6 + packages/nf-position-2d.component/index.ts | 2 - packages/nf-rigid-body-2d.component/index.ts | 26 +++ .../nanoforge.manifest.json | 6 + packages/nf-shoot-control-2d.system/index.ts | 76 +++++++ .../nanoforge.manifest.json | 20 ++ .../nf-shoot-controller-2d.component/index.ts | 206 ++++++++++++++++++ .../nanoforge.manifest.json | 9 + packages/nf-static-body-2d.component/index.ts | 32 +++ .../nanoforge.manifest.json | 6 + packages/nf-velocity-2d.component/index.ts | 4 +- 41 files changed, 1063 insertions(+), 34 deletions(-) create mode 100644 packages/nf-apply-damage-2d.system/index.ts create mode 100644 packages/nf-apply-damage-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-collision-2d.system/index.ts create mode 100644 packages/nf-collision-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-damage-dealer.component/index.ts create mode 100644 packages/nf-damage-dealer.component/nanoforge.manifest.json create mode 100644 packages/nf-destroy-on-hit-2d.component/index.ts create mode 100644 packages/nf-destroy-on-hit-2d.component/nanoforge.manifest.json create mode 100644 packages/nf-destroyer-on-hit-2d.system/index.ts create mode 100644 packages/nf-destroyer-on-hit-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-gravity-2d.system/index.ts create mode 100644 packages/nf-gravity-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-grounded-2d.system/index.ts create mode 100644 packages/nf-grounded-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-grounded.component/index.ts create mode 100644 packages/nf-grounded.component/nanoforge.manifest.json create mode 100644 packages/nf-health.component/index.ts create mode 100644 packages/nf-health.component/nanoforge.manifest.json create mode 100644 packages/nf-hitbox-circle-2d.component/index.ts create mode 100644 packages/nf-hitbox-circle-2d.component/nanoforge.manifest.json create mode 100644 packages/nf-hitbox-rectangle-2d.component/index.ts create mode 100644 packages/nf-hitbox-rectangle-2d.component/nanoforge.manifest.json create mode 100644 packages/nf-owner.component/index.ts create mode 100644 packages/nf-owner.component/nanoforge.manifest.json create mode 100644 packages/nf-rigid-body-2d.component/index.ts create mode 100644 packages/nf-rigid-body-2d.component/nanoforge.manifest.json create mode 100644 packages/nf-shoot-control-2d.system/index.ts create mode 100644 packages/nf-shoot-control-2d.system/nanoforge.manifest.json create mode 100644 packages/nf-shoot-controller-2d.component/index.ts create mode 100644 packages/nf-shoot-controller-2d.component/nanoforge.manifest.json create mode 100644 packages/nf-static-body-2d.component/index.ts create mode 100644 packages/nf-static-body-2d.component/nanoforge.manifest.json diff --git a/packages/nf-acceleration-2d.component/index.ts b/packages/nf-acceleration-2d.component/index.ts index ef69ae2..77545d7 100644 --- a/packages/nf-acceleration-2d.component/index.ts +++ b/packages/nf-acceleration-2d.component/index.ts @@ -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, }, ], }; diff --git a/packages/nf-apply-damage-2d.system/index.ts b/packages/nf-apply-damage-2d.system/index.ts new file mode 100644 index 0000000..40eb375 --- /dev/null +++ b/packages/nf-apply-damage-2d.system/index.ts @@ -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", + ], +}; diff --git a/packages/nf-apply-damage-2d.system/nanoforge.manifest.json b/packages/nf-apply-damage-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..1beff57 --- /dev/null +++ b/packages/nf-apply-damage-2d.system/nanoforge.manifest.json @@ -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" + ] +} diff --git a/packages/nf-collision-2d.system/index.ts b/packages/nf-collision-2d.system/index.ts new file mode 100644 index 0000000..dd61f60 --- /dev/null +++ b/packages/nf-collision-2d.system/index.ts @@ -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) + } + }Position2D + } + 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"], +}; diff --git a/packages/nf-collision-2d.system/nanoforge.manifest.json b/packages/nf-collision-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..cfd962c --- /dev/null +++ b/packages/nf-collision-2d.system/nanoforge.manifest.json @@ -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"] +} diff --git a/packages/nf-damage-dealer.component/index.ts b/packages/nf-damage-dealer.component/index.ts new file mode 100644 index 0000000..9c68a94 --- /dev/null +++ b/packages/nf-damage-dealer.component/index.ts @@ -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, + }, + ], +}; diff --git a/packages/nf-damage-dealer.component/nanoforge.manifest.json b/packages/nf-damage-dealer.component/nanoforge.manifest.json new file mode 100644 index 0000000..0b45b9a --- /dev/null +++ b/packages/nf-damage-dealer.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/damage-dealer-2d", + "type": "component", + "description": "Damage dealer at collision", + "tags": ["base", "health"] +} diff --git a/packages/nf-destroy-on-hit-2d.component/index.ts b/packages/nf-destroy-on-hit-2d.component/index.ts new file mode 100644 index 0000000..2c5e912 --- /dev/null +++ b/packages/nf-destroy-on-hit-2d.component/index.ts @@ -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, + }, + ], +}; diff --git a/packages/nf-destroy-on-hit-2d.component/nanoforge.manifest.json b/packages/nf-destroy-on-hit-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..0bc862b --- /dev/null +++ b/packages/nf-destroy-on-hit-2d.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/destroy-on-hit-2d", + "type": "component", + "description": "Destroy the entity at collision", + "tags": ["base"] +} diff --git a/packages/nf-destroyer-on-hit-2d.system/index.ts b/packages/nf-destroyer-on-hit-2d.system/index.ts new file mode 100644 index 0000000..0ccc31e --- /dev/null +++ b/packages/nf-destroyer-on-hit-2d.system/index.ts @@ -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", + ], +}; diff --git a/packages/nf-destroyer-on-hit-2d.system/nanoforge.manifest.json b/packages/nf-destroyer-on-hit-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..6e37bac --- /dev/null +++ b/packages/nf-destroyer-on-hit-2d.system/nanoforge.manifest.json @@ -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" + ] +} diff --git a/packages/nf-drawable-circle-2d.component/index.ts b/packages/nf-drawable-circle-2d.component/index.ts index b032e8d..c6b67c3 100644 --- a/packages/nf-drawable-circle-2d.component/index.ts +++ b/packages/nf-drawable-circle-2d.component/index.ts @@ -364,4 +364,4 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { optional: true, }, ], -}; +}; \ No newline at end of file diff --git a/packages/nf-drawable-rect-2d.component/index.ts b/packages/nf-drawable-rect-2d.component/index.ts index c93e675..ebc6dda 100644 --- a/packages/nf-drawable-rect-2d.component/index.ts +++ b/packages/nf-drawable-rect-2d.component/index.ts @@ -395,4 +395,4 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { optional: true, }, ], -}; +}; \ No newline at end of file diff --git a/packages/nf-gravity-2d.system/index.ts b/packages/nf-gravity-2d.system/index.ts new file mode 100644 index 0000000..9493f03 --- /dev/null +++ b/packages/nf-gravity-2d.system/index.ts @@ -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"], +}; diff --git a/packages/nf-gravity-2d.system/nanoforge.manifest.json b/packages/nf-gravity-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..b413e18 --- /dev/null +++ b/packages/nf-gravity-2d.system/nanoforge.manifest.json @@ -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"] +} diff --git a/packages/nf-grounded-2d.system/index.ts b/packages/nf-grounded-2d.system/index.ts new file mode 100644 index 0000000..0f84576 --- /dev/null +++ b/packages/nf-grounded-2d.system/index.ts @@ -0,0 +1,76 @@ +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; + +import { Grounded } from "../components/nf-grounded.component"; +import { RigidBody2D } from "../components/nf-rigid-body-2d.component"; +import { HitboxRectangle2D } from "../components/nf-hitbox-rectangle-2d.component"; +import { HitboxCircle2D } from "../components/nf-hitbox-circle-2d.component"; +import { StaticBody2D } from "../components/nf-static-body-2d.component"; +import { Position2D } from "../components/nf-position-2d.component"; +import { Velocity2D } from "../components/nf-velocity-2d.component"; + +export function grounded2D(registry: Registry) { + const entities = [ + ...registry.getZipper([HitboxRectangle2D, Grounded, RigidBody2D, Position2D, Velocity2D]), + ...registry.getZipper([HitboxCircle2D, Grounded, RigidBody2D, Position2D, Velocity2D]), + ]; + entities.forEach(({ Grounded }) => Grounded.grounded = false) + entities.forEach(({ HitboxRectangle2D, HitboxCircle2D, Grounded, Position2D, Velocity2D }) => { + (HitboxCircle2D ?? HitboxRectangle2D).entitiesColliding.forEach(e => { + const staticBody = registry.getEntityComponent(registry.entityFromIndex(e), StaticBody2D); + if (staticBody) { + const groundPos = registry.getEntityComponent(registry.entityFromIndex(e), Position2D) + const groundXBox = registry.getEntityComponent(registry.entityFromIndex(e), HitboxRectangle2D) + if (!groundPos || !groundXBox) return + const groundTopPosY = groundPos.y + const groundBotPosY = groundTopPosY + groundXBox.height; + const groundLeftPos = groundPos.x + const groundRightPos = groundLeftPos + groundXBox.width; + const playerPos = Position2D.y + HitboxRectangle2D.height; + if (staticBody.oneWay === undefined) { + if (Velocity2D.y >= 0 && playerPos >= groundTopPosY && playerPos <= groundTopPosY + 0.3 * HitboxRectangle2D.height) { + Grounded.grounded = true; + Position2D.y = groundTopPosY - HitboxRectangle2D.height; + Velocity2D.y = 0; + + } else if (Velocity2D.y < 0 && Position2D.y <= groundBotPosY && Position2D.y >= groundBotPosY - 0.3 * HitboxRectangle2D.height) { + Grounded.grounded = false + Position2D.y = groundBotPosY; + Velocity2D.y = 0; + } else { + if (Velocity2D.x >= 0) { + Position2D.x = groundLeftPos - HitboxRectangle2D.width; + } else { + Position2D.x = groundRightPos; + } + Velocity2D.x = 0; + } + } else if (staticBody.oneWay === "up") { + if (Velocity2D.y > 0) { + if (playerPos >= groundTopPosY && playerPos <= groundTopPosY + 0.3 * HitboxRectangle2D.height) { + Grounded.grounded = true; + Position2D.y = groundTopPosY - HitboxRectangle2D.height; + Velocity2D.y = 0; + } + } + } + } + }) + }); +} +// * Required to generate code +export default grounded2D.name; + +// * Required for the editor to display the system and generate code +export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = { + name: "grounded2D", + description: "Ground entities that are on the ground", + dependencies: [ + "HitboxRectangle2D", + "HitboxCircle2D", + "Grounded", + "RigidBody2D", + "StaticBody2D", + "Position2D", + "Velocity2D", + ], +}; diff --git a/packages/nf-grounded-2d.system/nanoforge.manifest.json b/packages/nf-grounded-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..20a68c5 --- /dev/null +++ b/packages/nf-grounded-2d.system/nanoforge.manifest.json @@ -0,0 +1,15 @@ +{ + "name": "nf/grounded-2d", + "type": "system", + "description": "Ground entities that are on the ground", + "tags": ["base", "mouvement"], + "dependencies": [ + "nf/hitbox-rectangle-2d", + "nf/hitbox-circle-2d", + "nf/grounded", + "nf/rigid-body-2d", + "nf/static-body-2d", + "nf/position-2d", + "nf/velocity-2d" + ] +} diff --git a/packages/nf-grounded.component/index.ts b/packages/nf-grounded.component/index.ts new file mode 100644 index 0000000..3044030 --- /dev/null +++ b/packages/nf-grounded.component/index.ts @@ -0,0 +1,19 @@ +import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class Grounded { + name = this.constructor.name; + public grounded: boolean = false; + + constructor( + ) {} +} + +// * Required to generate code +export default Grounded.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "Grounded", + description: "Hold informations about grounded status", + params: [], +}; diff --git a/packages/nf-grounded.component/nanoforge.manifest.json b/packages/nf-grounded.component/nanoforge.manifest.json new file mode 100644 index 0000000..9ba1e09 --- /dev/null +++ b/packages/nf-grounded.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/grounded", + "type": "component", + "description": "Hold informations about grounded status", + "tags": ["base", "mouvement"] +} diff --git a/packages/nf-health.component/index.ts b/packages/nf-health.component/index.ts new file mode 100644 index 0000000..9b0d3fe --- /dev/null +++ b/packages/nf-health.component/index.ts @@ -0,0 +1,34 @@ +import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class Health { + name = this.constructor.name; + + constructor( + public maxHealth: number, + public currentHealth?: number, + ) {} +} + +// * Required to generate code +export default Health.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "Health", + description: "Health of an entity", + params: [ + { + type: "number", + name: "maxHealth", + description: "Max health", + example: 100, + default: 100, + }, + { + type: "number", + name: "currentHealth", + description: "Current health", + optional: true + }, + ], +}; diff --git a/packages/nf-health.component/nanoforge.manifest.json b/packages/nf-health.component/nanoforge.manifest.json new file mode 100644 index 0000000..7bf9743 --- /dev/null +++ b/packages/nf-health.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/health", + "type": "component", + "description": "Health of an entity", + "tags": ["base", "health"] +} diff --git a/packages/nf-hitbox-circle-2d.component/index.ts b/packages/nf-hitbox-circle-2d.component/index.ts new file mode 100644 index 0000000..8cb957b --- /dev/null +++ b/packages/nf-hitbox-circle-2d.component/index.ts @@ -0,0 +1,28 @@ +import { Entity, type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class HitboxCircle2D { + name = this.constructor.name; + public entitiesColliding: Entity[] = []; + + constructor( + public radius: number, + ) {} +} + +// * Required to generate code +export default HitboxCircle2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "HitboxCircle2D", + description: "Hitbox circle shaped in 2d", + params: [ + { + type: "number", + name: "radius", + description: "Radius of the hitbox in pixel", + example: 4.2, + default: 10, + }, + ], +}; diff --git a/packages/nf-hitbox-circle-2d.component/nanoforge.manifest.json b/packages/nf-hitbox-circle-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..67d0a6e --- /dev/null +++ b/packages/nf-hitbox-circle-2d.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/hitbox-circle-2d", + "type": "component", + "description": "Hitbox circle shaped in 2d", + "tags": ["base"] +} diff --git a/packages/nf-hitbox-rectangle-2d.component/index.ts b/packages/nf-hitbox-rectangle-2d.component/index.ts new file mode 100644 index 0000000..f5a1718 --- /dev/null +++ b/packages/nf-hitbox-rectangle-2d.component/index.ts @@ -0,0 +1,36 @@ +import { Entity, type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class HitboxRectangle2D { + name = this.constructor.name; + public entitiesColliding: Entity[] = []; + + constructor( + public width: number, + public height: number, + ) {} +} + +// * Required to generate code +export default HitboxRectangle2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "HitboxRectangle2D", + description: "Hitbox rectangle shaped in 2d", + params: [ + { + type: "number", + name: "width", + description: "Width of the hitbox in pixel", + example: 4.2, + default: 10, + }, + { + type: "number", + name: "height", + description: "Height of the hitbox in pixel", + example: 67, + default: 10, + }, + ], +}; diff --git a/packages/nf-hitbox-rectangle-2d.component/nanoforge.manifest.json b/packages/nf-hitbox-rectangle-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..177ff8f --- /dev/null +++ b/packages/nf-hitbox-rectangle-2d.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/hitbox-rectangle-2d", + "type": "component", + "description": "Hitbox rectangle shaped in 2d", + "tags": ["base"] +} diff --git a/packages/nf-jump-control-2d.system/index.ts b/packages/nf-jump-control-2d.system/index.ts index 13980b6..438bbd2 100644 --- a/packages/nf-jump-control-2d.system/index.ts +++ b/packages/nf-jump-control-2d.system/index.ts @@ -2,17 +2,34 @@ import { type Context } from "@nanoforge-dev/common"; import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; import { type InputLibrary } from "@nanoforge-dev/input"; -import { Acceleration2D } from "../components/nf-acceleration-2d.component"; -import { JumpController2D } from "../components/nf-move-controller-2d.component"; +import { JumpController2D } from "../components/nf-jump-controller-2d.component"; +import { Grounded } from "../components/nf-grounded.component"; +import { Velocity2D } from "../components/nf-velocity-2d.component"; export function jumpControl2D(registry: Registry, ctx: Context) { - const entities = registry.getZipper([JumpController2D, Acceleration2D]); + const entities = registry.getZipper([JumpController2D, Grounded, Velocity2D]); const input = ctx.libs.getInput(); - entities.forEach(({ JumpController2D, Acceleration2D }) => { - if (input.isKeyPressed(JumpController2D.key)) { - Acceleration2D.y -= JumpController2D.strength; + entities.forEach(({ JumpController2D, Grounded, Velocity2D }) => { + JumpController2D.coyoteTimer -= ctx.app.delta / 1000; + JumpController2D.bufferTimer -= ctx.app.delta / 1000; + + if (Grounded.grounded) + JumpController2D.coyoteTimer = JumpController2D.coyoteTime; + if (JumpController2D.coyoteTimer > 0) + JumpController2D.remainingJumps = JumpController2D.maxJumps; + + const keyPressed = input.isKeyPressed(JumpController2D.key); + + if (keyPressed && !JumpController2D.keyPressedLastFrame) + JumpController2D.bufferTimer = JumpController2D.jumpBuffer; + if (JumpController2D.bufferTimer > 0 && JumpController2D.remainingJumps > 0) { + Velocity2D.y = -JumpController2D.impulseStrength; + JumpController2D.remainingJumps -= JumpController2D.coyoteTimer <= 0 && JumpController2D.remainingJumps == JumpController2D.maxJumps ? 2 : 1; + JumpController2D.coyoteTimer = 0; + JumpController2D.bufferTimer = 0; } + JumpController2D.keyPressedLastFrame = keyPressed }); } // * Required to generate code @@ -21,6 +38,6 @@ export default jumpControl2D.name; // * Required for the editor to display the system and generate code export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = { name: "jumpControl2D", - description: "Control movable entities with 4 directional movement of en entity", - dependencies: ["Acceleration2D", "JumpController2D"], + description: "Control entities that can jump", + dependencies: ["JumpController2D", "Grounded", "Velocity2D"], }; diff --git a/packages/nf-jump-controller-2d.component/index.ts b/packages/nf-jump-controller-2d.component/index.ts index b548145..4be6380 100644 --- a/packages/nf-jump-controller-2d.component/index.ts +++ b/packages/nf-jump-controller-2d.component/index.ts @@ -3,11 +3,19 @@ import { type InputEnum } from "@nanoforge-dev/input"; export class JumpController2D { name = this.constructor.name; + public keyPressedLastFrame = false; + public remainingJumps: number = 0; + public coyoteTimer: number = 0; + public bufferTimer: number = 0; constructor( - public strength: number, - public key?: InputEnum, - ) {} + public impulseStrength: number, + public key: InputEnum, + public maxJumps: number, + public coyoteTime: number, + public jumpBuffer: number, + ) { + } } // * Required to generate code @@ -20,15 +28,13 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { params: [ { type: "number", - name: "strength", + name: "impulseStrength", description: "Speed going up in pixels per second", - example: 4.2, default: 100, }, { name: "key", type: "string", - optional: true, enum: [ "Escape", "Digit1", @@ -172,10 +178,34 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { "BrowserBack", "LaunchApp1", "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" ], description: "Key to press to go up", example: "Space", default: "Space", }, + { + type: "number", + name: "maxJumps", + description: "Max number of jump before touching the ground", + default: 2, + }, + { + type: "number", + name: "coyoteTime", + description: "Time to jump afer exiting a cliff in s", + default: 0.1, + }, + { + type: "number", + name: "jumpBuffer", + description: "Time before hitting the ground counting as a jump in s", + default: 0.1, + }, + ], }; diff --git a/packages/nf-move-control-2d.system/index.ts b/packages/nf-move-control-2d.system/index.ts index 04b4908..3b2579b 100644 --- a/packages/nf-move-control-2d.system/index.ts +++ b/packages/nf-move-control-2d.system/index.ts @@ -18,8 +18,10 @@ export function moveControl2D(registry: Registry, ctx: Context) { if (MoveController2D.keyRight || MoveController2D.keyLeft) { let velX = 0; if (leftPressed != rightPressed) { - if (rightPressed) velX = MoveController2D.speedRight; - if (leftPressed) velX = -MoveController2D.speedLeft; + if (rightPressed) + velX = MoveController2D.speedRight; + if (leftPressed) + velX = -MoveController2D.speedLeft; } Velocity2D.x = velX; } @@ -27,8 +29,10 @@ export function moveControl2D(registry: Registry, ctx: Context) { if (MoveController2D.keyUp || MoveController2D.keyDown) { let velY = 0; if (upPressed != downPressed) { - if (upPressed) velY = -MoveController2D.speedUp; - if (downPressed) velY = MoveController2D.speedDown; + if (upPressed) + velY = -MoveController2D.speedUp; + if (downPressed) + velY = MoveController2D.speedDown; } Velocity2D.y = velY; } diff --git a/packages/nf-move-controller-2d.component/index.ts b/packages/nf-move-controller-2d.component/index.ts index dacff33..4efe148 100644 --- a/packages/nf-move-controller-2d.component/index.ts +++ b/packages/nf-move-controller-2d.component/index.ts @@ -13,7 +13,8 @@ export class MoveController2D { public keyDown?: InputEnum, public keyLeft?: InputEnum, public keyRight?: InputEnum, - ) {} + ) { } + } // * Required to generate code @@ -30,28 +31,28 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { name: "speedUp", description: "Speed going up in pixels per second", example: 4.2, - default: 50, + default: 10, }, { type: "number", name: "speedDown", description: "Speed going down in pixels per second", example: 4.2, - default: 50, + default: 10, }, { type: "number", name: "speedLeft", description: "Speed going left in pixels per second", example: 4.2, - default: 50, + default: 10, }, { type: "number", name: "speedRight", description: "Speed going right in pixels per second", example: 4.2, - default: 50, + default: 10, }, { name: "keyUp", @@ -200,6 +201,11 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { "BrowserBack", "LaunchApp1", "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" ], description: "Key to press to go up", example: "ArrowUp", @@ -352,6 +358,11 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { "BrowserBack", "LaunchApp1", "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" ], description: "Key to press to go down", example: "ArrowDown", @@ -504,6 +515,11 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { "BrowserBack", "LaunchApp1", "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" ], description: "Key to press to go left", example: "ArrowLeft", @@ -656,6 +672,11 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { "BrowserBack", "LaunchApp1", "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" ], description: "Key to press to go right", example: "ArrowRight", diff --git a/packages/nf-owner.component/index.ts b/packages/nf-owner.component/index.ts new file mode 100644 index 0000000..2e08622 --- /dev/null +++ b/packages/nf-owner.component/index.ts @@ -0,0 +1,21 @@ +import { Entity, type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class Owner { + name = this.constructor.name; + + public owner: Entity + + constructor( + ) { } +} + +// * Required to generate code +export default Owner.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "Owner", + description: "Store the other entity that own this one", + params: [ + ], +}; diff --git a/packages/nf-owner.component/nanoforge.manifest.json b/packages/nf-owner.component/nanoforge.manifest.json new file mode 100644 index 0000000..4300657 --- /dev/null +++ b/packages/nf-owner.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/owner", + "type": "component", + "description": "Store the other entity that own this one", + "tags": ["base", "health"] +} diff --git a/packages/nf-position-2d.component/index.ts b/packages/nf-position-2d.component/index.ts index 02b0d85..2e89f1b 100644 --- a/packages/nf-position-2d.component/index.ts +++ b/packages/nf-position-2d.component/index.ts @@ -23,7 +23,6 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { description: "Horizontal position in pixel", example: 4.2, default: 0, - optional: true, }, { type: "number", @@ -31,7 +30,6 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { description: "Vertical position in pixel", example: 67, default: 0, - optional: true, }, ], }; diff --git a/packages/nf-rigid-body-2d.component/index.ts b/packages/nf-rigid-body-2d.component/index.ts new file mode 100644 index 0000000..57064d2 --- /dev/null +++ b/packages/nf-rigid-body-2d.component/index.ts @@ -0,0 +1,26 @@ +import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class RigidBody2D { + name = this.constructor.name; + + constructor( + public gravityStrength: number, + ) { } +} + +// * Required to generate code +export default RigidBody2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "RigidBody2D", + description: "Rigid body of movable object, afected by gravity, blocked by static body", + params: [ + { + type: "number", + name: "gravityStrength", + description: "Strength of the gravity (acting as down acceleration) in px/s²", + default: 0, + }, + ], +}; diff --git a/packages/nf-rigid-body-2d.component/nanoforge.manifest.json b/packages/nf-rigid-body-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..8cd7d33 --- /dev/null +++ b/packages/nf-rigid-body-2d.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/rigid-body-2d", + "type": "component", + "description": "Rigid body of movable object, afected by gravity, blocked by static body", + "tags": ["base", "mouvement"] +} diff --git a/packages/nf-shoot-control-2d.system/index.ts b/packages/nf-shoot-control-2d.system/index.ts new file mode 100644 index 0000000..ccbfa5e --- /dev/null +++ b/packages/nf-shoot-control-2d.system/index.ts @@ -0,0 +1,76 @@ +import { type Context } from "@nanoforge-dev/common"; +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-lib"; +import { type InputLibrary } from "@nanoforge-dev/input"; +import { Graphics2DLibrary, Vector2d } from "@nanoforge-dev/graphics-2d"; + +import { ShootController2D } from "../components/nf-shoot-controller-2d.component"; +import { Position2D } from "../components/nf-position-2d.component"; +import { Velocity2D } from "../components/nf-velocity-2d.component"; +import { HitboxCircle2D } from "../components/nf-hitbox-circle-2d.component"; +import { DrawableCircle2D } from "../components/nf-drawable-circle-2d.component"; +import { DamageDealer } from "../components/nf-damage-dealer.component"; +import { HitboxRectangle2D } from "../components/nf-hitbox-rectangle-2d.component"; +import { DestroyOnHit2D } from "../components/nf-destroy-on-hit-2d.component"; +import { Owner } from "../components/nf-owner.component"; + +function createBullet(registry: Registry, id: number, p: Vector2d, m: Vector2d, s: ShootController2D) { + const b = registry.spawnEntity() + + if (!m?.x || !m?.y) return + const dx = m.x - p.x; + const dy = m.y - p.y; + + const length = Math.sqrt(dx * dx + dy * dy); + + const dirX = dx / length; + const dirY = dy / length; + + registry.addComponent(b, new Position2D(p.x, p.y)); + registry.addComponent(b, new Velocity2D(dirX * s.bulletSpeed, dirY * s.bulletSpeed)); + registry.addComponent(b, new HitboxCircle2D(s.bulletSize)) + registry.addComponent(b, new DrawableCircle2D(s.bulletSize, true, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, "grey")) + registry.addComponent(b, new DamageDealer(s.bulletDamage)) + registry.addComponent(b, new DestroyOnHit2D(false, true)) + const owner = new Owner(); + owner.owner = registry.entityFromIndex(id) + registry.addComponent(b, owner) +} + +export function shootControl2D(registry: Registry, ctx: Context) { + const entities = registry.getIndexedZipper([ShootController2D, Position2D, HitboxRectangle2D]); + const input = ctx.libs.getInput(); + const graphic2d = ctx.libs.getGraphics(); + + entities.forEach(({ id, ShootController2D, Position2D, HitboxRectangle2D }) => { + ShootController2D.reloadTimer -= ctx.app.delta / 1000; + + const keyPressed = input.isKeyPressed(ShootController2D.key); + + if (keyPressed && !ShootController2D.keyPressedLastFrame && ShootController2D.reloadTimer <= 0) { + createBullet(registry, id, { + x: Position2D.x + HitboxRectangle2D.width / 2, + y: Position2D.y + HitboxRectangle2D.height / 2 + }, graphic2d.stage.getPointerPosition(), ShootController2D) + ShootController2D.reloadTimer = ShootController2D.reloadTime; + } + }); +} +// * Required to generate code +export default shootControl2D.name; + +// * Required for the editor to display the system and generate code +export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = { + name: "shootControl2D", + description: "Control entities that can shoot bullets at mouse position", + dependencies: [ + "ShootController2D", + "Position2D", + "Velocity2D", + "HitboxRectangle2D", + "HitboxCircle2D", + "DrawableCircle2D", + "DamageDealer", + "DestroyOnHit2D", + "Owner", + ], +}; diff --git a/packages/nf-shoot-control-2d.system/nanoforge.manifest.json b/packages/nf-shoot-control-2d.system/nanoforge.manifest.json new file mode 100644 index 0000000..fe716d6 --- /dev/null +++ b/packages/nf-shoot-control-2d.system/nanoforge.manifest.json @@ -0,0 +1,20 @@ +{ + "name": "nf/shoot-control-2d", + "type": "system", + "description": "Control entities that can shoot bullets at mouse position", + "tags": ["base", "mouvement"], + "dependencies": [ + "nf/shoot-controller-2d", + "nf/position-2d", + "nf/velocity-2d", + "nf/hitbox-rectangle-2d", + "nf/hitbox-circle-2d", + "nf/drawable-circle-2d", + "nf/damage-dealer-2d", + "nf/destroy-on-hit-2d", + "nf/owner" + ], + "libDependencies": { + "@nanoforge-dev/input": "^1.0.2" + } +} diff --git a/packages/nf-shoot-controller-2d.component/index.ts b/packages/nf-shoot-controller-2d.component/index.ts new file mode 100644 index 0000000..946266b --- /dev/null +++ b/packages/nf-shoot-controller-2d.component/index.ts @@ -0,0 +1,206 @@ +import type { EditorComponentManifest, Entity } from "@nanoforge-dev/ecs-lib"; +import { type InputEnum } from "@nanoforge-dev/input"; + +export class ShootController2D { + name = this.constructor.name; + public reloadTimer: number = 0; + + constructor( + public bulletDamage: number, + public key: InputEnum, + public reloadTime: number, + public bulletSpeed: number, + public bulletSize: number, + ) { + } +} + +// * Required to generate code +export default ShootController2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "ShootController2D", + description: "Allow shoot at mouse position", + params: [ + { + type: "number", + name: "bulletDamage", + description: "Damage dealt by the bullet", + default: 10, + }, + { + name: "key", + type: "string", + enum: [ + "Escape", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "Backspace", + "Tab", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Enter", + "ControlLeft", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "Backquote", + "ShiftLeft", + "Backslash", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "ShiftRight", + "NumpadMultiply", + "AltLeft", + "Space", + "CapsLock", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "Pause", + "ScrollLock", + "Numpad7", + "Numpad8", + "Numpad9", + "NumpadSubtract", + "Numpad4", + "Numpad5", + "Numpad6", + "NumpadAdd", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad0", + "NumpadDecimal", + "IntlBackslash", + "F11", + "F12", + "NumpadEqual", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "KanaMode", + "Lang2", + "Lang1", + "IntlRo", + "F24", + "Convert", + "NonConvert", + "IntlYen", + "NumpadComma", + "MediaTrackPrevious", + "MediaTrackNext", + "NumpadEnter", + "ControlRight", + "AudioVolumeMute", + "LaunchApp2", + "MediaPlayPause", + "MediaStop", + "BrowserHome", + "NumpadDivide", + "PrintScreen", + "AltRight", + "NumLock", + "Home", + "ArrowUp", + "PageUp", + "ArrowLeft", + "ArrowRight", + "End", + "ArrowDown", + "PageDown", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "Power", + "BrowserSearch", + "BrowserFavorites", + "BrowserRefresh", + "BrowserStop", + "BrowserForward", + "BrowserBack", + "LaunchApp1", + "LaunchMail", + "MouseLeft", + "MouseMiddle", + "MouseRight", + "BackButton", + "Forward" + ], + description: "Key to press shoot", + default: "MouseLeft", + }, + { + type: "number", + name: "reloadTime", + description: "Time between 2 bullets in s", + default: 0.3, + }, + { + type: "number", + name: "bulletSpeed", + description: "Speed of the bullet in px/s", + default: 600, + }, + { + type: "number", + name: "bulletSize", + description: "Radius of the bullet in px", + default: 40, + }, + ], +}; diff --git a/packages/nf-shoot-controller-2d.component/nanoforge.manifest.json b/packages/nf-shoot-controller-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..92238d5 --- /dev/null +++ b/packages/nf-shoot-controller-2d.component/nanoforge.manifest.json @@ -0,0 +1,9 @@ +{ + "name": "nf/shoot-controller-2d", + "type": "component", + "description": "Allow shoot at mouse position", + "tags": ["base", "mouvement"], + "libDependencies": { + "@nanoforge-dev/input": "^1.0.2" + } +} diff --git a/packages/nf-static-body-2d.component/index.ts b/packages/nf-static-body-2d.component/index.ts new file mode 100644 index 0000000..f112588 --- /dev/null +++ b/packages/nf-static-body-2d.component/index.ts @@ -0,0 +1,32 @@ +import { type EditorComponentManifest } from "@nanoforge-dev/ecs-lib"; + +export class StaticBody2D { + name = this.constructor.name; + + constructor( + public oneWay?: string, + ) { } +} + +// * Required to generate code +export default StaticBody2D.name; + +// * Required for the editor to display the component and generate code +export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { + name: "StaticBody2D", + description: "Static body of immovable object (walls, grounds...)", + params: [ + { + name: "oneWay", + type: "string", + enum: [ + "up", + "down", + "left", + "right" + ], + description: "Only traversable in one direction (platform, doors...)", + optional: true + }, + ], +}; diff --git a/packages/nf-static-body-2d.component/nanoforge.manifest.json b/packages/nf-static-body-2d.component/nanoforge.manifest.json new file mode 100644 index 0000000..f833a75 --- /dev/null +++ b/packages/nf-static-body-2d.component/nanoforge.manifest.json @@ -0,0 +1,6 @@ +{ + "name": "nf/static-body-2d", + "type": "component", + "description": "Static body of immovable object (walls, grounds...)", + "tags": ["base", "mouvement"] +} diff --git a/packages/nf-velocity-2d.component/index.ts b/packages/nf-velocity-2d.component/index.ts index 54c54c4..a567f24 100644 --- a/packages/nf-velocity-2d.component/index.ts +++ b/packages/nf-velocity-2d.component/index.ts @@ -6,7 +6,7 @@ export class Velocity2D { constructor( public x: number, public y: number, - ) {} + ) { } } // * Required to generate code @@ -23,7 +23,6 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { description: "Horizontal velocity in px/s", example: 4.2, default: 0, - optional: true, }, { type: "number", @@ -31,7 +30,6 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = { description: "Vertical velocity in px/s", example: 67, default: 0, - optional: true, }, ], }; From 19c225baef489e50af42f38838724a4f8f7ae856 Mon Sep 17 00:00:00 2001 From: Tchips46 Date: Wed, 8 Jul 2026 17:04:25 +0200 Subject: [PATCH 9/9] feat: platformer shooter --- packages/nf-collision-2d.system/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nf-collision-2d.system/index.ts b/packages/nf-collision-2d.system/index.ts index dd61f60..2404130 100644 --- a/packages/nf-collision-2d.system/index.ts +++ b/packages/nf-collision-2d.system/index.ts @@ -44,7 +44,7 @@ export function hitboxCollinding2D(registry: Registry) { rectangles[i].HitboxRectangle2D.entitiesColliding.push(rectangles[k].id) rectangles[k].HitboxRectangle2D.entitiesColliding.push(rectangles[i].id) } - }Position2D + } } for (let i = 0; i < circles.length; i++) { for (let k = i + 1; k < circles.length; k++) {