Pick up Animation verbessert

This commit is contained in:
2026-09-27 21:55:55 +02:00
parent 0a7c7bc6d1
commit 555e2293dc
4 changed files with 38 additions and 14 deletions

View File

@@ -43,6 +43,8 @@ public class AnimPlayer {
private float pendingStartOffset; private float pendingStartOffset;
/** Wenn true: Clip rückwärts abspielen (speed=-1, Start am Ende). */ /** Wenn true: Clip rückwärts abspielen (speed=-1, Start am Ende). */
private boolean pendingReversed; private boolean pendingReversed;
/** Abspielgeschwindigkeit die beim nächsten direkten Clip-Start gesetzt wird (1f = normal). */
private float pendingSpeed = 1f;
public AnimPlayer(AnimComposer composer, SkinningControl skinning) { public AnimPlayer(AnimComposer composer, SkinningControl skinning) {
this.composer = composer; this.composer = composer;
@@ -150,6 +152,9 @@ public class AnimPlayer {
/** Aktuelle JME3-Action (BlendAction während Blend, ClipAction danach). */ /** Aktuelle JME3-Action (BlendAction während Blend, ClipAction danach). */
public Action getCurrentAction() { return currentAction; } public Action getCurrentAction() { return currentAction; }
/** Setzt die Abspielgeschwindigkeit für den nächsten Clip (wird nach Blend-Ende angewendet). */
public void setNextSpeed(float speed) { pendingSpeed = speed; }
// ── intern ─────────────────────────────────────────────────────────────── // ── intern ───────────────────────────────────────────────────────────────
private boolean directPlay(String clipName) { private boolean directPlay(String clipName) {
@@ -187,6 +192,10 @@ public class AnimPlayer {
} }
pendingStartOffset = 0f; pendingStartOffset = 0f;
pendingReversed = false; pendingReversed = false;
if (pendingSpeed != 1f && currentAction != null) {
currentAction.setSpeed(pendingSpeed);
pendingSpeed = 1f;
}
log.info("[AnimPlayer] direktPlay → '{}' length={}s", clipName, len); log.info("[AnimPlayer] direktPlay → '{}' length={}s", clipName, len);
return currentAction != null; return currentAction != null;
} catch (Exception e) { } catch (Exception e) {
@@ -219,6 +228,10 @@ public class AnimPlayer {
pendingStartOffset = 0f; pendingStartOffset = 0f;
} }
pendingReversed = false; pendingReversed = false;
if (pendingSpeed != 1f && currentAction != null) {
currentAction.setSpeed(pendingSpeed);
pendingSpeed = 1f;
}
log.debug("[AnimPlayer] finishBlend → '{}'", clip); log.debug("[AnimPlayer] finishBlend → '{}'", clip);
} catch (Exception e) { } catch (Exception e) {
log.warn("[AnimPlayer] finishBlend('{}') fehlgeschlagen: {}", clip, e.getMessage()); log.warn("[AnimPlayer] finishBlend('{}') fehlgeschlagen: {}", clip, e.getMessage());

View File

@@ -501,6 +501,7 @@ public class PlayerInputControl {
autopilotDir = null; autopilotDir = null;
forward = backward = left = right = false; forward = backward = left = right = false;
if (physicsChar != null) physicsChar.setWalkDirection(Vector3f.ZERO); if (physicsChar != null) physicsChar.setWalkDirection(Vector3f.ZERO);
if (animPlayer != null) animPlayer.setNextSpeed(4f);
playAction(AnimationAction.PICK_UP); playAction(AnimationAction.PICK_UP);
currentAnim = AnimationAction.PICK_UP; currentAnim = AnimationAction.PICK_UP;
} }

View File

@@ -409,17 +409,8 @@ public class WorldDummyState extends BaseAppState implements MeleeAttackCallback
} }
private void standUp(DummyRuntime dr) { private void standUp(DummyRuntime dr) {
playerInput.requestAnimation(AnimationAction.PICK_UP, 0f, null); playerInput.requestPickup(1.0f);
dr.fallen = false; dr.standUpTimer = 0f;
dr.fallenLerp = 0f;
dr.knockAngle = 0f;
dr.knockAngVel = 0f;
dr.currentHp = dr.maxHp;
dr.restoreTimer = 0f;
dr.dummyNode.setLocalRotation(new Quaternion());
dr.hpBarNode.setCullHint(Spatial.CullHint.Always);
refreshWorldHpBar(dr);
log.info("[Dummy {}] Aufgestellt.", dr.id);
} }
private void refreshWorldHpBar(DummyRuntime dr) { private void refreshWorldHpBar(DummyRuntime dr) {
@@ -445,6 +436,24 @@ public class WorldDummyState extends BaseAppState implements MeleeAttackCallback
for (int i = 0; i < dummies.size(); i++) { for (int i = 0; i < dummies.size(); i++) {
DummyRuntime dr = dummies.get(i); DummyRuntime dr = dummies.get(i);
// Aufstell-Timer: Puppe steht nach 0,5s auf (wenn Bücke-Animation halb durch ist)
if (dr.standUpTimer >= 0f) {
dr.standUpTimer += tpf;
if (dr.standUpTimer >= 0.5f) {
dr.standUpTimer = -1f;
dr.fallen = false;
dr.fallenLerp = 0f;
dr.knockAngle = 0f;
dr.knockAngVel = 0f;
dr.currentHp = dr.maxHp;
dr.restoreTimer = 0f;
dr.dummyNode.setLocalRotation(new Quaternion());
dr.hpBarNode.setCullHint(Spatial.CullHint.Always);
refreshWorldHpBar(dr);
log.info("[Dummy {}] Aufgestellt.", dr.id);
}
}
// Umfall-Animation (physikalisch: Schwerkraft-Drehmoment nimmt mit cos(Winkel) ab) // Umfall-Animation (physikalisch: Schwerkraft-Drehmoment nimmt mit cos(Winkel) ab)
if (dr.fallen && dr.fallenLerp < 1f) { if (dr.fallen && dr.fallenLerp < 1f) {
float gravAccel = KNOCK_GRAVITY * FastMath.cos(dr.knockAngle); float gravAccel = KNOCK_GRAVITY * FastMath.cos(dr.knockAngle);
@@ -564,6 +573,7 @@ public class WorldDummyState extends BaseAppState implements MeleeAttackCallback
float fallenLerp = 0f; float fallenLerp = 0f;
float knockAngle = 0f; // aktueller Kippwinkel (0..PI/2) float knockAngle = 0f; // aktueller Kippwinkel (0..PI/2)
float knockAngVel = 0f; // Winkelgeschwindigkeit (rad/s) float knockAngVel = 0f; // Winkelgeschwindigkeit (rad/s)
float standUpTimer = -1f; // >= 0 während Aufstell-Animation läuft
DummyRuntime(String id, float wx, float wy, float wz, DummyRuntime(String id, float wx, float wy, float wz,
Node dummyNode, Node hpBarNode, Geometry hpBarFg, int maxHp, Node dummyNode, Node hpBarNode, Geometry hpBarFg, int maxHp,

View File

@@ -50,7 +50,7 @@ public class WorldItemsState extends BaseAppState {
private static final float INTERACT_RANGE = 5f; private static final float INTERACT_RANGE = 5f;
private static final float REACH_DIST = 0.5f; private static final float REACH_DIST = 0.5f;
private static final float PICKUP_ANIM_DURATION = 0.8f; private static final float PICKUP_ANIM_DURATION = 1.0f;
private static final float WALK_TIMEOUT = 5.0f; private static final float WALK_TIMEOUT = 5.0f;
private static final String INTERACT_ACTION = "Interact"; private static final String INTERACT_ACTION = "Interact";