diff --git a/examples/lib/stories/components/priority.dart b/examples/lib/stories/components/priority.dart index 0f74f934d..72b695228 100644 --- a/examples/lib/stories/components/priority.dart +++ b/examples/lib/stories/components/priority.dart @@ -1,11 +1,9 @@ -import 'dart:math'; import 'dart:ui'; import 'package:flame/components.dart'; import 'package:flame/extensions.dart'; import 'package:flame/game.dart'; import 'package:flame/input.dart'; -import 'package:flame/palette.dart'; const priorityInfo = ''' On this example, click on the square to bring them to the front by changing the @@ -18,7 +16,7 @@ class Square extends PositionComponent with HasGameRef, Tappable { Square(Vector2 position) { this.position.setFrom(position); size.setValues(100, 100); - paint = _randomPaint(); + paint = PaintExtension.random(withAlpha: 0.9, base: 100); } @override @@ -35,17 +33,6 @@ class Square extends PositionComponent with HasGameRef, Tappable { super.render(canvas); canvas.drawRect(size.toRect(), paint); } - - static Paint _randomPaint() { - final rng = Random(); - final color = Color.fromRGBO( - rng.nextInt(256), - rng.nextInt(256), - rng.nextInt(256), - 0.9, - ); - return PaletteEntry(color).paint(); - } } class Priority extends FlameGame with HasTappableComponents { diff --git a/examples/lib/stories/input/overlapping_tappables.dart b/examples/lib/stories/input/overlapping_tappables.dart index b3b684a21..8b7276a06 100644 --- a/examples/lib/stories/input/overlapping_tappables.dart +++ b/examples/lib/stories/input/overlapping_tappables.dart @@ -1,26 +1,13 @@ -import 'dart:math' as math; - import 'package:flame/components.dart'; +import 'package:flame/extensions.dart'; import 'package:flame/game.dart'; -import 'package:flame/palette.dart'; import 'package:flutter/material.dart'; class TappableSquare extends PositionComponent with Tappable { - static Paint _randomPaint() { - final rng = math.Random(); - final color = Color.fromRGBO( - rng.nextInt(256), - rng.nextInt(256), - rng.nextInt(256), - 0.9, - ); - return PaletteEntry(color).paint(); - } - Paint currentPaint; TappableSquare({Vector2? position}) - : currentPaint = _randomPaint(), + : currentPaint = PaintExtension.random(withAlpha: 0.9, base: 100), super( position: position ?? Vector2.all(100), size: Vector2.all(100), diff --git a/packages/flame/CHANGELOG.md b/packages/flame/CHANGELOG.md index 2a5e2e03c..723b2cbaf 100644 --- a/packages/flame/CHANGELOG.md +++ b/packages/flame/CHANGELOG.md @@ -17,6 +17,7 @@ - Create default implementations of `RectangleComponent`, `CircleComponent` and `PolygonComponent` - Streamlined the argument list for all components extending `PositionComponent` - Improved interaction between viewport and isHud components + - `randomColor` method in the `Color` extension - Calling super-method in `.render()` is now optional - Components that manipulate canvas state are now responsible for saving/restoring that state diff --git a/packages/flame/lib/extensions.dart b/packages/flame/lib/extensions.dart index 71d15e158..cb3562c57 100644 --- a/packages/flame/lib/extensions.dart +++ b/packages/flame/lib/extensions.dart @@ -3,6 +3,7 @@ export 'src/extensions/color.dart'; export 'src/extensions/image.dart'; export 'src/extensions/matrix4.dart'; export 'src/extensions/offset.dart'; +export 'src/extensions/paint.dart'; export 'src/extensions/rect.dart'; export 'src/extensions/rectangle.dart'; export 'src/extensions/size.dart'; diff --git a/packages/flame/lib/palette.dart b/packages/flame/lib/palette.dart index 96a3dd457..caf3c809f 100644 --- a/packages/flame/lib/palette.dart +++ b/packages/flame/lib/palette.dart @@ -1 +1,3 @@ +export 'src/extensions/color.dart'; +export 'src/extensions/paint.dart'; export 'src/palette.dart'; diff --git a/packages/flame/lib/src/extensions/color.dart b/packages/flame/lib/src/extensions/color.dart index 3f4baff6f..e339c2644 100644 --- a/packages/flame/lib/src/extensions/color.dart +++ b/packages/flame/lib/src/extensions/color.dart @@ -1,3 +1,4 @@ +import 'dart:math'; import 'dart:ui'; export 'dart:ui' show Color; @@ -101,4 +102,27 @@ extension ColorExtension on Color { components[3], ); } + + /// Generates a random [Color] with the set [withAlpha] or the default (1.0). + /// You can pass in a random number generator [rng], if omitted the function + /// will create a new [Random] object without a seed and use that. + /// [base] can be used to get the random colors in only a lighter spectrum, it + /// should be between [0-256]. + static Color random({ + double withAlpha = 1.0, + int base = 0, + Random? rng, + }) { + assert( + base >= 0 && base <= 256, + 'The base argument should be between 0-256', + ); + rng ??= Random(); + return Color.fromRGBO( + base + (base == 256 ? 0 : rng.nextInt(256 - base)), + base + (base == 256 ? 0 : rng.nextInt(256 - base)), + base + (base == 256 ? 0 : rng.nextInt(256 - base)), + withAlpha, + ); + } } diff --git a/packages/flame/lib/src/extensions/paint.dart b/packages/flame/lib/src/extensions/paint.dart new file mode 100644 index 000000000..b7715b578 --- /dev/null +++ b/packages/flame/lib/src/extensions/paint.dart @@ -0,0 +1,81 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'color.dart'; + +export 'dart:ui' show Color; + +extension PaintExtension on Paint { + /// Darken the shade of the [Color] in the [Paint] object by the [amount]. + /// + /// [amount] is a double between 0 and 1. + /// + /// Based on: https://stackoverflow.com/a/60191441. + void darken(double amount) { + color = color.darken(amount); + } + + /// Brighten the shade of the [Color] in the [Paint] object by the [amount]. + /// + /// [amount] is a double between 0 and 1. + /// + /// Based on: https://stackoverflow.com/a/60191441. + void brighten(double amount) { + color = color.brighten(amount); + } + + /// Parses an RGB color from a valid hex string (e.g. #1C1C1C). + /// + /// The `#` is optional. + /// The short-hand syntax is support, e.g.: #CCC. + /// Lower-case letters are supported. + /// + /// Examples of valid inputs: + /// ccc, CCC, #ccc, #CCC, #c1c1c1, #C1C1C1, c1c1c1, C1C1C1 + /// + /// If the string is not valid, an error is thrown. + /// + /// Note: if you are hardcoding colors, use Dart's built-in hexadecimal + /// literals instead. + static Paint fromRGBHexString(String hexString) { + final color = ColorExtension.fromRGBHexString(hexString); + return Paint()..color = color; + } + + /// Parses an ARGB color from a valid hex string (e.g. #1C1C1C). + /// + /// The `#` is optional. + /// The short-hand syntax is support, e.g.: #CCCC. + /// Lower-case letters are supported. + /// + /// Examples of valid inputs: + /// fccc, FCCC, #fccc, #FCCC, #ffc1c1c1, #FFC1C1C1, ffc1c1c1, FFC1C1C1 + /// + /// If the string is not valid, an error is thrown. + /// + /// Note: if you are hardcoding colors, use Dart's built-in hexadecimal + /// literals instead. + static Paint fromARGBHexString(String hexString) { + final color = ColorExtension.fromARGBHexString(hexString); + return Paint()..color = color; + } + + /// Generates a random [Color] in a new [Paint] object with the set + /// alpha as [withAlpha] or the default (1.0). + /// You can pass in a random number generator [rng], if omitted the function + /// will create a new [Random] object without a seed and use that. + /// [base] can be used to get the random colors in only a lighter spectrum, it + /// should be between [0-256]. + static Paint random({ + double withAlpha = 1.0, + int base = 0, + Random? rng, + }) { + final color = ColorExtension.random( + withAlpha: withAlpha, + base: base, + rng: rng, + ); + return Paint()..color = color; + } +} diff --git a/packages/flame_forge2d/example/lib/balls.dart b/packages/flame_forge2d/example/lib/balls.dart index c78907182..156ba18d7 100644 --- a/packages/flame_forge2d/example/lib/balls.dart +++ b/packages/flame_forge2d/example/lib/balls.dart @@ -1,5 +1,3 @@ -import 'dart:math' as math; - import 'package:flame/palette.dart'; import 'package:flame_forge2d/body_component.dart'; import 'package:flame_forge2d/contact_callbacks.dart'; @@ -23,17 +21,7 @@ class Ball extends BodyComponent { paint = originalPaint; } - Paint randomPaint() { - final rng = math.Random(); - return PaletteEntry( - Color.fromARGB( - 100 + rng.nextInt(155), - 100 + rng.nextInt(155), - 100 + rng.nextInt(155), - 255, - ), - ).paint(); - } + Paint randomPaint() => PaintExtension.random(withAlpha: 0.9, base: 100); @override Body createBody() { diff --git a/packages/flame_rive/example/lib/main.dart b/packages/flame_rive/example/lib/main.dart index 5bcd9a85b..8ecb9a5e7 100644 --- a/packages/flame_rive/example/lib/main.dart +++ b/packages/flame_rive/example/lib/main.dart @@ -1,6 +1,5 @@ -import 'dart:math'; - import 'package:flame/components.dart'; +import 'package:flame/extensions.dart'; import 'package:flame/game.dart'; import 'package:flame/input.dart'; import 'package:flame/palette.dart'; @@ -85,7 +84,7 @@ class Square extends PositionComponent with HasGameRef { Square(Vector2 position) { this.position.setFrom(position); size.setValues(100, 100); - paint = _randomPaint(); + paint = PaintExtension.random(withAlpha: 0.9, base: 100); } @override @@ -93,15 +92,4 @@ class Square extends PositionComponent with HasGameRef { super.render(canvas); canvas.drawRect(size.toRect(), paint); } - - static Paint _randomPaint() { - final rng = Random(); - final color = Color.fromRGBO( - rng.nextInt(256), - rng.nextInt(256), - rng.nextInt(256), - 0.9, - ); - return PaletteEntry(color).paint(); - } }