flutter3d_game_physics

Gameplay parts for flutter3d games that need the native physics core, one library each. A game takes the parts it wants by importing their libraries; package:flutter3d_game_physics/flutter3d_game_physics.dart exports all of them.

They were in flutter3d_game_kit until 1.0.0-rc.1, and are kept apart so a game that uses none of them builds no C: flutter3d_physics_native's build hook compiles the core and fetches wgpu-native for every application that depends on it.

Library Was What it is
ragdoll.dart flutter3d_addon_ragdoll Actors that fall as bodies when they die, in place of a death clip
wrecks.dart flutter3d_addon_wrecks What a hit leaves burning
party.dart flutter3d_addon_party Local and network party sessions for a flutter3d game on the relay of flutter3d_net
elements.dart ElementSounds of flutter3d_addon_soundtrack, Daylight.lightWater of flutter3d_addon_world The fires and water of flutter3d_effects heard, and the water lit by the hour

ragdoll.dart

Until 1.0.0-rc.1, flutter3d_addon_ragdoll.

Actors that fall as bodies when they die, in place of a death clip. RagdollCorpses is the ActorCorpses an ActorVisuals asks the moment it sees a modelled actor dead: the actor's skeleton goes limp into a ragdoll in the physics core (flutter3d_physics_native), which falls against the level as the collision world has it, and every frame the bodies are written back into the joints.

Setting Default What it is
pushedFrom none Where the killing blow came from, asked when an actor dies
push 120 N s How hard the blow throws the chest away from there
chest 'Torso' The ragdoll body the push lands on
mass 60 kg What a whole body weighs
gravity the Earth's The fallen's own world's pull

A rig the ragdoll profile does not name is left to its death clip: begin answers false.

Display, not simulation. The bodies step on the frame, in fixed steps of a sixtieth and at most four a frame, and are not in a save or a replay. A game's step never asks where a body lies.

A library, not a plugin: it registers nothing with the engine, so the pubspec has no plugin marker.

Example

import 'package:flutter3d_game_physics/ragdoll.dart';
import 'package:flutter3d_game/flutter3d_game.dart';

final visuals = ActorVisuals(
  scene,
  appearance: appearance,
  device: device,
  corpses: RagdollCorpses(
    level.collision,
    pushedFrom: () => player.body.position,
  ),
);

Where it came from

The dungeon demo's dead, which fall this way when the run has the physics core. On the reference physics the dungeon hands no corpses, and its actors play their death clips.

wrecks.dart

Until 1.0.0-rc.1, flutter3d_addon_wrecks.

What a hit leaves burning: fires of the physics core's own heat in a game's Elements (flutter3d_effects), lit by a blast's fireball, burning as long as their fuel lasts and lighting what stands close enough.

Member What it places
oil(at) Sixty kilograms of crude spread over the water, a slick three metres by one and a half, afloat and alight; the current carries it and its fire off, and it is drawn as a black film as glossy as water
timbers(at) A 160 kg heap of wood, fixed where it fell and burning
step(distance) Lets go of every wreck more than behind metres back along along
clear() Puts every fire out, for a new run
bodies The wrecks still held

along is the way the player travels, −z unless a game says otherwise, and behind is forty metres unless it says otherwise. The fireball is BurningWrecks.fireball: a hundred kilowatts a square metre from gas at 1300 K, for one second.

A library, not a plugin: the elements step and draw the fires, and this registers nothing with the engine, so the pubspec has no plugin marker.

Example

import 'package:flutter3d_game_physics/wrecks.dart';

final wrecks = BurningWrecks(elements);

enum Target { tanker, depot }

void onHit(Target target, Vector3 at) => switch (target) {
  Target.tanker => wrecks.oil(at),
  Target.depot => wrecks.timbers(at.clone()..y = 0.5),
};

// Every frame, with how far the player has come.
wrecks.step(distance);

Where it came from

The River demo, whose tankers spill burning oil on the water and whose depots burn on the bank.

party.dart

Until 1.0.0-rc.1, flutter3d_addon_party.

Local and network party sessions for a flutter3d game on the relay of flutter3d_net: a party seated by one code or among strangers, a room for two, and one side's run kept as a .f3drun. Every ask carries the game's simulation version, so a build on other rules is turned away by the relay with a reason instead of being seated in a game that parts at its first contact.

Piece What it is
PartySession<G> A party of up to a full table, made or joined by code, or found among strangers who asked for the same game. The relay gives the slot; stage makes the game for it.
RoomSession A room for two: the maker plays seat 0, the one who joins seat 1. The socket for a rollback session, and why the relay closed it.
SideRecording One machine's own side of a session as a Demo: its start, its input tape, the digests of what it settled.
partyCode, physicsTerms, relayVersionOf A code with no 0/O or 1/I; the physics backend every machine must share; a SimulationVersion as the one number a relay compares.

It is a library, not a plugin: a screen opens a session when a player asks for one, and nothing is installed into the loop. What a session steps, the game's own rollback over the seat's wire, stays the game's.

Example

import 'dart:math' as math;

import 'package:flutter3d_game_physics/party.dart';

// `MyGame` is the game's own, made for the seat the relay gives.

final party = await PartySession.open<MyGame>(
  relayBase: Uri.parse('wss://relay.example/'),
  simulation: mySimulationVersion,
  terms: physicsTerms,
  game: 'my_game/harbour',
  find: true,
  size: 4,
  seats: 8,
  newCode: () => partyCode(math.Random()),
  stage: (PartySeat seat) => MyGame(wire: seat.wire, players: seat.size),
);
print('send a friend ${party.code}; you are player ${party.slot}');

A room for two:

final room = await RoomSession.host(
  relayBase: relay,
  code: partyCode(math.Random()),
  simulation: mySimulationVersion,
  terms: physicsTerms,
);
final recording = SideRecording(
  start: sim.save(),
  level: 'assets/levels/harbour.json',
  levelHash: level.digestHex,
);
// Each step: recording.record(input), then advance the rollback session
// with `onSettled: recording.settled`. At the end, `recording.toDemo()`.

Where it came from

The racing demo's party and two-car sessions. What was a race's — the grid, staging the cars, the number of laps — stayed in the demo as a thin adapter over these classes. The party used to ask the relay with no simulation version, so it met only other builds that named none, which is every build of every game; PartySession.open requires one.

Writing a run to a file is the application's: this package reaches no dart:io, and runs on the web.

elements.dart

Until 1.0.0-rc.1, part of flutter3d_game_kit's soundtrack.dart and world.dart.

The elements of flutter3d_effects, met by the rest of a game: the fires, falls and splashes PhysicsHearing reports, played as held voices, and the water lit by the hour of the day.

Type What it is
ElementCues Which recordings the elements play; near is the effects package's own
ElementSounds PhysicsHearing's fires, falls and splashes played, each fire and fall a held voice
DaylightOnWater lightWater on flutter3d_game_kit's Daylight: the sun's light and the sky on an Elements water

Example

import 'package:flutter3d_game_kit/world.dart';
import 'package:flutter3d_game_physics/elements.dart';

final elementSounds = ElementSounds();
final day = Daylight();

loop.addSystem('world.day', LoopPhase.animate, (frame) {
  day
    ..update(frame.dt)
    ..light(sun: sun, moon: moon)
    ..lightWater(elements);
  elementSounds.play(audio.scene, elements.hearing);
});

Libraries

elements
The elements of flutter3d_effects, met by the rest of a game: the fires and the water flutter3d_effects' PhysicsHearing reports, and the bodies a game wades through water (Wader), played as ElementSounds from ElementCues, and the water lit by the hour of the day (DaylightOnWater.lightWater).
flutter3d_game_physics
Every part of flutter3d_game_physics, in one import.
party
Local and network party sessions for any simulation on flutter3d's relay: a party of up to a full table found by a code or among strangers (PartySession), a two-machine room (RoomSession), and one side's run kept as a .f3drun (SideRecording).
ragdoll
Actors that fall as bodies when they die: RagdollCorpses, handed to ActorVisuals as its corpses, takes a dead actor's skeleton over and lets it fall in the physics core against the level. Under it, SkeletonRagdoll makes any scene skeleton a ragdoll by a RagdollProfile of joint names, and RagdollGetUp fades one back into the animation.
wrecks
Wrecks that burn and sink: BurningWrecks places a slick of oil or a heap of timbers in a game's elements, lights it with a blast's fireball, lets it go once the player is far enough past, and publishes each as a BurningWreck; WreckLooks draws the slicks from what was published. FuelCell says which crash breaks a car's tank, by the test it was built to pass.