Skip to content

feat: Add input, world snapshot and diff commands to flame_cli - #4057

Merged
spydon merged 2 commits into
mainfrom
feat/flame-cli-input
Sep 30, 2026
Merged

spydon merged 2 commits into
mainfrom
feat/flame-cli-input

Conversation

@spydon

@spydon spydon commented Sep 25, 2026

Copy link
Copy Markdown
Member

Description

Stacked on #4056. This turns the CLI from an observer into something that can play test a game,
and gives agents a way to compare snapshots that does not rely on eyeballing two images.

  • A new InputConnector in flame registers ext.flame_devtools.tap, drag and key. Taps
    and drags are delivered through the game's MultiTapDispatcher and MultiDragScaleDispatcher,
    so they reach TapCallbacks and DragCallbacks components with the same propagation as real
    input, in canvas coordinates (the same as the pixels of a snapshot). Keys go to onKeyEvent of
    a HasKeyboardHandlerComponents or KeyboardEvents game, with press, down and up
    actions. Key names are matched against the LogicalKeyboardKey names without regard to case,
    spaces and underscores (arrowLeft, Arrow Left, space, a, digit1). A missing mixin is
    reported as an invalid parameters error instead of silently doing nothing.
  • flame input tap <x,y>, flame input drag <x,y> <x,y> [--steps N] and
    flame input key <name> [--down|--up] call those.
  • getGameSnapshot takes world=true or rect=x,y,w,h to render the world directly without the
    camera, so off screen components are visible. Without a rect the image covers the bounding
    rectangle of all the position components in the world. flame snapshot --world and
    --rect expose it. Snapshotting the World component itself used to give a blank 100x100
    image, since World.renderTree is a no-op, it now renders the world's children the same way.
  • flame diff <before.png> <after.png> [--output diff.png] [--threshold N] [--exit-code]
    reports the percentage of differing pixels and the bounding rectangle of the change, and can
    write an image with the changes in red on a dimmed copy of the second image. This adds the
    image package as a dependency of flame_cli.

Tests cover the input connector with real components (tap position, drag steps, key down and up
with the pressed set, the missing mixin messages, key name lookup), world bounds and world
snapshots, the diff algorithm and command, and the usage errors of the new commands. Verified
end to end on the flutter-tester device: a tap toggled a component's color and flame diff
reported exactly the 200x100 rectangle at 300,250 with exit code 1, a drag and arrow keys moved
the component, and --world and --rect rendered an off screen component.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • [-] I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

@spydon
spydon added this pull request to stack #4058 September 25, 2026 16:13
@spydon
spydon force-pushed the feat/flame-cli-input branch 2 times, most recently from e649860 to 7eb2be4 Compare September 30, 2026 13:05
@spydon
spydon force-pushed the feat/flame-cli-input branch 2 times, most recently from bde7eda to a96f31c Compare September 30, 2026 13:14
Base automatically changed from feat/flame-cli-run to main September 30, 2026 14:53
A new InputConnector delivers synthetic taps, drags and key presses through the game's dispatchers. getGameSnapshot can render the world directly, in full or for a rect in world coordinates, and snapshotting the World component now renders its children. The diff command compares two PNG images and reports the differing pixels and their bounding rectangle.
The categories sort alphabetically in the order the commands are typically used: launching, observing, pausing and changing, and playing the game.
@spydon
spydon force-pushed the feat/flame-cli-input branch from a96f31c to 4bae36c Compare September 30, 2026 14:55
@spydon
spydon merged commit 60996d9 into main Sep 30, 2026
8 checks passed
@spydon
spydon deleted the feat/flame-cli-input branch September 30, 2026 15:09
spydon added a commit that referenced this pull request Sep 30, 2026
…e style command (#4059)

Stacked on #4057. This brings the scaffolding of
[ignite_cli](https://pub.dev/packages/ignite_cli)
into `flame_cli` as `flame create`, structured like `flutter create`: no
interactive prompts, a
positional output directory, sensible defaults and options to change
them.

```shell
flame create my_game
cd my_game
flame run
```

How it works:

- `flutter create --empty` generates the platform folders and the
`pubspec.yaml`, with
`--project-name`, `--org`, `--description`, `--platforms` and
`--overwrite` passed through.
- The files of the chosen template (`--template simple|basics|example`,
`basics` by default) are
written on top, plus an `analysis_options.yaml` that includes
`flame_lint`.
- `flutter pub remove flutter_lints` and `flutter pub add flame
dev:flame_lint [dev:flame_test]
[--packages ...]` set up the dependencies. Using `pub add` means the
game always starts on the
newest compatible versions, without a version list baked into the CLI or
fetched from pub.dev
the way ignite did. `--flame-version ^1.30.0` pins a constraint when
needed.
- The project name defaults to the directory name and is validated with
the same rules as
`flutter create` (a lowercase Dart identifier that is not a keyword or a
clashing package name),
with a suggestion when it is invalid. An existing project is not touched
without `--overwrite`.

The three templates are updated versions of ignite's:

- `simple`: an empty `FlameGame` in a `GameWidget`.
- `basics`: a world with a component that starts moving when tapped, and
a `FlameTester` widget
  test for it.
- `example`: a small complete game over a few files: a world, a camera
with a score in the
viewport, a player steered with the arrow keys or by tapping, stars to
collect through
  collision detection, and four `testWithGame` tests.

The command shows up in a new "Creating a game" group at the top of
`flame --help`.

Tests use a fake `flutter` process and check the exact command sequence,
the written files, the
options, the overwrite guard, the validation and the failure path. I
also created a game from each
template with the real `flutter`: all three pass `flutter analyze`,
`basics` and `example` pass
`flutter test`, and the example runs under `flame run` on
`flutter-tester`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants