Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: Fix background color blending by using doubles #102

Merged
merged 1 commit into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 11 additions & 51 deletions lib/game/components/background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import 'package:lightrunners/game/lightrunners_game.dart';
import 'package:lightrunners/ui/palette.dart';
import 'package:lightrunners/utils/delaunay.dart';
import 'package:lightrunners/utils/flame_utils.dart';
import 'package:lightrunners/utils/mutable_color.dart';

const _margin = 200.0;

const _numberShades = 5;
const _shadeStep = 0.1;
const _colorMoveSpeed = 30;
const _colorMoveSpeed = 0.8;
final _emptyColor = GamePalette.black.brighten(0.1);
final _borderPaint = Paint()
..color = GamePalette.black
Expand All @@ -33,7 +34,7 @@ class Background extends PositionComponent
late Rect clipArea;
late List<ShadedTriangle> mesh;

Color currentColor = _emptyColor;
MutableColor currentColor = MutableColor.fromColor(_emptyColor);

@override
void onGameResize(Vector2 gameSize) {
Expand Down Expand Up @@ -72,8 +73,7 @@ class Background extends PositionComponent
super.update(dt);

final targetColor = _computeTargetColor();
currentColor =
_moveTowards(currentColor, targetColor, _colorMoveSpeed * dt);
currentColor.moveTowards(targetColor, _colorMoveSpeed * dt);
}

@override
Expand All @@ -82,7 +82,8 @@ class Background extends PositionComponent
canvas.clipRect(clipArea);

for (final t in mesh) {
final shadedColor = currentColor.brighten(t.shadeLevel * _shadeStep);
final shadedColor =
currentColor.toColor().brighten(t.shadeLevel * _shadeStep);
canvas.drawPath(t.path, paint..color = shadedColor);
}

Expand All @@ -91,60 +92,19 @@ class Background extends PositionComponent
}
}

(int, int, int) _computeTargetColor() {
MutableColor _computeTargetColor() {
final sortedShips = game.ships.values.sortedBy<num>((ship) => -ship.score);
final maxScore = sortedShips.first.score;
if (maxScore == 0) {
return _fromColor(_emptyColor);
return MutableColor.fromColor(_emptyColor);
}
final colors = sortedShips
.takeWhile((ship) => ship.score == maxScore)
.map((ship) => ship.paint.color.darken(0.75))
.toList();
return colors.map(_fromColor).reduce((value, element) => value + element) /
return colors
.map(MutableColor.fromColor)
.reduce((value, element) => value + element) /
colors.length.toDouble();
}

Color _moveTowards(Color currentColor, (int, int, int) target, double ds) {
final color = _fromColor(currentColor);
if (color == target) {
return currentColor;
}
return color.moveTowards(target, ds).toColor();
}
}

extension on (int, int, int) {
Color toColor() => Color.fromARGB(255, $1, $2, $3);

(int, int, int) operator +((int, int, int) other) =>
(this.$1 + other.$1, this.$2 + other.$2, this.$3 + other.$3);

(int, int, int) operator -((int, int, int) other) => this + (-other);

(int, int, int) operator /(double other) =>
_fromDoubles(this.$1 / other, this.$2 / other, this.$3 / other);

(int, int, int) operator *(double other) =>
_fromDoubles(this.$1 * other, this.$2 * other, this.$3 * other);

(int, int, int) operator -() => (-this.$1, -this.$2, -this.$3);

double get length => sqrt($1 * $1 + $2 * $2 + $3 * $3);

(int, int, int) normalized() => this / length;

(int, int, int) moveTowards((int, int, int) target, double ds) {
final diff = target - this;
if (diff.length < ds) {
return target;
} else {
return this + diff.normalized() * ds;
}
}
}

(int, int, int) _fromDoubles(double r, double g, double b) =>
(r.round(), g.round(), b.round());

(int, int, int) _fromColor(Color color) => (color.red, color.green, color.blue);
48 changes: 48 additions & 0 deletions lib/utils/mutable_color.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import 'package:flame/extensions.dart';

class MutableColor {
final Vector3 rgb;

double get r => rgb.x;
set r(double value) => rgb.x = value;

double get g => rgb.y;
set g(double value) => rgb.y = value;

double get b => rgb.z;
set b(double value) => rgb.z = value;

MutableColor(double r, double g, double b) : rgb = Vector3(r, g, b);

MutableColor.fromColor(Color color)
: this(
color.red.toDouble(),
color.green.toDouble(),
color.blue.toDouble(),
);

Color toColor() => Color.fromARGB(255, r.round(), g.round(), b.round());

MutableColor operator +(MutableColor other) {
return MutableColor(r + other.r, g + other.g, b + other.b);
}

MutableColor operator /(double scalar) {
return MutableColor(r / scalar, g / scalar, b / scalar);
}

void moveTowards(MutableColor target, double ds) {
r = _moveTowards(r, target.r, ds);
g = _moveTowards(g, target.g, ds);
b = _moveTowards(b, target.b, ds);
}

double _moveTowards(double current, double target, double ds) {
final diff = target - current;
if (diff.abs() < ds) {
return target;
} else {
return current + ds * diff.sign;
}
}
}
Loading