Closed KurtLa closed 1 year ago
From a quick look it seems you are creating and resetting a complete separate ticker than what is used by the SpriteAnimationGroupComponent
.
SpriteAnimationGroupComponent
maintains a map of tickers for each of the animation states. You should get the active ticker using the animationTicker
getter from the SpriteAnimationGroupComponent
.
Additional info:
You shouldn't create your own ticker unless you have a raw SpriteAnimation
and want to manually tick it.
So to answer your question, you shouldn't maintain any ticker yourself 😄
@KurtLa here is your fixed Player class. See if this is what your intended to achieve.
class Player extends SpriteAnimationGroupComponent
with HasGameRef<MainGame>, CollisionCallbacks {
PlayerStats playerStats = PlayerStats();
LookDirection currentLookDirection = LookDirection.down;
Set<CollisionSide> collisionSides = {};
bool canMove = true;
late Vector2 previousPosition;
@override
FutureOr<void> onLoad() {
initializeAnimations();
setupHitbox();
previousPosition = position.clone();
return super.onLoad();
}
void initializeAnimations() {
offsetByRow(int row) => Vector2(0, row * 92.0);
animations = {
PlayerState.runTop: createAnimation(offsetByRow(0)),
PlayerState.runLeft: createAnimation(offsetByRow(1)),
PlayerState.runDown: createAnimation(offsetByRow(2)),
PlayerState.runRight: createAnimation(offsetByRow(3)),
PlayerState.idleTop: createAnimation(offsetByRow(0), loop: false),
PlayerState.idleLeft: createAnimation(offsetByRow(1), loop: false),
PlayerState.idleDown: createAnimation(offsetByRow(2), loop: false),
PlayerState.idleRight: createAnimation(offsetByRow(3), loop: false),
PlayerState.hammerTop: createAnimation(offsetByRow(5), loop: false),
PlayerState.hammerLeft: createAnimation(offsetByRow(4), loop: false),
PlayerState.hammerDown: createAnimation(offsetByRow(6), loop: false),
PlayerState.hammerRight: createAnimation(offsetByRow(7), loop: false),
};
current = PlayerState.idleLeft;
animationTickers![PlayerState.hammerTop]!.onComplete =
() => _resetOnComplete(PlayerState.hammerTop);
animationTickers![PlayerState.hammerLeft]!.onComplete =
() => _resetOnComplete(PlayerState.hammerLeft);
animationTickers![PlayerState.hammerDown]!.onComplete =
() => _resetOnComplete(PlayerState.hammerDown);
animationTickers![PlayerState.hammerRight]!.onComplete =
() => _resetOnComplete(PlayerState.hammerRight);
anchor = const Anchor(0.5, 0.65);
size = size / 1.5;
position = gameRef.survivalGame.roundProperties.spawnPosition.clone();
anchor = Anchor.center;
}
void _resetOnComplete(PlayerState stateToReset) {
animationTickers![stateToReset]!.reset();
beIdle();
}
SpriteAnimation createAnimation(Vector2 texturePosition, {bool loop = true}) {
return SpriteAnimation.fromFrameData(
Flame.images.fromCache("player/player.png"),
SpriteAnimationData.sequenced(
amount: loop ? 9 : 6,
stepTime: 0.1,
textureSize: Vector2(92, 92),
texturePosition: texturePosition,
loop: loop,
),
);
}
void setupHitbox() {
add(RectangleHitbox(
position: Vector2(size.x / 2, size.y / 1.5),
size: size / 4,
anchor: Anchor.center,
));
}
@override
void update(double dt) {
super.update(dt);
priority = (position.y).round() + 1;
}
void useTool() {
final animation = getPlayerAnimationForTool();
current = animation.state;
}
PlayerAnimation getPlayerAnimationForTool() {
switch (currentLookDirection) {
case LookDirection.left:
return PlayerAnimation(
PlayerState.hammerLeft, animations![PlayerState.hammerLeft]!);
case LookDirection.down:
return PlayerAnimation(
PlayerState.hammerDown, animations![PlayerState.hammerDown]!);
case LookDirection.right:
return PlayerAnimation(
PlayerState.hammerRight, animations![PlayerState.hammerRight]!);
case LookDirection.top:
return PlayerAnimation(
PlayerState.hammerTop, animations![PlayerState.hammerTop]!);
}
}
@override
void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
// if (other is ResourcesObject) {
// position.sub(position - previousPosition);
// }
super.onCollision(intersectionPoints, other);
}
void savePosition() {
previousPosition = position.clone();
}
void move(Vector2 displacement) {
if (displacement != Vector2.zero()) {
setPlayerStateAndLookDirection(displacement);
savePosition();
position.add(displacement);
updatePlayerPosition();
} else {
beIdle();
}
}
void setPlayerStateAndLookDirection(Vector2 displacement) {
if (displacement.x < 0) {
current = PlayerState.runLeft;
currentLookDirection = LookDirection.left;
} else if (displacement.x > 0) {
current = PlayerState.runRight;
currentLookDirection = LookDirection.right;
} else if (displacement.y < 0) {
current = PlayerState.runTop;
currentLookDirection = LookDirection.top;
} else if (displacement.y > 0) {
current = PlayerState.runDown;
currentLookDirection = LookDirection.down;
}
}
void updatePlayerPosition() {
gameRef.survivalGame.gameStatus.currentPlayerPosition = position.clone();
gameRef.survivalGame.gameStatus.currentPlayerTile = position.clone()
..x = (x ~/ 32).toDouble()
..y = (y ~/ 32).toDouble();
}
void beIdle() {
switch (currentLookDirection) {
case LookDirection.left:
current = PlayerState.idleLeft;
break;
case LookDirection.down:
current = PlayerState.idleDown;
break;
case LookDirection.right:
current = PlayerState.idleRight;
break;
case LookDirection.top:
current = PlayerState.idleTop;
break;
}
}
void executeTool(PlayerTools tool) {
switch (tool) {
case PlayerTools.hammer:
break;
}
}
}
@ufrshubham Ah, i see. I got my information from the SpriteAnimationComponent
Perfect, your solution works like a charm, thank you very much!
@ufrshubham Ah, i see. I got my information from the SpriteAnimationComponent
Perfect, your solution works like a charm, thank you very much!
Those docs should probably be updated to not use a separate ticker, you're not the first that has been confused by that. 😅
Current bug behavior
An animation cannot be reset after it is done, the old animation system could be reset. It gets stuck at the last frame.
Expected behavior
When you reset an animation, it should behave as if it were new.
Steps to reproduce
You can use my repository to reproduce it: https://bitbucket.org/Jinairu/islandsurvivor_bugs/src/master/
clone, flutter pub get, run press F to use the tool or W, A, S, D to navigate
Flutter doctor output
flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.10.2, on macOS 13.2.1 22D68 darwin-arm64, locale en-DE) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 14.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.2) [✓] VS Code (version 1.79.2) [✓] Connected device (2 available) [✓] Network resources
• No issues found!
More environment information
Flame version: 1.8.0 Platform affected: all
More information
It feels like SpriteAnimationTicker is not resetting as expected. Also: Why is it necessary to maintain a separate ticker? Shouldn't a default ticker per animation be kept? If an animation is not active, then the ticker does not have to be updated.