Conversation
flutter3d_core 0.8.3: VertexLayout.color and MeshBuilder.addVertex say what the shader always did, that a vertex colour is linear while a material's baseColor is sRGB. linearFromSrgb converts a colour picked on screen, and the sRGB curve the format readers kept to themselves is exported with it. MeshData.withColor paints a whole mesh, so shapes in several colours merge into one mesh drawn with one white material. flutter3d 0.8.3: ModelAsset.instantiateFitted scales a model uniformly to a length along one axis of its bounds and centres it on its parent, or stands it there with onGround. Free models come in any unit; Meteor Yard did this by hand and now calls it. flame_flutter3d 0.8.3: Object3dComponent takes size and anchor, which a hitbox and the point written into the scene both depend on.
The sixth demo game and the second on flame_flutter3d, after River Raid: a jet up a river that never ends, laid out a stretch at a time by a seeded generator. Flame owns the game, with its own hitboxes and collision callbacks deciding every hit and its canvas drawing the panel; each component is an Object3dComponent and the scene is only told where things are. Five levels, each a few bridges long with a task, whose last bridge is shielded until the task is done, and an open river after them. Tankers sink, helicopters spin into the water, a depot takes its neighbours with it, a bridge breaks in two, and gunner helicopters fire back. The sound is generated square waves and shift-register noise. Free models for the craft, credited in assets/models/LICENSES.md; the valley, the bridges and the effects are built in code. A stick and a fire button on Android and iOS. 43 tests. The site gets its demo page, its place in the sidebar and on the front page, and the test counts move to 10615.
flutter_soloud 5 ships one loader, init_soloud.js, where 4.x had the plugin script and init_module.dart.js. The shooter, the platformer and the racer still asked for the 4.x pair, and the second of them is a 404 against 5.x, so their web builds opened no speakers.
Object3dComponent: flowing Flame to the scene it writes again after its children, so an effect reaches the scene in the frame it moves; it places a nested component where Flame draws it, hides a component the moment it is let go, lifts it off the plane by an elevation, scales it, follows Flame's visibility, and offers a visual node under the bridged one that the bridge never turns. Flutter3dFlameWidget hands a game its renderer through onRendererReady. The engine gets Renderer.releaseMeshAfterFrame, which lets go of a mesh once no frame in flight can draw it, and ModelWardrobe, which loads models by key and puts them on every node waiting for them. River Sortie drops its second plane, its pivot nodes, its model maps and its own one-frame release queue; Meteor Yard its three craft maps. Test counts move to 10623.
River Sortie is the proof for the next part of the bridge. A chase camera follows the jet in perspective through the shared CameraRig, so a crash shakes it. A projector puts "+30" in Flame's viewport over a target that went down. The river's stretches come and go through ChunkStreamer, the shots are slots of one instanced batch, and fire and sparks go through a particle system on Flame's clock instead of a scene node per shard. The phone's stick and fire button go through the input bridge. In the engine, InstancedMeshNode hands out slots by handle and fills a released slot with the last one, so owners of instances that leave in any order keep finding their own.
A mesh particle could only add light, so River Sortie drew its dark smoke as a scene node per shard. MeshParticleContributor now takes a blend, and its darkening blend takes the particle's colour out of what is behind it. Multiplication commutes as addition does, so the pool is still one unsorted draw, and no shader changed: the fragment stage already handed back colour times alpha. Particles3dComponent passes the blend through. River Sortie's fire, sparks and spray share one pool and its smoke has another; BurstComponent is gone. flutter3d_particles goes to 0.8.1.
A near cascade reaches back to the furthest caster towards the sun, and its bias, kept in metres, shrank in stored depth by as much. The shadow map stores depth as a half float, and in River Sortie's valley the near cascade's bias came to a seventh of the step between two stored depths: a lit floor shadowed itself in diagonal bands on Metal, and not on the software backend, which keeps full floats in any format. The bias of each cascade no longer goes below the step the map stores depth with, unless the settings ask for less than that.
Every source had a low-pass open at 16 kHz. SoLoud runs a voice's filters at the voice's own rate, and 16 kHz is past the Nyquist frequency of a 22.05 kHz file, where the biquad is unstable and feeds itself until it overflows. River Sortie's engine came out as a scream and every shot, blast and refuel as silence, though each voice played to its end. The backend reads each file's sample rate from its WAV header and keeps each voice's cutoff below its Nyquist frequency for the speed it plays at. flutter3d_audio goes to 0.8.1.
Smoke puffs are soft balls that take a third of the light at their thickest and thin as they rise, so a burning tanker's column builds to a grey-brown rather than black. The engine is a low hum under everything instead of a loud square wave, and the shot, the blasts, the crash and the refuel tones were made again to cut through it.
Flame does not draw the children of a component it hides, and a child's scene node is not under its parent's, so a frog went on being drawn on a log that blinked. A bridged component now shows its node only while every ancestor that can be hidden is shown, and scales it by Flame's absolute scale rather than its own, which its place already carried. ActorComponent turns with its actor's yaw, and it and RigidBodyComponent take a size, an anchor and an elevation like Object3dComponent. The host widget's two tests, skipped as hanging, run in seconds and are back on.
HasFlutter3d gives a FlameGame its scene, device, camera, renderer and projector, with a clear colour and render settings the frame is drawn with. The game builds its world in onOpen3d and uses the renderer in onRenderer3d, each run once after the game has loaded, whatever order the widget or a test opens things in; handed the renderer at once, River Sortie met it with nothing built yet. Flutter3dFlameWidget takes such a game alone. River Sortie's main.dart no longer builds the scene, the lens, the haze, the projector or the chase camera; the game does.
PhysicsStepComponent and ActorSystemComponent handed Flame's frame time straight to the solver: a body fell a different distance at 30 and at 144 frames a second, and a stalled frame let it step through a wall. Both now cut the frame's time into steps of one size, at most five after a stall, and dispatch contacts after each step. A rigid body or an actor handed its stepper is drawn between its last two steps instead of in jumps.
Under a perspective 3D camera, Flame's taps and debug hitboxes work on the plane the game plays on, which is not where a craft is drawn. A bridged component with Tap3dCallbacks now hears a tap that falls on the screen rectangle its node covers, and a Taps3dComponent hands each tap to the nearest such component. HasFlutter3d.debugHitboxes3d draws every bridged hitbox in the scene, round its craft, red while it collides. For that the renderer takes lines of the application's own through Renderer.debugLines and draws them with its debug overlay. River Sortie shows its hitboxes with RIVER_HITBOXES.
flame_flutter3d_audio, a package of its own so the bridge carries no native audio library: AudioSceneComponent is the game's audio scene, silent until the player's first input opens the speakers and heard from the game's 3D camera; SoundEmitterComponent is a loop held open by the state it stands for, sounding from its bridged parent and moving onto the speakers when they open. River Sortie's hand-kept scene, ears and three loops became those, and its main.dart no longer opens or closes a device. The game says what its loops want before its children update, so the mix hears it the same frame.
MeshNode.tint multiplies its material's colour for that node's draw alone, and its alpha fades it through the transparent pass. No shader changed: the tint goes into the base colour each draw already sends, so every backend has it, and an untinted node draws exactly as before. On the bridge, Object3dComponent is an OpacityProvider and has a tint, so Flame's OpacityEffect fades a craft in 3D. River Sortie's wrecks go down charred and a fallen bridge fades rather than blinking out.
A node's setters mark it changed whatever they are given, and the engine redraws its shadow cascades and repacks its bounds when anything changed. Every bridged component rewrote its transform every frame, so one still tanker had every shadow redrawn every frame. Object3dComponent and InstancedObject3dComponent now write only when Flame's transform moved, and without allocating to do it. BridgePriority names the order a bridged frame runs in and is the default of the bridge's components. ColliderRegistry is the collider-to-component map the arcade kept by hand, forgetting a component when it leaves the game. Flutter3dFlameWidget draws with a camera or clear colour handed in by a rebuild, and says in a debug build when an opaque game background hides the 3D layer.
The README described the bridge as it was a week ago. It now covers a game that owns its world, what crosses between the layers, the camera, taps, hitboxes, fixed steps, streaming and particles, and points at the sound package. Two showcase pages show the newest of it: a HasFlutter3d game whose crates hear a tap on what the perspective camera shows, and eighty Flame sparks drawn as one instanced batch beside fire and darkening smoke. The showcase moves to 0.8.3+1 with them.
An analysis of six Atari games against the Flame bridge, and the state after the work it led to: what is in the bridge now, what the engine gained on the way, and what is left.
RigidBodyComponent and ActorComponent wrote their body's place onto the node every frame, so a sleeping body redrew every shadow the way a still prop did. They now leave a node alone where it already is. FlameInputBridge gains stepEnd, which closes the input step once the frame has read it, pointer, an aim and a tap as an action, and swipes as presses. River Sortie no longer calls endStep by hand.
HasFixedStep spends each frame in steps of one size and calls fixedUpdate on the game and on every FixedStepUpdate component in each, before Flame's frame update. River Sortie flew a different distance at 30 and at 120 frames a second; its run, targets, bridges and shots now step, and a second of flight covers the same river at any frame rate. The input step stays open through a frame with no step in it, so a press is read before it is closed.
CollisionBridge relays to any component with Flame's collision callbacks, so a bot's body can tell its ActorComponent what it touched; before, only a rigid body's could. InstancedObject3dComponent has a tint and an opacity, written into its slot's colour, for a hit flash on one of many.
Object3dComponent takes the meshes it owns and gives them back when it is removed, after the frames in flight, so a game no longer keeps its own list of what to release and when. River Sortie's bridges own their span and shield.
ProjectedViewfinder maps a screen point to the point of the game's plane under it through the 3D camera, and back. Under a perspective camera the viewfinder's affine transform put a tap metres from the craft it was on, so a world component's TapCallbacks, Flame's hit test and a game's own globalToLocal all missed. The sky meets no plane and hits nothing.
ModelAnimationComponent advances a model's AnimationPlayer from Flame's update, so a paused game's characters stop, and changes clip by name with a crossfade. MeshFlipbookComponent swaps a node's mesh through a few frames, for animation that is a handful of shapes.
…through CameraSyncController takes the viewport's height and maps Flame's zoom to pixels per world unit, and can keep Flame's viewfinder angle and the camera's roll the same. Flutter3dFlameWidget hands Flame's overlays, its initial overlays and its focus node to the GameWidget.
A tanker going up, a bridge falling, sparks off a shield and a helicopter's burst now play at their place on the river: quieter far up it and from the side of the screen they are on, heard from the chasing camera. The jet's own sounds stay flat, as on the cartridge.
WrapSpace wraps its children round a rectangle, draws a ghost of each one near an edge on the other side, and gives it ghost hitboxes one world across, so a rock half over the edge is seen on both sides and a shot coming in on the left hits it on the right, through Flame's own collision detection. buildPolyline joins a closed line's ends with an elbow.
OpenPath measures a path in metres along it, with a heading that turns through corners, and ribbon lays a strip of road on it between two distances. BridgeSpace says where a Flame point goes in the scene; BridgePlane is the flat one and CurvilinearSpace lays Flame's world along a path, so a racing game keeps its cars side by side in Flame while the road winds under them.
The engine gains Atmosphere, the sky, fog, sun and ambient light blended as one, with AtmosphereCycle for a day of them and LightGroup to dim lamps together; Material.fogged for a horizon that stands beyond the fog; CellGrid, cells worn away and drawn as merged blocks; and LineStripNode, a line that grows in place and bounds itself by its points. The bridge runs a day on Flame's clock with AtmosphereComponent, wears a CellGridComponent away where a shot lands, and lays a TrailComponent behind a bridged missile.
CharacterBodyComponent carries a bare CharacterController across the bridge and steps it with a drive, in the game's fixed steps when it has them, so the platformer's runner, which already climbs ladders and ropes, can be a Flame game's player. The bridge's README and roadmap say what the bridge now covers and what is left.
pad_input reads up to four controllers, each in a player's slot: GamepadPlatform.readPad and Gamepad(index:) pick the slot. On macOS and iOS the plugin reads every GameController pad and lights its player index; in the browser slots follow the standard pads' order; on Android every device is reported and its buttons are forwarded natively with their device, so two pads pressing A are no longer one A and a key-sending d-pad is the pad's own.
River Sortie draws pixel-art sprites in code and stands them in the scene as Flame sprite billboards: reeds and bushes along each stretch's banks, placed the same every time the stretch is built, and a one-shot flash in every blast. BillboardAtlas lets billboards share one texture, material and card set per image, and SpriteBillboardComponent gains removeOnFinish.
A billboard can now carry lettering. BillboardAtlas.spriteOfText writes a string with Flame's TextPaint into a sprite, and SpriteBillboardComponent gains smooth, for linear sampling, and a sprite setter that uploads the new picture before the card switches to it. Each fuel depot in River Sortie stands a FUEL sign on its near side, a child of the depot so it goes up with it. Drawing the sprites now happens once however often it is asked: the game and a caller both asking dressed the banks twice, and every reed stood doubled.
Renderer.renderPost queued bloom's pooled targets for release but never drained a slot of the ring or moved the frame counter; only render did. A host calling renderPost alone allocated a fresh chain on every call and the pool grew without bound, which on WebGL is a leak. The slot retirement render did at its top is now _retireFrameSlot, and renderPost calls it first and advances the counter when it is done, in a finally that also closes its timeline block.
The modeller's MCP server was bound once, to the history the window opened with. Opening a file, starting a new project or recovering an autosave installed a new ModelHistory, and every tool call after that landed on the old one: it reported success, and nothing was drawn or saved. ModelSession.rebind points a session at a new history, attaching the recovery journal and forgetting the export cache, since ids start again. Every opening path goes through _installOpened, which now calls rebindMcpHistory. The session is held before the socket is bound, so an open during start-up rebinds too, and a port already taken lets a later start try again.
The Play screen's frame is drawn inside the viewport's build, and the route is opaque, so the editor's ticker beneath it is muted. Nothing asked the screen to rebuild, and the game moved only when something else did: a held W walked nowhere. The screen now keeps a ticker of its own.
_onTick called setState on the modeller's screen every tick, rebuilding the panels, the outliner and every field sixty times a second to move a camera, and kept the main viewport rendering under dialogs that render a viewport of their own. The tick now bumps a notifier. ModelerViewport takes it as frames and redraws itself; the main viewport is configured inside a builder on it, so what follows the camera or the pointer stays current. The orientation dial, the retopology overlay and the LOD panel's reading follow the camera the same way, and the status line's frame time is a listenable written once a tick rather than during layout. What used to become visible only through the per-frame rebuild now asks for one: undo and redo when a stroke closes its transaction, the playhead in animation mode, a measurement report.
The tablet shell laid its actions out unbounded, and at the width a desktop window opens at they overflowed by 172 pixels, which the modeller reports as a crash on launch. They are now capped and scroll, as the desktop bar's already are.
- The host cleared the game's redrawer3d by comparing it with a fresh tear-off of _redraw, which is never identical, so a game that outlived its widget kept the disposed host. The tear-off is now taken once. - A host adds its clock only once it is showing the game. Added from the first build, a host still opening or one that failed to start ticked a game another host was showing, and every update called onTick twice. - New overlay builders under the same names reach the screen through the current config without a new GameWidget, which updated the game again from layout on every rebuild of a parent writing its map inline. - BillboardAtlas keys materials by sampling as well as image, makes no texture for an upload that finishes after dispose, and gives textures back after the frames in flight through Renderer.releaseTextureAfterFrame, which is new. - CharacterBodyComponent and KinematicBodyComponent take removeFrom, as RigidBodyComponent does, so a despawned character or lift leaves the collision world. The documents' test counts move with the tests of this and the last commits.
What the engine already has for a top-down co-op crawler, what it lacks, and in which order to build it: the horde measured first, then several foci swept by one multi-source flow field, heroes and a shared camera, generators, the rest of the rules, and an app.
flutter3d_core, flutter3d and flame_flutter3d say what this branch fixed in them since the entries already written, and flutter3d_model_mcp goes to 0.8.1 for ModelSession.rebind.
The page was built from the showcase's catalog alone, and flame_flutter3d has no showcase pages, so none of its releases appeared. Each release now also lists the bridge's changes: the bold claim every CHANGELOG entry opens with, linked to the full record on pub.dev, folded when a release has more than eight. A release that changed only the bridge gets a section of its own.
tool/horde_cost.dart steps fifty to four hundred awake chasers through a thirty-six-room maze behind a focus that never stops crossing cells. Two hundred cost 2.1 ms a step, an eighth of a frame; four hundred cost 7.8 ms, and the growth past two hundred comes from bodies packing round the focus, not from the field, which is one sweep whatever the count.
ActorSystem.step takes a list of foci beside the single focus it always took. The flow field is swept from all of them at once and records which one each cell's route ends at, so several players still cost one sweep per class of body, and each actor attends to the nearest by walking: a monster behind a wall goes round to the player it can reach, not through the stone to the one it is closest to. Without navigation it is the nearest in a straight line. Damage to the foci is counted per focus through hurtFocus, and ChaseBrain uses it, so a claw that catches the player beside the one it swung at counts against the one it caught. Velocities are measured per focus and a save carries every one; a single focus saves under the key it always had.
flutter3d_game_crawler is a new genre package: one to four heroes, each a class with its own speed and armour, whose health drains a point a second until food puts it back. Loot is taken by walking into it; a key opens any one locked door and is spent. Monsters are stepped with every living hero as a focus, so each goes for the hero it can reach first and its blows land through that hero's armour. The heroes share one view and none of them can walk out of it. The edge is read off CrawlFraming, which is worked out from where the heroes stand and numbers the game fixes, so it gives the same answer after a load and on every machine; CrawlCamera only eases towards it through CameraRig. flutter3d_sim goes to 0.8.1 for the several foci the crawl stands on.
A snapshot fills in a world that already exists, so an actor spawned after the level loaded had nothing to be filled in when the save was loaded afresh, and a rollback past its birth left one too many. ActorSystem.spawn(entity:) builds an actor under an entity a restore put back, and EcsWorld.vacant says whether a slot is one: restore the allocation, build each recorded actor under its own entity, restore again for the numbers. Same index and order, so the restored run thinks on the same beat as the one that was saved. Takeable.restore removed the trigger of a taken thing and never put it back, so a rollback to before the taking left it drawn and untakeable. It adds the trigger back now.
A Generator makes a MonsterKind every period until its cap is alive and stops when it is broken. The Horde keeps every monster, removes the dead, and records each one's kind, generator and entity, so a save loaded into a fresh world or rolled back past a birth continues as the run did; both are checked against a run that was never interrupted. Held fire shoots along the way a hero last walked, through other heroes and into the first wall, monster or generator. Walking into a monster is attacking it at the class's melee rate, a potion reaches everything in view scaled by the class's magic, and kills score for whoever made them.
Death drains fast, cannot be shot or fought, and leaves once it has dealt its fill; only a potion reaches it. A thief harms nobody: it takes a potion, or a key, from the hero it reaches and runs, and is gone with it after four seconds unless somebody kills it, which gives the thing back. crawlerRegistry reads the format's spawns, doors and exits with food, keys, potions, treasure, generators and placed monsters, and stageCrawl turns a level into a crawl with a hero on each spawn by its slot. Loot and generators an author left unnamed are saved under a name made from where they stand, so food eaten before a save stays eaten after the load.
ActorSystemComponent steps several foci and opens the system's step at the start of each game step, so a death caused by the game's own logic is still there to read. StepClock lets anything that steps - the game itself among them - tell ActorComponent, CharacterBodyComponent and the physics bodies to keep their places before it moves them, so a body the game moves is drawn between its steps rather than where it already is. An ActorComponent goes when its actor does, and can take the actor with it. InstancedActorComponent and InstancedPoseComponent draw a horde and its shots as slots of one batch. Keys can come from HardwareKeyboard instead of the game's focus, PlayerSeats lets players join by pressing, a game moves to its next level's scene with replaceScene3d, FixtureVisualsComponent keeps a level's furniture drawn and released, and ViewCamera frames whatever a function says.
apps/flutter3d_demo_crawler plays flutter3d_game_crawler on a screen: a select screen where players join by pressing fire, three levels written by flutter3d_editor_core/tool/levels/crawler.dart, the horde drawn one batch per kind, and the party carried from level to level. It runs its own loop, input and renderer for now; the next change moves it onto Flame and the bridge. The levels are rooms on a grid with no ceilings and one wall per grid edge, so the view from above sees into them and no two walls overlap. A bot walks the first one to its exit in a test. Shadows are drawn with one cascade: on Metal the near cascades left a black disc on the floor under the camera.
CrawlerGame is a FlameGame with HasFlutter3d and HasFixedStep: the crawl's own step runs in its fixedUpdate, and the game is the StepClock the heroes and the horde are drawn between steps by. Players join through PlayerSeats over two keyboard layouts and four controller slots, read from the keyboard itself. Heroes are CharacterBodyComponents, monsters InstancedActorComponents over one batch a kind, shots InstancedPoseComponents, the level's furniture a FixtureVisualsComponent, and the view a ViewCamera turned by the crawl's framing; the next level is replaceScene3d. The app's own loop, renderer, input and visuals are gone. The frame test loads the game itself with no widget, steps it and draws a frame. Grunts are purple now: brown, they were the colour of the pillars.
HasFixedStep keeps its list of stepping components and walks the tree only when one comes, goes or changes priority. A pad is read against this frame's time through HasFixedStep.frameSeconds. An upright billboard turns about its own plane's normal and writes its rotation only when it changed. The crawl's view starts at fifteen metres and opens to twenty-six: at ten a party standing together saw one room, and monsters arrived from off screen.
0.8.3 ordered a CameraSyncComponent after Flame's CameraComponent by its priority, but a priority orders siblings only: added to the world, where a game adds its components, it ran inside the world's update, before the camera, and the 3D camera trailed camera.follow() by a frame again. UpdatesAtRoot does a component's frame work from a driver at the game's root, at the component's own priority, when it is mounted anywhere else. The camera sync has it, and so do the two others that assumed the same: the input step's end, which closed a press before a button in the viewport had read it, and AudioSceneComponent, whose listener stood where the camera had been a frame before.
The crawler gets an online mode over the flutter3d_net relay: one machine makes a room, the other joins, and each drives its own hero. A handshake trades classes so both put the party in the room's order, each level runs its own rollback session on its own channel of one wire, and a level ends only on a step both machines have agreed on. The next level starts from that agreed state on both. net_crawl_test holds two crawls against each other and against a run that never guessed, over a late and lossy loopback; online_game_test does the same through two whole CrawlerGames, handshake included.
flame_multiplayer holds what the crawler's co-op had grown on its own: a room with a handshake and separate channels, rollback play in step with an ending both machines agree on, turns where one machine plays and the other replays it, and a feed for a ghost. It depends on nothing. A wire is an adapter: NetTransportWire in flutter3d_net for its relay and WebRTC, and flame_multiplayer_dashwire for a dashwire connection, whose binary WebSocket passes through the same relay. The crawler's online co-op now runs on RollbackPlay. River Sortie gets two players: turns on one machine, turns across two with the other watching a replay, and a race against a ghost on the same river.
flutter3d_net's NetSession wraps flame_multiplayer's RollbackSession over a Snapshot, keeping its constructor, defaults and wire format, so the repository has one rollback rather than two. droppedCorrections becomes a getter.
The co-op crawler, its genre package and its level generator leave this branch, and River Sortie goes back to one player; both live on the multiplayer branch until that work is ready to be shown. The package count, the test counts and the publishing order follow. The article on the Flame bridge gets two pictures of River Sortie: a stretch of river in play and a bridge coming down.
flame_flutter3d and flame_flutter3d_audio go to 0.8.4, the audio package asking for the bridge that has UpdatesAtRoot. flutter3d_game_shooter goes to 0.8.1: its chase brain credits a hit through hurtFocus, which is flutter3d_sim 0.8.1's, so it asks for that release. flutter3d_sim 0.8.1 and flutter3d_net 0.8.1 keep what 0.8.0 code wrote to: ActorSystem.focusBody can still be set, deprecated since step overwrites it, and NetSession.droppedCorrections still writes through to the shared session. Code built against 0.8.0 compiles against both.
Three pages for flame_flutter3d 0.8.4. Two keyboard layouts claim seats by pressing, keys read from the keyboard rather than the focus. Ninety-six simulated monsters take slots in one instanced batch and each chases the nearer of two players, drawn between their steps. A game moves between two level scenes with replaceScene3d while a view camera keeps the whole party in frame. Each page has a guide and a test that fails when its feature is taken away. The showcase moves to 0.8.4+1 so its pages may name that release.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #41 (0.8.2), which is still open.
River Sortie (
apps/flutter3d_demo_river): the second game onflame_flutter3d, after River Raid. Flame decides every hit with its own hitboxes and draws the panel; flutter3d draws the river. Five levels with a task each, targets that go down the way their kind would, generated sound, a stick and a fire button on Android and iOS. Demo page, sidebar entry and front-page card on the site.0.8.3 of three packages, each for something the game had to work around:
flutter3d_core: vertex colour documented as linear,linearFromSrgb, the sRGB curve exported,MeshData.withColor.flutter3d:ModelAsset.instantiateFitted, which Meteor Yard now uses in place of its own copy.flame_flutter3d:Object3dComponenttakessizeandanchor.0.8.4, published to pub.dev and tagged
v0.8.4on a796eca:flame_flutter3d0.8.4: an actor system with several foci, a horde drawn as slots of one instanced batch (InstancedActorComponent,InstancedPoseComponent), bodies drawn between their steps,PlayerSeatsand keys read from the keyboard rather than the focus,replaceScene3d,ViewCamera,FixtureVisualsComponent, andUpdatesAtRoot, which puts the camera sync back after Flame's camera wherever it is added.flame_flutter3d_audio0.8.4: the audio scene hears from where the camera is this frame.flutter3d_sim0.8.1: several foci, damage counted per focus, a restore that builds again what was born during play.focusBodycan still be set, deprecated.flutter3d_game_shooter0.8.1: a claw that catches the player beside the one it swung at has caught them.flame_multiplayer0.1.0 (new, no dependencies): a room with a handshake and channels, rollback play in step, turns with a replay for the one watching, a feed for a ghost.flame_multiplayer_dashwire0.1.0 (new): a dashwire connection as its wire.flutter3d_net0.8.1:NetTransportWire, andNetSessionrunning on the shared rollback with the same wire format.Three showcase pages for the bridge's 0.8.4 (seats, the horde, a level as a scene), and two River Sortie pictures for the article on the bridge.
Checked:
tool/structure.dart35/35;dart pub publish --dry-runwith no warnings on all seven packages; the suites of every changed package and of what depends on them: flame_multiplayer (9), flame_multiplayer_dashwire (3, including a room through the relay over dashwire's WebSocket), flutter3d_net (15), flutter3d_sim (606), flutter3d_game (254), the four genre packages, flame_flutter3d (213), flame_flutter3d_audio (11), River Sortie (53), Meteor Yard (20), racing (193), dungeon (133), showcase (502). Published shooter 0.8.0 analyzes clean against flutter3d_sim 0.8.1.