mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-03 12:28:03 +08:00
Unify multiple render methods on Sprite
This commit is contained in:
@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
28
lib/components/joystick/joystick_utils.dart
Normal file
28
lib/components/joystick/joystick_utils.dart
Normal 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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user