通过 Google Crash Analytics 获取错误“错误状态:无元素。抛出错误”。 这是堆栈跟踪:
Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError
Bad state: No element. Error thrown .
List.last (dart:core)
DisplacementEvent.localEndPosition (displacement_event.dart:97)
DisplacementEvent.localDelta (displacement_event.dart:118)
Road.onDragUpdate (road.dart:189)
MultiDragDispatcher.onDragUpdate (multi_drag_dispatcher.dart:81)
MultiDragDispatcher.handleDragUpdate (multi_drag_dispatcher.dart:124)
FlameDragAdapter.update (flame_drag_adapter.dart:30)
MultiDragPointerState._move (multidrag.dart:100)
GestureBinding._handlePointerDataPacket(绑定.dart:299)
我正在使用火焰:^1.18.0
这是我的 onDragUpdate 代码,位于一个名为 Road 的类中,它扩展了 SpriteComponent
@override
void onDragUpdate(DragUpdateEvent event) {
if (isDraggable) {
position += event.localDelta;
dropX = position.x + 64;
dropY = position.y + 64;
}
}
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.24.0, on Microsoft Windows [Version 10.0.22631.4037], locale en-US)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.10.6)
[√] Android Studio (version 2023.3)
[√] VS Code (version 1.92.2)
[√] Connected device (5 available)
[√] Network resources
不知道从哪里开始寻找。 看起来像是 Dart Core 中的一个问题? 有人可以帮忙吗?
这里要求的是道路组件的完整代码:
import 'dart:async';
import 'dart:math';
import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:umfths/audio/sounds.dart';
import 'package:umfths/flame/components/cell.dart';
import 'package:umfths/flame/components/gnome.dart';
import 'package:umfths/flame/components/path_stop.dart';
import 'package:umfths/flame/components/treasure.dart';
import 'package:umfths/flame/umfth_game.dart';
import 'package:umfths/flame/umfth_world.dart';
class Road extends SpriteComponent
with
CollisionCallbacks,
DragCallbacks,
HasGameRef<UmfthGame>,
HasWorldReference<UmfthWorld> {
Road(this.roadType) : super(anchor: Anchor.topLeft);
RoadTypes roadType;
double dropX = 0;
double dropY = 0;
double startX = 0;
double startY = 0;
double gravity = 2;
Vector2 velocity = Vector2(0, 20);
bool isDraggable = false;
bool isWaiting = false;
bool isInTube = false;
bool isDragging = false;
bool isAvailable = false;
bool isSlowZone = false;
bool isSpecial = false;
int cellId = 0;
String mess = '';
final textChild = TextComponent(position: Vector2(1, 20), priority: 99);
@override
Future<void> onLoad() async {
add(textChild);
add(RectangleHitbox(size: Vector2(128, 128), isSolid: true));
if (roadType == RoadTypes.none) {
roadType = gameRef.getRandomRoad();
int special = Random().nextInt(20);
if (special > 18) {
isSpecial == true;
setSpecial();
}
}
String roadName = roadType.name;
sprite =
await Sprite.load('roads/$roadName.png', srcSize: Vector2(128, 128));
/* RoadBlock rbh = RoadBlock();
RoadBlockVertical rbv = RoadBlockVertical();
switch (roadType) {
case RoadTypes.nw:
add(rbh..position = Vector2(0, 124));
add(rbv..position = Vector2(124, 0));
break;
case RoadTypes.ne:
add(rbh..position = Vector2(0, 124));
add(rbv..position = Vector2(0, 0));
break;
case RoadTypes.se:
add(rbh..position = Vector2(0, 0));
add(rbv..position = Vector2(0, 0));
break;
case RoadTypes.sw:
add(rbh..position = Vector2(0, 0));
add(rbv..position = Vector2(124, 0));
break;
case RoadTypes.horiz:
add(rbh..position = Vector2(0, 0));
RoadBlock rbh2 = RoadBlock();
add(rbh2..position = Vector2(0, 124));
break;
case RoadTypes.vert:
add(rbv..position = Vector2(0, 0));
RoadBlockVertical rbv2 = RoadBlockVertical();
add(rbv2..position = Vector2(124, 0));
break;
case RoadTypes.splitEast:
add(rbv..position = Vector2(0, 0));
break;
case RoadTypes.splitWest:
add(rbv..position = Vector2(124, 0));
break;
default:
}
if (roadType == RoadTypes.nw) {} */
}
@override
void update(double dt) {
super.update(dt);
if (isInTube == true) {
// Sitting in glass emitter tube
if (!isWaiting) {
// Not waiting so let it drop down emitter tube
velocity.y += gravity;
position.y += velocity.y * dt;
} else {
// Has colided with another road in emitter so waiting
// to drop down
velocity.y = 0;
}
}
//textChild.text = mess;
}
@override
void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
super.onCollision(intersectionPoints, other);
if (other is PathStop) {
velocity.y = 0;
isAvailable = true;
velocity.y = 0;
opacity = 1;
isInTube = false;
isWaiting = false;
isDraggable = true;
}
if (!isWaiting) {
if (other is Road) {
isWaiting = true;
}
}
if (other is Gnome && UmfthWorld.isDragging == false) {
setOccupied(cellId, false, false);
for (Road rd in UmfthWorld.gridRoads) {
if (rd.cellId == cellId) {
UmfthWorld.gridRoads.remove(rd);
break;
}
}
UmfthWorld.gridRoads.remove(this);
parent!.remove(this);
game.playAudio(SfxType.steal, false);
}
}
@override
void onDragStart(DragStartEvent event) {
super.onDragStart(event);
if (isDraggable) {
if (cellId > 0) {
setOccupied(cellId, false, false);
}
priority = 1;
isDragging = true;
UmfthWorld.isDragging = true;
velocity.y = 0;
}
}
@override
void onDragUpdate(DragUpdateEvent event) {
/* if you are using DragUpdateEvent events, the devicePosition, canvasPosition, localPosition, and delta are deprecated as they are unclear.
use xStartPosition to get the position at the start of the drag event ("from")
use xEndPosition to get the position at the end of the drag event ("to")
if you want the delta, use localDelta. it now already considers the camera zoom. no need to manually account for that
now you keep receiving drag events for the same component even if the mouse leaves the component (breaking) */
if (isDraggable) {
position += event.localDelta;
dropX = position.x + 64;
dropY = position.y + 64;
}
}
@override
Future<void> onDragEnd(DragEndEvent event) async {
super.onDragEnd(event);
isDragging = false;
UmfthWorld.isDragging = false;
if (isDraggable) {
Cell? cb = getDroppedOn(dropX, dropY, this);
if (cb != null) {
if (cb.occupied == false) {
setOccupied(cb.id, true, true);
cellId = cb.id;
cb.ignoreCollisions = true;
x = cb.x;
y = cb.y;
velocity = Vector2(0, 0);
opacity = 1;
isDraggable = true;
gravity = 0;
isInTube = false;
for (Road rd in UmfthWorld.gridRoads) {
if (rd.cellId == cellId) {
UmfthWorld.gridRoads.remove(rd);
break;
}
}
UmfthWorld.gridRoads.add(this);
} else {
//not a cell
parent!.remove(this);
}
} else {
// No empty cell found
parent!.remove(this);
}
if (isAvailable == true) {
// Removes first road from queue after user drags and drops
gameRef.roadQueue.removeFirst();
double firstY = 830;
for (var w in gameRef.roadQueue) {
// move each road in queue down by road height
w.position.y = firstY;
firstY -= 135;
}
// Set first road in queue properties
// first is the one user can drag
if (gameRef.roadQueue.isNotEmpty) {
gameRef.roadQueue.first.isDraggable = true;
gameRef.roadQueue.first.opacity = 1;
gameRef.roadQueue.first.velocity.y = 0;
gameRef.roadQueue.first.isInTube = false;
gameRef.roadQueue.first.isWaiting = false;
gameRef.roadQueue.first.isAvailable = true;
}
isAvailable = false;
}
}
}
setSlow() async {
isSlowZone = true;
SpriteComponent slow = SpriteComponent();
slow.sprite =
await Sprite.load('slow-down.png', srcSize: Vector2(128, 128));
add(slow);
}
setSpecial() async {
SpriteAnimationComponent s = Treasure();
add(s
..priority = 100
..position = Vector2(32, 32));
}
Cell? getDroppedOn(x, y, road) {
List<Cell> blocks = UmfthWorld.gridCells;
for (final cell in blocks) {
if (x >= cell.position.x &&
x <= cell.position.x + 128 &&
y >= cell.position.y &&
y <= cell.position.y + 128) {
if (!cell.occupied) {
return cell;
}
}
}
//No cell
List<Cell> cells = UmfthWorld.gridCells;
for (final cell in cells) {
if (cell.occupied == false) {
return cell;
}
}
return null;
}
Cell? getCell(x, y, road) {
List<Cell> blocks = UmfthWorld.gridCells;
for (final cell in blocks) {
if (x >= cell.position.x &&
x <= cell.position.x + 128 &&
y >= cell.position.y &&
y <= cell.position.y + 128) {
return cell;
}
}
return null;
}
void setOccupied(int id, bool val, bool ignore) {
List<Cell> cells = UmfthWorld.gridCells;
findById(obj) => obj.id == id;
var result = cells.where(findById);
Cell? c = result.isNotEmpty ? result.first : null;
if (c != null) {
c.occupied = val;
c.ignoreCollisions = ignore;
}
}
}
我也有类似的问题。我可以解决这个问题,检查对象是否被删除或被删除。希望这对您有帮助。
@override
void onDragUpdate(DragUpdateEvent event) {
if(isRemoving || isRemoved)
return;
if (isDraggable) {
position += event.localDelta;
dropX = position.x + 64;
dropY = position.y + 64;
}
}