Commit a66a5c4b authored by Viktor Lidholt's avatar Viktor Lidholt

Improvements to EffectLine in sprites

parent 93ebc9e4
...@@ -42,19 +42,20 @@ class TestApp extends App { ...@@ -42,19 +42,20 @@ class TestApp extends App {
List<String> _labelTexts = [ List<String> _labelTexts = [
"Colored", "Colored",
"Smoke", "Smoke",
"Electric" "Electric",
"Rocket Trail"
]; ];
Widget build() { Widget build() {
ThemeData theme = new ThemeData( ThemeData theme = new ThemeData(
brightness: ThemeBrightness.light, brightness: ThemeBrightness.light,
primarySwatch: Colors.purple primarySwatch: Colors.blue
); );
return new Theme( return new Theme(
data: theme, data: theme,
child: new Title( child: new Title(
title: 'Test drawAtlas', title: 'EffectLine Demo',
child: _buildColumn() child: _buildColumn()
) )
); );
...@@ -114,11 +115,10 @@ class TestBed extends NodeWithSize { ...@@ -114,11 +115,10 @@ class TestBed extends NodeWithSize {
// Create a line with no texture and a color sequence // Create a line with no texture and a color sequence
_line = new EffectLine( _line = new EffectLine(
texture: null, texture: null,
colorSequence: new ColorSequence.fromStartAndEndColor(new Color(0xffff0000), new Color(0xff0000ff)), colorSequence: new ColorSequence.fromStartAndEndColor(new Color(0xaaffff00), new Color(0xaaff9900)),
widthMode: EffectLineWidthMode.barrel, widthMode: EffectLineWidthMode.barrel,
minWidth: 20.0, minWidth: 10.0,
maxWidth: 50.0, maxWidth: 15.0,
animationMode: EffectLineAnimationMode.scroll,
fadeAfterDelay: 1.0, fadeAfterDelay: 1.0,
fadeDuration: 1.0 fadeDuration: 1.0
); );
...@@ -147,6 +147,20 @@ class TestBed extends NodeWithSize { ...@@ -147,6 +147,20 @@ class TestBed extends NodeWithSize {
maxWidth: 100.0, maxWidth: 100.0,
animationMode: EffectLineAnimationMode.random animationMode: EffectLineAnimationMode.random
); );
} else if (lineType == "Rocket Trail") {
Texture baseTexture = new Texture(_images['assets/line_effects.png']);
Texture trailLineTexture = baseTexture.textureFromRect(new Rect.fromLTRB(0.0, 896.0, 1024.0, 1024.0));
_line = new EffectLine(
texture: trailLineTexture,
textureLoopLength: 300.0,
widthMode: EffectLineWidthMode.barrel,
minWidth: 20.0,
maxWidth: 40.0,
widthGrowthSpeed: 40.0,
fadeAfterDelay: 0.5,
fadeDuration: 1.5
);
} }
addChild(_line); addChild(_line);
......
...@@ -15,12 +15,15 @@ class EffectLine extends Node { ...@@ -15,12 +15,15 @@ class EffectLine extends Node {
EffectLine({ EffectLine({
this.texture: null, this.texture: null,
this.transferMode: sky.TransferMode.dstOver,
List<Point> points, List<Point> points,
this.widthMode : EffectLineWidthMode.linear, this.widthMode : EffectLineWidthMode.linear,
this.minWidth: 10.0, this.minWidth: 10.0,
this.maxWidth: 10.0, this.maxWidth: 10.0,
this.widthGrowthSpeed: 0.0,
this.animationMode: EffectLineAnimationMode.none, this.animationMode: EffectLineAnimationMode.none,
this.scrollSpeed: 0.1, this.scrollSpeed: 0.1,
double scrollStart: 0.0,
this.fadeDuration: null, this.fadeDuration: null,
this.fadeAfterDelay: null, this.fadeAfterDelay: null,
this.textureLoopLength: null, this.textureLoopLength: null,
...@@ -36,15 +39,20 @@ class EffectLine extends Node { ...@@ -36,15 +39,20 @@ class EffectLine extends Node {
new Color(0xffffffff), new Color(0xffffffff),
new Color(0xffffffff)); new Color(0xffffffff));
_offset = scrollStart;
_painter = new TexturedLinePainter(points, _colors, _widths, texture); _painter = new TexturedLinePainter(points, _colors, _widths, texture);
_painter.textureLoopLength = textureLoopLength; _painter.textureLoopLength = textureLoopLength;
} }
final Texture texture; final Texture texture;
final sky.TransferMode transferMode;
final EffectLineWidthMode widthMode; final EffectLineWidthMode widthMode;
final double minWidth; final double minWidth;
final double maxWidth; final double maxWidth;
final double widthGrowthSpeed;
final EffectLineAnimationMode animationMode; final EffectLineAnimationMode animationMode;
final double scrollSpeed; final double scrollSpeed;
...@@ -86,14 +94,25 @@ class EffectLine extends Node { ...@@ -86,14 +94,25 @@ class EffectLine extends Node {
_offset = randomDouble(); _offset = randomDouble();
} }
// Update age of line points, and remove if neccessary // Update age of line points and remove if neccesasry
if (fadeDuration != null && fadeAfterDelay != null) { if (fadeDuration != null && fadeAfterDelay != null) {
// Increase age of points
for (int i = _points.length - 1; i >= 0; i--) { for (int i = _points.length - 1; i >= 0; i--) {
_pointAges[i] += dt; _pointAges[i] += dt;
if (_pointAges[i] > (fadeDuration + fadeAfterDelay)) { }
_pointAges.removeAt(i);
_points.removeAt(i); // Check if the first/oldest point should be removed
while(_points.length > 0 && _pointAges[0] > (fadeDuration + fadeAfterDelay)) {
// Update scroll if it isn't the last and only point that is about to removed
if (_points.length > 1 && textureLoopLength != null) {
double dist = GameMath.pointQuickDist(_points[0], _points[1]);
_offset = (_offset - (dist / textureLoopLength)) % 1.0;
if (_offset < 0.0) _offset += 1;
} }
// Remove the point
_pointAges.removeAt(0);
_points.removeAt(0);
} }
} }
} }
...@@ -101,8 +120,6 @@ class EffectLine extends Node { ...@@ -101,8 +120,6 @@ class EffectLine extends Node {
void paint(PaintingCanvas canvas) { void paint(PaintingCanvas canvas) {
if (points.length < 2) return; if (points.length < 2) return;
//_painter.textureLoopLength = textureLoopLength;
_painter.points = points; _painter.points = points;
// Calculate colors // Calculate colors
...@@ -127,12 +144,14 @@ class EffectLine extends Node { ...@@ -127,12 +144,14 @@ class EffectLine extends Node {
// Calculate widths // Calculate widths
List<double> widths = []; List<double> widths = [];
for (double stop in stops) { for (int i = 0; i < stops.length; i++) {
double stop = stops[i];
double growth = math.max(widthGrowthSpeed * _pointAges[i], 0.0);
if (widthMode == EffectLineWidthMode.linear) { if (widthMode == EffectLineWidthMode.linear) {
double width = minWidth + (maxWidth - minWidth) * stop; double width = minWidth + (maxWidth - minWidth) * stop + growth;
widths.add(width); widths.add(width);
} else if (widthMode == EffectLineWidthMode.barrel) { } else if (widthMode == EffectLineWidthMode.barrel) {
double width = minWidth + math.sin(stop * math.PI) * (maxWidth - minWidth); double width = minWidth + math.sin(stop * math.PI) * (maxWidth - minWidth) + growth;
widths.add(width); widths.add(width);
} }
} }
...@@ -148,12 +167,38 @@ class EffectLine extends Node { ...@@ -148,12 +167,38 @@ class EffectLine extends Node {
if (points.length > 0 && point.x == points[points.length - 1].x && point.y == points[points.length - 1].y) if (points.length > 0 && point.x == points[points.length - 1].x && point.y == points[points.length - 1].y)
return; return;
if (simplify) { if (simplify && points.length >= 2 && GameMath.pointQuickDist(point, points[points.length - 2]) < 10.0) {
// Check if we should remove last point before adding the new one
// Calculate the square distance from the middle point to the line of the
// new point and the second to last point
double dist2 = _distToSeqment2(
points[points.length - 1],
point,
points[points.length - 2]
);
// If the point is on the line, remove it
if (dist2 < 1.0) {
_points.removeAt(_points.length - 1);
}
} }
// Add point and point's age // Add point and point's age
_points.add(point); _points.add(point);
_pointAges.add(0.0); _pointAges.add(0.0);
} }
double _sqr(double x) => x * x;
double _dist2(Point v, Point w) => _sqr(v.x - w.x) + _sqr(v.y - w.y);
double _distToSeqment2(Point p, Point v, Point w) {
double l2 = _dist2(v, w);
if (l2 == 0.0) return _dist2(p, v);
double t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
if (t < 0) return _dist2(p, v);
if (t > 1) return _dist2(p, w);
return _dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)));
}
} }
...@@ -75,6 +75,8 @@ class TexturedLinePainter { ...@@ -75,6 +75,8 @@ class TexturedLinePainter {
_calculatedTextureStops = null; _calculatedTextureStops = null;
} }
sky.TransferMode transferMode = sky.TransferMode.srcOver;
Paint _cachedPaint = new Paint(); Paint _cachedPaint = new Paint();
void paint(PaintingCanvas canvas) { void paint(PaintingCanvas canvas) {
...@@ -85,6 +87,8 @@ class TexturedLinePainter { ...@@ -85,6 +87,8 @@ class TexturedLinePainter {
assert(_points.length == colors.length); assert(_points.length == colors.length);
assert(_points.length == widths.length); assert(_points.length == widths.length);
_cachedPaint.transferMode = transferMode;
// Calculate normals // Calculate normals
List<Vector2> vectors = []; List<Vector2> vectors = [];
for (Point pt in _points) { for (Point pt in _points) {
...@@ -216,7 +220,13 @@ Vector2 _computeMiter(Vector2 lineA, Vector2 lineB) { ...@@ -216,7 +220,13 @@ Vector2 _computeMiter(Vector2 lineA, Vector2 lineB) {
Vector2 miter = new Vector2(- (lineA[1] + lineB[1]), lineA[0] + lineB[0]); Vector2 miter = new Vector2(- (lineA[1] + lineB[1]), lineA[0] + lineB[0]);
miter.normalize(); miter.normalize();
double miterLength = 1.0 / dot2(miter, new Vector2(-lineA[1], lineA[0])); double dot = dot2(miter, new Vector2(-lineA[1], lineA[0]));
if (dot.abs() < 0.1) {
miter = _vectorNormal(lineA).normalize();
return miter;
}
double miterLength = 1.0 / dot;
miter = miter.scale(miterLength); miter = miter.scale(miterLength);
return miter; return miter;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment