Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add TimeTrackComponent and ChildCounterComponent #2846

Merged
merged 13 commits into from
Nov 21, 2023
1 change: 1 addition & 0 deletions .github/.cspell/dart_dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ endtemplate # Use @endtemplate to close a @template block in dartdoc
pubspec # dependency and configuration file of every Dart project
typedefs # plural of typedef
intelli # JetBrain's IDE
writeln # StringBuffer.writeln
2 changes: 1 addition & 1 deletion doc/flame/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ removing it from the tree. This affects the visibility of the component and all
/// Example that implements HasVisibility
class MyComponent extends PositionComponent with HasVisibility {}

/// Usage of the isVisible property
/// Usage of the isVisible property
final myComponent = MyComponent();
add(myComponent);

Expand Down
43 changes: 43 additions & 0 deletions doc/flame/other/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,46 @@ commonly want to show the current FPS somewhere when the `FpsComponent` is used.


[TextComponent]: ../rendering/text_rendering.md#textcomponent


### ChildCounterComponent

`ChildCounterComponent` is a component that renders the number of children of
type `T` from a component (`target`) every second. So for example:

So for example, the following will render the number of `SpriteAnimationComponent` that are
children of the game `world`:

```dart
add(
ChildCounterComponent<SpriteAnimationComponent>(
target: world,
),
);
```


### TimeTrackComponent

This component allows developers to track time spent inside their code. This can be useful for
performance debugging time spent in certain parts of the code.

To use it, add it to your game somewhere (since this is a debug feature, we advise to only add the
component in a debug build/flavor):

```dart
add(TimeTrackComponent());
```

Then in the code section that you want to track time, do the following:

```dart
void update(double dt) {
TimeTrackComponent.start('MyComponent.update');
// ...
TimeTrackComponent.end('MyComponent.update');
}
```

With the calls above, the added `TimeTrackComponent` will render the elapsed time in
microseconds.
4 changes: 4 additions & 0 deletions packages/flame/lib/debug.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export 'src/components/debug/child_counter_component.dart';
export 'src/components/debug/time_track_component.dart';
export 'src/components/fps_component.dart';
export 'src/components/fps_text_component.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dart:async';
import 'dart:ui';

import 'package:flame/components.dart';
import 'package:flame/text.dart';

/// A debug component that shows the number of children of a given type from
/// a target component.
///
/// Add it to the game to start seeing the count.
class ChildCounterComponent<T extends Component> extends TextComponent {
ChildCounterComponent({
required this.target,
super.position,
});

final Component target;
late String _label;

@override
FutureOr<void> onLoad() async {
await super.onLoad();
_label = T.toString();

textRenderer = TextPaint(
style: const TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 12,
),
);

add(
TimerComponent(
period: 1,
repeat: true,
onTick: () {
text = '$_label: ${target.children.query<T>().length}';
},
),
);
}
}
65 changes: 65 additions & 0 deletions packages/flame/lib/src/components/debug/time_track_component.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import 'dart:async';
import 'dart:ui';

import 'package:flame/components.dart';
import 'package:flame/text.dart';

/// A component that offers a simple way to track time spent in different parts
/// of your game.
///
/// This component is meant to be used for debugging purposes only and should
/// not be added in production builds.
///
/// To start tracking time, call [TimeTrackComponent.start] with an identifier
/// and [TimeTrackComponent.end] with that same identifier to finish tracking.
///
/// To see the recorded times, simply add this component to your game.
class TimeTrackComponent extends TextComponent {
TimeTrackComponent({super.position});

static final Map<String, int> _startTimes = {};
static final Map<String, int> _endTimes = {};

static void clear() {
_startTimes.clear();
_endTimes.clear();
}

static void start(String name) {
_startTimes[name] = DateTime.now().microsecondsSinceEpoch;
}

static void end(String name) {
_endTimes[name] = DateTime.now().microsecondsSinceEpoch;
}

@override
FutureOr<void> onLoad() async {
await super.onLoad();

textRenderer = TextPaint(
style: const TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 12,
),
);

add(
TimerComponent(
period: 1,
repeat: true,
onTick: () {
final sb = StringBuffer();
for (final entry in _startTimes.entries) {
final name = entry.key;
final startTime = entry.value;
final endTime = _endTimes[name];
final duration = endTime == null ? 0 : endTime - startTime;
sb.writeln('$name: $duration');
}
text = sb.toString();
},
),
);
}
}