├── LICENSE ├── example ├── README.md ├── assets │ └── images │ │ ├── city.png │ │ ├── space.png │ │ └── desert │ │ ├── train.png │ │ ├── clouds.png │ │ ├── ground.png │ │ ├── foreground.png │ │ ├── mountains.png │ │ ├── train.aseprite │ │ └── mountains.aseprite ├── web │ ├── icons │ │ ├── Icon-192.png │ │ └── Icon-512.png │ ├── manifest.json │ └── index.html ├── .metadata ├── pubspec.yaml ├── .gitignore ├── lib │ ├── main_city.dart │ ├── main_space.dart │ ├── main_desert.dart │ └── main.dart └── pubspec.lock ├── scripts └── format.sh ├── lib ├── flame_scrolling_sprite.dart ├── scrolling_sprite_component.dart └── scrolling_sprite.dart ├── CHANGELOG.md ├── .metadata ├── .github └── workflows │ └── test.yml ├── pubspec.yaml ├── .gitignore ├── analysis_options.yaml ├── README.md └── pubspec.lock /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | The project showcasing how to use this package. 4 | -------------------------------------------------------------------------------- /example/assets/images/city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/city.png -------------------------------------------------------------------------------- /example/assets/images/space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/space.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /scripts/format.sh: -------------------------------------------------------------------------------- 1 | if [[ $(flutter format -n .) ]]; then 2 | echo "files not formatted" 3 | exit 1 4 | else 5 | exit 0 6 | fi -------------------------------------------------------------------------------- /example/assets/images/desert/train.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/train.png -------------------------------------------------------------------------------- /example/assets/images/desert/clouds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/clouds.png -------------------------------------------------------------------------------- /example/assets/images/desert/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/ground.png -------------------------------------------------------------------------------- /example/assets/images/desert/foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/foreground.png -------------------------------------------------------------------------------- /example/assets/images/desert/mountains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/mountains.png -------------------------------------------------------------------------------- /example/assets/images/desert/train.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/train.aseprite -------------------------------------------------------------------------------- /lib/flame_scrolling_sprite.dart: -------------------------------------------------------------------------------- 1 | library flame_scrolling_sprite; 2 | 3 | export './scrolling_sprite.dart'; 4 | export './scrolling_sprite_component.dart'; 5 | -------------------------------------------------------------------------------- /example/assets/images/desert/mountains.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flame-engine/flame_scrolling_sprite/HEAD/example/assets/images/desert/mountains.aseprite -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.3] 2 | 3 | - Updating Flame version 4 | 5 | ## [0.0.2] 6 | 7 | - Updating Flame version 8 | 9 | ## [0.0.1] 10 | 11 | - Initial release 12 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: fabeb2a16f1d008ab8230f450c49141d35669798 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: fabeb2a16f1d008ab8230f450c49141d35669798 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v1 11 | - uses: actions/setup-java@v1 12 | with: 13 | java-version: '12.x' 14 | - uses: subosito/flutter-action@v1 15 | with: 16 | channel: 'stable' 17 | - run: flutter pub get 18 | - run: ./scripts/format.sh 19 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flame_scrolling_sprite 2 | description: Flame package adding a simple scrolling sprite to make it easy to repeat the same image over time. 3 | version: 0.0.3 4 | homepage: https://github.com/flame-engine/flame_scrolling_sprite 5 | 6 | environment: 7 | sdk: ">=2.1.0 <3.0.0" 8 | 9 | dependencies: 10 | flame: ">=0.24.0 <1.0.0" 11 | meta: ^1.1.8 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | flutter: 20 | -------------------------------------------------------------------------------- /lib/scrolling_sprite_component.dart: -------------------------------------------------------------------------------- 1 | import 'package:flame/components/component.dart'; 2 | import 'dart:ui'; 3 | 4 | import './scrolling_sprite.dart'; 5 | 6 | class ScrollingSpriteComponent extends Component { 7 | ScrollingSprite scrollingSprite; 8 | double x; 9 | double y; 10 | 11 | ScrollingSpriteComponent({this.x, this.y, this.scrollingSprite}); 12 | 13 | @override 14 | void update(double dt) { 15 | scrollingSprite.update(dt); 16 | } 17 | 18 | @override 19 | void render(Canvas canvas) { 20 | if (scrollingSprite.loaded()) { 21 | scrollingSprite.renderAt(x, y, canvas); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flame_scrolling_sprite_example 2 | description: a flame scrolling sprite example 3 | 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: ">=2.1.0 <3.0.0" 8 | 9 | dependencies: 10 | flame: 0.24.0 11 | flame_scrolling_sprite: 12 | path: ../ 13 | flutter: 14 | sdk: flutter 15 | 16 | cupertino_icons: ^0.1.2 17 | 18 | flutter: 19 | assets: 20 | - assets/images/space.png 21 | - assets/images/city.png 22 | 23 | - assets/images/desert/clouds.png 24 | - assets/images/desert/mountains.png 25 | - assets/images/desert/ground.png 26 | - assets/images/desert/train.png 27 | - assets/images/desert/foreground.png 28 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | 39 | android 40 | ios 41 | -------------------------------------------------------------------------------- /example/lib/main_city.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flame/game.dart'; 3 | import 'package:flame/flame.dart'; 4 | import 'package:flame_scrolling_sprite/flame_scrolling_sprite.dart'; 5 | 6 | void main() async { 7 | WidgetsFlutterBinding.ensureInitialized(); 8 | await Flame.util.fullScreen(); 9 | final size = await Flame.util.initialDimensions(); 10 | runApp(MyGame(size).widget); 11 | } 12 | 13 | class MyGame extends Game { 14 | ScrollingSprite sprite; 15 | final Size size; 16 | 17 | MyGame(this.size) { 18 | sprite = ScrollingSprite( 19 | spritePath: 'city.png', 20 | width: size.width, 21 | horizontalSpeed: -100, 22 | spriteDestWidth: 300, 23 | spriteDestHeight: 150, 24 | ); 25 | } 26 | 27 | @override 28 | void update(double dt) { 29 | sprite.update(dt); 30 | } 31 | 32 | @override 33 | void render(Canvas canvas) { 34 | if (sprite.loaded()) { 35 | sprite.renderAt(0, size.height - 150, canvas); 36 | } 37 | } 38 | 39 | @override 40 | Color backgroundColor() => const Color(0xFF3f3f74); 41 | } 42 | -------------------------------------------------------------------------------- /example/lib/main_space.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flame/game.dart'; 3 | import 'package:flame/flame.dart'; 4 | import 'package:flame_scrolling_sprite/flame_scrolling_sprite.dart'; 5 | 6 | void main() async { 7 | WidgetsFlutterBinding.ensureInitialized(); 8 | await Flame.util.fullScreen(); 9 | final size = await Flame.util.initialDimensions(); 10 | runApp(MyGame(size).widget); 11 | } 12 | 13 | class MyGame extends Game { 14 | ScrollingSprite sprite; 15 | final Size size; 16 | 17 | MyGame(this.size) { 18 | sprite = ScrollingSprite( 19 | spritePath: 'space.png', 20 | width: size.width, 21 | height: size.height, 22 | verticalSpeed: 300, 23 | spriteDestWidth: 500, 24 | spriteDestHeight: 500, 25 | ); 26 | } 27 | 28 | @override 29 | void update(double dt) { 30 | sprite.update(dt); 31 | } 32 | 33 | @override 34 | void render(Canvas canvas) { 35 | if (sprite.loaded()) { 36 | sprite.renderAt(0, 0, canvas); 37 | } 38 | } 39 | 40 | @override 41 | Color backgroundColor() => const Color(0xFF3f3f74); 42 | } 43 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | example 15 | 16 | 17 | 18 | 21 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 76 | -------------------------------------------------------------------------------- /example/lib/main_desert.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flame/game.dart'; 3 | import 'package:flame/flame.dart'; 4 | import 'package:flame/components/animation_component.dart'; 5 | import 'package:flame_scrolling_sprite/flame_scrolling_sprite.dart'; 6 | 7 | void main() async { 8 | WidgetsFlutterBinding.ensureInitialized(); 9 | await Flame.util.fullScreen(); 10 | final size = await Flame.util.initialDimensions(); 11 | runApp(MyGame(size).widget); 12 | } 13 | 14 | class MyGame extends BaseGame { 15 | final Size size; 16 | 17 | MyGame(this.size) { 18 | add(ScrollingSpriteComponent( 19 | scrollingSprite: ScrollingSprite( 20 | spritePath: 'desert/clouds.png', 21 | width: size.width, 22 | spriteDestWidth: 640, 23 | spriteDestHeight: 160, 24 | horizontalSpeed: -50, 25 | ), 26 | y: 40, 27 | )); 28 | 29 | add(ScrollingSpriteComponent( 30 | scrollingSprite: ScrollingSprite( 31 | spritePath: 'desert/mountains.png', 32 | width: size.width, 33 | spriteDestWidth: 640, 34 | spriteDestHeight: 160, 35 | height: size.height, 36 | horizontalSpeed: -100, 37 | ), 38 | y: size.height - 180, 39 | )); 40 | 41 | add(ScrollingSpriteComponent( 42 | scrollingSprite: ScrollingSprite( 43 | spritePath: 'desert/ground.png', 44 | width: size.width, 45 | spriteDestWidth: 320, 46 | spriteDestHeight: 160, 47 | horizontalSpeed: -300, 48 | ), 49 | y: size.height - 160, 50 | )); 51 | 52 | add(AnimationComponent.sequenced( 53 | 192.0, 54 | 64.0, 55 | 'desert/train.png', 56 | 8, 57 | textureWidth: 96.0, 58 | textureHeight: 32.0, 59 | ) 60 | ..y = size.height - 65 61 | ..x = size.width / 2 - 96); 62 | 63 | add(ScrollingSpriteComponent( 64 | scrollingSprite: ScrollingSprite( 65 | spritePath: 'desert/foreground.png', 66 | width: size.width, 67 | spriteDestWidth: 1280, 68 | spriteDestHeight: 160, 69 | height: size.height, 70 | horizontalSpeed: -1500, 71 | ), 72 | y: size.height - 160, 73 | )); 74 | } 75 | 76 | @override 77 | Color backgroundColor() => const Color(0xFF73acb6); 78 | } 79 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Source of linter options: 2 | # http://dart-lang.github.io/linter/lints/options/options.html 3 | 4 | linter: 5 | rules: 6 | - always_declare_return_types 7 | - always_put_control_body_on_new_line 8 | - always_require_non_null_named_parameters 9 | - annotate_overrides 10 | - avoid_empty_else 11 | - avoid_field_initializers_in_const_classes 12 | - avoid_init_to_null 13 | - avoid_null_checks_in_equality_operators 14 | - avoid_relative_lib_imports 15 | - avoid_return_types_on_setters 16 | - avoid_slow_async_io 17 | - await_only_futures 18 | - camel_case_types 19 | - cancel_subscriptions 20 | - control_flow_in_finally 21 | - empty_catches 22 | - empty_constructor_bodies 23 | - empty_statements 24 | - hash_and_equals 25 | - implementation_imports 26 | - iterable_contains_unrelated_type 27 | - library_names 28 | - library_prefixes 29 | - list_remove_unrelated_type 30 | - no_adjacent_strings_in_list 31 | - no_duplicate_case_values 32 | - non_constant_identifier_names 33 | - package_api_docs 34 | - package_names 35 | - package_prefixed_library_names 36 | - prefer_adjacent_string_concatenation 37 | - prefer_asserts_in_initializer_lists 38 | - prefer_collection_literals 39 | - prefer_conditional_assignment 40 | - prefer_const_constructors 41 | - prefer_const_declarations 42 | - prefer_const_literals_to_create_immutables 43 | - prefer_contains 44 | - prefer_equal_for_default_values 45 | - prefer_final_fields 46 | - prefer_final_locals 47 | - prefer_foreach 48 | - prefer_initializing_formals 49 | - prefer_is_empty 50 | - prefer_is_not_empty 51 | - prefer_typing_uninitialized_variables 52 | - recursive_getters 53 | - slash_for_doc_comments 54 | - sort_unnamed_constructors_first 55 | - test_types_in_equals 56 | - throw_in_finally 57 | - type_init_formals 58 | - unnecessary_brace_in_string_interps 59 | - unnecessary_getters_setters 60 | - unnecessary_null_aware_assignments 61 | - unnecessary_null_in_if_null_operators 62 | - unnecessary_overrides 63 | - unnecessary_parenthesis 64 | - unnecessary_this 65 | - unrelated_type_equality_checks 66 | - use_rethrow_when_possible 67 | - unnecessary_new 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Pub](https://img.shields.io/pub/v/flame_scrolling_sprite.svg?style=popout)](https://pub.dartlang.org/packages/flame_scrolling_sprite) 2 | ![Build Status](https://img.shields.io/github/workflow/status/flame-engine/flame_scrolling_sprite/Test/master?label=tests) 3 | 4 | # Flame Scrolling Sprite 5 | 6 | Flame Scrolling Sprite is a [Flame](https://github.com/flame-engine/flame) package to make it easy to render sprites that scrolls and repeat itself forever given a velocity. 7 | 8 | This can be used to create things like an scrolling background, or even create scenes, bellow you can see one example of this: 9 | 10 | ![train](https://user-images.githubusercontent.com/835641/75399796-fdf51180-58db-11ea-92ef-f7cee92c99ef.gif) 11 | 12 | This package can be used by using the plain class `ScrollingSprite` or the `ScrollingSpriteComponent`, they do example the same thing, but the later can be used together with Flame component system. 13 | 14 | Bellow you can find all the parameters that the classes receives 15 | 16 | ```dart 17 | //// Resource path of the sprite 18 | @required String spritePath, 19 | 20 | //// X and Y coordinate do be used to map the sprite 21 | double spriteX = 0.0, 22 | double spriteY = 0.0, 23 | 24 | //// Width and height of the mapped sprite 25 | double spriteWidth, 26 | double spriteHeight, 27 | 28 | //// Destination width and height of the sprite, in case you want to scale its original size 29 | double spriteDestWidth, 30 | double spriteDestHeight, 31 | 32 | //// Width and height of the total area where the sprites will scroll 33 | double width, 34 | double height, 35 | 36 | //// Vertical and horizontal speed of the scrolling speed in pixels per second 37 | this.verticalSpeed = 0.0, 38 | this.horizontalSpeed = 0.0, 39 | 40 | //// Since the sprites are scrolling on an endless manner, the sprite can be draw outside of its 41 | //// area, by default, the package already clips the area to prevent it from showing, use this flag to change 42 | //// this behaviour 43 | this.clipToDimensions = true, 44 | ``` 45 | 46 | When using the `ScrollingSpriteComponent` the same paramenters above apply to it, and additionally, you can inform the `x` and `y` where the area will place placed. 47 | 48 | For a live example of this running, please refer to the [example](/example) folder. 49 | -------------------------------------------------------------------------------- /lib/scrolling_sprite.dart: -------------------------------------------------------------------------------- 1 | import 'package:flame/sprite.dart'; 2 | import 'package:meta/meta.dart'; 3 | import 'dart:ui'; 4 | 5 | /// Describes a Sprite image that will animate on a axis resembling scroll moviment 6 | class ScrollingSprite { 7 | Sprite _sprite; 8 | double _width; 9 | double _height; 10 | double _spriteWidth; 11 | double _spriteHeight; 12 | final double verticalSpeed; 13 | final double horizontalSpeed; 14 | 15 | /// 16 | final bool clipToDimensions; 17 | 18 | List _chunks = []; 19 | 20 | /// Constructs a [ScrollingSprite] with the following params: 21 | /// 22 | /// [spritePath] - Resource path of the sprite 23 | /// [spriteX] and [spriteY] - X and Y coordinate do be used to map the sprite 24 | /// [spriteWidth] and [spriteHeight] - Width and height of the mapped sprite 25 | /// [spriteDestWidth] and [spriteDestHeight] - Destination width and height of the sprite, in case you want to scale its original size 26 | /// [width] and [height] - Width and height of the total area where the sprites will scroll 27 | /// [verticalSpeed] and [horizontalSpeed] - Vertical and horizontal speed of the scrolling speed in pixels per second 28 | /// [clipToDimensions] - Since the sprites are scrolling on an endless manner, the sprite can be draw outside of its 29 | /// area, by default, the package already clips the area to prevent it from showing, use this flag to change 30 | /// this behaviour 31 | ScrollingSprite({ 32 | @required String spritePath, 33 | double spriteX = 0.0, 34 | double spriteY = 0.0, 35 | double spriteWidth, 36 | double spriteHeight, 37 | double spriteDestWidth, 38 | double spriteDestHeight, 39 | double width, 40 | double height, 41 | this.verticalSpeed = 0.0, 42 | this.horizontalSpeed = 0.0, 43 | this.clipToDimensions = true, 44 | }) { 45 | Sprite.loadSprite( 46 | spritePath, 47 | x: spriteX, 48 | y: spriteY, 49 | width: spriteWidth, 50 | height: spriteHeight, 51 | ).then((loadedSprite) { 52 | _sprite = loadedSprite; 53 | 54 | _spriteWidth = spriteDestWidth ?? _sprite.size.x; 55 | _spriteHeight = spriteDestHeight ?? _sprite.size.y; 56 | 57 | _width = width ?? _spriteWidth; 58 | _height = height ?? _spriteHeight; 59 | 60 | _calculate(); 61 | }); 62 | } 63 | 64 | set width(double w) { 65 | _width = w; 66 | _calculate(); 67 | } 68 | 69 | double get width => _width; 70 | 71 | set height(double h) { 72 | _height = h; 73 | _calculate(); 74 | } 75 | 76 | double get height => _height; 77 | 78 | void _calculate() { 79 | _chunks = []; 80 | final columns = (_width / _spriteWidth).ceil() + 1; 81 | final rows = (_height / _spriteHeight).ceil() + 1; 82 | 83 | for (var y = 0; y < rows; y++) { 84 | for (var x = 0; x < columns; x++) { 85 | _chunks.add(Rect.fromLTWH( 86 | x * _spriteWidth, 87 | y * _spriteHeight, 88 | _spriteWidth, 89 | _spriteHeight, 90 | )); 91 | } 92 | } 93 | } 94 | 95 | void update(double dt) { 96 | for (var i = 0; i < _chunks.length; i++) { 97 | Rect _c = _chunks[i]; 98 | 99 | if (_c.top > _height && verticalSpeed > 0) { 100 | _c = _chunks[i] = _c.translate(0, -(height + _spriteHeight)); 101 | } else if (_c.bottom < 0 && verticalSpeed < 0) { 102 | _c = _chunks[i] = _c.translate(0, height + _spriteHeight); 103 | } 104 | 105 | if (_c.left > _width && horizontalSpeed > 0) { 106 | _c = _chunks[i] = _c.translate(-(_width + _spriteWidth), 0); 107 | } else if (_c.right < 0 && horizontalSpeed < 0) { 108 | _c = _chunks[i] = _c.translate(_width + _spriteWidth, 0); 109 | } 110 | 111 | _c = _chunks[i] = _c.translate(horizontalSpeed * dt, verticalSpeed * dt); 112 | } 113 | } 114 | 115 | void renderAt(double x, double y, Canvas canvas) { 116 | if (!loaded()) { 117 | return; 118 | } 119 | 120 | if (clipToDimensions) { 121 | canvas.save(); 122 | canvas.translate(x, y); 123 | canvas.clipRect(Rect.fromLTWH(0, 0, _width, _height)); 124 | } 125 | _chunks.forEach((rect) { 126 | _sprite.renderRect(canvas, rect); 127 | }); 128 | if (clipToDimensions) { 129 | canvas.restore(); 130 | } 131 | } 132 | 133 | bool loaded() => _sprite != null && _sprite.loaded(); 134 | } 135 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | // This widget is the root of your application. 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Flutter Demo', 11 | theme: ThemeData( 12 | // This is the theme of your application. 13 | // 14 | // Try running your application with "flutter run". You'll see the 15 | // application has a blue toolbar. Then, without quitting the app, try 16 | // changing the primarySwatch below to Colors.green and then invoke 17 | // "hot reload" (press "r" in the console where you ran "flutter run", 18 | // or simply save your changes to "hot reload" in a Flutter IDE). 19 | // Notice that the counter didn't reset back to zero; the application 20 | // is not restarted. 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: MyHomePage(title: 'Flutter Demo Home Page'), 24 | ); 25 | } 26 | } 27 | 28 | class MyHomePage extends StatefulWidget { 29 | MyHomePage({Key key, this.title}) : super(key: key); 30 | 31 | // This widget is the home page of your application. It is stateful, meaning 32 | // that it has a State object (defined below) that contains fields that affect 33 | // how it looks. 34 | 35 | // This class is the configuration for the state. It holds the values (in this 36 | // case the title) provided by the parent (in this case the App widget) and 37 | // used by the build method of the State. Fields in a Widget subclass are 38 | // always marked "final". 39 | 40 | final String title; 41 | 42 | @override 43 | _MyHomePageState createState() => _MyHomePageState(); 44 | } 45 | 46 | class _MyHomePageState extends State { 47 | int _counter = 0; 48 | 49 | void _incrementCounter() { 50 | setState(() { 51 | // This call to setState tells the Flutter framework that something has 52 | // changed in this State, which causes it to rerun the build method below 53 | // so that the display can reflect the updated values. If we changed 54 | // _counter without calling setState(), then the build method would not be 55 | // called again, and so nothing would appear to happen. 56 | _counter++; 57 | }); 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | // This method is rerun every time setState is called, for instance as done 63 | // by the _incrementCounter method above. 64 | // 65 | // The Flutter framework has been optimized to make rerunning build methods 66 | // fast, so that you can just rebuild anything that needs updating rather 67 | // than having to individually change instances of widgets. 68 | return Scaffold( 69 | appBar: AppBar( 70 | // Here we take the value from the MyHomePage object that was created by 71 | // the App.build method, and use it to set our appbar title. 72 | title: Text(widget.title), 73 | ), 74 | body: Center( 75 | // Center is a layout widget. It takes a single child and positions it 76 | // in the middle of the parent. 77 | child: Column( 78 | // Column is also a layout widget. It takes a list of children and 79 | // arranges them vertically. By default, it sizes itself to fit its 80 | // children horizontally, and tries to be as tall as its parent. 81 | // 82 | // Invoke "debug painting" (press "p" in the console, choose the 83 | // "Toggle Debug Paint" action from the Flutter Inspector in Android 84 | // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) 85 | // to see the wireframe for each widget. 86 | // 87 | // Column has various properties to control how it sizes itself and 88 | // how it positions its children. Here we use mainAxisAlignment to 89 | // center the children vertically; the main axis here is the vertical 90 | // axis because Columns are vertical (the cross axis would be 91 | // horizontal). 92 | mainAxisAlignment: MainAxisAlignment.center, 93 | children: [ 94 | Text( 95 | 'You have pushed the button this many times:', 96 | ), 97 | Text( 98 | '$_counter', 99 | style: Theme.of(context).textTheme.headline4, 100 | ), 101 | ], 102 | ), 103 | ), 104 | floatingActionButton: FloatingActionButton( 105 | onPressed: _incrementCounter, 106 | tooltip: 'Increment', 107 | child: Icon(Icons.add), 108 | ), // This trailing comma makes auto-formatting nicer for build methods. 109 | ); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.13" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.2" 18 | audioplayers: 19 | dependency: transitive 20 | description: 21 | name: audioplayers 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "0.15.1" 25 | box2d_flame: 26 | dependency: transitive 27 | description: 28 | name: box2d_flame 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "0.4.6" 32 | characters: 33 | dependency: transitive 34 | description: 35 | name: characters 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.0.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.2" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.14.13" 53 | convert: 54 | dependency: transitive 55 | description: 56 | name: convert 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.1.1" 60 | crypto: 61 | dependency: transitive 62 | description: 63 | name: crypto 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.1.3" 67 | cupertino_icons: 68 | dependency: "direct main" 69 | description: 70 | name: cupertino_icons 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "0.1.3" 74 | flame: 75 | dependency: "direct main" 76 | description: 77 | name: flame 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "0.24.0" 81 | flame_scrolling_sprite: 82 | dependency: "direct main" 83 | description: 84 | path: ".." 85 | relative: true 86 | source: path 87 | version: "0.0.3" 88 | flare_dart: 89 | dependency: transitive 90 | description: 91 | name: flare_dart 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "2.3.3" 95 | flare_flutter: 96 | dependency: transitive 97 | description: 98 | name: flare_flutter 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "2.0.1" 102 | flutter: 103 | dependency: "direct main" 104 | description: flutter 105 | source: sdk 106 | version: "0.0.0" 107 | flutter_web_plugins: 108 | dependency: transitive 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | meta: 113 | dependency: transitive 114 | description: 115 | name: meta 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "1.1.8" 119 | ordered_set: 120 | dependency: transitive 121 | description: 122 | name: ordered_set 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "2.0.0" 126 | path: 127 | dependency: transitive 128 | description: 129 | name: path 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "1.6.4" 133 | path_provider: 134 | dependency: transitive 135 | description: 136 | name: path_provider 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "1.6.0" 140 | petitparser: 141 | dependency: transitive 142 | description: 143 | name: petitparser 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "3.0.4" 147 | platform: 148 | dependency: transitive 149 | description: 150 | name: platform 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "2.2.1" 154 | sky_engine: 155 | dependency: transitive 156 | description: flutter 157 | source: sdk 158 | version: "0.0.99" 159 | synchronized: 160 | dependency: transitive 161 | description: 162 | name: synchronized 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.2.0" 166 | tiled: 167 | dependency: transitive 168 | description: 169 | name: tiled 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "0.6.0" 173 | typed_data: 174 | dependency: transitive 175 | description: 176 | name: typed_data 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.2.0" 180 | uuid: 181 | dependency: transitive 182 | description: 183 | name: uuid 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.0.4" 187 | vector_math: 188 | dependency: transitive 189 | description: 190 | name: vector_math 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "2.0.8" 194 | xml: 195 | dependency: transitive 196 | description: 197 | name: xml 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "4.2.0" 201 | sdks: 202 | dart: ">=2.9.0-14.0.dev <3.0.0" 203 | flutter: ">=1.10.0 <2.0.0" 204 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.13" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.4.2" 25 | audioplayers: 26 | dependency: transitive 27 | description: 28 | name: audioplayers 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "0.15.1" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.0.0" 39 | box2d_flame: 40 | dependency: transitive 41 | description: 42 | name: box2d_flame 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "0.4.6" 46 | characters: 47 | dependency: transitive 48 | description: 49 | name: characters 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.0" 53 | charcode: 54 | dependency: transitive 55 | description: 56 | name: charcode 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.1.3" 60 | clock: 61 | dependency: transitive 62 | description: 63 | name: clock 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.0.1" 67 | collection: 68 | dependency: transitive 69 | description: 70 | name: collection 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.14.13" 74 | convert: 75 | dependency: transitive 76 | description: 77 | name: convert 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "2.1.1" 81 | crypto: 82 | dependency: transitive 83 | description: 84 | name: crypto 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "2.1.3" 88 | fake_async: 89 | dependency: transitive 90 | description: 91 | name: fake_async 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.1.0" 95 | flame: 96 | dependency: "direct main" 97 | description: 98 | name: flame 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "0.24.0" 102 | flare_dart: 103 | dependency: transitive 104 | description: 105 | name: flare_dart 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "2.3.3" 109 | flare_flutter: 110 | dependency: transitive 111 | description: 112 | name: flare_flutter 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "2.0.1" 116 | flutter: 117 | dependency: "direct main" 118 | description: flutter 119 | source: sdk 120 | version: "0.0.0" 121 | flutter_test: 122 | dependency: "direct dev" 123 | description: flutter 124 | source: sdk 125 | version: "0.0.0" 126 | flutter_web_plugins: 127 | dependency: transitive 128 | description: flutter 129 | source: sdk 130 | version: "0.0.0" 131 | matcher: 132 | dependency: transitive 133 | description: 134 | name: matcher 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.12.8" 138 | meta: 139 | dependency: "direct main" 140 | description: 141 | name: meta 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.1.8" 145 | ordered_set: 146 | dependency: transitive 147 | description: 148 | name: ordered_set 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.0.0" 152 | path: 153 | dependency: transitive 154 | description: 155 | name: path 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.7.0" 159 | path_provider: 160 | dependency: transitive 161 | description: 162 | name: path_provider 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.6.0" 166 | petitparser: 167 | dependency: transitive 168 | description: 169 | name: petitparser 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "3.0.4" 173 | platform: 174 | dependency: transitive 175 | description: 176 | name: platform 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.2.1" 180 | sky_engine: 181 | dependency: transitive 182 | description: flutter 183 | source: sdk 184 | version: "0.0.99" 185 | source_span: 186 | dependency: transitive 187 | description: 188 | name: source_span 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "1.7.0" 192 | stack_trace: 193 | dependency: transitive 194 | description: 195 | name: stack_trace 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "1.9.5" 199 | stream_channel: 200 | dependency: transitive 201 | description: 202 | name: stream_channel 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "2.0.0" 206 | string_scanner: 207 | dependency: transitive 208 | description: 209 | name: string_scanner 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "1.0.5" 213 | synchronized: 214 | dependency: transitive 215 | description: 216 | name: synchronized 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "2.2.0" 220 | term_glyph: 221 | dependency: transitive 222 | description: 223 | name: term_glyph 224 | url: "https://pub.dartlang.org" 225 | source: hosted 226 | version: "1.1.0" 227 | test_api: 228 | dependency: transitive 229 | description: 230 | name: test_api 231 | url: "https://pub.dartlang.org" 232 | source: hosted 233 | version: "0.2.17" 234 | tiled: 235 | dependency: transitive 236 | description: 237 | name: tiled 238 | url: "https://pub.dartlang.org" 239 | source: hosted 240 | version: "0.6.0" 241 | typed_data: 242 | dependency: transitive 243 | description: 244 | name: typed_data 245 | url: "https://pub.dartlang.org" 246 | source: hosted 247 | version: "1.2.0" 248 | uuid: 249 | dependency: transitive 250 | description: 251 | name: uuid 252 | url: "https://pub.dartlang.org" 253 | source: hosted 254 | version: "2.0.4" 255 | vector_math: 256 | dependency: transitive 257 | description: 258 | name: vector_math 259 | url: "https://pub.dartlang.org" 260 | source: hosted 261 | version: "2.0.8" 262 | xml: 263 | dependency: transitive 264 | description: 265 | name: xml 266 | url: "https://pub.dartlang.org" 267 | source: hosted 268 | version: "4.2.0" 269 | sdks: 270 | dart: ">=2.9.0-14.0.dev <3.0.0" 271 | flutter: ">=1.10.0 <2.0.0" 272 | --------------------------------------------------------------------------------