This is a cleanup identified on this issue: #2308
Using an amazing unused-code tooling
Now, since Flame is a public API, unused code might not be trivial - it might just mean untested code.
This one was a no-brainer -- the variable was clearly replaced by specific counters during the writing of the test and forgotten there:
int nOnTapDown = 0;
int nOnLongTapDown = 0;
int nOnTapUp = 0;
int nOnTap = 0;
int nOnTapCancel = 0;
It wasn't even increment and the taps are already thoroughly tested more granularly
The link went directly to the Flame channel instead of being an invite link to the server, so it didn't work for people that weren't already on the server.
This PR ensures that all component rebalancing operations are resolved from a single location, after the update stage but before the render stage (thus, components may get reordered during the update, and these changes will go into effect during the rendering step on the same game tick).
This also fixes the problem where the child changing the priorities of its parent would cause a ConcurrentModificationError.
A number of methods that were used to handle rebalancing are now marked as deprecated. From the user's perspective, the only API they should be using is the .priority setter.
This fixes the regression with that the graphs aren't rendering.
Unfortunately they will forever be broken in the v1.6.0 release of the
docs now.
Fix comes from here:
2eaff4220a
The grid position variable is non-private: gridPosition in the PlatformBlock class definition but was used as private: _gridPosition in the onLoad method.
This PR updates the grid position variable in the onLoad to gridPosition.
Detailed use-case examples are described in #2337.
As-is
A single source TiledAtlas doesn't check if there is a cached image that is already loaded in the memory.
It re-loads the image into the memory.
To-be
A single source TiledAtlas now uses the cached image if it exists.
Add ability to display game's component tree in the left panel.
The tree automatically re-syncs with the game every 300ms (eventually this should be a configurable value).
Nested parts of the tree can be expanded/collapsed, and one component can be selected.
In the future, the selected component can be shown in the Inspector, but that is not implemented yet.
At the *Other classes* session, when it is mentioned that we need to
create the `components` sub-directory, the tutorial is guiding us to add
it in the root, but on the structure below, it is possible to see that
it should be created inside the `libs` folder instead.
It seems to be better to be more explicit in this paragraph.
As stated in #2357, the field `limit` of the class `Timer` had no reason
to be final. By removing this keyword, we make it possible to add more
time to a given `Timer` object (so that they can be used as a countdown
for example).
0.10.2:
Performance improvement: No longer drawing components with an opacity of 0.
Updated example, see "Skinning Demo".
Support for negative speeds on linear animations when played back in state machines.
Support for overriding speed on animation states.
This is the beginning of work on Flame Studio. In this PR we add a simple UI, which shows the game itself, an info panel, and a toolbar with 2 buttons: start/pause. The UI is able to control the embedded game; in particular the toolbar buttons can pause or resume the game engine.
There is a new feature on pub.dev where you can add your logo or screenshots of examples to your pub.dev listing.
In this PR I'm just adding the Flame logo for the Flame core package.
Example of how it looks like for Bloc:
https://pub.dev/packages/bloc
* Fix benchmark file name to run as test
* QuadTree now uses a parentHitbox instead of parent
* Add tests
* Apply suggestions from code review
Co-authored-by: Lukas Klingsbo <lukas.klingsbo@gmail.com>
* Replace the var name
* Revert mark as final
* Change default parameter name
---------
Co-authored-by: Lukas Klingsbo <lukas.klingsbo@gmail.com>
Move commands are now stored inside the global queue of lifecycle events, and processed at each game tick before the start of the update() phase.
Component's LifecycleManager now completely removed.
As-is
As mentioned in #2321, the user needs to propagate double-tap events to the component tree using DoubleTapDetector & propagateToChildren until now.
To-be
Any components that are mixed into the DoubleTapCallbacks receive double-tap-related events.
Same as DragCallbacks, there is no need to add mixin to the game like HasDoubleTapCallbaks as before.
As-is
The TileLayer became too big to maintain.
Some tile related classes doesn't have factory method, their creation is done in other classes with big switch-case.
To-be
Divided TileLayer into its Layer type. The Layer type is determined by MapOrientaion which has a member of isometric, orthogonal, staggered, and hexagonal.
Instantiation is done by factory method inside the class.
This PR migrates us to the prerelease version of Melos (3.0.0-dev.0) and our pipelines to Flutter 3.7.1
It's a golden opportunity for us to test the upcoming version of melos and give them any feedback that we might have. :)
The migration instructions can be read here:
https://melos.invertase.dev/guides/migrations
Component removal is now handled via the ComponentTreeRoot class and its queue of lifecycle events.
The onGameResize event now only fires before the component's onMount, but not before its onLoad.
Migration instructions
If you have components that rely on receiving onGameResize calls before they load, then
you can retrieve the game's size in onLoad manually via findGame()!.size.
I am on a crusade to improve our spellchecking. I have a big PR that I am now going to break down into very small chunks to for review.
zwaldowski's cspell-action has been deprecated in favor of streetsidesoftware/cspell-action.
This PR:
updates to use the new recommended cspell action
update to use checkout v3, because why not
fixes a few violations the new action caught
Note: I think we should make a distinction between things that should be in a dictionary (e.g. AABB, a standard industry acronym that we expect people to know what it is) and specific edge-cases/ignore rules for specific parts of specific files (e.g. something like fccc which is meaningless outside of the very specific context in which it is used). For the latter, I believe we should use case-by case exceptions.
I am on a crusade to improve our spellchecking. I have a big PR that I am now going to break down into very small chunks to for review.
This is another hopefully not controversial one - broken links referencing the old Fire Slime.
Updating the links means we no longer need that word in our dictionary file.
As I mentioned on #2310 (comment),
it's inevitable to create an atlas that has 2x width from the original one to support flip, it could bring some limitations. So it would be great to opt out the flip.
Here's the reason why this is needed.
Flip may impact performance if the composed tileset(AKA texture) is big.
The software tiled has shortcuts to go back by cmd(ctrl)-z, rotating by z, and flipping horizontally by x. Imagine that you clicked a tile to the wrong place, you may press cmd-z and so on. In this situation, you can also accidentally press z or x, and as a result, the tile flips! It is fine with some complicated or flip(rotate)-consiousable tiles. But some things like the floor or sky are hard to recognize. I even made a program for my design team to pick out coordinates of where the flipped tiles exist but often there are flips. So, providing a way by simple boolean argument may prevent this.
This PR is first in a series of refactors that aim to simplify event handling in Flame. The approach is as follows:
Added class GestureDetectorBuilder, which encapsulates the logic of applyGestureDetectors() in a class. This class resides within the Game and initiates widget rebuild whenever any new gesture detectors are added or removed. Note:
[idea] Convert HasTappableComponents/HasDraggableComponents into classes #1733 suggests having a list of interfaces inside the Game class -- this is essentially that list, encapsulated in a class.
Added the MultiDragDispatcher component, which contains the logic that used to be within the HasDraggableComponents mixin. This component is internal; it mounts to a FlameGame directly, and ensures that it is a singleton.
Whenever any DragCallbacks component is added to a game, it automatically adds the MultiDragDispatcher component (unless there is already one), which in turn registers a drag gesture detector with GestureDetectorBuilder and rebuilds the game widget.
The end result is that now in order to make a component draggable you only need to add the DragCallbacks mixin to that component, everything else will be handled by the framework.
Consequently, the HasDraggableComponents mixin is now empty and marked as deprecated.
I am on a crusade to improve our spellchecking. I have a big PR that I am now going to break down into very small chunks to for review.
Here I am renaming an asset to include a word separator, as the combined word "caveace" doesn't exist. This not only allows us to remove one unclear entry in our dictionary, but make our example code easier to read for new users.
Note: in order to easily update the internal name of the atlas (unrelated to file name), that is stored in the binary, I used this pending feature from Fire Atlas.
Since we started using ComponentTreeRoot, the children of an unmounted component are stored in its children container -- which means the components added during onLoad are now accessible during onMount via children (even though they are still unmounted).
This PR adds a test for that.
The ComponentTreeRoot is a special Component designed to sit at the root of a component tree. For example, FlameGame is a ComponentTreeRoot.
The class contains a game-wide queue (RecycledQueue) for component lifecycle events. Currently this supports only Component.add functionality, but in the future we'll extend it to other functions as well: remove, re-parent, and re-balance.
The new approach is supposed to be more efficient: instead of each component having their own queues of events, now there is just one central queue, which also supports recycling of elements, which means no unnecessary objects are created on every tick.
The new approach should be more robust as well: previously, each component's queue was processed during that component's updateTree cycle -- now, all lifecycle events are resolved from one location, before the component tree is updated or rendered. If during the update phase the user schedules new components to be added/removed, then those changes will be always deferred to the next game tick. Thus, we have a guarantee that during a single game tick the structure of a component tree will remain constant.
This is, of course, pending future refactoring to move the remaining lifecycle handling functionality into the ComponentTreeRoot.
Previously, when using BoundedPositionBehavior, the camera would "stick" to the world boundary as soon as the target moves outside. With this PR, the camera will now try to keep as close to the target as possible, even if it moves outside of the world boundary. Thus, the camera will now behave as if the boundary became "slippery".
Also added method nearestPoint() in class Shape.
Before when you only had two routes you'd get:
Bad state: No element
dart:core List.last
package:flame/src/components/router_component.dart 260:30 RouterComponent._popWithoutMinimumAssert
package:flame/src/components/router_component.dart 122:7 RouterComponent.pushReplacementNamed
test/components/router_component_test.dart 20:14 main.<fn>.<fn>
This creates a new component HardwareKeyboardDetector, which is a more advanced version of the KeyboardEvents mixin:
HardwareKeyboardDetector is a component instead of a mixin, which means it can be added/removed by the user at any point;
multiple such detectors can be attached to a game - for example, in a 2-player game one component may be paying attention to arrow keys, while another to WASD keys;
the new component uses Flutter's HardwareKeyboard interface, bypassing the need for a Focus widget;
the component keeps the ordered list of keys that are currently being pressed, which is helpful for games where this order is important;
there is the ability to temporarily pause the reception of key events using keyEventsPaused property.