From 85c6a11819ebb3df5c19235d1629eea5c942dc4b Mon Sep 17 00:00:00 2001 From: Serge Matveenko Date: Mon, 18 Jan 2021 03:37:46 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=91=8C=20Use=20`Offset`=20type=20dire?= =?UTF-8?q?ctly=20in=20`JoystickAction.update`=20calculations=20(#631)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + doc/examples/animations/lib/main.dart | 4 +- doc/examples/aseprite/lib/main.dart | 4 +- doc/examples/composability/lib/main.dart | 5 +- doc/examples/debug/lib/main.dart | 4 +- .../effects/combined_effects/lib/main.dart | 10 +- .../effects/combined_effects/lib/square.dart | 5 +- .../effects/infinite_effects/lib/main.dart | 5 +- .../effects/infinite_effects/lib/square.dart | 5 +- .../effects/sequence_effect/lib/main.dart | 11 +- .../effects/sequence_effect/lib/square.dart | 5 +- .../effects/simple/lib/main_move.dart | 8 +- .../effects/simple/lib/main_rotate.dart | 4 +- .../effects/simple/lib/main_scale.dart | 5 +- doc/examples/effects/simple/lib/square.dart | 5 +- .../gestures/lib/main_draggables.dart | 7 +- .../gestures/lib/main_mouse_movement.dart | 3 +- .../lib/main_overlapping_tapables.dart | 4 +- doc/examples/gestures/lib/main_scroll.dart | 3 +- doc/examples/gestures/lib/main_tapables.dart | 6 +- doc/examples/isometric/lib/main.dart | 5 +- doc/examples/joystick/lib/main.dart | 4 +- doc/examples/joystick/lib/player.dart | 6 +- doc/examples/layers/lib/main.dart | 8 +- doc/examples/nine_tile_box/lib/main.dart | 5 +- doc/examples/parallax/lib/main.dart | 3 +- doc/examples/parallax/lib/main_advanced.dart | 3 +- doc/examples/particles/lib/main.dart | 25 +- doc/examples/render_flip/lib/main.dart | 4 +- doc/examples/sprite_batch/lib/main.dart | 3 +- doc/examples/sprites/lib/main.dart | 5 +- doc/examples/sprites/lib/main_base64.dart | 6 +- doc/examples/spritesheet/lib/main.dart | 4 +- doc/examples/text/lib/main.dart | 5 +- doc/examples/timer/lib/main.dart | 3 - doc/examples/widgets/lib/main.dart | 10 +- example/lib/main.dart | 7 +- lib/components.dart | 21 ++ lib/components/timer_component.dart | 23 -- lib/effects.dart | 9 + lib/extensions.dart | 5 + lib/flame.dart | 50 +-- lib/game.dart | 11 +- lib/gestures.dart | 112 +------ lib/joystick.dart | 7 + lib/keyboard.dart | 8 +- lib/layers.dart | 2 + lib/palette.dart | 31 +- lib/parallax.dart | 316 +----------------- lib/particles.dart | 18 + lib/sprite_batch.dart | 296 +--------------- lib/spritesheet.dart | 106 +----- lib/{ => src}/anchor.dart | 0 lib/{ => src}/assets/assets_cache.dart | 0 lib/{ => src}/assets/images.dart | 0 lib/{ => src}/components/base_component.dart | 2 +- lib/{ => src}/components/component.dart | 3 +- .../isometric_tile_map_component.dart | 0 .../components/joystick/joystick_action.dart | 0 .../joystick/joystick_component.dart | 0 .../joystick/joystick_directional.dart | 0 .../components/joystick/joystick_events.dart | 0 .../components/joystick/joystick_utils.dart | 0 .../components/mixins/draggable.dart | 0 .../components/mixins/has_game_ref.dart | 2 +- .../mixins/single_child_particle.dart | 2 +- lib/{ => src}/components/mixins/tapable.dart | 0 .../components/nine_tile_box_component.dart | 2 + .../components/parallax_component.dart | 2 +- .../components/particle_component.dart | 2 +- .../components/position_component.dart | 0 .../sprite_animation_component.dart | 2 + .../components/sprite_batch_component.dart | 0 .../components/sprite_component.dart | 2 + .../components/text_box_component.dart | 0 lib/{ => src}/components/text_component.dart | 0 lib/{ => src}/effects/combined_effect.dart | 0 lib/{ => src}/effects/effects.dart | 0 lib/{ => src}/effects/effects_handler.dart | 0 lib/{ => src}/effects/move_effect.dart | 0 lib/{ => src}/effects/rotate_effect.dart | 0 lib/{ => src}/effects/scale_effect.dart | 0 lib/{ => src}/effects/sequence_effect.dart | 0 lib/{ => src}/extensions/canvas.dart | 0 lib/{ => src}/extensions/offset.dart | 0 lib/{ => src}/extensions/rect.dart | 0 lib/{ => src}/extensions/size.dart | 0 lib/{ => src}/extensions/vector2.dart | 0 lib/src/flame.dart | 49 +++ lib/{ => src}/fps_counter.dart | 0 lib/{ => src}/game/base_game.dart | 0 lib/{ => src}/game/game.dart | 0 lib/{ => src}/game/game_loop.dart | 0 lib/{ => src}/game/game_render_box.dart | 0 lib/{ => src}/game/game_widget.dart | 0 lib/src/gestures.dart | 111 ++++++ lib/src/keyboard.dart | 7 + lib/{ => src}/layers/layer.dart | 2 - lib/{ => src}/layers/processors.dart | 0 lib/{ => src}/memory_cache.dart | 0 lib/{ => src}/nine_tile_box.dart | 0 lib/src/palette.dart | 30 ++ lib/src/parallax.dart | 315 +++++++++++++++++ .../particles/accelerated_particle.dart | 2 +- .../particles/animation_particle.dart | 4 +- lib/{ => src}/particles/circle_particle.dart | 2 +- .../particles/component_particle.dart | 2 +- .../particles/composed_particle.dart | 2 +- .../particles/computed_particle.dart | 2 +- lib/{ => src}/particles/curved_particle.dart | 2 +- lib/{ => src}/particles/image_particle.dart | 2 +- lib/{ => src}/particles/moving_particle.dart | 2 +- lib/{ => src}/particles/paint_particle.dart | 2 +- lib/{ => src/particles}/particle.dart | 18 +- .../particles/rotating_particle.dart | 2 +- lib/{ => src}/particles/scaled_particle.dart | 2 +- lib/{ => src}/particles/sprite_particle.dart | 4 +- .../particles/translated_particle.dart | 2 +- lib/{ => src}/profiler.dart | 0 lib/{ => src}/sprite.dart | 0 lib/{ => src}/sprite_animation.dart | 2 + lib/src/sprite_batch.dart | 295 ++++++++++++++++ lib/src/spritesheet.dart | 105 ++++++ lib/{ => src}/text_config.dart | 0 lib/src/timer.dart | 85 +++++ lib/{ => src}/util.dart | 0 lib/{ => src}/widgets/animation_widget.dart | 2 + lib/{ => src}/widgets/nine_tile_box.dart | 27 +- lib/{ => src}/widgets/sprite_button.dart | 10 +- lib/{ => src}/widgets/sprite_widget.dart | 2 + lib/timer.dart | 64 +--- lib/widgets.dart | 6 + test/base_game_test.dart | 8 +- test/components/component_test.dart | 5 +- test/components/composed_component_test.dart | 7 +- test/components/has_game_ref_test.dart | 6 +- test/components/position_component_test.dart | 4 +- test/components/resizable_test.dart | 6 +- test/effects/combined_effect_test.dart | 6 +- test/effects/effect_test_utils.dart | 6 +- test/effects/move_effect_test.dart | 5 +- test/effects/rotate_effect_test.dart | 4 +- test/effects/scale_effect_test.dart | 5 +- test/effects/sequence_effect_test.dart | 5 +- test/memory_cache_test.dart | 2 +- test/vector2_test.dart | 2 +- 146 files changed, 1229 insertions(+), 1248 deletions(-) create mode 100644 lib/components.dart delete mode 100644 lib/components/timer_component.dart create mode 100644 lib/effects.dart create mode 100644 lib/extensions.dart create mode 100644 lib/joystick.dart create mode 100644 lib/layers.dart create mode 100644 lib/particles.dart rename lib/{ => src}/anchor.dart (100%) rename lib/{ => src}/assets/assets_cache.dart (100%) rename lib/{ => src}/assets/images.dart (100%) rename lib/{ => src}/components/base_component.dart (99%) rename lib/{ => src}/components/component.dart (98%) rename lib/{ => src}/components/isometric_tile_map_component.dart (100%) rename lib/{ => src}/components/joystick/joystick_action.dart (100%) rename lib/{ => src}/components/joystick/joystick_component.dart (100%) rename lib/{ => src}/components/joystick/joystick_directional.dart (100%) rename lib/{ => src}/components/joystick/joystick_events.dart (100%) rename lib/{ => src}/components/joystick/joystick_utils.dart (100%) rename lib/{ => src}/components/mixins/draggable.dart (100%) rename lib/{ => src}/components/mixins/has_game_ref.dart (62%) rename lib/{ => src}/components/mixins/single_child_particle.dart (95%) rename lib/{ => src}/components/mixins/tapable.dart (100%) rename lib/{ => src}/components/nine_tile_box_component.dart (95%) rename lib/{ => src}/components/parallax_component.dart (99%) rename lib/{ => src}/components/particle_component.dart (96%) rename lib/{ => src}/components/position_component.dart (100%) rename lib/{ => src}/components/sprite_animation_component.dart (98%) rename lib/{ => src}/components/sprite_batch_component.dart (100%) rename lib/{ => src}/components/sprite_component.dart (97%) rename lib/{ => src}/components/text_box_component.dart (100%) rename lib/{ => src}/components/text_component.dart (100%) rename lib/{ => src}/effects/combined_effect.dart (100%) rename lib/{ => src}/effects/effects.dart (100%) rename lib/{ => src}/effects/effects_handler.dart (100%) rename lib/{ => src}/effects/move_effect.dart (100%) rename lib/{ => src}/effects/rotate_effect.dart (100%) rename lib/{ => src}/effects/scale_effect.dart (100%) rename lib/{ => src}/effects/sequence_effect.dart (100%) rename lib/{ => src}/extensions/canvas.dart (100%) rename lib/{ => src}/extensions/offset.dart (100%) rename lib/{ => src}/extensions/rect.dart (100%) rename lib/{ => src}/extensions/size.dart (100%) rename lib/{ => src}/extensions/vector2.dart (100%) create mode 100644 lib/src/flame.dart rename lib/{ => src}/fps_counter.dart (100%) rename lib/{ => src}/game/base_game.dart (100%) rename lib/{ => src}/game/game.dart (100%) rename lib/{ => src}/game/game_loop.dart (100%) rename lib/{ => src}/game/game_render_box.dart (100%) rename lib/{ => src}/game/game_widget.dart (100%) create mode 100644 lib/src/gestures.dart create mode 100644 lib/src/keyboard.dart rename lib/{ => src}/layers/layer.dart (98%) rename lib/{ => src}/layers/processors.dart (100%) rename lib/{ => src}/memory_cache.dart (100%) rename lib/{ => src}/nine_tile_box.dart (100%) create mode 100644 lib/src/palette.dart create mode 100644 lib/src/parallax.dart rename lib/{ => src}/particles/accelerated_particle.dart (97%) rename lib/{ => src}/particles/animation_particle.dart (94%) rename lib/{ => src}/particles/circle_particle.dart (94%) rename lib/{ => src}/particles/component_particle.dart (95%) rename lib/{ => src}/particles/composed_particle.dart (96%) rename lib/{ => src}/particles/computed_particle.dart (96%) rename lib/{ => src}/particles/curved_particle.dart (93%) rename lib/{ => src}/particles/image_particle.dart (97%) rename lib/{ => src}/particles/moving_particle.dart (97%) rename lib/{ => src}/particles/paint_particle.dart (97%) rename lib/{ => src/particles}/particle.dart (93%) rename lib/{ => src}/particles/rotating_particle.dart (96%) rename lib/{ => src}/particles/scaled_particle.dart (96%) rename lib/{ => src}/particles/sprite_particle.dart (92%) rename lib/{ => src}/particles/translated_particle.dart (96%) rename lib/{ => src}/profiler.dart (100%) rename lib/{ => src}/sprite.dart (100%) rename lib/{ => src}/sprite_animation.dart (99%) create mode 100644 lib/src/sprite_batch.dart create mode 100644 lib/src/spritesheet.dart rename lib/{ => src}/text_config.dart (100%) create mode 100644 lib/src/timer.dart rename lib/{ => src}/util.dart (100%) rename lib/{ => src}/widgets/animation_widget.dart (98%) rename lib/{ => src}/widgets/nine_tile_box.dart (87%) rename lib/{ => src}/widgets/sprite_button.dart (85%) rename lib/{ => src}/widgets/sprite_widget.dart (98%) create mode 100644 lib/widgets.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 45032a6732a..c35dbec3417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Updated the `widgets.md` documentation - Removing methods `initialDimensions` and `removeGestureRecognizer` to avoid confusion - Adding standard for `SpriteComponent` and `SpriteAnimationComponent` constructors + - move files to comply with the dart package layout convention ## 1.0.0-rc5 - Option for overlays to be already visible on the GameWidget diff --git a/doc/examples/animations/lib/main.dart b/doc/examples/animations/lib/main.dart index 65c8aa0740f..48217df2a3b 100644 --- a/doc/examples/animations/lib/main.dart +++ b/doc/examples/animations/lib/main.dart @@ -1,9 +1,7 @@ +import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame/gestures.dart'; import 'package:flutter/gestures.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/sprite_animation.dart'; -import 'package:flame/components/sprite_animation_component.dart'; import 'package:flutter/material.dart' hide Image; import 'dart:ui'; diff --git a/doc/examples/aseprite/lib/main.dart b/doc/examples/aseprite/lib/main.dart index 04c1f745938..348826fb723 100644 --- a/doc/examples/aseprite/lib/main.dart +++ b/doc/examples/aseprite/lib/main.dart @@ -1,7 +1,5 @@ +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/sprite_animation.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/components/sprite_animation_component.dart'; import 'package:flutter/material.dart'; void main() async { diff --git a/doc/examples/composability/lib/main.dart b/doc/examples/composability/lib/main.dart index e647aeb0355..cdfe4a9d74f 100644 --- a/doc/examples/composability/lib/main.dart +++ b/doc/examples/composability/lib/main.dart @@ -1,8 +1,5 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/components/position_component.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flutter/material.dart'; void main() async { diff --git a/doc/examples/debug/lib/main.dart b/doc/examples/debug/lib/main.dart index bf84dcc0521..cbc04719fa6 100644 --- a/doc/examples/debug/lib/main.dart +++ b/doc/examples/debug/lib/main.dart @@ -1,8 +1,6 @@ +import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame/flame.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/components/sprite_component.dart'; -import 'package:flame/text_config.dart'; import 'package:flutter/material.dart' hide Image; diff --git a/doc/examples/effects/combined_effects/lib/main.dart b/doc/examples/effects/combined_effects/lib/main.dart index eb63d6963a3..f1fa93590f2 100644 --- a/doc/examples/effects/combined_effects/lib/main.dart +++ b/doc/examples/effects/combined_effects/lib/main.dart @@ -1,13 +1,9 @@ -import 'package:flame/effects/combined_effect.dart'; -import 'package:flame/effects/move_effect.dart'; -import 'package:flame/effects/scale_effect.dart'; -import 'package:flame/effects/rotate_effect.dart'; +import 'package:flame/effects.dart'; import 'package:flame/game.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/extensions/offset.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flame/flame.dart'; -import 'package:flutter/material.dart'; +import 'package:flame/extensions.dart'; +import 'package:flutter/widgets.dart'; import './square.dart'; diff --git a/doc/examples/effects/combined_effects/lib/square.dart b/doc/examples/effects/combined_effects/lib/square.dart index 93154bf4d04..cd92de4d622 100644 --- a/doc/examples/effects/combined_effects/lib/square.dart +++ b/doc/examples/effects/combined_effects/lib/square.dart @@ -1,9 +1,6 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; - import 'dart:ui'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; class Square extends PositionComponent { final Paint _paint; diff --git a/doc/examples/effects/infinite_effects/lib/main.dart b/doc/examples/effects/infinite_effects/lib/main.dart index ffa835f975a..7fdf23d30e7 100644 --- a/doc/examples/effects/infinite_effects/lib/main.dart +++ b/doc/examples/effects/infinite_effects/lib/main.dart @@ -1,8 +1,5 @@ -import 'package:flame/effects/move_effect.dart'; -import 'package:flame/effects/scale_effect.dart'; -import 'package:flame/effects/rotate_effect.dart'; +import 'package:flame/effects.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; diff --git a/doc/examples/effects/infinite_effects/lib/square.dart b/doc/examples/effects/infinite_effects/lib/square.dart index 93154bf4d04..cd92de4d622 100644 --- a/doc/examples/effects/infinite_effects/lib/square.dart +++ b/doc/examples/effects/infinite_effects/lib/square.dart @@ -1,9 +1,6 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; - import 'dart:ui'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; class Square extends PositionComponent { final Paint _paint; diff --git a/doc/examples/effects/sequence_effect/lib/main.dart b/doc/examples/effects/sequence_effect/lib/main.dart index 1cceb20584d..b2aa51f021a 100644 --- a/doc/examples/effects/sequence_effect/lib/main.dart +++ b/doc/examples/effects/sequence_effect/lib/main.dart @@ -1,13 +1,8 @@ -import 'package:flame/effects/combined_effect.dart'; -import 'package:flame/effects/move_effect.dart'; -import 'package:flame/effects/scale_effect.dart'; -import 'package:flame/effects/rotate_effect.dart'; -import 'package:flame/effects/sequence_effect.dart'; -import 'package:flame/gestures.dart'; -import 'package:flame/extensions/offset.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/effects.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; +import 'package:flame/gestures.dart'; +import 'package:flame/extensions.dart'; import 'package:flutter/material.dart'; import './square.dart'; diff --git a/doc/examples/effects/sequence_effect/lib/square.dart b/doc/examples/effects/sequence_effect/lib/square.dart index 93154bf4d04..cd92de4d622 100644 --- a/doc/examples/effects/sequence_effect/lib/square.dart +++ b/doc/examples/effects/sequence_effect/lib/square.dart @@ -1,9 +1,6 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; - import 'dart:ui'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; class Square extends PositionComponent { final Paint _paint; diff --git a/doc/examples/effects/simple/lib/main_move.dart b/doc/examples/effects/simple/lib/main_move.dart index 5dc2bd88717..7f6b4947ae5 100644 --- a/doc/examples/effects/simple/lib/main_move.dart +++ b/doc/examples/effects/simple/lib/main_move.dart @@ -1,9 +1,9 @@ +import 'package:flame/effects.dart'; import 'package:flame/game.dart'; -import 'package:flutter/material.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/offset.dart'; +import 'package:flame/extensions.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/widgets.dart'; import './square.dart'; diff --git a/doc/examples/effects/simple/lib/main_rotate.dart b/doc/examples/effects/simple/lib/main_rotate.dart index ba318ea9daf..56f161b776e 100644 --- a/doc/examples/effects/simple/lib/main_rotate.dart +++ b/doc/examples/effects/simple/lib/main_rotate.dart @@ -1,10 +1,10 @@ import 'dart:math'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/anchor.dart'; -import 'package:flame/effects/effects.dart'; import './square.dart'; diff --git a/doc/examples/effects/simple/lib/main_scale.dart b/doc/examples/effects/simple/lib/main_scale.dart index fc332c4884d..3fdba1a9436 100644 --- a/doc/examples/effects/simple/lib/main_scale.dart +++ b/doc/examples/effects/simple/lib/main_scale.dart @@ -1,9 +1,8 @@ +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter/material.dart'; import 'package:flame/game.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/anchor.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/effects/effects.dart'; import './square.dart'; diff --git a/doc/examples/effects/simple/lib/square.dart b/doc/examples/effects/simple/lib/square.dart index b34fab6b78f..bcaf8516e4b 100644 --- a/doc/examples/effects/simple/lib/square.dart +++ b/doc/examples/effects/simple/lib/square.dart @@ -1,10 +1,7 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; +import 'package:flame/components.dart'; import 'dart:ui'; -import 'package:flame/extensions/vector2.dart'; - class Square extends PositionComponent { static final _paint = Paint()..color = const Color(0xFFFFFFFF); diff --git a/doc/examples/gestures/lib/main_draggables.dart b/doc/examples/gestures/lib/main_draggables.dart index c52d59ac43c..a188d10f830 100644 --- a/doc/examples/gestures/lib/main_draggables.dart +++ b/doc/examples/gestures/lib/main_draggables.dart @@ -1,11 +1,8 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/components/mixins/draggable.dart'; -import 'package:flame/extensions/offset.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/extensions.dart'; import 'package:flame/gestures.dart'; import 'package:flutter/material.dart' hide Draggable; import 'package:flame/game.dart'; -import 'package:flame/components/position_component.dart'; void main() { final widget = Container( diff --git a/doc/examples/gestures/lib/main_mouse_movement.dart b/doc/examples/gestures/lib/main_mouse_movement.dart index 1209d1ed2f1..544c7514e14 100644 --- a/doc/examples/gestures/lib/main_mouse_movement.dart +++ b/doc/examples/gestures/lib/main_mouse_movement.dart @@ -2,8 +2,7 @@ import 'package:flame/game.dart'; import 'package:flutter/material.dart'; import 'package:flame/gestures.dart'; import 'package:flame/palette.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/extensions/offset.dart'; +import 'package:flame/extensions.dart'; void main() { runApp( diff --git a/doc/examples/gestures/lib/main_overlapping_tapables.dart b/doc/examples/gestures/lib/main_overlapping_tapables.dart index f2175d754a8..3593925eeb6 100644 --- a/doc/examples/gestures/lib/main_overlapping_tapables.dart +++ b/doc/examples/gestures/lib/main_overlapping_tapables.dart @@ -1,11 +1,9 @@ import 'dart:math' as math; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flame/palette.dart'; import 'package:flutter/material.dart'; import 'package:flame/game.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/mixins/tapable.dart'; void main() { final game = MyGame(); diff --git a/doc/examples/gestures/lib/main_scroll.dart b/doc/examples/gestures/lib/main_scroll.dart index 1510098c0e3..6e630f5a046 100644 --- a/doc/examples/gestures/lib/main_scroll.dart +++ b/doc/examples/gestures/lib/main_scroll.dart @@ -2,8 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flame/game.dart'; import 'package:flame/gestures.dart'; import 'package:flame/palette.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/extensions/offset.dart'; +import 'package:flame/extensions.dart'; void main() { final game = MyGame(); diff --git a/doc/examples/gestures/lib/main_tapables.dart b/doc/examples/gestures/lib/main_tapables.dart index 50985962c6e..3bd0c6354da 100644 --- a/doc/examples/gestures/lib/main_tapables.dart +++ b/doc/examples/gestures/lib/main_tapables.dart @@ -1,9 +1,7 @@ -import 'package:flame/anchor.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:flame/game.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/mixins/tapable.dart'; +import 'package:flame/extensions.dart'; void main() { runApp( diff --git a/doc/examples/isometric/lib/main.dart b/doc/examples/isometric/lib/main.dart index b5e16a9cb07..e971481f888 100644 --- a/doc/examples/isometric/lib/main.dart +++ b/doc/examples/isometric/lib/main.dart @@ -1,9 +1,6 @@ -import 'package:flame/components/sprite_component.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/components/isometric_tile_map_component.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/sprite.dart'; import 'package:flame/spritesheet.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart' hide Image; diff --git a/doc/examples/joystick/lib/main.dart b/doc/examples/joystick/lib/main.dart index 17cdc90c2c9..dceddc205a2 100644 --- a/doc/examples/joystick/lib/main.dart +++ b/doc/examples/joystick/lib/main.dart @@ -1,8 +1,6 @@ -import 'package:flame/components/joystick/joystick_action.dart'; -import 'package:flame/components/joystick/joystick_component.dart'; -import 'package:flame/components/joystick/joystick_directional.dart'; import 'package:flame/game.dart'; import 'package:flame/gestures.dart'; +import 'package:flame/joystick.dart'; import 'package:flutter/material.dart'; import 'player.dart'; diff --git a/doc/examples/joystick/lib/player.dart b/doc/examples/joystick/lib/player.dart index 26620a45fba..31c2b1a3232 100644 --- a/doc/examples/joystick/lib/player.dart +++ b/doc/examples/joystick/lib/player.dart @@ -1,11 +1,9 @@ import 'dart:math'; import 'dart:ui'; -import 'package:flame/components/component.dart'; -import 'package:flame/components/joystick/joystick_component.dart'; -import 'package:flame/components/joystick/joystick_events.dart'; +import 'package:flame/components.dart'; +import 'package:flame/joystick.dart'; import 'package:flame/palette.dart'; -import 'package:flame/extensions/vector2.dart'; class Player extends Component implements JoystickListener { final _whitePaint = BasicPalette.white.paint; diff --git a/doc/examples/layers/lib/main.dart b/doc/examples/layers/lib/main.dart index d39a085c441..8deb5e4f6ff 100644 --- a/doc/examples/layers/lib/main.dart +++ b/doc/examples/layers/lib/main.dart @@ -1,12 +1,12 @@ -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flutter/material.dart' hide Animation; -import 'package:flame/sprite.dart'; -import 'package:flame/layers/layer.dart'; import 'package:flame/flame.dart'; +import 'package:flame/layers.dart'; import 'dart:ui'; +import 'package:flutter/widgets.dart'; + void main() async { Flame.initializeWidget(); diff --git a/doc/examples/nine_tile_box/lib/main.dart b/doc/examples/nine_tile_box/lib/main.dart index 15b89c053f9..f850c9ea274 100644 --- a/doc/examples/nine_tile_box/lib/main.dart +++ b/doc/examples/nine_tile_box/lib/main.dart @@ -1,8 +1,5 @@ +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/nine_tile_box.dart'; -import 'package:flame/sprite.dart'; -import 'package:flame/extensions/vector2.dart'; - import 'package:flutter/material.dart'; void main() async { diff --git a/doc/examples/parallax/lib/main.dart b/doc/examples/parallax/lib/main.dart index 045b5c35750..8b5b0ca9e8d 100644 --- a/doc/examples/parallax/lib/main.dart +++ b/doc/examples/parallax/lib/main.dart @@ -1,6 +1,5 @@ +import 'package:flame/components.dart'; import 'package:flame/flame.dart'; -import 'package:flame/components/parallax_component.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; diff --git a/doc/examples/parallax/lib/main_advanced.dart b/doc/examples/parallax/lib/main_advanced.dart index 691b5e6b000..4e497cf53e6 100644 --- a/doc/examples/parallax/lib/main_advanced.dart +++ b/doc/examples/parallax/lib/main_advanced.dart @@ -1,7 +1,6 @@ +import 'package:flame/components.dart'; import 'package:flame/flame.dart'; import 'package:flame/parallax.dart'; -import 'package:flame/components/parallax_component.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; diff --git a/doc/examples/particles/lib/main.dart b/doc/examples/particles/lib/main.dart index 7c83673f89e..3a6867a896a 100644 --- a/doc/examples/particles/lib/main.dart +++ b/doc/examples/particles/lib/main.dart @@ -2,29 +2,12 @@ import 'dart:async'; import 'dart:math'; import 'dart:ui'; -import 'package:flame/sprite_animation.dart'; -import 'package:flame/components/component.dart'; -import 'package:flame/particles/circle_particle.dart'; -import 'package:flame/particles/composed_particle.dart'; -import 'package:flame/particles/curved_particle.dart'; -import 'package:flame/particles/moving_particle.dart'; -import 'package:flame/particles/sprite_particle.dart'; -import 'package:flame/particles/translated_particle.dart'; -import 'package:flame/particles/computed_particle.dart'; -import 'package:flame/particles/image_particle.dart'; -import 'package:flame/particles/rotating_particle.dart'; -import 'package:flame/particles/accelerated_particle.dart'; -import 'package:flame/particles/paint_particle.dart'; -import 'package:flame/particles/animation_particle.dart'; -import 'package:flame/particles/component_particle.dart'; +import 'package:flame/components.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; -import 'package:flame/timer.dart' as flame_time; -import 'package:flame/particle.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/sprite.dart'; +import 'package:flame/particles.dart'; import 'package:flame/spritesheet.dart'; -import 'package:flame/text_config.dart'; +import 'package:flame/timer.dart' as flame_timer; import 'package:flutter/material.dart' hide Image; void main() async { @@ -570,7 +553,7 @@ class SineCurve extends Curve { /// each 2s of registered lifetime. class TrafficLightComponent extends Component { final Rect rect = Rect.fromCenter(center: Offset.zero, height: 32, width: 32); - final flame_time.Timer colorChangeTimer = flame_time.Timer(2, repeat: true); + final flame_timer.Timer colorChangeTimer = flame_timer.Timer(2, repeat: true); final colors = [ Colors.green, Colors.orange, diff --git a/doc/examples/render_flip/lib/main.dart b/doc/examples/render_flip/lib/main.dart index c1ec8174f2d..95027ddc272 100644 --- a/doc/examples/render_flip/lib/main.dart +++ b/doc/examples/render_flip/lib/main.dart @@ -1,7 +1,5 @@ -import 'package:flame/sprite_animation.dart'; -import 'package:flame/components/sprite_animation_component.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/extensions/vector2.dart'; import 'package:flutter/material.dart' hide Image; import 'dart:ui'; diff --git a/doc/examples/sprite_batch/lib/main.dart b/doc/examples/sprite_batch/lib/main.dart index 0f454f4b8d3..167032686aa 100644 --- a/doc/examples/sprite_batch/lib/main.dart +++ b/doc/examples/sprite_batch/lib/main.dart @@ -1,10 +1,9 @@ import 'dart:math'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:flame/game.dart'; import 'package:flame/sprite_batch.dart'; -import 'package:flame/components/sprite_batch_component.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/doc/examples/sprites/lib/main.dart b/doc/examples/sprites/lib/main.dart index de5ce9d77fa..7bafdc71d6f 100644 --- a/doc/examples/sprites/lib/main.dart +++ b/doc/examples/sprites/lib/main.dart @@ -1,9 +1,8 @@ import 'dart:math'; -import 'package:flame/components/sprite_component.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/doc/examples/sprites/lib/main_base64.dart b/doc/examples/sprites/lib/main_base64.dart index eaceb1e55dc..d6299f35361 100644 --- a/doc/examples/sprites/lib/main_base64.dart +++ b/doc/examples/sprites/lib/main_base64.dart @@ -1,10 +1,10 @@ -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flutter/material.dart'; -import 'package:flame/sprite.dart'; import 'dart:ui'; +import 'package:flutter/widgets.dart'; + void main() { runApp( GameWidget( diff --git a/doc/examples/spritesheet/lib/main.dart b/doc/examples/spritesheet/lib/main.dart index 89e26521837..12259da3fb4 100644 --- a/doc/examples/spritesheet/lib/main.dart +++ b/doc/examples/spritesheet/lib/main.dart @@ -1,6 +1,4 @@ -import 'package:flame/components/sprite_animation_component.dart'; -import 'package:flame/components/sprite_component.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame/spritesheet.dart'; import 'package:flutter/material.dart'; diff --git a/doc/examples/text/lib/main.dart b/doc/examples/text/lib/main.dart index e78cc77156d..33f8d3678e3 100644 --- a/doc/examples/text/lib/main.dart +++ b/doc/examples/text/lib/main.dart @@ -1,11 +1,8 @@ import 'dart:ui'; -import 'package:flame/anchor.dart'; -import 'package:flame/components/text_box_component.dart'; -import 'package:flame/components/text_component.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame/palette.dart'; -import 'package:flame/text_config.dart'; import 'package:flutter/material.dart'; void main() { diff --git a/doc/examples/timer/lib/main.dart b/doc/examples/timer/lib/main.dart index 1393795b57b..8fc3d144e24 100644 --- a/doc/examples/timer/lib/main.dart +++ b/doc/examples/timer/lib/main.dart @@ -1,10 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flame/game.dart'; import 'package:flame/timer.dart'; -import 'package:flame/text_config.dart'; import 'package:flame/gestures.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/components/timer_component.dart'; void main() { runApp(MyGameApp()); diff --git a/doc/examples/widgets/lib/main.dart b/doc/examples/widgets/lib/main.dart index 8adf16afb53..acffeecc5d3 100644 --- a/doc/examples/widgets/lib/main.dart +++ b/doc/examples/widgets/lib/main.dart @@ -1,16 +1,10 @@ -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/widgets.dart'; import 'package:flutter/material.dart' hide Animation; import 'package:flame/flame.dart'; -import 'package:flame/sprite.dart'; import 'package:flame/spritesheet.dart'; import 'package:dashbook/dashbook.dart'; -import 'package:flame/widgets/nine_tile_box.dart'; -import 'package:flame/widgets/sprite_button.dart'; -import 'package:flame/widgets/sprite_widget.dart'; -import 'package:flame/widgets/animation_widget.dart'; -import 'package:flame/anchor.dart'; - Anchor parseAnchor(String name) { switch (name) { case 'Anchor.topLeft': diff --git a/example/lib/main.dart b/example/lib/main.dart index 970dec01e97..a169745aa08 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,9 @@ import 'dart:math' as math; import 'dart:ui'; -import 'package:flame/anchor.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/gestures.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/mixins/has_game_ref.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; +import 'package:flame/gestures.dart'; import 'package:flame/palette.dart'; import 'package:flutter/material.dart'; diff --git a/lib/components.dart b/lib/components.dart new file mode 100644 index 00000000000..ae4b7e36d65 --- /dev/null +++ b/lib/components.dart @@ -0,0 +1,21 @@ +export 'src/components/component.dart'; +export 'src/components/base_component.dart'; +export 'src/components/isometric_tile_map_component.dart'; +export 'src/components/nine_tile_box_component.dart'; +export 'src/components/parallax_component.dart'; +export 'src/components/particle_component.dart'; +export 'src/components/position_component.dart'; +export 'src/components/sprite_animation_component.dart'; +export 'src/components/sprite_batch_component.dart'; +export 'src/components/sprite_component.dart'; +export 'src/components/text_box_component.dart'; +export 'src/components/text_component.dart'; + +export 'src/components/mixins/draggable.dart'; +export 'src/components/mixins/has_game_ref.dart'; +export 'src/components/mixins/single_child_particle.dart'; +export 'src/components/mixins/tapable.dart'; + +export 'src/extensions/vector2.dart'; +export 'src/anchor.dart'; +export 'src/text_config.dart'; diff --git a/lib/components/timer_component.dart b/lib/components/timer_component.dart deleted file mode 100644 index 1d0e1d1d40f..00000000000 --- a/lib/components/timer_component.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'dart:ui'; - -import '../timer.dart'; -import 'component.dart'; - -/// Simple component which wraps a [Timer] instance allowing it to be easily used inside a [BaseGame] game. -class TimerComponent extends Component { - Timer timer; - - TimerComponent(this.timer); - - @override - void update(double dt) { - super.update(dt); - timer.update(dt); - } - - @override - void render(Canvas canvas) {} - - @override - bool get shouldRemove => timer.finished; -} diff --git a/lib/effects.dart b/lib/effects.dart new file mode 100644 index 00000000000..454c378099c --- /dev/null +++ b/lib/effects.dart @@ -0,0 +1,9 @@ +export 'src/effects/combined_effect.dart'; +export 'src/effects/effects.dart'; +export 'src/effects/effects_handler.dart'; +export 'src/effects/move_effect.dart'; +export 'src/effects/rotate_effect.dart'; +export 'src/effects/scale_effect.dart'; +export 'src/effects/sequence_effect.dart'; + +export 'src/extensions/vector2.dart'; diff --git a/lib/extensions.dart b/lib/extensions.dart new file mode 100644 index 00000000000..062bba021ae --- /dev/null +++ b/lib/extensions.dart @@ -0,0 +1,5 @@ +export 'src/extensions/canvas.dart'; +export 'src/extensions/offset.dart'; +export 'src/extensions/rect.dart'; +export 'src/extensions/size.dart'; +export 'src/extensions/vector2.dart'; diff --git a/lib/flame.dart b/lib/flame.dart index c1a843f92df..86e70164f3d 100644 --- a/lib/flame.dart +++ b/lib/flame.dart @@ -1,49 +1 @@ -library flame; - -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; - -import 'assets/assets_cache.dart'; -import 'assets/images.dart'; -import 'util.dart'; - -/// This class holds static references to some useful objects to use in your game. -/// -/// You can access shared instances of [AssetsCache], [Images] and [Util]. -/// Most games should need only one instance of each, and should use this class to manage that reference. -class Flame { - // Flame asset bundle, defaults to root - static AssetBundle _bundle; - static AssetBundle get bundle => _bundle ?? rootBundle; - - /// Access a shared instance of [AssetsCache] class. - static AssetsCache assets = AssetsCache(); - - /// Access a shared instance of the [Images] class. - static Images images = Images(); - - /// Access a shared instance of the [Util] class. - static Util util = Util(); - - static Future init({ - AssetBundle bundle, - bool fullScreen = true, - DeviceOrientation orientation, - }) async { - initializeWidget(); - - if (fullScreen) { - await util.fullScreen(); - } - - if (orientation != null) { - await util.setOrientation(orientation); - } - - _bundle = bundle; - } - - static void initializeWidget() { - WidgetsFlutterBinding.ensureInitialized(); - } -} +export 'src/flame.dart'; diff --git a/lib/game.dart b/lib/game.dart index 05b2f92fefc..0530c2691c7 100644 --- a/lib/game.dart +++ b/lib/game.dart @@ -1,4 +1,7 @@ -// Keeping compatible with earlier versions of Flame -export './game/base_game.dart'; -export './game/game.dart'; -export './game/game_widget.dart'; +export 'src/game/base_game.dart'; +export 'src/game/game.dart'; +export 'src/game/game_widget.dart'; + +export 'src/extensions/vector2.dart'; +export 'src/fps_counter.dart'; +export 'src/text_config.dart'; diff --git a/lib/gestures.dart b/lib/gestures.dart index 252d51668d6..ddd3c75c39a 100644 --- a/lib/gestures.dart +++ b/lib/gestures.dart @@ -1,111 +1 @@ -import 'package:flutter/gestures.dart'; - -import 'game/game.dart'; - -mixin MultiTouchTapDetector on Game { - void onTap(int pointerId) {} - void onTapCancel(int pointerId) {} - void onTapDown(int pointerId, TapDownDetails details) {} - void onTapUp(int pointerId, TapUpDetails details) {} - void onLongTapDown(int pointerId, TapDownDetails details) {} -} - -class DragEvent extends Drag { - final Offset initialPosition; - - DragEvent(this.initialPosition); - - void Function(DragUpdateDetails) onUpdate; - void Function() onCancel; - void Function(DragEndDetails) onEnd; - - @override - void update(details) { - onUpdate?.call(details); - } - - @override - void cancel() { - onCancel?.call(); - } - - @override - void end(details) { - onEnd?.call(details); - } -} - -mixin MultiTouchDragDetector on Game { - void onReceiveDrag(DragEvent drag) {} -} - -// Basic touch detectors -mixin TapDetector on Game { - void onTap() {} - void onTapCancel() {} - void onTapDown(TapDownDetails details) {} - void onTapUp(TapUpDetails details) {} -} - -mixin SecondaryTapDetector on Game { - void onSecondaryTapDown(TapDownDetails details) {} - void onSecondaryTapUp(TapUpDetails details) {} - void onSecondaryTapCancel() {} -} - -mixin DoubleTapDetector on Game { - void onDoubleTap() {} -} - -mixin LongPressDetector on Game { - void onLongPress() {} - void onLongPressStart(LongPressStartDetails details) {} - void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {} - void onLongPressUp() {} - void onLongPressEnd(LongPressEndDetails details) {} -} - -mixin VerticalDragDetector on Game { - void onVerticalDragDown(DragDownDetails details) {} - void onVerticalDragStart(DragStartDetails details) {} - void onVerticalDragUpdate(DragUpdateDetails details) {} - void onVerticalDragEnd(DragEndDetails details) {} - void onVerticalDragCancel() {} -} - -mixin HorizontalDragDetector on Game { - void onHorizontalDragDown(DragDownDetails details) {} - void onHorizontalDragStart(DragStartDetails details) {} - void onHorizontalDragUpdate(DragUpdateDetails details) {} - void onHorizontalDragEnd(DragEndDetails details) {} - void onHorizontalDragCancel() {} -} - -mixin ForcePressDetector on Game { - void onForcePressStart(ForcePressDetails details) {} - void onForcePressPeak(ForcePressDetails details) {} - void onForcePressUpdate(ForcePressDetails details) {} - void onForcePressEnd(ForcePressDetails details) {} -} - -mixin PanDetector on Game { - void onPanDown(DragDownDetails details) {} - void onPanStart(DragStartDetails details) {} - void onPanUpdate(DragUpdateDetails details) {} - void onPanEnd(DragEndDetails details) {} - void onPanCancel() {} -} - -mixin ScaleDetector on Game { - void onScaleStart(ScaleStartDetails details) {} - void onScaleUpdate(ScaleUpdateDetails details) {} - void onScaleEnd(ScaleEndDetails details) {} -} - -mixin MouseMovementDetector on Game { - void onMouseMove(PointerHoverEvent event) {} -} - -mixin ScrollDetector on Game { - void onScroll(PointerScrollEvent event) {} -} +export 'src/gestures.dart'; diff --git a/lib/joystick.dart b/lib/joystick.dart new file mode 100644 index 00000000000..f48b02e7733 --- /dev/null +++ b/lib/joystick.dart @@ -0,0 +1,7 @@ +export 'src/components/joystick/joystick_action.dart'; +export 'src/components/joystick/joystick_component.dart'; +export 'src/components/joystick/joystick_directional.dart'; +export 'src/components/joystick/joystick_events.dart'; +export 'src/components/joystick/joystick_utils.dart'; + +export 'src/sprite.dart'; diff --git a/lib/keyboard.dart b/lib/keyboard.dart index 0317cf11dfa..16c5a53d3c0 100644 --- a/lib/keyboard.dart +++ b/lib/keyboard.dart @@ -1,7 +1 @@ -import 'package:flutter/services.dart'; - -import 'game.dart'; - -mixin KeyboardEvents on Game { - void onKeyEvent(RawKeyEvent event); -} +export 'src/keyboard.dart'; diff --git a/lib/layers.dart b/lib/layers.dart new file mode 100644 index 00000000000..c65598dc34a --- /dev/null +++ b/lib/layers.dart @@ -0,0 +1,2 @@ +export 'src/layers/layer.dart'; +export 'src/layers/processors.dart'; diff --git a/lib/palette.dart b/lib/palette.dart index c4854740763..96a3dd4572e 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -1,30 +1 @@ -import 'dart:ui'; - -class PaletteEntry { - final Color color; - - Paint get paint => Paint()..color = color; - - const PaletteEntry(this.color); - - PaletteEntry withAlpha(int alpha) { - return PaletteEntry(color.withAlpha(alpha)); - } - - PaletteEntry withRed(int red) { - return PaletteEntry(color.withRed(red)); - } - - PaletteEntry withGreen(int green) { - return PaletteEntry(color.withGreen(green)); - } - - PaletteEntry withBlue(int blue) { - return PaletteEntry(color.withBlue(blue)); - } -} - -class BasicPalette { - static const PaletteEntry white = PaletteEntry(Color(0xFFFFFFFF)); - static const PaletteEntry black = PaletteEntry(Color(0xFF000000)); -} +export 'src/palette.dart'; diff --git a/lib/parallax.dart b/lib/parallax.dart index 274c1aeebaa..5b115bb6f90 100644 --- a/lib/parallax.dart +++ b/lib/parallax.dart @@ -1,315 +1 @@ -import 'dart:async'; -import 'dart:ui'; - -import 'package:flutter/painting.dart'; - -import 'assets/images.dart'; -import 'extensions/rect.dart'; -import 'extensions/vector2.dart'; -import 'flame.dart'; -import 'game/game.dart'; - -extension ParallaxExtension on Game { - Future loadParallax( - List paths, { - Vector2 baseVelocity, - Vector2 velocityMultiplierDelta, - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - }) { - return Parallax.load( - paths, - baseVelocity: baseVelocity, - velocityMultiplierDelta: velocityMultiplierDelta, - repeat: repeat, - alignment: alignment, - fill: fill, - images: images, - ); - } - - Future loadParallaxImage( - String path, { - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - }) { - return ParallaxImage.load( - path, - repeat: repeat, - alignment: alignment, - fill: fill, - images: images, - ); - } - - Future loadParallaxLayer( - String path, { - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - Vector2 velocityMultiplier, - }) { - return ParallaxLayer.load( - path, - velocityMultiplier: velocityMultiplier, - repeat: repeat, - alignment: alignment, - fill: fill, - images: images, - ); - } -} - -/// Specifications with a path to an image and how it should be drawn in -/// relation to the device screen -class ParallaxImage { - /// The image - final Image image; - - /// If and how the image should be repeated on the canvas - final ImageRepeat repeat; - - /// How to align the image in relation to the screen - final Alignment alignment; - - /// How to fill the screen with the image, always proportionally scaled. - final LayerFill fill; - - ParallaxImage( - this.image, { - this.repeat = ImageRepeat.repeatX, - this.alignment = Alignment.bottomLeft, - this.fill = LayerFill.height, - }); - - /// Takes a path of an image, and optionally arguments for how the image should - /// repeat ([repeat]), which edge it should align with ([alignment]), which axis - /// it should fill the image on ([fill]) and [images] which is the image cache - /// that should be used. If no image cache is set, the global flame cache is used. - static Future load( - String path, { - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - Images images, - }) async { - images ??= Flame.images; - return ParallaxImage( - await images.load(path), - repeat: repeat, - alignment: alignment, - fill: fill, - ); - } -} - -/// Represents one layer in the parallax, draws out an image on a canvas in the -/// manner specified by the parallaxImage -class ParallaxLayer { - final ParallaxImage parallaxImage; - Vector2 velocityMultiplier; - Rect _paintArea; - Vector2 _scroll; - Vector2 _imageSize; - double _scale = 1.0; - - /// [parallaxImage] is the representation of the image with data of how the - /// image should behave. - /// [velocityMultiplier] will be used to determine the velocity of the layer by - /// multiplying the [baseVelocity] with the [velocityMultiplier]. - ParallaxLayer( - this.parallaxImage, { - Vector2 velocityMultiplier, - }) : velocityMultiplier = velocityMultiplier ?? Vector2.all(1.0); - - Vector2 currentOffset() => _scroll; - - void resize(Vector2 size) { - double scale(LayerFill fill) { - switch (fill) { - case LayerFill.height: - return parallaxImage.image.height / size.y; - case LayerFill.width: - return parallaxImage.image.width / size.x; - default: - return _scale; - } - } - - _scale = scale(parallaxImage.fill); - - // The image size so that it fulfills the LayerFill parameter - _imageSize = Vector2Extension.fromInts( - parallaxImage.image.width, - parallaxImage.image.height, - ) / - _scale; - - // Number of images that can fit on the canvas plus one - // to have something to scroll to without leaving canvas empty - final Vector2 count = Vector2.all(1) + (size.clone()..divide(_imageSize)); - - // Percentage of the image size that will overflow - final Vector2 overflow = ((_imageSize.clone()..multiply(count)) - size) - ..divide(_imageSize); - - // Align image to correct side of the screen - final alignment = parallaxImage.alignment; - final marginX = alignment.x == 0 ? overflow.x / 2 : alignment.x; - final marginY = alignment.y == 0 ? overflow.y / 2 : alignment.y; - _scroll ??= Vector2(marginX, marginY); - - // Size of the area to paint the images on - final Vector2 paintSize = count..multiply(_imageSize); - _paintArea = paintSize.toRect(); - } - - void update(Vector2 delta) { - // Scale the delta so that images that are larger don't scroll faster - _scroll += delta.clone()..divide(_imageSize); - switch (parallaxImage.repeat) { - case ImageRepeat.repeat: - _scroll = Vector2(_scroll.x % 1, _scroll.y % 1); - break; - case ImageRepeat.repeatX: - _scroll = Vector2(_scroll.x % 1, _scroll.y); - break; - case ImageRepeat.repeatY: - _scroll = Vector2(_scroll.x, _scroll.y % 1); - break; - case ImageRepeat.noRepeat: - break; - } - - final Vector2 scrollPosition = _scroll.clone()..multiply(_imageSize); - _paintArea = Rect.fromLTWH( - -scrollPosition.x, - -scrollPosition.y, - _paintArea.width, - _paintArea.height, - ); - } - - void render(Canvas canvas) { - paintImage( - canvas: canvas, - image: parallaxImage.image, - rect: _paintArea, - repeat: parallaxImage.repeat, - scale: _scale, - alignment: parallaxImage.alignment, - ); - } - - /// Takes a path of an image, and optionally arguments for how the image should - /// repeat ([repeat]), which edge it should align with ([alignment]), which axis - /// it should fill the image on ([fill]) and [images] which is the image cache - /// that should be used. If no image cache is set, the global flame cache is used. - static Future load( - String path, { - Vector2 velocityMultiplier, - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - Images images, - }) async { - return ParallaxLayer( - await ParallaxImage.load( - path, - repeat: repeat, - alignment: alignment, - fill: fill, - images: images, - ), - velocityMultiplier: velocityMultiplier, - ); - } -} - -/// How to fill the screen with the image, always proportionally scaled. -enum LayerFill { height, width, none } - -/// A full parallax, several layers of images drawn out on the screen and each -/// layer moves with different velocities to give an effect of depth. -class Parallax { - Vector2 baseVelocity; - final List layers; - - Parallax( - this.layers, { - Vector2 baseVelocity, - }) : baseVelocity = baseVelocity ?? Vector2.zero(); - - /// The base offset of the parallax, can be used in an outer update loop - /// if you want to transition the parallax to a certain position. - Vector2 currentOffset() => layers[0].currentOffset(); - - /// If the `ParallaxComponent` isn't used your own wrapper needs to call this - /// on creation. - void resize(Vector2 size) => layers.forEach((layer) => layer.resize(size)); - - void update(double t) { - layers.forEach((layer) { - layer.update( - (baseVelocity.clone()..multiply(layer.velocityMultiplier)) * t, - ); - }); - } - - /// Note that this method only should be used if all of your layers should - /// have the same layer arguments (how the images should be repeated, aligned - /// and filled), otherwise load the [ParallaxLayer]s individually and use the - /// normal constructor. - /// - /// [load] takes a list of paths to all the images that you want to use in the - /// parallax. - /// Optionally arguments for the [baseVelocity] and [layerDelta] can be passed - /// in, [baseVelocity] defines what the base velocity of the layers should be - /// and [velocityMultiplierDelta] defines how the velocity should change the - /// closer the layer is ([velocityMultiplierDelta ^ n], where n is the - /// layer index). - /// Arguments for how all the images should repeat ([repeat]), - /// which edge it should align with ([alignment]), which axis it should fill - /// the image on ([fill]) and [images] which is the image cache that should be - /// used can also be passed in. - /// If no image cache is set, the global flame cache is used. - static Future load( - List paths, { - Vector2 baseVelocity, - Vector2 velocityMultiplierDelta, - ImageRepeat repeat = ImageRepeat.repeatX, - Alignment alignment = Alignment.bottomLeft, - LayerFill fill = LayerFill.height, - Images images, - }) async { - velocityMultiplierDelta ??= Vector2.all(1.0); - int depth = 0; - final layers = await Future.wait( - paths.map((path) async { - final image = ParallaxImage.load( - path, - repeat: repeat, - alignment: alignment, - fill: fill, - images: images, - ); - final velocityMultiplier = - List.filled(depth, velocityMultiplierDelta).fold( - velocityMultiplierDelta, - (previousValue, delta) => previousValue.clone()..multiply(delta), - ); - ++depth; - return ParallaxLayer( - await image, - velocityMultiplier: velocityMultiplier, - ); - }), - ); - return Parallax( - layers, - baseVelocity: baseVelocity, - ); - } -} +export 'src/parallax.dart'; diff --git a/lib/particles.dart b/lib/particles.dart new file mode 100644 index 00000000000..4b0fd119c14 --- /dev/null +++ b/lib/particles.dart @@ -0,0 +1,18 @@ +export 'src/particles/particle.dart'; + +export 'src/particles/accelerated_particle.dart'; +export 'src/particles/animation_particle.dart'; +export 'src/particles/circle_particle.dart'; +export 'src/particles/component_particle.dart'; +export 'src/particles/composed_particle.dart'; +export 'src/particles/computed_particle.dart'; +export 'src/particles/curved_particle.dart'; +export 'src/particles/image_particle.dart'; +export 'src/particles/moving_particle.dart'; +export 'src/particles/paint_particle.dart'; +export 'src/particles/rotating_particle.dart'; +export 'src/particles/scaled_particle.dart'; +export 'src/particles/sprite_particle.dart'; +export 'src/particles/translated_particle.dart'; + +export 'src/anchor.dart'; diff --git a/lib/sprite_batch.dart b/lib/sprite_batch.dart index 1899e10b0e4..790deceb84c 100644 --- a/lib/sprite_batch.dart +++ b/lib/sprite_batch.dart @@ -1,295 +1 @@ -import 'dart:collection'; -import 'dart:ui'; - -import 'package:flutter/foundation.dart'; - -import 'assets/images.dart'; -import 'extensions/vector2.dart'; -import 'flame.dart'; -import 'game/game.dart'; - -extension SpriteBatchExtension on Game { - /// Utility method to load and cache the image for a [SpriteBatch] based on its options - Future loadSpriteBatch( - String path, { - Color defaultColor = const Color(0x00000000), - BlendMode defaultBlendMode = BlendMode.srcOver, - RSTransform defaultTransform, - }) { - return SpriteBatch.load( - path, - defaultColor: defaultColor, - defaultBlendMode: defaultBlendMode, - defaultTransform: defaultTransform, - images: images, - ); - } -} - -/// This is the scale value used in [BatchItem.matrix], we can't determine this from the [Batchitem.transform], -/// but we also don't need to do so because it is already calculated inside the transform values. -const _defaultScale = 0.0; - -/// A single item in a SpriteBatch. -/// -/// Holds all the important information of a batch item, -/// -/// Web currently does not support `Canvas.drawAtlas`, so a BatchItem will -/// automatically calculate a transform matrix based on the [transform] value, to be -/// used when rendering on the web. It will initialize a [destination] object -/// and a [paint] object. -class BatchItem { - /// The source rectangle on the [SpriteBatch.atlas]. - final Rect source; - - /// The destination rectangle for the Canvas. - /// - /// It will be transformed by [matrix]. - final Rect destination; - - /// The transform values for this batch item. - final RSTransform transform; - - /// The background color for this batch item. - final Color color; - - /// Fallback matrix for the web. - /// - /// Because `Canvas.drawAtlas` is not supported on the web we also - /// build a `Matrix4` based on the [transform] values. - final Matrix4 matrix; - - /// Paint object used for the web. - final Paint paint; - - BatchItem({ - @required this.source, - @required this.transform, - @required this.color, - }) : assert(source != null), - assert(transform != null), - assert(color != null), - matrix = Matrix4( - transform.scos, transform.ssin, 0, 0, // - -transform.ssin, transform.scos, 0, 0, // - 0, 0, _defaultScale, 0, // - transform.tx, transform.ty, 0, 1, // - ), - paint = Paint()..color = color, - destination = Offset.zero & source.size; -} - -/// The SpriteBatch API allows for rendering multiple items at once. -/// -/// This class allows for optimization when you want to draw many parts of an -/// image onto the canvas. It is more efficient than using multiple calls to [drawImageRect] -/// and provides more functionality by allowing each [BatchItem] to have their own transform -/// rotation and color. -/// -/// By collecting all the necessary transforms on a single image and sending those transforms -/// in a single batch to the GPU, we can render multiple parts of a single image at once. -/// -/// **Note**: Currently web does not support `Canvas.drawAtlas`, which SpriteBatch uses under -/// the hood, instead it will render each [BatchItem] using `Canvas.drawImageRect`, so there -/// might be a performance hit on web when working with many batch items. -class SpriteBatch { - /// List of all the existing batch items. - final _batchItems = []; - - /// The sources to use on the [atlas]. - final _sources = []; - - /// The sources list shouldn't be modified directly, that is why an - /// [UnmodifiableListView] is used. If you want to add sources use the - /// [add] or [addTransform] method. - UnmodifiableListView get sources { - return UnmodifiableListView(_sources); - } - - /// The transforms that should be applied on the [_sources]. - final _transforms = []; - - /// The transforms list shouldn't be modified directly, that is why an - /// [UnmodifiableListView] is used. If you want to add transforms use the - /// [add] or [addTransform] method. - UnmodifiableListView get transforms { - return UnmodifiableListView(_transforms); - } - - /// The background color for the [_sources]. - final _colors = []; - - /// The colors list shouldn't be modified directly, that is why an - /// [UnmodifiableListView] is used. If you want to add colors use the - /// [add] or [addTransform] method. - UnmodifiableListView get colors { - return UnmodifiableListView(_colors); - } - - /// The atlas used by the [SpriteBatch]. - final Image atlas; - - /// The default color, used as a background color for a [BatchItem]. - final Color defaultColor; - - /// The default transform, used when a transform was not supplied for a [BatchItem]. - final RSTransform defaultTransform; - - /// The default blend mode, used for blending a batch item. - final BlendMode defaultBlendMode; - - /// The width of the [atlas]. - int get width => atlas.width; - - /// The height of the [atlas]. - int get height => atlas.height; - - /// The size of the [atlas]. - Vector2 get size => Vector2Extension.fromInts(width, height); - - SpriteBatch( - this.atlas, { - this.defaultColor = const Color(0x00000000), - this.defaultBlendMode = BlendMode.srcOver, - this.defaultTransform, - }) : assert(atlas != null), - assert(defaultColor != null); - - /// Takes a path of an image, and optional arguments for the SpriteBatch. - /// - /// When the [images] is omitted, the global [Flame.images] is used. - static Future load( - String path, { - Color defaultColor = const Color(0x00000000), - BlendMode defaultBlendMode = BlendMode.srcOver, - RSTransform defaultTransform, - Images images, - }) async { - final _images = images ?? Flame.images; - return SpriteBatch( - await _images.load(path), - defaultColor: defaultColor, - defaultTransform: defaultTransform ?? RSTransform(1, 0, 0, 0), - defaultBlendMode: defaultBlendMode, - ); - } - - /// Add a new batch item using a RSTransform. - /// - /// The [source] parameter is the source location on the [atlas]. You can position it - /// on the canvas using the [offset] parameter. - /// - /// The [color] paramater allows you to render a color behind the batch item, as a background color. - /// - /// The [add] method may be a simpler way to add a batch item to the batch. However, - /// if there is a way to factor out the computations of the sine and cosine of the - /// rotation so that they can be reused over multiple calls to this constructor, - /// it may be more efficient to directly use this method instead. - void addTransform({ - @required Rect source, - RSTransform transform, - Color color, - }) { - final batchItem = BatchItem( - source: source, - transform: transform ??= defaultTransform ?? RSTransform(1, 0, 0, 0), - color: color ?? defaultColor, - ); - - _batchItems.add(batchItem); - - _sources.add(batchItem.source); - _transforms.add(batchItem.transform); - _colors.add(batchItem.color); - } - - /// Add a new batch item. - /// - /// The [source] parameter is the source location on the [atlas]. You can position it - /// on the canvas using the [offset] parameter. - /// - /// You can transform the sprite from its [offset] using [scale], [rotation] and [anchor]. - /// - /// The [color] paramater allows you to render a color behind the batch item, as a background color. - /// - /// This method creates a new [RSTransform] based on the given transform arguments. If many [RSTransform] objects are being - /// created and there is a way to factor out the computations of the sine and cosine of the rotation - /// (which are computed each time this method is called) and reuse them over multiple [RSTransform] objects, - /// it may be more efficient to directly use the more direct [addTransform] method instead. - void add({ - @required Rect source, - double scale = 1.0, - Vector2 anchor, - double rotation = 0, - Vector2 offset, - Color color, - }) { - anchor ??= Vector2.zero(); - offset ??= Vector2.zero(); - RSTransform transform; - - // If any of the transform arguments is different from the defaults, - // then we create one. This is to prevent unnecessary computations - // of the sine and cosine of the rotation. - if (scale != 1.0 || - anchor != Vector2.zero() || - rotation != 0 || - offset != Vector2.zero()) { - transform = RSTransform.fromComponents( - scale: scale, - anchorX: anchor.x, - anchorY: anchor.y, - rotation: rotation, - translateX: offset.x, - translateY: offset.y, - ); - } - - addTransform(source: source, transform: transform, color: color); - } - - /// Clear the SpriteBatch so it can be reused. - void clear() { - _sources.clear(); - _transforms.clear(); - _colors.clear(); - _batchItems.clear(); - } - - void render( - Canvas canvas, { - BlendMode blendMode, - Rect cullRect, - Paint paint, - }) { - paint ??= Paint(); - - if (kIsWeb) { - for (final batchItem in _batchItems) { - paint..blendMode = blendMode ?? paint.blendMode ?? defaultBlendMode; - - canvas - ..save() - ..transform(batchItem.matrix.storage) - ..drawRect(batchItem.destination, batchItem.paint) - ..drawImageRect( - atlas, - batchItem.source, - batchItem.destination, - paint, - ) - ..restore(); - } - } else { - canvas.drawAtlas( - atlas, - _transforms, - _sources, - _colors, - blendMode ?? defaultBlendMode, - cullRect, - paint, - ); - } - } -} +export 'src/sprite_batch.dart'; diff --git a/lib/spritesheet.dart b/lib/spritesheet.dart index af8a91b69ac..b34ae469a27 100644 --- a/lib/spritesheet.dart +++ b/lib/spritesheet.dart @@ -1,105 +1 @@ -import 'dart:ui'; - -import 'package:meta/meta.dart'; - -import 'extensions/vector2.dart'; -import 'sprite.dart'; -import 'sprite_animation.dart'; - -/// Utility class to help extract animations and sprites from a sprite sheet image. -/// -/// A sprite sheet is a single image in which several regions can be defined as individual sprites. -/// For the purposes of this class, all of these regions must be identically sized rectangles. -/// You can use the [Sprite] class directly if you want to have varying shapes. -/// -/// Each sprite in this sheet can be identified either by it's (row, col) pair or -/// by it's "id", which is basically it's sequenced index if the image is put in a -/// single line. The sprites can be used to compose an animation easily if they -/// all the frames happen to be sequentially on the same row. -/// Sprites are lazily generated but cached. -class SpriteSheet { - /// The src image from which each sprite will be generated. - final Image image; - - /// The size of each rectangle within the image that define each sprite. - /// - /// For example, if this sprite sheet is a tile map, this would be the tile size. - /// If it's an animation sheet, this would be the frame size. - final Vector2 srcSize; - - final Map _spriteCache = {}; - - /// Creates a sprite sheet given the image and the tile size. - SpriteSheet({ - @required this.image, - @required this.srcSize, - }); - - SpriteSheet.fromColumnsAndRows({ - @required this.image, - @required int columns, - @required int rows, - }) : srcSize = Vector2( - image.width / columns, - image.height / rows, - ); - - /// Compute the number of columns the image has - /// by using the image width and tile size. - int get columns => image.width ~/ srcSize.x; - - /// Compute the number of rows the image has - /// by using the image height and tile size. - int get rows => image.height ~/ srcSize.y; - - /// Gets the sprite in the position (row, column) on the sprite sheet grid. - /// - /// This is lazily computed and cached for your convenience. - Sprite getSprite(int row, int column) { - return getSpriteById(row * columns + column); - } - - /// Gets teh sprite with id [spriteId] from the grid. - /// - /// The ids are defined as starting at 0 on the top left and going - /// sequentially on each row. - /// This is lazily computed and cached for your convenience. - Sprite getSpriteById(int spriteId) { - return _spriteCache[spriteId] ??= _computeSprite(spriteId); - } - - Sprite _computeSprite(int spriteId) { - final i = spriteId % columns; - final j = spriteId ~/ columns; - return Sprite( - image, - srcPosition: Vector2Extension.fromInts(i, j)..multiply(srcSize), - srcSize: srcSize, - ); - } - - /// Creates a [SpriteAnimation] from this SpriteSheet, using the sequence - /// of sprites on a given row. - /// - /// [from] and [to] can be specified to create an animation - /// from a subset of the columns on the row - SpriteAnimation createAnimation({ - @required int row, - @required double stepTime, - bool loop = true, - int from = 0, - int to, - }) { - to ??= columns; - - final spriteList = List.generate(to - from, (i) => from + i) - .map((e) => getSprite(row, e)) - .toList(); - - return SpriteAnimation.spriteList( - spriteList, - stepTime: stepTime, - loop: loop, - ); - } -} +export 'src/spritesheet.dart'; diff --git a/lib/anchor.dart b/lib/src/anchor.dart similarity index 100% rename from lib/anchor.dart rename to lib/src/anchor.dart diff --git a/lib/assets/assets_cache.dart b/lib/src/assets/assets_cache.dart similarity index 100% rename from lib/assets/assets_cache.dart rename to lib/src/assets/assets_cache.dart diff --git a/lib/assets/images.dart b/lib/src/assets/images.dart similarity index 100% rename from lib/assets/images.dart rename to lib/src/assets/images.dart diff --git a/lib/components/base_component.dart b/lib/src/components/base_component.dart similarity index 99% rename from lib/components/base_component.dart rename to lib/src/components/base_component.dart index e8a2de1c44f..446301739af 100644 --- a/lib/components/base_component.dart +++ b/lib/src/components/base_component.dart @@ -5,10 +5,10 @@ import 'package:meta/meta.dart'; import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/ordered_set.dart'; +import '../../game.dart'; import '../effects/effects.dart'; import '../effects/effects_handler.dart'; import '../extensions/vector2.dart'; -import '../game.dart'; import '../text_config.dart'; import 'component.dart'; import 'mixins/has_game_ref.dart'; diff --git a/lib/components/component.dart b/lib/src/components/component.dart similarity index 98% rename from lib/components/component.dart rename to lib/src/components/component.dart index b99900f6aa2..9c17d86e019 100644 --- a/lib/components/component.dart +++ b/lib/src/components/component.dart @@ -1,10 +1,9 @@ import 'dart:ui'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; import '../extensions/vector2.dart'; -import '../game.dart'; /// This represents a Component for your game. /// diff --git a/lib/components/isometric_tile_map_component.dart b/lib/src/components/isometric_tile_map_component.dart similarity index 100% rename from lib/components/isometric_tile_map_component.dart rename to lib/src/components/isometric_tile_map_component.dart diff --git a/lib/components/joystick/joystick_action.dart b/lib/src/components/joystick/joystick_action.dart similarity index 100% rename from lib/components/joystick/joystick_action.dart rename to lib/src/components/joystick/joystick_action.dart diff --git a/lib/components/joystick/joystick_component.dart b/lib/src/components/joystick/joystick_component.dart similarity index 100% rename from lib/components/joystick/joystick_component.dart rename to lib/src/components/joystick/joystick_component.dart diff --git a/lib/components/joystick/joystick_directional.dart b/lib/src/components/joystick/joystick_directional.dart similarity index 100% rename from lib/components/joystick/joystick_directional.dart rename to lib/src/components/joystick/joystick_directional.dart diff --git a/lib/components/joystick/joystick_events.dart b/lib/src/components/joystick/joystick_events.dart similarity index 100% rename from lib/components/joystick/joystick_events.dart rename to lib/src/components/joystick/joystick_events.dart diff --git a/lib/components/joystick/joystick_utils.dart b/lib/src/components/joystick/joystick_utils.dart similarity index 100% rename from lib/components/joystick/joystick_utils.dart rename to lib/src/components/joystick/joystick_utils.dart diff --git a/lib/components/mixins/draggable.dart b/lib/src/components/mixins/draggable.dart similarity index 100% rename from lib/components/mixins/draggable.dart rename to lib/src/components/mixins/draggable.dart diff --git a/lib/components/mixins/has_game_ref.dart b/lib/src/components/mixins/has_game_ref.dart similarity index 62% rename from lib/components/mixins/has_game_ref.dart rename to lib/src/components/mixins/has_game_ref.dart index 312e2f565d4..441dff8573d 100644 --- a/lib/components/mixins/has_game_ref.dart +++ b/lib/src/components/mixins/has_game_ref.dart @@ -1,4 +1,4 @@ -import '../../game.dart'; +import '../../game/game.dart'; mixin HasGameRef { T gameRef; diff --git a/lib/components/mixins/single_child_particle.dart b/lib/src/components/mixins/single_child_particle.dart similarity index 95% rename from lib/components/mixins/single_child_particle.dart rename to lib/src/components/mixins/single_child_particle.dart index c98f0eb8fcd..0a1ed2479df 100644 --- a/lib/components/mixins/single_child_particle.dart +++ b/lib/src/components/mixins/single_child_particle.dart @@ -1,6 +1,6 @@ import 'dart:ui'; -import '../../particle.dart'; +import '../../particles/particle.dart'; /// Implements basic behavior for nesting [Particle] instances /// into each other. diff --git a/lib/components/mixins/tapable.dart b/lib/src/components/mixins/tapable.dart similarity index 100% rename from lib/components/mixins/tapable.dart rename to lib/src/components/mixins/tapable.dart diff --git a/lib/components/nine_tile_box_component.dart b/lib/src/components/nine_tile_box_component.dart similarity index 95% rename from lib/components/nine_tile_box_component.dart rename to lib/src/components/nine_tile_box_component.dart index 88e489ddd75..bcbb9cb6af9 100644 --- a/lib/components/nine_tile_box_component.dart +++ b/lib/src/components/nine_tile_box_component.dart @@ -6,6 +6,8 @@ import '../extensions/vector2.dart'; import '../nine_tile_box.dart'; import 'position_component.dart'; +export '../nine_tile_box.dart'; + /// This class is a thin wrapper on top of [NineTileBox] as a component. class NineTileBoxComponent extends PositionComponent { NineTileBox nineTileBox; diff --git a/lib/components/parallax_component.dart b/lib/src/components/parallax_component.dart similarity index 99% rename from lib/components/parallax_component.dart rename to lib/src/components/parallax_component.dart index 854f976fad5..3af84652946 100644 --- a/lib/components/parallax_component.dart +++ b/lib/src/components/parallax_component.dart @@ -6,7 +6,7 @@ import 'package:flutter/painting.dart'; import '../assets/images.dart'; import '../extensions/vector2.dart'; -import '../game.dart'; +import '../game/game.dart'; import '../parallax.dart'; import 'position_component.dart'; diff --git a/lib/components/particle_component.dart b/lib/src/components/particle_component.dart similarity index 96% rename from lib/components/particle_component.dart rename to lib/src/components/particle_component.dart index 5f6f38faaf0..383203bc775 100644 --- a/lib/components/particle_component.dart +++ b/lib/src/components/particle_component.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import '../particle.dart'; +import '../particles/particle.dart'; import 'component.dart'; /// Base container for [Particle] instances to be attach diff --git a/lib/components/position_component.dart b/lib/src/components/position_component.dart similarity index 100% rename from lib/components/position_component.dart rename to lib/src/components/position_component.dart diff --git a/lib/components/sprite_animation_component.dart b/lib/src/components/sprite_animation_component.dart similarity index 98% rename from lib/components/sprite_animation_component.dart rename to lib/src/components/sprite_animation_component.dart index 2193ec96bfd..989642fe6f4 100644 --- a/lib/components/sprite_animation_component.dart +++ b/lib/src/components/sprite_animation_component.dart @@ -6,6 +6,8 @@ import '../extensions/vector2.dart'; import '../sprite_animation.dart'; import 'position_component.dart'; +export '../sprite_animation.dart'; + class SpriteAnimationComponent extends PositionComponent { SpriteAnimation animation; Paint overridePaint; diff --git a/lib/components/sprite_batch_component.dart b/lib/src/components/sprite_batch_component.dart similarity index 100% rename from lib/components/sprite_batch_component.dart rename to lib/src/components/sprite_batch_component.dart diff --git a/lib/components/sprite_component.dart b/lib/src/components/sprite_component.dart similarity index 97% rename from lib/components/sprite_component.dart rename to lib/src/components/sprite_component.dart index 5db737b3287..152bbe6a9a0 100644 --- a/lib/components/sprite_component.dart +++ b/lib/src/components/sprite_component.dart @@ -7,6 +7,8 @@ import '../sprite.dart'; import 'component.dart'; import 'position_component.dart'; +export '../sprite.dart'; + /// A [PositionComponent] that renders a single [Sprite] at the designated /// position, scaled to have the designated size and rotated to the specified /// angle. diff --git a/lib/components/text_box_component.dart b/lib/src/components/text_box_component.dart similarity index 100% rename from lib/components/text_box_component.dart rename to lib/src/components/text_box_component.dart diff --git a/lib/components/text_component.dart b/lib/src/components/text_component.dart similarity index 100% rename from lib/components/text_component.dart rename to lib/src/components/text_component.dart diff --git a/lib/effects/combined_effect.dart b/lib/src/effects/combined_effect.dart similarity index 100% rename from lib/effects/combined_effect.dart rename to lib/src/effects/combined_effect.dart diff --git a/lib/effects/effects.dart b/lib/src/effects/effects.dart similarity index 100% rename from lib/effects/effects.dart rename to lib/src/effects/effects.dart diff --git a/lib/effects/effects_handler.dart b/lib/src/effects/effects_handler.dart similarity index 100% rename from lib/effects/effects_handler.dart rename to lib/src/effects/effects_handler.dart diff --git a/lib/effects/move_effect.dart b/lib/src/effects/move_effect.dart similarity index 100% rename from lib/effects/move_effect.dart rename to lib/src/effects/move_effect.dart diff --git a/lib/effects/rotate_effect.dart b/lib/src/effects/rotate_effect.dart similarity index 100% rename from lib/effects/rotate_effect.dart rename to lib/src/effects/rotate_effect.dart diff --git a/lib/effects/scale_effect.dart b/lib/src/effects/scale_effect.dart similarity index 100% rename from lib/effects/scale_effect.dart rename to lib/src/effects/scale_effect.dart diff --git a/lib/effects/sequence_effect.dart b/lib/src/effects/sequence_effect.dart similarity index 100% rename from lib/effects/sequence_effect.dart rename to lib/src/effects/sequence_effect.dart diff --git a/lib/extensions/canvas.dart b/lib/src/extensions/canvas.dart similarity index 100% rename from lib/extensions/canvas.dart rename to lib/src/extensions/canvas.dart diff --git a/lib/extensions/offset.dart b/lib/src/extensions/offset.dart similarity index 100% rename from lib/extensions/offset.dart rename to lib/src/extensions/offset.dart diff --git a/lib/extensions/rect.dart b/lib/src/extensions/rect.dart similarity index 100% rename from lib/extensions/rect.dart rename to lib/src/extensions/rect.dart diff --git a/lib/extensions/size.dart b/lib/src/extensions/size.dart similarity index 100% rename from lib/extensions/size.dart rename to lib/src/extensions/size.dart diff --git a/lib/extensions/vector2.dart b/lib/src/extensions/vector2.dart similarity index 100% rename from lib/extensions/vector2.dart rename to lib/src/extensions/vector2.dart diff --git a/lib/src/flame.dart b/lib/src/flame.dart new file mode 100644 index 00000000000..c1a843f92df --- /dev/null +++ b/lib/src/flame.dart @@ -0,0 +1,49 @@ +library flame; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +import 'assets/assets_cache.dart'; +import 'assets/images.dart'; +import 'util.dart'; + +/// This class holds static references to some useful objects to use in your game. +/// +/// You can access shared instances of [AssetsCache], [Images] and [Util]. +/// Most games should need only one instance of each, and should use this class to manage that reference. +class Flame { + // Flame asset bundle, defaults to root + static AssetBundle _bundle; + static AssetBundle get bundle => _bundle ?? rootBundle; + + /// Access a shared instance of [AssetsCache] class. + static AssetsCache assets = AssetsCache(); + + /// Access a shared instance of the [Images] class. + static Images images = Images(); + + /// Access a shared instance of the [Util] class. + static Util util = Util(); + + static Future init({ + AssetBundle bundle, + bool fullScreen = true, + DeviceOrientation orientation, + }) async { + initializeWidget(); + + if (fullScreen) { + await util.fullScreen(); + } + + if (orientation != null) { + await util.setOrientation(orientation); + } + + _bundle = bundle; + } + + static void initializeWidget() { + WidgetsFlutterBinding.ensureInitialized(); + } +} diff --git a/lib/fps_counter.dart b/lib/src/fps_counter.dart similarity index 100% rename from lib/fps_counter.dart rename to lib/src/fps_counter.dart diff --git a/lib/game/base_game.dart b/lib/src/game/base_game.dart similarity index 100% rename from lib/game/base_game.dart rename to lib/src/game/base_game.dart diff --git a/lib/game/game.dart b/lib/src/game/game.dart similarity index 100% rename from lib/game/game.dart rename to lib/src/game/game.dart diff --git a/lib/game/game_loop.dart b/lib/src/game/game_loop.dart similarity index 100% rename from lib/game/game_loop.dart rename to lib/src/game/game_loop.dart diff --git a/lib/game/game_render_box.dart b/lib/src/game/game_render_box.dart similarity index 100% rename from lib/game/game_render_box.dart rename to lib/src/game/game_render_box.dart diff --git a/lib/game/game_widget.dart b/lib/src/game/game_widget.dart similarity index 100% rename from lib/game/game_widget.dart rename to lib/src/game/game_widget.dart diff --git a/lib/src/gestures.dart b/lib/src/gestures.dart new file mode 100644 index 00000000000..252d51668d6 --- /dev/null +++ b/lib/src/gestures.dart @@ -0,0 +1,111 @@ +import 'package:flutter/gestures.dart'; + +import 'game/game.dart'; + +mixin MultiTouchTapDetector on Game { + void onTap(int pointerId) {} + void onTapCancel(int pointerId) {} + void onTapDown(int pointerId, TapDownDetails details) {} + void onTapUp(int pointerId, TapUpDetails details) {} + void onLongTapDown(int pointerId, TapDownDetails details) {} +} + +class DragEvent extends Drag { + final Offset initialPosition; + + DragEvent(this.initialPosition); + + void Function(DragUpdateDetails) onUpdate; + void Function() onCancel; + void Function(DragEndDetails) onEnd; + + @override + void update(details) { + onUpdate?.call(details); + } + + @override + void cancel() { + onCancel?.call(); + } + + @override + void end(details) { + onEnd?.call(details); + } +} + +mixin MultiTouchDragDetector on Game { + void onReceiveDrag(DragEvent drag) {} +} + +// Basic touch detectors +mixin TapDetector on Game { + void onTap() {} + void onTapCancel() {} + void onTapDown(TapDownDetails details) {} + void onTapUp(TapUpDetails details) {} +} + +mixin SecondaryTapDetector on Game { + void onSecondaryTapDown(TapDownDetails details) {} + void onSecondaryTapUp(TapUpDetails details) {} + void onSecondaryTapCancel() {} +} + +mixin DoubleTapDetector on Game { + void onDoubleTap() {} +} + +mixin LongPressDetector on Game { + void onLongPress() {} + void onLongPressStart(LongPressStartDetails details) {} + void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {} + void onLongPressUp() {} + void onLongPressEnd(LongPressEndDetails details) {} +} + +mixin VerticalDragDetector on Game { + void onVerticalDragDown(DragDownDetails details) {} + void onVerticalDragStart(DragStartDetails details) {} + void onVerticalDragUpdate(DragUpdateDetails details) {} + void onVerticalDragEnd(DragEndDetails details) {} + void onVerticalDragCancel() {} +} + +mixin HorizontalDragDetector on Game { + void onHorizontalDragDown(DragDownDetails details) {} + void onHorizontalDragStart(DragStartDetails details) {} + void onHorizontalDragUpdate(DragUpdateDetails details) {} + void onHorizontalDragEnd(DragEndDetails details) {} + void onHorizontalDragCancel() {} +} + +mixin ForcePressDetector on Game { + void onForcePressStart(ForcePressDetails details) {} + void onForcePressPeak(ForcePressDetails details) {} + void onForcePressUpdate(ForcePressDetails details) {} + void onForcePressEnd(ForcePressDetails details) {} +} + +mixin PanDetector on Game { + void onPanDown(DragDownDetails details) {} + void onPanStart(DragStartDetails details) {} + void onPanUpdate(DragUpdateDetails details) {} + void onPanEnd(DragEndDetails details) {} + void onPanCancel() {} +} + +mixin ScaleDetector on Game { + void onScaleStart(ScaleStartDetails details) {} + void onScaleUpdate(ScaleUpdateDetails details) {} + void onScaleEnd(ScaleEndDetails details) {} +} + +mixin MouseMovementDetector on Game { + void onMouseMove(PointerHoverEvent event) {} +} + +mixin ScrollDetector on Game { + void onScroll(PointerScrollEvent event) {} +} diff --git a/lib/src/keyboard.dart b/lib/src/keyboard.dart new file mode 100644 index 00000000000..03314229838 --- /dev/null +++ b/lib/src/keyboard.dart @@ -0,0 +1,7 @@ +import 'package:flutter/services.dart'; + +import './game/game.dart'; + +mixin KeyboardEvents on Game { + void onKeyEvent(RawKeyEvent event); +} diff --git a/lib/layers/layer.dart b/lib/src/layers/layer.dart similarity index 98% rename from lib/layers/layer.dart rename to lib/src/layers/layer.dart index 3b75e755502..701ca3f45cd 100644 --- a/lib/layers/layer.dart +++ b/lib/src/layers/layer.dart @@ -4,8 +4,6 @@ import 'package:meta/meta.dart'; import 'processors.dart'; -export 'processors.dart'; - abstract class Layer { List preProcessors = []; List postProcessors = []; diff --git a/lib/layers/processors.dart b/lib/src/layers/processors.dart similarity index 100% rename from lib/layers/processors.dart rename to lib/src/layers/processors.dart diff --git a/lib/memory_cache.dart b/lib/src/memory_cache.dart similarity index 100% rename from lib/memory_cache.dart rename to lib/src/memory_cache.dart diff --git a/lib/nine_tile_box.dart b/lib/src/nine_tile_box.dart similarity index 100% rename from lib/nine_tile_box.dart rename to lib/src/nine_tile_box.dart diff --git a/lib/src/palette.dart b/lib/src/palette.dart new file mode 100644 index 00000000000..c4854740763 --- /dev/null +++ b/lib/src/palette.dart @@ -0,0 +1,30 @@ +import 'dart:ui'; + +class PaletteEntry { + final Color color; + + Paint get paint => Paint()..color = color; + + const PaletteEntry(this.color); + + PaletteEntry withAlpha(int alpha) { + return PaletteEntry(color.withAlpha(alpha)); + } + + PaletteEntry withRed(int red) { + return PaletteEntry(color.withRed(red)); + } + + PaletteEntry withGreen(int green) { + return PaletteEntry(color.withGreen(green)); + } + + PaletteEntry withBlue(int blue) { + return PaletteEntry(color.withBlue(blue)); + } +} + +class BasicPalette { + static const PaletteEntry white = PaletteEntry(Color(0xFFFFFFFF)); + static const PaletteEntry black = PaletteEntry(Color(0xFF000000)); +} diff --git a/lib/src/parallax.dart b/lib/src/parallax.dart new file mode 100644 index 00000000000..274c1aeebaa --- /dev/null +++ b/lib/src/parallax.dart @@ -0,0 +1,315 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/painting.dart'; + +import 'assets/images.dart'; +import 'extensions/rect.dart'; +import 'extensions/vector2.dart'; +import 'flame.dart'; +import 'game/game.dart'; + +extension ParallaxExtension on Game { + Future loadParallax( + List paths, { + Vector2 baseVelocity, + Vector2 velocityMultiplierDelta, + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + }) { + return Parallax.load( + paths, + baseVelocity: baseVelocity, + velocityMultiplierDelta: velocityMultiplierDelta, + repeat: repeat, + alignment: alignment, + fill: fill, + images: images, + ); + } + + Future loadParallaxImage( + String path, { + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + }) { + return ParallaxImage.load( + path, + repeat: repeat, + alignment: alignment, + fill: fill, + images: images, + ); + } + + Future loadParallaxLayer( + String path, { + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + Vector2 velocityMultiplier, + }) { + return ParallaxLayer.load( + path, + velocityMultiplier: velocityMultiplier, + repeat: repeat, + alignment: alignment, + fill: fill, + images: images, + ); + } +} + +/// Specifications with a path to an image and how it should be drawn in +/// relation to the device screen +class ParallaxImage { + /// The image + final Image image; + + /// If and how the image should be repeated on the canvas + final ImageRepeat repeat; + + /// How to align the image in relation to the screen + final Alignment alignment; + + /// How to fill the screen with the image, always proportionally scaled. + final LayerFill fill; + + ParallaxImage( + this.image, { + this.repeat = ImageRepeat.repeatX, + this.alignment = Alignment.bottomLeft, + this.fill = LayerFill.height, + }); + + /// Takes a path of an image, and optionally arguments for how the image should + /// repeat ([repeat]), which edge it should align with ([alignment]), which axis + /// it should fill the image on ([fill]) and [images] which is the image cache + /// that should be used. If no image cache is set, the global flame cache is used. + static Future load( + String path, { + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + Images images, + }) async { + images ??= Flame.images; + return ParallaxImage( + await images.load(path), + repeat: repeat, + alignment: alignment, + fill: fill, + ); + } +} + +/// Represents one layer in the parallax, draws out an image on a canvas in the +/// manner specified by the parallaxImage +class ParallaxLayer { + final ParallaxImage parallaxImage; + Vector2 velocityMultiplier; + Rect _paintArea; + Vector2 _scroll; + Vector2 _imageSize; + double _scale = 1.0; + + /// [parallaxImage] is the representation of the image with data of how the + /// image should behave. + /// [velocityMultiplier] will be used to determine the velocity of the layer by + /// multiplying the [baseVelocity] with the [velocityMultiplier]. + ParallaxLayer( + this.parallaxImage, { + Vector2 velocityMultiplier, + }) : velocityMultiplier = velocityMultiplier ?? Vector2.all(1.0); + + Vector2 currentOffset() => _scroll; + + void resize(Vector2 size) { + double scale(LayerFill fill) { + switch (fill) { + case LayerFill.height: + return parallaxImage.image.height / size.y; + case LayerFill.width: + return parallaxImage.image.width / size.x; + default: + return _scale; + } + } + + _scale = scale(parallaxImage.fill); + + // The image size so that it fulfills the LayerFill parameter + _imageSize = Vector2Extension.fromInts( + parallaxImage.image.width, + parallaxImage.image.height, + ) / + _scale; + + // Number of images that can fit on the canvas plus one + // to have something to scroll to without leaving canvas empty + final Vector2 count = Vector2.all(1) + (size.clone()..divide(_imageSize)); + + // Percentage of the image size that will overflow + final Vector2 overflow = ((_imageSize.clone()..multiply(count)) - size) + ..divide(_imageSize); + + // Align image to correct side of the screen + final alignment = parallaxImage.alignment; + final marginX = alignment.x == 0 ? overflow.x / 2 : alignment.x; + final marginY = alignment.y == 0 ? overflow.y / 2 : alignment.y; + _scroll ??= Vector2(marginX, marginY); + + // Size of the area to paint the images on + final Vector2 paintSize = count..multiply(_imageSize); + _paintArea = paintSize.toRect(); + } + + void update(Vector2 delta) { + // Scale the delta so that images that are larger don't scroll faster + _scroll += delta.clone()..divide(_imageSize); + switch (parallaxImage.repeat) { + case ImageRepeat.repeat: + _scroll = Vector2(_scroll.x % 1, _scroll.y % 1); + break; + case ImageRepeat.repeatX: + _scroll = Vector2(_scroll.x % 1, _scroll.y); + break; + case ImageRepeat.repeatY: + _scroll = Vector2(_scroll.x, _scroll.y % 1); + break; + case ImageRepeat.noRepeat: + break; + } + + final Vector2 scrollPosition = _scroll.clone()..multiply(_imageSize); + _paintArea = Rect.fromLTWH( + -scrollPosition.x, + -scrollPosition.y, + _paintArea.width, + _paintArea.height, + ); + } + + void render(Canvas canvas) { + paintImage( + canvas: canvas, + image: parallaxImage.image, + rect: _paintArea, + repeat: parallaxImage.repeat, + scale: _scale, + alignment: parallaxImage.alignment, + ); + } + + /// Takes a path of an image, and optionally arguments for how the image should + /// repeat ([repeat]), which edge it should align with ([alignment]), which axis + /// it should fill the image on ([fill]) and [images] which is the image cache + /// that should be used. If no image cache is set, the global flame cache is used. + static Future load( + String path, { + Vector2 velocityMultiplier, + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + Images images, + }) async { + return ParallaxLayer( + await ParallaxImage.load( + path, + repeat: repeat, + alignment: alignment, + fill: fill, + images: images, + ), + velocityMultiplier: velocityMultiplier, + ); + } +} + +/// How to fill the screen with the image, always proportionally scaled. +enum LayerFill { height, width, none } + +/// A full parallax, several layers of images drawn out on the screen and each +/// layer moves with different velocities to give an effect of depth. +class Parallax { + Vector2 baseVelocity; + final List layers; + + Parallax( + this.layers, { + Vector2 baseVelocity, + }) : baseVelocity = baseVelocity ?? Vector2.zero(); + + /// The base offset of the parallax, can be used in an outer update loop + /// if you want to transition the parallax to a certain position. + Vector2 currentOffset() => layers[0].currentOffset(); + + /// If the `ParallaxComponent` isn't used your own wrapper needs to call this + /// on creation. + void resize(Vector2 size) => layers.forEach((layer) => layer.resize(size)); + + void update(double t) { + layers.forEach((layer) { + layer.update( + (baseVelocity.clone()..multiply(layer.velocityMultiplier)) * t, + ); + }); + } + + /// Note that this method only should be used if all of your layers should + /// have the same layer arguments (how the images should be repeated, aligned + /// and filled), otherwise load the [ParallaxLayer]s individually and use the + /// normal constructor. + /// + /// [load] takes a list of paths to all the images that you want to use in the + /// parallax. + /// Optionally arguments for the [baseVelocity] and [layerDelta] can be passed + /// in, [baseVelocity] defines what the base velocity of the layers should be + /// and [velocityMultiplierDelta] defines how the velocity should change the + /// closer the layer is ([velocityMultiplierDelta ^ n], where n is the + /// layer index). + /// Arguments for how all the images should repeat ([repeat]), + /// which edge it should align with ([alignment]), which axis it should fill + /// the image on ([fill]) and [images] which is the image cache that should be + /// used can also be passed in. + /// If no image cache is set, the global flame cache is used. + static Future load( + List paths, { + Vector2 baseVelocity, + Vector2 velocityMultiplierDelta, + ImageRepeat repeat = ImageRepeat.repeatX, + Alignment alignment = Alignment.bottomLeft, + LayerFill fill = LayerFill.height, + Images images, + }) async { + velocityMultiplierDelta ??= Vector2.all(1.0); + int depth = 0; + final layers = await Future.wait( + paths.map((path) async { + final image = ParallaxImage.load( + path, + repeat: repeat, + alignment: alignment, + fill: fill, + images: images, + ); + final velocityMultiplier = + List.filled(depth, velocityMultiplierDelta).fold( + velocityMultiplierDelta, + (previousValue, delta) => previousValue.clone()..multiply(delta), + ); + ++depth; + return ParallaxLayer( + await image, + velocityMultiplier: velocityMultiplier, + ); + }), + ); + return Parallax( + layers, + baseVelocity: baseVelocity, + ); + } +} diff --git a/lib/particles/accelerated_particle.dart b/lib/src/particles/accelerated_particle.dart similarity index 97% rename from lib/particles/accelerated_particle.dart rename to lib/src/particles/accelerated_particle.dart index b505b06a378..145dd397b75 100644 --- a/lib/particles/accelerated_particle.dart +++ b/lib/src/particles/accelerated_particle.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; import 'curved_particle.dart'; /// A particle serves as a container for basic diff --git a/lib/particles/animation_particle.dart b/lib/src/particles/animation_particle.dart similarity index 94% rename from lib/particles/animation_particle.dart rename to lib/src/particles/animation_particle.dart index d0f2d4a05b7..600a211a751 100644 --- a/lib/particles/animation_particle.dart +++ b/lib/src/particles/animation_particle.dart @@ -4,9 +4,11 @@ import 'package:flutter/foundation.dart'; import '../anchor.dart'; import '../extensions/vector2.dart'; -import '../particle.dart'; +import 'particle.dart'; import '../sprite_animation.dart'; +export '../sprite_animation.dart'; + class SpriteAnimationParticle extends Particle { final SpriteAnimation animation; final Vector2 size; diff --git a/lib/particles/circle_particle.dart b/lib/src/particles/circle_particle.dart similarity index 94% rename from lib/particles/circle_particle.dart rename to lib/src/particles/circle_particle.dart index 5aac07c8ff8..743eb1babfd 100644 --- a/lib/particles/circle_particle.dart +++ b/lib/src/particles/circle_particle.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import '../particle.dart'; +import 'particle.dart'; /// Plain circle with no other behaviors /// Consider composing with other [Particle] diff --git a/lib/particles/component_particle.dart b/lib/src/particles/component_particle.dart similarity index 95% rename from lib/particles/component_particle.dart rename to lib/src/particles/component_particle.dart index 28769d86568..c31ca34a73c 100644 --- a/lib/particles/component_particle.dart +++ b/lib/src/particles/component_particle.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import '../components/component.dart'; import '../extensions/vector2.dart'; -import '../particle.dart'; +import 'particle.dart'; class ComponentParticle extends Particle { final Component component; diff --git a/lib/particles/composed_particle.dart b/lib/src/particles/composed_particle.dart similarity index 96% rename from lib/particles/composed_particle.dart rename to lib/src/particles/composed_particle.dart index fe123a7aeb8..d10fe0e9d29 100644 --- a/lib/particles/composed_particle.dart +++ b/lib/src/particles/composed_particle.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import '../particle.dart'; +import 'particle.dart'; /// A single [Particle] which manages multiple children /// by proxying all lifecycle hooks. diff --git a/lib/particles/computed_particle.dart b/lib/src/particles/computed_particle.dart similarity index 96% rename from lib/particles/computed_particle.dart rename to lib/src/particles/computed_particle.dart index 0ee9216ddab..b1738a5c89b 100644 --- a/lib/particles/computed_particle.dart +++ b/lib/src/particles/computed_particle.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import '../particle.dart'; +import 'particle.dart'; /// A function which should render desired contents /// onto a given canvas. External state needed for diff --git a/lib/particles/curved_particle.dart b/lib/src/particles/curved_particle.dart similarity index 93% rename from lib/particles/curved_particle.dart rename to lib/src/particles/curved_particle.dart index e1579c79700..4702568661f 100644 --- a/lib/particles/curved_particle.dart +++ b/lib/src/particles/curved_particle.dart @@ -1,6 +1,6 @@ import 'package:flutter/animation.dart'; -import '../particle.dart'; +import 'particle.dart'; /// A [Particle] which applies certain [Curve] for /// easing or other purposes to its [progress] getter. diff --git a/lib/particles/image_particle.dart b/lib/src/particles/image_particle.dart similarity index 97% rename from lib/particles/image_particle.dart rename to lib/src/particles/image_particle.dart index 5ba9fe2244e..03e73c5140b 100644 --- a/lib/particles/image_particle.dart +++ b/lib/src/particles/image_particle.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../extensions/vector2.dart'; -import '../particle.dart'; +import 'particle.dart'; /// A [Particle] which renders given [Image] on a [Canvas] /// image is centered. If any other behavior is needed, consider diff --git a/lib/particles/moving_particle.dart b/lib/src/particles/moving_particle.dart similarity index 97% rename from lib/particles/moving_particle.dart rename to lib/src/particles/moving_particle.dart index 1542c865670..31ae6fac5d1 100644 --- a/lib/particles/moving_particle.dart +++ b/lib/src/particles/moving_particle.dart @@ -4,7 +4,7 @@ import 'package:flutter/animation.dart'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; import '../particles/curved_particle.dart'; /// Statically offset given child [Particle] by given [Offset] diff --git a/lib/particles/paint_particle.dart b/lib/src/particles/paint_particle.dart similarity index 97% rename from lib/particles/paint_particle.dart rename to lib/src/particles/paint_particle.dart index 599c01dd146..821be4602c8 100644 --- a/lib/particles/paint_particle.dart +++ b/lib/src/particles/paint_particle.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; import 'curved_particle.dart'; /// A particle which renders its child with certain [Paint] diff --git a/lib/particle.dart b/lib/src/particles/particle.dart similarity index 93% rename from lib/particle.dart rename to lib/src/particles/particle.dart index 17bbe109219..90ce52a5016 100644 --- a/lib/particle.dart +++ b/lib/src/particles/particle.dart @@ -4,15 +4,15 @@ import 'dart:ui'; import 'package:flutter/animation.dart'; import 'package:flutter/foundation.dart'; -import 'components/component.dart'; -import 'components/particle_component.dart'; -import 'particles/accelerated_particle.dart'; -import 'particles/composed_particle.dart'; -import 'particles/moving_particle.dart'; -import 'particles/rotating_particle.dart'; -import 'particles/scaled_particle.dart'; -import 'particles/translated_particle.dart'; -import 'timer.dart'; +import '../components/component.dart'; +import '../components/particle_component.dart'; +import 'accelerated_particle.dart'; +import 'composed_particle.dart'; +import 'moving_particle.dart'; +import 'rotating_particle.dart'; +import 'scaled_particle.dart'; +import 'translated_particle.dart'; +import '../timer.dart'; /// A function which returns [Particle] when called typedef ParticleGenerator = Particle Function(int); diff --git a/lib/particles/rotating_particle.dart b/lib/src/particles/rotating_particle.dart similarity index 96% rename from lib/particles/rotating_particle.dart rename to lib/src/particles/rotating_particle.dart index eca8136fbb1..6e371fcdbed 100644 --- a/lib/particles/rotating_particle.dart +++ b/lib/src/particles/rotating_particle.dart @@ -4,7 +4,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; import 'curved_particle.dart'; /// A particle which rotates its child over the lifespan diff --git a/lib/particles/scaled_particle.dart b/lib/src/particles/scaled_particle.dart similarity index 96% rename from lib/particles/scaled_particle.dart rename to lib/src/particles/scaled_particle.dart index e327226f793..75fd3c37e25 100644 --- a/lib/particles/scaled_particle.dart +++ b/lib/src/particles/scaled_particle.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; import 'curved_particle.dart'; /// A particle which rotates its child over the lifespan diff --git a/lib/particles/sprite_particle.dart b/lib/src/particles/sprite_particle.dart similarity index 92% rename from lib/particles/sprite_particle.dart rename to lib/src/particles/sprite_particle.dart index 49a30c5fd87..9063aca8a78 100644 --- a/lib/particles/sprite_particle.dart +++ b/lib/src/particles/sprite_particle.dart @@ -3,10 +3,12 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../anchor.dart'; -import '../particle.dart'; +import 'particle.dart'; import '../sprite.dart'; import '../extensions/vector2.dart'; +export '../sprite.dart'; + class SpriteParticle extends Particle { final Sprite sprite; final Vector2 size; diff --git a/lib/particles/translated_particle.dart b/lib/src/particles/translated_particle.dart similarity index 96% rename from lib/particles/translated_particle.dart rename to lib/src/particles/translated_particle.dart index 70c3551bd05..69eacc142ab 100644 --- a/lib/particles/translated_particle.dart +++ b/lib/src/particles/translated_particle.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import '../components/mixins/single_child_particle.dart'; -import '../particle.dart'; +import 'particle.dart'; /// Statically offset given child [Particle] by given [Offset] /// If you're loking to move the child, consider [MovingParticle] diff --git a/lib/profiler.dart b/lib/src/profiler.dart similarity index 100% rename from lib/profiler.dart rename to lib/src/profiler.dart diff --git a/lib/sprite.dart b/lib/src/sprite.dart similarity index 100% rename from lib/sprite.dart rename to lib/src/sprite.dart diff --git a/lib/sprite_animation.dart b/lib/src/sprite_animation.dart similarity index 99% rename from lib/sprite_animation.dart rename to lib/src/sprite_animation.dart index d729a73b61f..a482bd11afd 100644 --- a/lib/sprite_animation.dart +++ b/lib/src/sprite_animation.dart @@ -6,6 +6,8 @@ import 'extensions/vector2.dart'; import 'flame.dart'; import 'sprite.dart'; +export 'sprite.dart'; + class SpriteAnimationFrameData { /// Coordinates of the sprite of this Frame final Vector2 srcPosition; diff --git a/lib/src/sprite_batch.dart b/lib/src/sprite_batch.dart new file mode 100644 index 00000000000..0411a0679b5 --- /dev/null +++ b/lib/src/sprite_batch.dart @@ -0,0 +1,295 @@ +import 'dart:collection'; +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; + +import 'assets/images.dart'; +import 'extensions/vector2.dart'; +import 'flame.dart'; +import 'game/game.dart'; + +extension SpriteBatchExtension on Game { + /// Utility method to load and cache the image for a [SpriteBatch] based on its options + Future loadSpriteBatch( + String path, { + Color defaultColor = const Color(0x00000000), + BlendMode defaultBlendMode = BlendMode.srcOver, + RSTransform defaultTransform, + }) { + return SpriteBatch.load( + path, + defaultColor: defaultColor, + defaultBlendMode: defaultBlendMode, + defaultTransform: defaultTransform, + images: images, + ); + } +} + +/// This is the scale value used in [BatchItem.matrix], we can't determine this from the [Batchitem.transform], +/// but we also don't need to do so because it is already calculated inside the transform values. +const _defaultScale = 0.0; + +/// A single item in a SpriteBatch. +/// +/// Holds all the important information of a batch item, +/// +/// Web currently does not support `Canvas.drawAtlas`, so a BatchItem will +/// automatically calculate a transform matrix based on the [transform] value, to be +/// used when rendering on the web. It will initialize a [destination] object +/// and a [paint] object. +class BatchItem { + /// The source rectangle on the [SpriteBatch.atlas]. + final Rect source; + + /// The destination rectangle for the Canvas. + /// + /// It will be transformed by [matrix]. + final Rect destination; + + /// The transform values for this batch item. + final RSTransform transform; + + /// The background color for this batch item. + final Color color; + + /// Fallback matrix for the web. + /// + /// Because `Canvas.drawAtlas` is not supported on the web we also + /// build a `Matrix4` based on the [transform] values. + final Matrix4 matrix; + + /// Paint object used for the web. + final Paint paint; + + BatchItem({ + @required this.source, + @required this.transform, + @required this.color, + }) : assert(source != null), + assert(transform != null), + assert(color != null), + matrix = Matrix4( + transform.scos, transform.ssin, 0, 0, // + -transform.ssin, transform.scos, 0, 0, // + 0, 0, _defaultScale, 0, // + transform.tx, transform.ty, 0, 1, // + ), + paint = Paint()..color = color, + destination = Offset.zero & source.size; +} + +/// The SpriteBatch API allows for rendering multiple items at once. +/// +/// This class allows for optimization when you want to draw many parts of an +/// image onto the canvas. It is more efficient than using multiple calls to [drawImageRect] +/// and provides more functionality by allowing each [BatchItem] to have their own transform +/// rotation and color. +/// +/// By collecting all the necessary transforms on a single image and sending those transforms +/// in a single batch to the GPU, we can render multiple parts of a single image at once. +/// +/// **Note**: Currently web does not support `Canvas.drawAtlas`, which SpriteBatch uses under +/// the hood, instead it will render each [BatchItem] using `Canvas.drawImageRect`, so there +/// might be a performance hit on web when working with many batch items. +class SpriteBatch { + /// List of all the existing batch items. + final _batchItems = []; + + /// The sources to use on the [atlas]. + final _sources = []; + + /// The sources list shouldn't be modified directly, that is why an + /// [UnmodifiableListView] is used. If you want to add sources use the + /// [add] or [addTransform] method. + UnmodifiableListView get sources { + return UnmodifiableListView(_sources); + } + + /// The transforms that should be applied on the [_sources]. + final _transforms = []; + + /// The transforms list shouldn't be modified directly, that is why an + /// [UnmodifiableListView] is used. If you want to add transforms use the + /// [add] or [addTransform] method. + UnmodifiableListView get transforms { + return UnmodifiableListView(_transforms); + } + + /// The background color for the [_sources]. + final _colors = []; + + /// The colors list shouldn't be modified directly, that is why an + /// [UnmodifiableListView] is used. If you want to add colors use the + /// [add] or [addTransform] method. + UnmodifiableListView get colors { + return UnmodifiableListView(_colors); + } + + /// The atlas used by the [SpriteBatch]. + final Image atlas; + + /// The default color, used as a background color for a [BatchItem]. + final Color defaultColor; + + /// The default transform, used when a transform was not supplied for a [BatchItem]. + final RSTransform defaultTransform; + + /// The default blend mode, used for blending a batch item. + final BlendMode defaultBlendMode; + + /// The width of the [atlas]. + int get width => atlas.width; + + /// The height of the [atlas]. + int get height => atlas.height; + + /// The size of the [atlas]. + Vector2 get size => Vector2Extension.fromInts(width, height); + + SpriteBatch( + this.atlas, { + this.defaultColor = const Color(0x00000000), + this.defaultBlendMode = BlendMode.srcOver, + this.defaultTransform, + }) : assert(atlas != null), + assert(defaultColor != null); + + /// Takes a path of an image, and optional arguments for the SpriteBatch. + /// + /// When the [images] is omitted, the global [Flame.images] is used. + static Future load( + String path, { + Color defaultColor = const Color(0x00000000), + BlendMode defaultBlendMode = BlendMode.srcOver, + RSTransform defaultTransform, + Images images, + }) async { + final _images = images ?? Flame.images; + return SpriteBatch( + await _images.load(path), + defaultColor: defaultColor, + defaultTransform: defaultTransform ?? RSTransform(1, 0, 0, 0), + defaultBlendMode: defaultBlendMode, + ); + } + + /// Add a new batch item using a RSTransform. + /// + /// The [source] parameter is the source location on the [atlas]. You can position it + /// on the canvas using the [offset] parameter. + /// + /// The [color] paramater allows you to render a color behind the batch item, as a background color. + /// + /// The [add] method may be a simpler way to add a batch item to the batch. However, + /// if there is a way to factor out the computations of the sine and cosine of the + /// rotation so that they can be reused over multiple calls to this constructor, + /// it may be more efficient to directly use this method instead. + void addTransform({ + @required Rect source, + RSTransform transform, + Color color, + }) { + final batchItem = BatchItem( + source: source, + transform: transform ??= defaultTransform ?? RSTransform(1, 0, 0, 0), + color: color ?? defaultColor, + ); + + _batchItems.add(batchItem); + + _sources.add(batchItem.source); + _transforms.add(batchItem.transform); + _colors.add(batchItem.color); + } + + /// Add a new batch item. + /// + /// The [source] parameter is the source location on the [atlas]. You can position it + /// on the canvas using the [offset] parameter. + /// + /// You can transform the sprite from its [offset] using [scale], [rotation] and [anchor]. + /// + /// The [color] paramater allows you to render a color behind the batch item, as a background color. + /// + /// This method creates a new [RSTransform] based on the given transform arguments. If many [RSTransform] objects are being + /// created and there is a way to factor out the computations of the sine and cosine of the rotation + /// (which are computed each time this method is called) and reuse them over multiple [RSTransform] objects, + /// it may be more efficient to directly use the more direct [addTransform] method instead. + void add({ + @required Rect source, + double scale = 1.0, + Vector2 anchor, + double rotation = 0, + Vector2 offset, + Color color, + }) { + anchor ??= Vector2.zero(); + offset ??= Vector2.zero(); + RSTransform transform; + + // If any of the transform arguments is different from the defaults, + // then we create one. This is to prevent unnecessary computations + // of the sine and cosine of the rotation. + if (scale != 1.0 || + anchor != Vector2.zero() || + rotation != 0 || + offset != Vector2.zero()) { + transform = RSTransform.fromComponents( + scale: scale, + anchorX: anchor.x, + anchorY: anchor.y, + rotation: rotation, + translateX: offset.x, + translateY: offset.y, + ); + } + + addTransform(source: source, transform: transform, color: color); + } + + /// Clear the SpriteBatch so it can be reused. + void clear() { + _sources.clear(); + _transforms.clear(); + _colors.clear(); + _batchItems.clear(); + } + + void render( + Canvas canvas, { + BlendMode blendMode, + Rect cullRect, + Paint paint, + }) { + paint ??= Paint(); + + if (kIsWeb) { + for (final batchItem in _batchItems) { + paint..blendMode = blendMode ?? paint.blendMode ?? defaultBlendMode; + + canvas + ..save() + ..transform(batchItem.matrix.storage) + ..drawRect(batchItem.destination, batchItem.paint) + ..drawImageRect( + atlas, + batchItem.source, + batchItem.destination, + paint, + ) + ..restore(); + } + } else { + canvas.drawAtlas( + atlas, + _transforms, + _sources, + _colors, + blendMode ?? defaultBlendMode, + cullRect, + paint, + ); + } + } +} \ No newline at end of file diff --git a/lib/src/spritesheet.dart b/lib/src/spritesheet.dart new file mode 100644 index 00000000000..af8a91b69ac --- /dev/null +++ b/lib/src/spritesheet.dart @@ -0,0 +1,105 @@ +import 'dart:ui'; + +import 'package:meta/meta.dart'; + +import 'extensions/vector2.dart'; +import 'sprite.dart'; +import 'sprite_animation.dart'; + +/// Utility class to help extract animations and sprites from a sprite sheet image. +/// +/// A sprite sheet is a single image in which several regions can be defined as individual sprites. +/// For the purposes of this class, all of these regions must be identically sized rectangles. +/// You can use the [Sprite] class directly if you want to have varying shapes. +/// +/// Each sprite in this sheet can be identified either by it's (row, col) pair or +/// by it's "id", which is basically it's sequenced index if the image is put in a +/// single line. The sprites can be used to compose an animation easily if they +/// all the frames happen to be sequentially on the same row. +/// Sprites are lazily generated but cached. +class SpriteSheet { + /// The src image from which each sprite will be generated. + final Image image; + + /// The size of each rectangle within the image that define each sprite. + /// + /// For example, if this sprite sheet is a tile map, this would be the tile size. + /// If it's an animation sheet, this would be the frame size. + final Vector2 srcSize; + + final Map _spriteCache = {}; + + /// Creates a sprite sheet given the image and the tile size. + SpriteSheet({ + @required this.image, + @required this.srcSize, + }); + + SpriteSheet.fromColumnsAndRows({ + @required this.image, + @required int columns, + @required int rows, + }) : srcSize = Vector2( + image.width / columns, + image.height / rows, + ); + + /// Compute the number of columns the image has + /// by using the image width and tile size. + int get columns => image.width ~/ srcSize.x; + + /// Compute the number of rows the image has + /// by using the image height and tile size. + int get rows => image.height ~/ srcSize.y; + + /// Gets the sprite in the position (row, column) on the sprite sheet grid. + /// + /// This is lazily computed and cached for your convenience. + Sprite getSprite(int row, int column) { + return getSpriteById(row * columns + column); + } + + /// Gets teh sprite with id [spriteId] from the grid. + /// + /// The ids are defined as starting at 0 on the top left and going + /// sequentially on each row. + /// This is lazily computed and cached for your convenience. + Sprite getSpriteById(int spriteId) { + return _spriteCache[spriteId] ??= _computeSprite(spriteId); + } + + Sprite _computeSprite(int spriteId) { + final i = spriteId % columns; + final j = spriteId ~/ columns; + return Sprite( + image, + srcPosition: Vector2Extension.fromInts(i, j)..multiply(srcSize), + srcSize: srcSize, + ); + } + + /// Creates a [SpriteAnimation] from this SpriteSheet, using the sequence + /// of sprites on a given row. + /// + /// [from] and [to] can be specified to create an animation + /// from a subset of the columns on the row + SpriteAnimation createAnimation({ + @required int row, + @required double stepTime, + bool loop = true, + int from = 0, + int to, + }) { + to ??= columns; + + final spriteList = List.generate(to - from, (i) => from + i) + .map((e) => getSprite(row, e)) + .toList(); + + return SpriteAnimation.spriteList( + spriteList, + stepTime: stepTime, + loop: loop, + ); + } +} diff --git a/lib/text_config.dart b/lib/src/text_config.dart similarity index 100% rename from lib/text_config.dart rename to lib/src/text_config.dart diff --git a/lib/src/timer.dart b/lib/src/timer.dart new file mode 100644 index 00000000000..bede18d4be3 --- /dev/null +++ b/lib/src/timer.dart @@ -0,0 +1,85 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'components/component.dart'; + +/// Simple utility class that helps handling time counting and implementing +/// interval like events. +class Timer { + final double limit; + void Function() callback; + bool repeat; + double _current = 0; + bool _running = false; + + Timer(this.limit, {this.callback, this.repeat = false}); + + /// The current amount of ms that has passed on this iteration + double get current => _current; + + /// If the timer is finished, timers that repeat never finish + bool get finished => _current >= limit && !repeat; + + /// Whether the timer is running or not + bool isRunning() => _running; + + /// A value between 0.0 and 1.0 indicating the timer progress + double get progress => min(_current / limit, 1.0); + + void update(double dt) { + if (_running) { + _current += dt; + if (_current >= limit) { + if (!repeat) { + _running = false; + callback?.call(); + return; + } + // This is used to cover the rare case of _current being more than + // two times the value of limit, so that the callback is called the + // correct number of times + while (_current >= limit) { + _current -= limit; + callback?.call(); + } + } + } + } + + void start() { + _current = 0; + _running = true; + } + + void stop() { + _current = 0; + _running = false; + } + + void pause() { + _running = false; + } + + void resume() { + _running = true; + } +} + +/// Simple component which wraps a [Timer] instance allowing it to be easily used inside a [BaseGame] game. +class TimerComponent extends Component { + Timer timer; + + TimerComponent(this.timer); + + @override + void update(double dt) { + super.update(dt); + timer.update(dt); + } + + @override + void render(Canvas canvas) {} + + @override + bool get shouldRemove => timer.finished; +} diff --git a/lib/util.dart b/lib/src/util.dart similarity index 100% rename from lib/util.dart rename to lib/src/util.dart diff --git a/lib/widgets/animation_widget.dart b/lib/src/widgets/animation_widget.dart similarity index 98% rename from lib/widgets/animation_widget.dart rename to lib/src/widgets/animation_widget.dart index b8744e0e0f3..9de9b7560d8 100644 --- a/lib/widgets/animation_widget.dart +++ b/lib/src/widgets/animation_widget.dart @@ -6,6 +6,8 @@ import '../anchor.dart'; import '../sprite_animation.dart'; import 'sprite_widget.dart'; +export '../sprite_animation.dart'; + /// A [StatefulWidget] that render a [SpriteAnimation]. class SpriteAnimationWidget extends StatefulWidget { /// The [SpriteAnimation] to be rendered diff --git a/lib/widgets/nine_tile_box.dart b/lib/src/widgets/nine_tile_box.dart similarity index 87% rename from lib/widgets/nine_tile_box.dart rename to lib/src/widgets/nine_tile_box.dart index d99863cc0ad..f6d4cb5a00a 100644 --- a/lib/widgets/nine_tile_box.dart +++ b/lib/src/widgets/nine_tile_box.dart @@ -1,14 +1,17 @@ -import 'dart:ui'; +import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart' as widgets; +import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import '../extensions/vector2.dart'; import '../sprite.dart'; -class _Painter extends widgets.CustomPainter { - final Image image; +export '../nine_tile_box.dart'; +export '../sprite.dart'; + +class _Painter extends CustomPainter { + final ui.Image image; final double tileSize; final double destTileSize; @@ -120,16 +123,16 @@ class _Painter extends widgets.CustomPainter { bool shouldRepaint(_) => false; } -class NineTileBox extends widgets.StatelessWidget { - final Image image; +class NineTileBox extends StatelessWidget { + final ui.Image image; final double tileSize; final double destTileSize; final double width; final double height; - final widgets.Widget child; + final Widget child; - final widgets.EdgeInsetsGeometry padding; + final EdgeInsetsGeometry padding; NineTileBox({ @required this.image, @@ -143,17 +146,17 @@ class NineTileBox extends widgets.StatelessWidget { }) : super(key: key); @override - widgets.Widget build(widgets.BuildContext context) { - return widgets.Container( + Widget build(BuildContext context) { + return Container( width: width, height: height, - child: widgets.CustomPaint( + child: CustomPaint( painter: _Painter( image: image, tileSize: tileSize, destTileSize: destTileSize, ), - child: widgets.Container( + child: Container( child: child, padding: padding, ), diff --git a/lib/widgets/sprite_button.dart b/lib/src/widgets/sprite_button.dart similarity index 85% rename from lib/widgets/sprite_button.dart rename to lib/src/widgets/sprite_button.dart index 4fa0c4835b3..716755c64d5 100644 --- a/lib/widgets/sprite_button.dart +++ b/lib/src/widgets/sprite_button.dart @@ -4,6 +4,8 @@ import 'package:meta/meta.dart'; import '../extensions/size.dart'; import '../sprite.dart'; +export '../sprite.dart'; + class SpriteButton extends StatefulWidget { final VoidCallback onPressed; final Widget label; @@ -47,7 +49,7 @@ class _ButtonState extends State { height: height, child: CustomPaint( painter: - _ButtonPainer(_pressed ? widget.pressedSprite : widget.sprite), + _ButtonPainter(_pressed ? widget.pressedSprite : widget.sprite), child: Center( child: Container( padding: _pressed ? const EdgeInsets.only(top: 5) : null, @@ -60,13 +62,13 @@ class _ButtonState extends State { } } -class _ButtonPainer extends CustomPainter { +class _ButtonPainter extends CustomPainter { final Sprite _sprite; - _ButtonPainer(this._sprite); + _ButtonPainter(this._sprite); @override - bool shouldRepaint(_ButtonPainer old) => old._sprite != _sprite; + bool shouldRepaint(_ButtonPainter old) => old._sprite != _sprite; @override void paint(Canvas canvas, Size size) { diff --git a/lib/widgets/sprite_widget.dart b/lib/src/widgets/sprite_widget.dart similarity index 98% rename from lib/widgets/sprite_widget.dart rename to lib/src/widgets/sprite_widget.dart index 715ee3fb3e8..fee754b5afd 100644 --- a/lib/widgets/sprite_widget.dart +++ b/lib/src/widgets/sprite_widget.dart @@ -8,6 +8,8 @@ import '../extensions/size.dart'; import '../sprite.dart'; import 'animation_widget.dart'; +export '../sprite.dart'; + /// A [StatefulWidget] that renders a still [Sprite]. /// /// To render an animation, use [SpriteAnimationWidget]. diff --git a/lib/timer.dart b/lib/timer.dart index b05255781e7..b48a455775b 100644 --- a/lib/timer.dart +++ b/lib/timer.dart @@ -1,63 +1 @@ -import 'dart:math'; - -/// Simple utility class that helps handling time counting and implementing -/// interval like events. -class Timer { - final double limit; - void Function() callback; - bool repeat; - double _current = 0; - bool _running = false; - - Timer(this.limit, {this.callback, this.repeat = false}); - - /// The current amount of ms that has passed on this iteration - double get current => _current; - - /// If the timer is finished, timers that repeat never finish - bool get finished => _current >= limit && !repeat; - - /// Whether the timer is running or not - bool isRunning() => _running; - - /// A value between 0.0 and 1.0 indicating the timer progress - double get progress => min(_current / limit, 1.0); - - void update(double dt) { - if (_running) { - _current += dt; - if (_current >= limit) { - if (!repeat) { - _running = false; - callback?.call(); - return; - } - // This is used to cover the rare case of _current being more than - // two times the value of limit, so that the callback is called the - // correct number of times - while (_current >= limit) { - _current -= limit; - callback?.call(); - } - } - } - } - - void start() { - _current = 0; - _running = true; - } - - void stop() { - _current = 0; - _running = false; - } - - void pause() { - _running = false; - } - - void resume() { - _running = true; - } -} +export 'src/timer.dart'; diff --git a/lib/widgets.dart b/lib/widgets.dart new file mode 100644 index 00000000000..1595ed96b56 --- /dev/null +++ b/lib/widgets.dart @@ -0,0 +1,6 @@ +export 'src/widgets/animation_widget.dart'; +export 'src/widgets/nine_tile_box.dart'; +export 'src/widgets/sprite_button.dart'; +export 'src/widgets/sprite_widget.dart'; + +export 'src/anchor.dart'; diff --git a/test/base_game_test.dart b/test/base_game_test.dart index a4ed8e3bf49..e5260af609d 100644 --- a/test/base_game_test.dart +++ b/test/base_game_test.dart @@ -1,12 +1,8 @@ import 'dart:ui'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/components/mixins/tapable.dart'; +import 'package:flame/components.dart'; import 'package:flame/game.dart'; -import 'package:flame/game/base_game.dart'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/game/game_render_box.dart'; +import 'package:flame/src/game/game_render_box.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; diff --git a/test/components/component_test.dart b/test/components/component_test.dart index e209fbf90dd..7868c66885e 100644 --- a/test/components/component_test.dart +++ b/test/components/component_test.dart @@ -1,9 +1,6 @@ import 'dart:ui'; -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/sprite_component.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:test/test.dart'; void main() { diff --git a/test/components/composed_component_test.dart b/test/components/composed_component_test.dart index a4845f90e1f..0c3f7bd6966 100644 --- a/test/components/composed_component_test.dart +++ b/test/components/composed_component_test.dart @@ -1,10 +1,7 @@ import 'dart:ui'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/components/mixins/tapable.dart'; -import 'package:flame/game/base_game.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; diff --git a/test/components/has_game_ref_test.dart b/test/components/has_game_ref_test.dart index 5f9d7c9a5a8..14e0b3b2ef4 100644 --- a/test/components/has_game_ref_test.dart +++ b/test/components/has_game_ref_test.dart @@ -1,9 +1,7 @@ -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/game/base_game.dart'; +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; import 'package:test/test.dart'; -import 'package:flame/components/position_component.dart'; - class MyGame extends BaseGame { bool calledFoo = false; void foo() { diff --git a/test/components/position_component_test.dart b/test/components/position_component_test.dart index d9ba41455fa..34ff5ce84ab 100644 --- a/test/components/position_component_test.dart +++ b/test/components/position_component_test.dart @@ -1,8 +1,6 @@ import 'dart:math' as math; -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:test/test.dart'; class MyComponent extends PositionComponent {} diff --git a/test/components/resizable_test.dart b/test/components/resizable_test.dart index 71665e30c1c..9b5a1076e56 100644 --- a/test/components/resizable_test.dart +++ b/test/components/resizable_test.dart @@ -1,9 +1,7 @@ -import 'package:flame/game/base_game.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; import 'package:test/test.dart'; -import 'package:flame/components/position_component.dart'; - class MyComponent extends PositionComponent { String name; @override diff --git a/test/effects/combined_effect_test.dart b/test/effects/combined_effect_test.dart index 301c8978830..e5dd7121c83 100644 --- a/test/effects/combined_effect_test.dart +++ b/test/effects/combined_effect_test.dart @@ -1,9 +1,7 @@ import 'dart:math'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/combined_effect.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter_test/flutter_test.dart'; import 'effect_test_utils.dart'; diff --git a/test/effects/effect_test_utils.dart b/test/effects/effect_test_utils.dart index f1fc802e844..4fa6957387e 100644 --- a/test/effects/effect_test_utils.dart +++ b/test/effects/effect_test_utils.dart @@ -1,9 +1,7 @@ import 'dart:math'; -import 'package:flame/anchor.dart'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flame/game.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/effects/move_effect_test.dart b/test/effects/move_effect_test.dart index b0b74c669e3..6114ed6aacd 100644 --- a/test/effects/move_effect_test.dart +++ b/test/effects/move_effect_test.dart @@ -1,8 +1,7 @@ import 'dart:math'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter_test/flutter_test.dart'; import 'effect_test_utils.dart'; diff --git a/test/effects/rotate_effect_test.dart b/test/effects/rotate_effect_test.dart index 95803a2eb09..277a58a3ad3 100644 --- a/test/effects/rotate_effect_test.dart +++ b/test/effects/rotate_effect_test.dart @@ -1,5 +1,5 @@ -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/effects.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter_test/flutter_test.dart'; import 'effect_test_utils.dart'; diff --git a/test/effects/scale_effect_test.dart b/test/effects/scale_effect_test.dart index 948b8848016..71aa0ca05de 100644 --- a/test/effects/scale_effect_test.dart +++ b/test/effects/scale_effect_test.dart @@ -1,8 +1,7 @@ import 'dart:math'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter_test/flutter_test.dart'; import 'effect_test_utils.dart'; diff --git a/test/effects/sequence_effect_test.dart b/test/effects/sequence_effect_test.dart index 70513b75d24..160a5e81b6f 100644 --- a/test/effects/sequence_effect_test.dart +++ b/test/effects/sequence_effect_test.dart @@ -1,8 +1,7 @@ import 'dart:math'; -import 'package:flame/components/position_component.dart'; -import 'package:flame/effects/effects.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; import 'package:flutter_test/flutter_test.dart'; import 'effect_test_utils.dart'; diff --git a/test/memory_cache_test.dart b/test/memory_cache_test.dart index bf4cf64737f..9f74ba8bea9 100644 --- a/test/memory_cache_test.dart +++ b/test/memory_cache_test.dart @@ -1,6 +1,6 @@ import 'package:test/test.dart'; -import 'package:flame/memory_cache.dart'; +import 'package:flame/src/memory_cache.dart'; void main() { group('MemoryCache', () { diff --git a/test/vector2_test.dart b/test/vector2_test.dart index dc5a4001572..5bbb08765c5 100644 --- a/test/vector2_test.dart +++ b/test/vector2_test.dart @@ -1,4 +1,4 @@ -import 'package:flame/extensions/vector2.dart'; +import 'package:flame/components.dart'; import 'package:test/test.dart'; import 'dart:math' as math; From 1ec2d07f53b68e523f30470915371d7ebb5659f4 Mon Sep 17 00:00:00 2001 From: renancaraujo Date: Tue, 12 Jan 2021 15:23:41 -0300 Subject: [PATCH 2/3] Move files to src and comply with the dart package layout convention --- CHANGELOG.md | 2 +- doc/examples/particles/lib/main.dart | 4 +-- lib/components.dart | 3 ++ lib/src/profiler.dart | 27 ----------------- lib/src/sprite_batch.dart | 44 ++++++++++++++-------------- test/vector2_test.dart | 2 +- 6 files changed, 29 insertions(+), 53 deletions(-) delete mode 100644 lib/src/profiler.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index c35dbec3417..c68979b2300 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ - Updated the `widgets.md` documentation - Removing methods `initialDimensions` and `removeGestureRecognizer` to avoid confusion - Adding standard for `SpriteComponent` and `SpriteAnimationComponent` constructors - - move files to comply with the dart package layout convention + - Move files to comply with the dart package layout convention ## 1.0.0-rc5 - Option for overlays to be already visible on the GameWidget diff --git a/doc/examples/particles/lib/main.dart b/doc/examples/particles/lib/main.dart index 3a6867a896a..e1a7a4cb1b0 100644 --- a/doc/examples/particles/lib/main.dart +++ b/doc/examples/particles/lib/main.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'dart:math'; import 'dart:ui'; -import 'package:flame/components.dart'; +import 'package:flame/components.dart' hide Timer; import 'package:flame/flame.dart'; +import 'package:flame/timer.dart' as flame_timer; import 'package:flame/game.dart'; import 'package:flame/particles.dart'; import 'package:flame/spritesheet.dart'; -import 'package:flame/timer.dart' as flame_timer; import 'package:flutter/material.dart' hide Image; void main() async { diff --git a/lib/components.dart b/lib/components.dart index ae4b7e36d65..2f7046d6ccf 100644 --- a/lib/components.dart +++ b/lib/components.dart @@ -11,6 +11,9 @@ export 'src/components/sprite_component.dart'; export 'src/components/text_box_component.dart'; export 'src/components/text_component.dart'; +export 'src/timer.dart'; +export 'joystick.dart'; + export 'src/components/mixins/draggable.dart'; export 'src/components/mixins/has_game_ref.dart'; export 'src/components/mixins/single_child_particle.dart'; diff --git a/lib/src/profiler.dart b/lib/src/profiler.dart deleted file mode 100644 index a39cb2b720b..00000000000 --- a/lib/src/profiler.dart +++ /dev/null @@ -1,27 +0,0 @@ -class Records { - static void save(Profiler p) { - print('${p.name} : ${p.dts.last - p.dts.first} ms'); - } -} - -class Profiler { - final String name; - List dts = []; - - Profiler(this.name) { - tick(); - } - - void tick() { - dts.add(currentTime()); - } - - void end() { - tick(); - Records.save(this); - } - - static double currentTime() => - DateTime.now().microsecondsSinceEpoch.toDouble() / - Duration.microsecondsPerMillisecond; -} diff --git a/lib/src/sprite_batch.dart b/lib/src/sprite_batch.dart index 0411a0679b5..1899e10b0e4 100644 --- a/lib/src/sprite_batch.dart +++ b/lib/src/sprite_batch.dart @@ -11,11 +11,11 @@ import 'game/game.dart'; extension SpriteBatchExtension on Game { /// Utility method to load and cache the image for a [SpriteBatch] based on its options Future loadSpriteBatch( - String path, { - Color defaultColor = const Color(0x00000000), - BlendMode defaultBlendMode = BlendMode.srcOver, - RSTransform defaultTransform, - }) { + String path, { + Color defaultColor = const Color(0x00000000), + BlendMode defaultBlendMode = BlendMode.srcOver, + RSTransform defaultTransform, + }) { return SpriteBatch.load( path, defaultColor: defaultColor, @@ -148,23 +148,23 @@ class SpriteBatch { Vector2 get size => Vector2Extension.fromInts(width, height); SpriteBatch( - this.atlas, { - this.defaultColor = const Color(0x00000000), - this.defaultBlendMode = BlendMode.srcOver, - this.defaultTransform, - }) : assert(atlas != null), + this.atlas, { + this.defaultColor = const Color(0x00000000), + this.defaultBlendMode = BlendMode.srcOver, + this.defaultTransform, + }) : assert(atlas != null), assert(defaultColor != null); /// Takes a path of an image, and optional arguments for the SpriteBatch. /// /// When the [images] is omitted, the global [Flame.images] is used. static Future load( - String path, { - Color defaultColor = const Color(0x00000000), - BlendMode defaultBlendMode = BlendMode.srcOver, - RSTransform defaultTransform, - Images images, - }) async { + String path, { + Color defaultColor = const Color(0x00000000), + BlendMode defaultBlendMode = BlendMode.srcOver, + RSTransform defaultTransform, + Images images, + }) async { final _images = images ?? Flame.images; return SpriteBatch( await _images.load(path), @@ -257,11 +257,11 @@ class SpriteBatch { } void render( - Canvas canvas, { - BlendMode blendMode, - Rect cullRect, - Paint paint, - }) { + Canvas canvas, { + BlendMode blendMode, + Rect cullRect, + Paint paint, + }) { paint ??= Paint(); if (kIsWeb) { @@ -292,4 +292,4 @@ class SpriteBatch { ); } } -} \ No newline at end of file +} diff --git a/test/vector2_test.dart b/test/vector2_test.dart index 5bbb08765c5..341476cd071 100644 --- a/test/vector2_test.dart +++ b/test/vector2_test.dart @@ -1,4 +1,4 @@ -import 'package:flame/components.dart'; +import 'package:flame/extensions.dart'; import 'package:test/test.dart'; import 'dart:math' as math; From 8f18b20d827bd807f368a71fd75d114adc98746a Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Wed, 20 Jan 2021 09:00:02 -0300 Subject: [PATCH 3/3] Fixing widgets example --- doc/examples/widgets/lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/examples/widgets/lib/main.dart b/doc/examples/widgets/lib/main.dart index acffeecc5d3..0bd804be5cf 100644 --- a/doc/examples/widgets/lib/main.dart +++ b/doc/examples/widgets/lib/main.dart @@ -1,4 +1,4 @@ -import 'package:flame/components.dart'; +import 'package:flame/extensions.dart'; import 'package:flame/widgets.dart'; import 'package:flutter/material.dart' hide Animation; import 'package:flame/flame.dart';