Files
flame/lib/components/joystick/Joystick_action.dart
2020-06-22 13:12:21 -03:00

223 lines
6.0 KiB
Dart

import 'dart:math';
import 'package:flame/components/joystick/joystick_component.dart';
import 'package:flame/sprite.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
enum JoystickActionAlign { TOP_LEFT, BOTTOM_LEFT, TOP_RIGHT, BOTTOM_RIGHT }
class JoystickAction {
final int actionId;
final Sprite sprite;
final Sprite spritePressed;
final Sprite spriteBackgroundDirection;
final double size;
double sizeBackgroundDirection;
final EdgeInsets margin;
final JoystickActionAlign align;
final bool enableDirection;
final Color color;
int _pointerDragging;
Rect _rect;
Rect _rectBackgroundDirection;
bool _dragging = false;
Sprite _sprite;
double _tileSize;
Offset _dragPosition;
Paint _paintBackground;
Paint _paintAction;
JoystickController _joystickController;
JoystickAction({
@required this.actionId,
this.sprite,
this.spritePressed,
this.spriteBackgroundDirection,
this.enableDirection = false,
this.size = 50,
this.sizeBackgroundDirection,
this.margin = EdgeInsets.zero,
this.color = Colors.blueGrey,
this.align = JoystickActionAlign.BOTTOM_RIGHT,
}) {
_sprite = sprite;
sizeBackgroundDirection = sizeBackgroundDirection ?? size * 1.5;
_tileSize = sizeBackgroundDirection;
}
void initialize(Size _screenSize, JoystickController joystickController) {
_joystickController = joystickController;
final double radius = size / 2;
double dx = 0, dy = 0;
switch (align) {
case JoystickActionAlign.TOP_LEFT:
dx = margin.left + radius;
dy = margin.top + radius;
break;
case JoystickActionAlign.BOTTOM_LEFT:
dx = margin.left + radius;
dy = _screenSize.height - (margin.bottom + radius);
break;
case JoystickActionAlign.TOP_RIGHT:
dx = _screenSize.width - (margin.right + radius);
dy = margin.top + radius;
break;
case JoystickActionAlign.BOTTOM_RIGHT:
dx = _screenSize.width - (margin.right + radius);
dy = _screenSize.height - (margin.bottom + radius);
break;
}
_rect = Rect.fromCircle(
center: Offset(dx, dy),
radius: radius,
);
_rectBackgroundDirection = Rect.fromCircle(
center: Offset(dx, dy),
radius: sizeBackgroundDirection / 2,
);
_paintBackground = Paint()
..color = color.withOpacity(0.5)
..style = PaintingStyle.fill;
_paintAction = Paint()
..color = color.withOpacity(0.8)
..style = PaintingStyle.fill;
_dragPosition = _rect.center;
}
void render(Canvas c) {
if (_rectBackgroundDirection != null && _dragging && enableDirection) {
if (spriteBackgroundDirection == null) {
double radiusBackground = _rectBackgroundDirection.width / 2;
c.drawCircle(
Offset(
_rectBackgroundDirection.left + radiusBackground,
_rectBackgroundDirection.top + radiusBackground,
),
radiusBackground,
_paintBackground,
);
} else {
spriteBackgroundDirection.renderRect(c, _rectBackgroundDirection);
}
}
if (_sprite != null) {
if (_rect != null) _sprite.renderRect(c, _rect);
} else {
double radiusAction = _rect.width / 2;
c.drawCircle(
Offset(
_rect.left + radiusAction,
_rect.top + radiusAction,
),
radiusAction,
_paintAction,
);
}
}
void update(double dt) {
if (_dragging) {
double _radAngle = atan2(
_dragPosition.dy - _rectBackgroundDirection.center.dy,
_dragPosition.dx - _rectBackgroundDirection.center.dx,
);
// Distance between the center of joystick background & drag position
Point centerPoint = Point(
_rectBackgroundDirection.center.dx,
_rectBackgroundDirection.center.dy,
);
double dist =
centerPoint.distanceTo(Point(_dragPosition.dx, _dragPosition.dy));
// 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 = dist < (_tileSize / 3) ? dist : (_tileSize / 3);
// Calculation the knob position
final double nextX = dist * cos(_radAngle);
final double nextY = dist * sin(_radAngle);
final Offset nextPoint = Offset(nextX, nextY);
final Offset diff = Offset(
_rectBackgroundDirection.center.dx + nextPoint.dx,
_rectBackgroundDirection.center.dy + nextPoint.dy,
) -
_rect.center;
_rect = _rect.shift(diff);
final double _intensity = dist / (_tileSize / 3);
_joystickController.joystickAction(
JoystickActionEvent(
id: actionId,
event: ActionEvent.MOVE,
intensity: _intensity,
radAngle: _radAngle,
),
);
} else {
if (_rect != null) {
final Offset diff = _dragPosition - _rect.center;
_rect = _rect.shift(diff);
}
}
}
void actionDown(int pointer, Offset localPosition) {
if (!_dragging && _rect != null && _rect.contains(localPosition)) {
_pointerDragging = pointer;
if (enableDirection) {
_dragPosition = localPosition;
_dragging = true;
}
_joystickController.joystickAction(
JoystickActionEvent(
id: actionId,
event: ActionEvent.DOWN,
),
);
pressed();
}
}
void actionMove(int pointer, Offset localPosition) {
if (pointer == _pointerDragging) {
if (_dragging) {
_dragPosition = localPosition;
}
}
}
void actionUp(int pointer) {
if (pointer == _pointerDragging) {
_dragging = false;
_dragPosition = _rectBackgroundDirection.center;
_joystickController.joystickAction(
JoystickActionEvent(
id: actionId,
event: ActionEvent.UP,
),
);
unPressed();
}
}
void pressed() {
if (spritePressed != null) {
_sprite = spritePressed;
}
}
void unPressed() {
_sprite = sprite;
}
}