I've been trying to create player movement in my Flutter game. I want the player to stop moving if no movement key is pressed but the code below doesn't work:
import 'dart:async';
import 'package:farm_game/farm_lands.dart';
import 'package:flame/components.dart';
import 'package:flame/sprite.dart';
import 'package:flutter/src/services/raw_keyboard.dart';
enum PlayerState {
idle,
backIdle,
leftIdle,
rightIdle,
walkFront,
walkBack,
walkLeft,
walkRight
}
enum PlayerDirection {
front,
back,
left,
right,
none
}
class Player extends SpriteAnimationGroupComponent
with HasGameRef<FarmLands>, KeyboardHandler {
late final SpriteSheet spriteSheet;
final double stepTime = 0.3;
PlayerDirection playerDirection = PlayerDirection.none;
double moveSpeed = 50;
Vector2 velocity = Vector2.zero();
Player({position}): super(position: position);
@override
FutureOr<void> onLoad() {
spriteSheet = SpriteSheet.fromColumnsAndRows(
image: game.images.fromCache('characters/Character_Spritesheet.png'),
columns: 4, // Number of columns in the sprite sheet
rows: 4, // Number of rows in the sprite sheet
);
_loadAllAnimations();
return super.onLoad();
}
@override
void update(double dt) {
_updatePlayerMovement(dt);
super.update(dt);
}
@override
bool onKeyEvent(RawKeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
final isLeftKeyPressed = keysPressed.contains(LogicalKeyboardKey.keyA) ||
keysPressed.contains(LogicalKeyboardKey.arrowLeft);
final isRightKeyPressed = keysPressed.contains(LogicalKeyboardKey.keyD) ||
keysPressed.contains(LogicalKeyboardKey.arrowRight);
final isUpKeyPressed = keysPressed.contains(LogicalKeyboardKey.keyW) ||
keysPressed.contains(LogicalKeyboardKey.arrowUp);
final isDownKeyPressed = keysPressed.contains(LogicalKeyboardKey.keyS) ||
keysPressed.contains(LogicalKeyboardKey.arrowDown);
if (isLeftKeyPressed && isRightKeyPressed) {
playerDirection = PlayerDirection.none;
} else if (isUpKeyPressed && isDownKeyPressed) {
playerDirection = PlayerDirection.none;
} else if (isLeftKeyPressed) {
playerDirection = PlayerDirection.left;
print('left');
} else if (isRightKeyPressed) {
playerDirection = PlayerDirection.right;
print('right');
} else if (isUpKeyPressed) {
playerDirection = PlayerDirection.back;
print('back');
} else if (isDownKeyPressed) {
playerDirection = PlayerDirection.front;
print('front');
} else {
playerDirection = PlayerDirection.none;
}
return super.onKeyEvent(event, keysPressed);
}
void _updatePlayerMovement(double dt){
double dirX = 0.0;
double dirY = 0.0;
switch(playerDirection){
case PlayerDirection.front:
current = PlayerState.walkFront;
dirY += moveSpeed;
break;
case PlayerDirection.back:
current = PlayerState.walkBack;
dirY -= moveSpeed;
break;
case PlayerDirection.left:
current = PlayerState.walkLeft;
dirX -= moveSpeed;
break;
case PlayerDirection.right:
current = PlayerState.walkRight;
dirX += moveSpeed;
break;
case PlayerDirection.none:
current = PlayerState.idle;
break;
default:
}
velocity = Vector2(dirX, dirY);
position += velocity * dt;
}
// Load all animations
void _loadAllAnimations() {
// Create sprite animations using the sprite sheet
animations = {
PlayerState.idle: spriteSheet.createAnimation(
row: 0,
stepTime: stepTime,
from: 0,
to: 2,
),
PlayerState.backIdle: spriteSheet.createAnimation(
row: 1,
stepTime: stepTime,
from: 0,
to: 2
),
PlayerState.leftIdle: spriteSheet.createAnimation(
row: 2,
stepTime: stepTime,
from: 0,
to: 2
),
PlayerState.rightIdle: spriteSheet.createAnimation(
row: 3,
stepTime: stepTime,
from: 0,
to: 2
),
PlayerState.walkFront: spriteSheet.createAnimation(
row: 0,
stepTime: stepTime,
from: 2,
to: 4
),
PlayerState.walkBack: spriteSheet.createAnimation(
row: 1,
stepTime: stepTime,
from: 2,
to: 4
),
PlayerState.walkLeft: spriteSheet.createAnimation(
row: 2,
stepTime: stepTime,
from: 2,
to: 4
),
PlayerState.walkRight: spriteSheet.createAnimation(
row: 3,
stepTime: stepTime,
from: 2,
to: 4
),
};
}
}
Also, player movement keys are only available when I remove the else statement at the end. I'm sorry if this is a dumb question, I'm still new to Flutter and Flame.
I tried moving the PlayerDirection.none to higher parts of the code and also tried to add a boolean if keyup then PlayerDirection.none and else the movement keys are activated.
You can simplify that logic a bit and get it correctly working:
The code is extracted from this example: https://examples.flame-engine.org/#/Input_Keyboard