@ -1 +1,2 @@
|
||||
export 'bloc/leaderboard_bloc.dart';
|
||||
export 'models/leader_board_entry.dart';
|
||||
|
@ -0,0 +1,80 @@
|
||||
import 'package:leaderboard_repository/leaderboard_repository.dart';
|
||||
import 'package:pinball_theme/pinball_theme.dart';
|
||||
|
||||
/// {@template leaderboard_entry}
|
||||
/// A model representing a leaderboard entry containing the ranking position,
|
||||
/// player's initials, score, and chosen character.
|
||||
///
|
||||
/// {@endtemplate}
|
||||
class LeaderboardEntry {
|
||||
/// {@macro leaderboard_entry}
|
||||
LeaderboardEntry({
|
||||
required this.rank,
|
||||
required this.playerInitials,
|
||||
required this.score,
|
||||
required this.character,
|
||||
});
|
||||
|
||||
/// Ranking position for [LeaderboardEntry].
|
||||
final String rank;
|
||||
|
||||
/// Player's chosen initials for [LeaderboardEntry].
|
||||
final String playerInitials;
|
||||
|
||||
/// Score for [LeaderboardEntry].
|
||||
final int score;
|
||||
|
||||
/// [CharacterTheme] for [LeaderboardEntry].
|
||||
final AssetGenImage character;
|
||||
}
|
||||
|
||||
/// Converts [LeaderboardEntryData] from repository to [LeaderboardEntry].
|
||||
extension LeaderboardEntryDataX on LeaderboardEntryData {
|
||||
/// Conversion method to [LeaderboardEntry]
|
||||
LeaderboardEntry toEntry(int position) {
|
||||
return LeaderboardEntry(
|
||||
rank: position.toString(),
|
||||
playerInitials: playerInitials,
|
||||
score: score,
|
||||
character: character.toTheme.characterAsset,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts [CharacterType] to [CharacterTheme] to show on UI character theme
|
||||
/// from repository.
|
||||
extension CharacterTypeX on CharacterType {
|
||||
/// Conversion method to [CharacterTheme]
|
||||
CharacterTheme get toTheme {
|
||||
switch (this) {
|
||||
case CharacterType.dash:
|
||||
return const DashTheme();
|
||||
case CharacterType.sparky:
|
||||
return const SparkyTheme();
|
||||
case CharacterType.android:
|
||||
return const AndroidTheme();
|
||||
case CharacterType.dino:
|
||||
return const DinoTheme();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts [CharacterTheme] to [CharacterType] to persist at repository the
|
||||
/// character theme from UI.
|
||||
extension CharacterThemeX on CharacterTheme {
|
||||
/// Conversion method to [CharacterType]
|
||||
CharacterType get toType {
|
||||
switch (runtimeType) {
|
||||
case DashTheme:
|
||||
return CharacterType.dash;
|
||||
case SparkyTheme:
|
||||
return CharacterType.sparky;
|
||||
case AndroidTheme:
|
||||
return CharacterType.android;
|
||||
case DinoTheme:
|
||||
return CharacterType.dino;
|
||||
default:
|
||||
return CharacterType.dash;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'leaderboard_entry.dart';
|
||||
part of 'leaderboard_entry_data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
LeaderboardEntry _$LeaderboardEntryFromJson(Map<String, dynamic> json) =>
|
||||
LeaderboardEntry(
|
||||
LeaderboardEntryData _$LeaderboardEntryFromJson(Map<String, dynamic> json) =>
|
||||
LeaderboardEntryData(
|
||||
playerInitials: json['playerInitials'] as String,
|
||||
score: json['score'] as int,
|
||||
character: $enumDecode(_$CharacterTypeEnumMap, json['character']),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LeaderboardEntryToJson(LeaderboardEntry instance) =>
|
||||
Map<String, dynamic> _$LeaderboardEntryToJson(LeaderboardEntryData instance) =>
|
||||
<String, dynamic>{
|
||||
'playerInitials': instance.playerInitials,
|
||||
'score': instance.score,
|
@ -1,2 +1,2 @@
|
||||
export 'leaderboard_entry.dart';
|
||||
export 'leaderboard_entry_data.dart';
|
||||
export 'leaderboard_ranking.dart';
|
||||
|
@ -1 +1,4 @@
|
||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
||||
analyzer:
|
||||
exclude:
|
||||
- lib/**/*.gen.dart
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@ -0,0 +1,68 @@
|
||||
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
/// *****************************************************
|
||||
/// FlutterGen
|
||||
/// *****************************************************
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class $AssetsImagesGen {
|
||||
const $AssetsImagesGen();
|
||||
|
||||
AssetGenImage get ball => const AssetGenImage('assets/images/ball.png');
|
||||
}
|
||||
|
||||
class Assets {
|
||||
Assets._();
|
||||
|
||||
static const $AssetsImagesGen images = $AssetsImagesGen();
|
||||
}
|
||||
|
||||
class AssetGenImage extends AssetImage {
|
||||
const AssetGenImage(String assetName)
|
||||
: super(assetName, package: 'pinball_components');
|
||||
|
||||
Image image({
|
||||
Key? key,
|
||||
ImageFrameBuilder? frameBuilder,
|
||||
ImageLoadingBuilder? loadingBuilder,
|
||||
ImageErrorWidgetBuilder? errorBuilder,
|
||||
String? semanticLabel,
|
||||
bool excludeFromSemantics = false,
|
||||
double? width,
|
||||
double? height,
|
||||
Color? color,
|
||||
BlendMode? colorBlendMode,
|
||||
BoxFit? fit,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
ImageRepeat repeat = ImageRepeat.noRepeat,
|
||||
Rect? centerSlice,
|
||||
bool matchTextDirection = false,
|
||||
bool gaplessPlayback = false,
|
||||
bool isAntiAlias = false,
|
||||
FilterQuality filterQuality = FilterQuality.low,
|
||||
}) {
|
||||
return Image(
|
||||
key: key,
|
||||
image: this,
|
||||
frameBuilder: frameBuilder,
|
||||
loadingBuilder: loadingBuilder,
|
||||
errorBuilder: errorBuilder,
|
||||
semanticLabel: semanticLabel,
|
||||
excludeFromSemantics: excludeFromSemantics,
|
||||
width: width,
|
||||
height: height,
|
||||
color: color,
|
||||
colorBlendMode: colorBlendMode,
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
repeat: repeat,
|
||||
centerSlice: centerSlice,
|
||||
matchTextDirection: matchTextDirection,
|
||||
gaplessPlayback: gaplessPlayback,
|
||||
isAntiAlias: isAntiAlias,
|
||||
filterQuality: filterQuality,
|
||||
);
|
||||
}
|
||||
|
||||
String get path => assetName;
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
library pinball_components;
|
||||
|
||||
export 'gen/assets.gen.dart';
|
||||
export 'src/pinball_components.dart';
|
||||
|
@ -0,0 +1,72 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template ball}
|
||||
/// A solid, [BodyType.dynamic] sphere that rolls and bounces around
|
||||
/// {@endtemplate}
|
||||
class Ball<T extends Forge2DGame> extends BodyComponent<T>
|
||||
with Layered, InitialPosition {
|
||||
/// {@macro ball_body}
|
||||
Ball({
|
||||
required this.baseColor,
|
||||
}) {
|
||||
// TODO(ruimiguel): while developing Ball can be launched by clicking mouse,
|
||||
// and default layer is Layer.all. But on final game Ball will be always be
|
||||
// be launched from Plunger and LauncherRamp will modify it to Layer.board.
|
||||
// We need to see what happens if Ball appears from other place like nest
|
||||
// bumper, it will need to explicit change layer to Layer.board then.
|
||||
layer = Layer.board;
|
||||
}
|
||||
|
||||
/// The size of the [Ball]
|
||||
final Vector2 size = Vector2.all(2);
|
||||
|
||||
/// The base [Color] used to tint this [Ball]
|
||||
final Color baseColor;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
final sprite = await gameRef.loadSprite(Assets.images.ball.keyName);
|
||||
final tint = baseColor.withOpacity(0.5);
|
||||
await add(
|
||||
SpriteComponent(
|
||||
sprite: sprite,
|
||||
size: size,
|
||||
anchor: Anchor.center,
|
||||
)..tint(tint),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Body createBody() {
|
||||
final shape = CircleShape()..radius = size.x / 2;
|
||||
|
||||
final fixtureDef = FixtureDef(shape)..density = 1;
|
||||
|
||||
final bodyDef = BodyDef()
|
||||
..position = initialPosition
|
||||
..userData = this
|
||||
..type = BodyType.dynamic;
|
||||
|
||||
return world.createBody(bodyDef)..createFixture(fixtureDef);
|
||||
}
|
||||
|
||||
/// Immediatly and completly [stop]s the ball.
|
||||
///
|
||||
/// The [Ball] will no longer be affected by any forces, including it's
|
||||
/// weight and those emitted from collisions.
|
||||
void stop() {
|
||||
body.setType(BodyType.static);
|
||||
}
|
||||
|
||||
/// Allows the [Ball] to be affected by forces.
|
||||
///
|
||||
/// If previously [stop]ed, the previous ball's velocity is not kept.
|
||||
void resume() {
|
||||
body.setType(BodyType.dynamic);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export 'ball.dart';
|
||||
export 'initial_position.dart';
|
||||
export 'layer.dart';
|
@ -1,7 +1 @@
|
||||
/// {@template pinball_components}
|
||||
/// Package with the UI game components for the Pinball Game
|
||||
/// {@endtemplate}
|
||||
class PinballComponents {
|
||||
/// {@macro pinball_components}
|
||||
const PinballComponents();
|
||||
}
|
||||
export 'components/components.dart';
|
||||
|
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
Thanks for contributing!
|
||||
|
||||
Provide a description of your changes below and a general summary in the title
|
||||
|
||||
Please look at the following checklist to ensure that your PR can be accepted quickly:
|
||||
-->
|
||||
|
||||
## Description
|
||||
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
<!--- Put an `x` in all the boxes that apply: -->
|
||||
|
||||
- [ ] ✨ New feature (non-breaking change which adds functionality)
|
||||
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
|
||||
- [ ] 🧹 Code refactor
|
||||
- [ ] ✅ Build configuration change
|
||||
- [ ] 📝 Documentation
|
||||
- [ ] 🗑️ Chore
|
@ -0,0 +1,10 @@
|
||||
name: sandbox
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
|
||||
with:
|
||||
flutter_channel: stable
|
||||
flutter_version: 2.10.0
|
@ -0,0 +1,127 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/*
|
||||
|
||||
# Visual Studio Code related
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
.vscode/*
|
||||
|
||||
# Flutter repo-specific
|
||||
/bin/cache/
|
||||
/bin/mingit/
|
||||
/dev/benchmarks/mega_gallery/
|
||||
/dev/bots/.recipe_deps
|
||||
/dev/bots/android_tools/
|
||||
/dev/docs/doc/
|
||||
/dev/docs/flutter.docs.zip
|
||||
/dev/docs/lib/
|
||||
/dev/docs/pubspec.yaml
|
||||
/dev/integration_tests/**/xcuserdata
|
||||
/dev/integration_tests/**/Pods
|
||||
/packages/flutter/coverage/
|
||||
version
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
flutter_*.png
|
||||
linked_*.ds
|
||||
unlinked.ds
|
||||
unlinked_spec.ds
|
||||
.fvm/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
**/android/key.properties
|
||||
**/android/.idea/
|
||||
*.jks
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/.last_build_id
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# Submodules
|
||||
!pubspec.lock
|
||||
packages/**/pubspec.lock
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Exceptions to the above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
!/dev/ci/**/Gemfile.lock
|
||||
!.vscode/extensions.json
|
||||
!.vscode/launch.json
|
||||
!.idea/codeStyles/
|
||||
!.idea/dictionaries/
|
||||
!.idea/runConfigurations/
|
@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Very Good Ventures
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,164 @@
|
||||
# Sandbox
|
||||
|
||||
![coverage][coverage_badge]
|
||||
[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link]
|
||||
[![License: MIT][license_badge]][license_link]
|
||||
|
||||
Generated by the [Very Good CLI][very_good_cli_link] 🤖
|
||||
|
||||
A sanbox application where components are showcased and developed in an isolated way
|
||||
|
||||
---
|
||||
|
||||
## Getting Started 🚀
|
||||
|
||||
This project contains 3 flavors:
|
||||
|
||||
- development
|
||||
- staging
|
||||
- production
|
||||
|
||||
To run the desired flavor either use the launch configuration in VSCode/Android Studio or use the following commands:
|
||||
|
||||
```sh
|
||||
# Development
|
||||
$ flutter run --flavor development --target lib/main_development.dart
|
||||
|
||||
# Staging
|
||||
$ flutter run --flavor staging --target lib/main_staging.dart
|
||||
|
||||
# Production
|
||||
$ flutter run --flavor production --target lib/main_production.dart
|
||||
```
|
||||
|
||||
_\*Sandbox works on iOS, Android, Web, and Windows._
|
||||
|
||||
---
|
||||
|
||||
## Running Tests 🧪
|
||||
|
||||
To run all unit and widget tests use the following command:
|
||||
|
||||
```sh
|
||||
$ flutter test --coverage --test-randomize-ordering-seed random
|
||||
```
|
||||
|
||||
To view the generated coverage report you can use [lcov](https://github.com/linux-test-project/lcov).
|
||||
|
||||
```sh
|
||||
# Generate Coverage Report
|
||||
$ genhtml coverage/lcov.info -o coverage/
|
||||
|
||||
# Open Coverage Report
|
||||
$ open coverage/index.html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Working with Translations 🌐
|
||||
|
||||
This project relies on [flutter_localizations][flutter_localizations_link] and follows the [official internationalization guide for Flutter][internationalization_link].
|
||||
|
||||
### Adding Strings
|
||||
|
||||
1. To add a new localizable string, open the `app_en.arb` file at `lib/l10n/arb/app_en.arb`.
|
||||
|
||||
```arb
|
||||
{
|
||||
"@@locale": "en",
|
||||
"counterAppBarTitle": "Counter",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Text shown in the AppBar of the Counter Page"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Then add a new key/value and description
|
||||
|
||||
```arb
|
||||
{
|
||||
"@@locale": "en",
|
||||
"counterAppBarTitle": "Counter",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Text shown in the AppBar of the Counter Page"
|
||||
},
|
||||
"helloWorld": "Hello World",
|
||||
"@helloWorld": {
|
||||
"description": "Hello World Text"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Use the new string
|
||||
|
||||
```dart
|
||||
import 'package:sandbox/l10n/l10n.dart';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
return Text(l10n.helloWorld);
|
||||
}
|
||||
```
|
||||
|
||||
### Adding Supported Locales
|
||||
|
||||
Update the `CFBundleLocalizations` array in the `Info.plist` at `ios/Runner/Info.plist` to include the new locale.
|
||||
|
||||
```xml
|
||||
...
|
||||
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
<string>es</string>
|
||||
</array>
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
### Adding Translations
|
||||
|
||||
1. For each supported locale, add a new ARB file in `lib/l10n/arb`.
|
||||
|
||||
```
|
||||
├── l10n
|
||||
│ ├── arb
|
||||
│ │ ├── app_en.arb
|
||||
│ │ └── app_es.arb
|
||||
```
|
||||
|
||||
2. Add the translated strings to each `.arb` file:
|
||||
|
||||
`app_en.arb`
|
||||
|
||||
```arb
|
||||
{
|
||||
"@@locale": "en",
|
||||
"counterAppBarTitle": "Counter",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Text shown in the AppBar of the Counter Page"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`app_es.arb`
|
||||
|
||||
```arb
|
||||
{
|
||||
"@@locale": "es",
|
||||
"counterAppBarTitle": "Contador",
|
||||
"@counterAppBarTitle": {
|
||||
"description": "Texto mostrado en la AppBar de la página del contador"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[coverage_badge]: coverage_badge.svg
|
||||
[flutter_localizations_link]: https://api.flutter.dev/flutter/flutter_localizations/flutter_localizations-library.html
|
||||
[internationalization_link]: https://flutter.dev/docs/development/accessibility-and-localization/internationalization
|
||||
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[license_link]: https://opensource.org/licenses/MIT
|
||||
[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg
|
||||
[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis
|
||||
[very_good_cli_link]: https://github.com/VeryGoodOpenSource/very_good_cli
|
@ -0,0 +1,4 @@
|
||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
||||
linter:
|
||||
rules:
|
||||
public_member_api_docs: false
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,11 @@
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
|
||||
String buildSourceLink(String path) {
|
||||
return 'https://github.com/VGVentures/pinball/tree/main/packages/pinball_components/sandbox/lib/stories/$path';
|
||||
}
|
||||
|
||||
class BasicGame extends Forge2DGame {
|
||||
BasicGame() {
|
||||
images.prefix = '';
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2022, Very Good Ventures
|
||||
// https://verygood.ventures
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sandbox/stories/stories.dart';
|
||||
|
||||
void main() {
|
||||
final dashbook = Dashbook(theme: ThemeData.dark());
|
||||
|
||||
addBallStories(dashbook);
|
||||
runApp(dashbook);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/ball/basic.dart';
|
||||
|
||||
void addBallStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('Ball').add(
|
||||
'Basic',
|
||||
(context) => GameWidget(
|
||||
game: BasicBallGame(
|
||||
color: context.colorProperty('color', Colors.blue),
|
||||
),
|
||||
),
|
||||
codeLink: buildSourceLink('ball/basic.dart'),
|
||||
info: BasicBallGame.info,
|
||||
);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import 'package:flame/input.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
|
||||
class BasicBallGame extends BasicGame with TapDetector {
|
||||
BasicBallGame({ required this.color });
|
||||
|
||||
static const info = '''
|
||||
Basic example of how a Ball works, tap anywhere on the
|
||||
screen to spawn a ball into the game.
|
||||
''';
|
||||
|
||||
final Color color;
|
||||
|
||||
@override
|
||||
void onTapUp(TapUpInfo info) {
|
||||
add(Ball(baseColor: color)
|
||||
..initialPosition = info.eventPosition.game,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'ball/ball.dart';
|
@ -0,0 +1,446 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
dashbook:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dashbook
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.7"
|
||||
device_frame:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_frame
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
flame:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flame
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-releasecandidate.6"
|
||||
flame_forge2d:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flame_forge2d
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0-releasecandidate.6"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_colorpicker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
flutter_markdown:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_markdown
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.9"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
forge2d:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: forge2d
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0"
|
||||
freezed_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: freezed_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.4.0"
|
||||
markdown:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: markdown
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
ordered_set:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ordered_set
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
pinball_components:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0+1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
shared_preferences:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.13"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
shared_preferences_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
shared_preferences_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.8"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.20"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.15"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.15"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
very_good_analysis:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: very_good_analysis
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+1"
|
||||
sdks:
|
||||
dart: ">=2.16.0 <3.0.0"
|
||||
flutter: ">=2.10.0"
|
@ -0,0 +1,24 @@
|
||||
name: sandbox
|
||||
description: A sanbox application where components are showcased and developed in an isolated way
|
||||
version: 1.0.0+1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
dashbook: ^0.1.7
|
||||
flame: ^1.1.0-releasecandidate.6
|
||||
flame_forge2d: ^0.9.0-releasecandidate.6
|
||||
flutter:
|
||||
sdk: flutter
|
||||
pinball_components:
|
||||
path: ../
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
very_good_analysis: ^2.4.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
After Width: | Height: | Size: 917 B |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
If you are serving your web app in a path other than the root, change the
|
||||
href value below to reflect the base path you are serving from.
|
||||
|
||||
The path provided below has to start and end with a slash "/" in order for
|
||||
it to work correctly.
|
||||
|
||||
For more details:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
|
||||
This is a placeholder for base href that will be replaced by the value of
|
||||
the `--base-href` argument provided to `flutter build`.
|
||||
-->
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="sandbox">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<title>sandbox</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
</head>
|
||||
<body>
|
||||
<!-- This script installs service_worker.js to provide PWA functionality to
|
||||
application. For more information, see:
|
||||
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
||||
<script>
|
||||
var serviceWorkerVersion = null;
|
||||
var scriptLoaded = false;
|
||||
function loadMainDartJs() {
|
||||
if (scriptLoaded) {
|
||||
return;
|
||||
}
|
||||
scriptLoaded = true;
|
||||
var scriptTag = document.createElement('script');
|
||||
scriptTag.src = 'main.dart.js';
|
||||
scriptTag.type = 'application/javascript';
|
||||
document.body.append(scriptTag);
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
// Service workers are supported. Use them.
|
||||
window.addEventListener('load', function () {
|
||||
// Wait for registration to finish before dropping the <script> tag.
|
||||
// Otherwise, the browser will load the script multiple times,
|
||||
// potentially different versions.
|
||||
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
|
||||
navigator.serviceWorker.register(serviceWorkerUrl)
|
||||
.then((reg) => {
|
||||
function waitForActivation(serviceWorker) {
|
||||
serviceWorker.addEventListener('statechange', () => {
|
||||
if (serviceWorker.state == 'activated') {
|
||||
console.log('Installed new service worker.');
|
||||
loadMainDartJs();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!reg.active && (reg.installing || reg.waiting)) {
|
||||
// No active web worker and we have installed or are installing
|
||||
// one for the first time. Simply wait for it to activate.
|
||||
waitForActivation(reg.installing || reg.waiting);
|
||||
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
|
||||
// When the app updates the serviceWorkerVersion changes, so we
|
||||
// need to ask the service worker to update.
|
||||
console.log('New service worker available.');
|
||||
reg.update();
|
||||
waitForActivation(reg.installing);
|
||||
} else {
|
||||
// Existing service worker is still good.
|
||||
console.log('Loading app from service worker.');
|
||||
loadMainDartJs();
|
||||
}
|
||||
});
|
||||
|
||||
// If service worker doesn't succeed in a reasonable amount of time,
|
||||
// fallback to plaint <script> tag.
|
||||
setTimeout(() => {
|
||||
if (!scriptLoaded) {
|
||||
console.warn(
|
||||
'Failed to load app from service worker. Falling back to plain <script> tag.',
|
||||
);
|
||||
loadMainDartJs();
|
||||
}
|
||||
}, 4000);
|
||||
});
|
||||
} else {
|
||||
// Service workers not supported. Just drop the <script> tag.
|
||||
loadMainDartJs();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "sandbox",
|
||||
"short_name": "sandbox",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'test_game.dart';
|
@ -0,0 +1,7 @@
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
|
||||
class TestGame extends Forge2DGame {
|
||||
TestGame() {
|
||||
images.prefix = '';
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(TestGame.new);
|
||||
|
||||
group('Ball', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ready();
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
expect(game.contains(ball), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
group('body', () {
|
||||
flameTester.test(
|
||||
'is dynamic',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
expect(ball.body.bodyType, equals(BodyType.dynamic));
|
||||
},
|
||||
);
|
||||
|
||||
group('can be moved', () {
|
||||
flameTester.test('by its weight', (game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
game.update(1);
|
||||
expect(ball.body.position, isNot(equals(ball.initialPosition)));
|
||||
});
|
||||
|
||||
flameTester.test('by applying velocity', (game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
ball.body.gravityScale = 0;
|
||||
ball.body.linearVelocity.setValues(10, 10);
|
||||
game.update(1);
|
||||
expect(ball.body.position, isNot(equals(ball.initialPosition)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('fixture', () {
|
||||
flameTester.test(
|
||||
'exists',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
expect(ball.body.fixtures[0], isA<Fixture>());
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'is dense',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
final fixture = ball.body.fixtures[0];
|
||||
expect(fixture.density, greaterThan(0));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'shape is circular',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
|
||||
final fixture = ball.body.fixtures[0];
|
||||
expect(fixture.shape.shapeType, equals(ShapeType.circle));
|
||||
expect(fixture.shape.radius, equals(1));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'has Layer.all as default filter maskBits',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ready();
|
||||
await game.ensureAdd(ball);
|
||||
await game.ready();
|
||||
|
||||
final fixture = ball.body.fixtures[0];
|
||||
expect(fixture.filterData.maskBits, equals(Layer.board.maskBits));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('stop', () {
|
||||
group("can't be moved", () {
|
||||
flameTester.test('by its weight', (game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
ball.stop();
|
||||
|
||||
game.update(1);
|
||||
expect(ball.body.position, equals(ball.initialPosition));
|
||||
});
|
||||
});
|
||||
|
||||
flameTester.test('by applying velocity', (game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
ball.stop();
|
||||
|
||||
ball.body.linearVelocity.setValues(10, 10);
|
||||
game.update(1);
|
||||
expect(ball.body.position, equals(ball.initialPosition));
|
||||
});
|
||||
});
|
||||
|
||||
group('resume', () {
|
||||
group('can move', () {
|
||||
flameTester.test(
|
||||
'by its weight when previously stopped',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
ball.stop();
|
||||
ball.resume();
|
||||
|
||||
game.update(1);
|
||||
expect(ball.body.position, isNot(equals(ball.initialPosition)));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'by applying velocity when previously stopped',
|
||||
(game) async {
|
||||
final ball = Ball(baseColor: Colors.blue);
|
||||
await game.ensureAdd(ball);
|
||||
ball.stop();
|
||||
ball.resume();
|
||||
|
||||
ball.body.gravityScale = 0;
|
||||
ball.body.linearVelocity.setValues(10, 10);
|
||||
game.update(1);
|
||||
expect(ball.body.position, isNot(equals(ball.initialPosition)));
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
void main() {
|
||||
group('PinballComponents', () {
|
||||
test('can be instantiated', () {
|
||||
expect(PinballComponents(), isNotNull);
|
||||
});
|
||||
});
|
||||
}
|