Physics stage 1b: six new nodes act on dynamic bodies in play (Apply force over the frame, independent of the frame rate, Apply impulse, Set velocity, Set angular velocity, Get velocity, Set gravity for the rest of the run), a node on an object without a dynamic body and moving a dynamic body directly each log a hint once per object, and Move with collision now pushes dynamic bodies with a mass-dependent push while the mover stays flush; Move keeps its own move-and-slide instead of Rapier's character controller, which measurably snags on seams between colliders (#147)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
78899b1ace
commit
0ff3c8b742
10 files changed
+783
-43
No files matched your search
@@ -0,0 +1,112 @@
|
||||
import type { NodeDef } from '../../NodeRegistry';
|
||||
import { asEntity, asNumber } from '../../values';
|
||||
import { exec, num, obj, withDefault } from '../shared';
|
||||
|
||||
const PLAY_ONLY =
|
||||
'Acts on a dynamic rigidbody while the game is played; the editor run does not simulate, and an ' +
|
||||
'object without one is left alone (the console says so once).';
|
||||
|
||||
export const ApplyForce: NodeDef = {
|
||||
type: 'ApplyForce',
|
||||
label: 'Apply force',
|
||||
category: 'action',
|
||||
description:
|
||||
'Pushes an object with a force (world units × kg per second²) for the length of this frame, so ' +
|
||||
'from On update it pushes steadily whatever the frame rate. A heavier body speeds up less. ' +
|
||||
PLAY_ONLY,
|
||||
inputs: [exec(), obj('object'), num('x'), num('y')],
|
||||
outputs: [exec()],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
if (target) ctx.physics?.applyImpulse(target, asNumber(inputs.x) * ctx.dt, asNumber(inputs.y) * ctx.dt);
|
||||
return { next: 'exec' };
|
||||
},
|
||||
};
|
||||
|
||||
export const ApplyImpulse: NodeDef = {
|
||||
type: 'ApplyImpulse',
|
||||
label: 'Apply impulse',
|
||||
category: 'action',
|
||||
description:
|
||||
'Kicks an object at once (world units × kg per second): its velocity changes by impulse ÷ mass – ' +
|
||||
'a jump, a hit, an explosion. ' +
|
||||
PLAY_ONLY,
|
||||
inputs: [exec(), obj('object'), num('x'), num('y')],
|
||||
outputs: [exec()],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
if (target) ctx.physics?.applyImpulse(target, asNumber(inputs.x), asNumber(inputs.y));
|
||||
return { next: 'exec' };
|
||||
},
|
||||
};
|
||||
|
||||
export const SetVelocity: NodeDef = {
|
||||
type: 'SetVelocity',
|
||||
label: 'Set velocity',
|
||||
category: 'action',
|
||||
description:
|
||||
'Sets how fast an object moves, in world units per second, whatever it weighs. To change one ' +
|
||||
'direction only, feed the other from Get velocity. ' +
|
||||
PLAY_ONLY,
|
||||
inputs: [exec(), obj('object'), num('x'), num('y')],
|
||||
outputs: [exec()],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
if (target) ctx.physics?.setVelocity(target, asNumber(inputs.x), asNumber(inputs.y));
|
||||
return { next: 'exec' };
|
||||
},
|
||||
};
|
||||
|
||||
export const SetAngularVelocity: NodeDef = {
|
||||
type: 'SetAngularVelocity',
|
||||
label: 'Set angular velocity',
|
||||
category: 'action',
|
||||
description:
|
||||
'Sets how fast an object turns, in degrees per second, counted like its rotation. A body with ' +
|
||||
'Fixed rotation does not turn. ' +
|
||||
PLAY_ONLY,
|
||||
inputs: [exec(), obj('object'), num('speed', 'degrees/s')],
|
||||
outputs: [exec()],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
if (target) ctx.physics?.setAngularVelocity(target, asNumber(inputs.speed));
|
||||
return { next: 'exec' };
|
||||
},
|
||||
};
|
||||
|
||||
export const GetVelocity: NodeDef = {
|
||||
type: 'GetVelocity',
|
||||
label: 'Get velocity',
|
||||
category: 'data',
|
||||
description:
|
||||
'How fast an object moves (world units per second) and turns (degrees per second) while the game ' +
|
||||
'is played; 0 for an object without a dynamic rigidbody, and in the editor run.',
|
||||
inputs: [obj('object')],
|
||||
outputs: [num('x'), num('y'), num('angular', 'degrees/s')],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
const target = asEntity(inputs.object);
|
||||
const v = (target && ctx.physics?.velocityOf(target)) || { x: 0, y: 0, angular: 0 };
|
||||
return { outputs: { x: v.x, y: v.y, angular: v.angular } };
|
||||
},
|
||||
};
|
||||
|
||||
export const SetGravity: NodeDef = {
|
||||
type: 'SetGravity',
|
||||
label: 'Set gravity',
|
||||
category: 'action',
|
||||
description:
|
||||
"Changes the scene's gravity (world units per second²; y points down) for the rest of the run – " +
|
||||
'the next scene starts with its own. Only dynamic rigidbodies feel it, times their Gravity scale.',
|
||||
inputs: [exec(), withDefault(num('x'), 0), withDefault(num('y'), 980)],
|
||||
outputs: [exec()],
|
||||
params: [],
|
||||
run: (ctx, inputs) => {
|
||||
ctx.physics?.setGravity(asNumber(inputs.x), asNumber(inputs.y));
|
||||
return { next: 'exec' };
|
||||
},
|
||||
};
|
||||
@@ -5,6 +5,14 @@ import { Emit } from './action/Emit';
|
||||
import { LoadScene } from './action/LoadScene';
|
||||
import { Log } from './action/Log';
|
||||
import { Move } from './action/Move';
|
||||
import {
|
||||
ApplyForce,
|
||||
ApplyImpulse,
|
||||
GetVelocity,
|
||||
SetAngularVelocity,
|
||||
SetGravity,
|
||||
SetVelocity,
|
||||
} from './action/physicsNodes';
|
||||
import { PlaySound } from './action/PlaySound';
|
||||
import { RestartGame } from './action/RestartGame';
|
||||
import { SetPosition } from './action/SetPosition';
|
||||
@@ -204,6 +212,12 @@ export const BUILT_IN_NODES: readonly NodeDef[] = [
|
||||
IsTouching,
|
||||
Move,
|
||||
SetPosition,
|
||||
GetVelocity,
|
||||
ApplyForce,
|
||||
ApplyImpulse,
|
||||
SetVelocity,
|
||||
SetAngularVelocity,
|
||||
SetGravity,
|
||||
Spawn,
|
||||
Destroy,
|
||||
Emit,
|
||||
|
||||
Reference in new issue
Block a user