Unify multiple render methods on Sprite

This commit is contained in:
Luan Nico
2020-12-05 14:26:22 -05:00
committed by renancaraujo
parent f110fc228d
commit 4f989e49f5
13 changed files with 137 additions and 166 deletions

View File

@ -1,3 +1,4 @@
import 'package:flame/extensions/vector2.dart';
import 'package:flutter/material.dart' hide Animation;
import 'package:flame/game.dart';
import 'package:flame/sprite.dart';
@ -24,13 +25,15 @@ class GameLayer extends DynamicLayer {
@override
void drawLayer() {
playerSprite.renderRect(
playerSprite.render(
canvas,
const Rect.fromLTWH(50, 50, 150, 150),
position: Vector2.all(50),
size: Vector2.all(150),
);
enemySprite.renderRect(
enemySprite.render(
canvas,
const Rect.fromLTWH(250, 150, 100, 50),
position: Vector2(250, 150),
size: Vector2(100, 50),
);
}
}
@ -44,9 +47,10 @@ class BackgroundLayer extends PreRenderedLayer {
@override
void drawLayer() {
sprite.renderRect(
sprite.render(
canvas,
const Rect.fromLTWH(50, 200, 300, 150),
position: Vector2(50, 200),
size: Vector2(300, 150),
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:flame/extensions/vector2.dart';
import 'package:flutter/material.dart';
import 'package:flame/sprite.dart';
@ -25,6 +26,6 @@ class MyGame extends Game {
@override
void render(Canvas canvas) {
_sprite.renderRect(canvas, const Rect.fromLTWH(100, 100, 100, 100));
_sprite.render(canvas, position: Vector2.all(100), size: Vector2.all(100));
}
}

View File

@ -46,7 +46,7 @@ These two functions help with registering (and de-registering) gesture recognize
### Other functions
* `text`: discussed [here](/doc/text.md)
* `drawWhere`: a very simple function that manually applies an offset to the `Canvas`, render stuff given via a function and then reset the `Canvas`, without using the `Canvas`' built-in `save`/`restore` functionality. This might be useful because `BaseGame` uses the state of the canvas, and you should not mess with it.
* `renderWhere`: a very simple function that manually applies an offset to the `Canvas`, render stuff given via a function and then reset the `Canvas`, without using the `Canvas`' built-in `save`/`restore` functionality. This might be useful because `BaseGame` uses the state of the canvas, and you should not mess with it.
## Timer

View File

@ -49,7 +49,7 @@ class IsometricTileMapComponent extends PositionComponent {
if (element != -1) {
final sprite = tileset.getSpriteById(element);
final p = getBlockPositionInts(j, i);
sprite.renderRect(c, p.toPositionedRect(size));
sprite.render(c, position: p, size: size);
}
}
}

View File

@ -10,6 +10,7 @@ import '../../gestures.dart';
import '../../sprite.dart';
import 'joystick_component.dart';
import 'joystick_events.dart';
import 'joystick_utils.dart';
enum JoystickActionAlign { TOP_LEFT, BOTTOM_LEFT, TOP_RIGHT, BOTTOM_RIGHT }
@ -113,37 +114,17 @@ class JoystickAction {
}
void render(Canvas c) {
if (_rectBackgroundDirection != null && _dragging && enableDirection) {
if (spriteBackgroundDirection == null) {
final double radiusBackground = _rectBackgroundDirection.width / 2;
c.drawCircle(
Offset(
_rectBackgroundDirection.left + radiusBackground,
_rectBackgroundDirection.top + radiusBackground,
),
radiusBackground,
_paintBackground,
);
} else {
spriteBackgroundDirection.renderRect(c, _rectBackgroundDirection);
}
}
if (_spriteAction != null) {
if (_rectAction != null) {
_spriteAction.renderRect(c, _rectAction);
}
} else {
final double radiusAction = _rectAction.width / 2;
c.drawCircle(
Offset(
_rectAction.left + radiusAction,
_rectAction.top + radiusAction,
),
radiusAction,
isPressed ? _paintActionPressed : _paintAction,
if (_dragging && enableDirection) {
JoystickUtils.renderControl(
c,
spriteBackgroundDirection,
_rectBackgroundDirection,
_paintBackground,
);
}
final actionPaint = isPressed ? _paintActionPressed : _paintAction;
JoystickUtils.renderControl(c, _spriteAction, _rectAction, actionPaint);
}
void update(double dt) {

View File

@ -8,6 +8,7 @@ import '../../gestures.dart';
import '../../sprite.dart';
import 'joystick_component.dart';
import 'joystick_events.dart';
import 'joystick_utils.dart';
class JoystickDirectional {
final double size;
@ -19,13 +20,12 @@ class JoystickDirectional {
final double opacityBackground;
final double opacityKnob;
Paint _paintBackground;
Paint _paintKnob;
Sprite _backgroundSprite;
Sprite _knobSprite;
Paint _paintBackground;
Rect _backgroundRect;
Sprite _knobSprite;
Paint _paintKnob;
Rect _knobRect;
bool _dragging = false;
@ -66,77 +66,59 @@ class JoystickDirectional {
_tileSize = size / 2;
}
void initialize(Vector2 _screenSize, JoystickController joystickController) {
this._screenSize = _screenSize;
void initialize(Vector2 screenSize, JoystickController joystickController) {
_screenSize = _screenSize;
_joystickController = joystickController;
final Offset osBackground =
Offset(margin.left, _screenSize.y - margin.bottom);
final osBackground = Offset(margin.left, _screenSize.y - margin.bottom);
_backgroundRect = Rect.fromCircle(center: osBackground, radius: size / 2);
final Offset osKnob =
Offset(_backgroundRect.center.dx, _backgroundRect.center.dy);
final osKnob = _backgroundRect.center;
_knobRect = Rect.fromCircle(center: osKnob, radius: size / 4);
_dragPosition = _knobRect.center;
}
void render(Canvas canvas) {
if (_backgroundRect != null) {
if (_backgroundSprite != null) {
_backgroundSprite.renderRect(canvas, _backgroundRect);
} else {
final double radiusBackground = _backgroundRect.width / 2;
canvas.drawCircle(
Offset(_backgroundRect.left + radiusBackground,
_backgroundRect.top + radiusBackground),
radiusBackground,
_paintBackground,
);
}
}
JoystickUtils.renderControl(
canvas,
_backgroundSprite,
_backgroundRect,
_paintBackground,
);
if (_knobRect != null) {
if (_knobSprite != null) {
_knobSprite.renderRect(canvas, _knobRect);
} else {
final double radiusKnob = _knobRect.width / 2;
canvas.drawCircle(
Offset(_knobRect.left + radiusKnob, _knobRect.top + radiusKnob),
radiusKnob,
_paintKnob,
);
}
}
JoystickUtils.renderControl(
canvas,
_knobSprite,
_knobRect,
_paintKnob,
);
}
void update(double t) {
if (_dragging) {
final double _radAngle = atan2(
_dragPosition.dy - _backgroundRect.center.dy,
_dragPosition.dx - _backgroundRect.center.dx);
_dragPosition.dy - _backgroundRect.center.dy,
_dragPosition.dx - _backgroundRect.center.dx,
);
final double degrees = _radAngle * 180 / pi;
final degrees = _radAngle * 180 / pi;
// Distance between the center of joystick background & drag position
final centerPosition = _backgroundRect.center.toVector2();
final dragPosition = _dragPosition.toVector2();
double dist = centerPosition.distanceTo(dragPosition);
// The maximum distance for the knob position the edge of
// the background + half of its own size. The knob can wander in the
// background image, but not outside.
dist = min(dist, _tileSize);
final dist = min(centerPosition.distanceTo(dragPosition), _tileSize);
// Calculation the knob position
final double nextX = dist * cos(_radAngle);
final double nextY = dist * sin(_radAngle);
final Offset nextPoint = Offset(nextX, nextY);
final nextX = dist * cos(_radAngle);
final nextY = dist * sin(_radAngle);
final nextPoint = Offset(nextX, nextY);
final Offset diff = Offset(
_backgroundRect.center.dx + nextPoint.dx,
_backgroundRect.center.dy + nextPoint.dy,
) -
_knobRect.center;
final diff = _backgroundRect.center + nextPoint - _knobRect.center;
_knobRect = _knobRect.shift(diff);
final double _intensity = dist / _tileSize;
@ -167,18 +149,11 @@ class JoystickDirectional {
void onReceiveDrag(DragEvent event) {
_updateDirectionalRect(event.initialPosition);
final Rect directional = Rect.fromLTWH(
_backgroundRect.left - 50,
_backgroundRect.top - 50,
_backgroundRect.width + 100,
_backgroundRect.height + 100,
);
final directional = _backgroundRect.inflate(50.0);
if (!_dragging && directional.contains(event.initialPosition)) {
_dragging = true;
_dragPosition = event.initialPosition;
_currentDragEvent = event;
_currentDragEvent
_currentDragEvent = event
..onUpdate = onPanUpdate
..onEnd = onPanEnd
..onCancel = onPanCancel;
@ -195,10 +170,7 @@ class JoystickDirectional {
_backgroundRect = Rect.fromCircle(center: position, radius: size / 2);
final Offset osKnob = Offset(
_backgroundRect.center.dx,
_backgroundRect.center.dy,
);
final osKnob = _backgroundRect.center;
_knobRect = Rect.fromCircle(center: osKnob, radius: size / 4);
}

View File

@ -0,0 +1,28 @@
import 'dart:ui';
import '../../sprite.dart';
import '../../extensions/offset.dart';
import '../../extensions/size.dart';
class JoystickUtils {
static void renderControl(Canvas c, Sprite sprite, Rect rect, Paint paint) {
if (rect == null) {
return;
}
if (sprite == null) {
final double radius = rect.width / 2;
c.drawCircle(
Offset(rect.left + radius, rect.top + radius),
radius,
paint,
);
} else {
sprite.render(
c,
position: rect.topLeft.toVector2(),
size: rect.size.toVector2(),
);
}
}
}

View File

@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:flutter/foundation.dart';
import '../anchor.dart';
import '../extensions/vector2.dart';
import '../particle.dart';
import '../sprite_animation.dart';
@ -34,11 +35,11 @@ class SpriteAnimationParticle extends Particle {
@override
void render(Canvas canvas) {
animation.getSprite().renderCentered(
animation.getSprite().render(
canvas,
Vector2.zero(),
overridePaint: overridePaint,
size: size,
anchor: Anchor.center,
overridePaint: overridePaint,
);
}

View File

@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:flutter/foundation.dart';
import '../anchor.dart';
import '../particle.dart';
import '../sprite.dart';
import '../extensions/vector2.dart';
@ -22,11 +23,11 @@ class SpriteParticle extends Particle {
@override
void render(Canvas canvas) {
sprite.renderCentered(
sprite.render(
canvas,
Vector2.zero(),
overridePaint: overridePaint,
size: size,
anchor: Anchor.center,
overridePaint: overridePaint,
);
}
}

View File

@ -1,5 +1,6 @@
import 'dart:ui';
import 'anchor.dart';
import 'extensions/offset.dart';
import 'extensions/vector2.dart';
import 'palette.dart';
@ -37,67 +38,28 @@ class Sprite {
src = (position ?? Vector2.zero()).toPositionedRect(srcSize);
}
/// Renders this Sprite on the position [p], scaled by the [scale] factor provided.
/// Renders this sprite onto the canvas.
///
/// It renders with src size multiplied by [scale] in both directions.
/// Anchor is on top left as default.
/// If not loaded, does nothing.
void renderScaled(
Canvas canvas,
Vector2 p, {
double scale = 1.0,
Paint overridePaint,
}) {
renderPosition(
canvas,
p,
size: srcSize * scale,
overridePaint: overridePaint,
);
}
void renderPosition(
Canvas canvas,
Vector2 p, {
Vector2 size,
Paint overridePaint,
}) {
size ??= srcSize;
renderRect(canvas, p.toPositionedRect(size), overridePaint: overridePaint);
}
/// * position: x,y coordinates where it will be drawn; default to origin.
/// * size: width/height dimensions; it can be bigger or smaller than the original size -- but it defaults to the original texture size.
/// * overridePaint: paint to use. You can also change the paint on your Sprite instance. Default is white.
/// * anchor: where in the sprite the x/y coordinates refer to; defaults to topLeft.
void render(
Canvas canvas, {
Vector2 position,
Vector2 size,
Anchor anchor = Anchor.topLeft,
Paint overridePaint,
}) {
size ??= srcSize;
renderRect(canvas, size.toRect(), overridePaint: overridePaint);
}
final drawPosition = position ?? Vector2.zero();
final drawSize = size ?? srcSize;
/// Renders this sprite centered in the position [p], i.e., on [p] - [size] / 2.
///
/// If [size] is not provided, the original size of the src image is used.
/// If the asset is not yet loaded, it does nothing.
void renderCentered(
Canvas canvas,
Vector2 p, {
Vector2 size,
Paint overridePaint,
}) {
size ??= srcSize;
renderRect(
canvas,
(p - size / 2).toPositionedRect(size),
overridePaint: overridePaint,
);
}
final delta = -anchor.relativePosition
..multiply(drawSize);
final drawRect = (drawPosition + delta).toPositionedRect(drawSize);
void renderRect(
Canvas canvas,
Rect dst, {
Paint overridePaint,
}) {
canvas.drawImageRect(image, src, dst, overridePaint ?? paint);
final drawPaint = overridePaint ?? paint;
canvas.drawImageRect(image, src, drawRect, drawPaint);
}
}

View File

@ -127,10 +127,30 @@ class Util {
/// Utility method to render stuff on a specific place.
///
/// Some render methods don't allow to pass a offset.
/// This method translate the canvas, draw what you want, and then translate back.
void drawWhere(Canvas c, Vector2 p, void Function(Canvas) fn) {
/// This method translate the canvas before rendering your block.
/// The changes are reset after the block is run.
void renderAt(Canvas c, Vector2 p, void Function(Canvas) block) {
c.save();
c.translate(p.x, p.y);
fn(c);
c.translate(-p.x, -p.y);
block(c);
c.restore();
}
/// Utility method to render stuff rotated at specific angle.
///
/// It rotates the canvas around the center of rotation.
/// The changes are reset after the block is run.
void renderRotated(
Canvas c,
double angle,
Vector2 rotationCenter,
void Function(Canvas) block,
) {
c.save();
c.translate(-rotationCenter.x, -rotationCenter.y);
c.rotate(angle);
c.translate(rotationCenter.x, rotationCenter.y);
block(c);
c.restore();
}
}

View File

@ -41,7 +41,7 @@ class _Painter extends widgets.CustomPainter {
final verticalHeight = size.height - destTileSize * 2;
void render(Sprite sprite, double x, double y, double w, double h) {
sprite.renderRect(canvas, Rect.fromLTWH(x, y, w, h));
sprite.render(canvas, position: Vector2(x, y), size: Vector2(w, h));
}
// Middle

View File

@ -1,6 +1,7 @@
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import '../extensions/size.dart';
import '../sprite.dart';
class SpriteButton extends StatefulWidget {
@ -69,6 +70,6 @@ class _ButtonPainer extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
_sprite.renderRect(canvas, Rect.fromLTWH(0, 0, size.width, size.height));
_sprite.render(canvas, size: size.toVector2());
}
}