Animated character movement with W-A-S-D

Hello everyone again.

I have the slight feeling, that I create to many topics, but I need the knowledge.
As I already mentioned in

and

I’m trying to create a First-Person-Shooter with a playable character.
I have many questions, but I try to unify them in a few topics.

https://www.babylonjs-playground.com/#BCU1XR#282
This is my current work.

With W-A-S-D keys the character should be moving while an animation is played.
Currently, the character moves in the direction of z-axis, while holding W-key. But the animation doesn’t play correctly, because the key is fired constantly. I know I have to call the function outside/without switch-case, but I don’t know how. Probably with a true/false statement.

There are many forums with a similar problem, but no solution was working for me.
For example:

So my questions are:
1. How do I get the animation played and moving the character only while key is pressed?
2. How do I get the character moving in the direction of the camera?
3. How do I get the run animation played, when w and shift are pressed at the same time?

I hope at least one question can be solved :slight_smile:
As always, thank you in advance.

Hello,

You can find all basics informations about animations here : Animations - Babylon.js Documentation

1. How do I get the animation played and moving the character only while key is pressed?

First, you have to listen to the keyboard events :

Example
let isZPressed = false;
let isQPressed = false;
let isSPressed = false;
let isDPressed = false;

document.addEventListener('keydown', (e) => {
    if (e.keyCode == 90) { isZPressed = true; }
    if (e.keyCode == 81) { isQPressed = true; }
    if (e.keyCode == 83) { isSPressed = true; }
    if (e.keyCode == 68) { isDPressed = true; }
    if (e.keyCode == 66) { isBPressed = true; }
});

document.addEventListener('keyup', (e) => {
    if (e.keyCode == 90) { isZPressed = false; }
    if (e.keyCode == 81) { isQPressed = false; }
    if (e.keyCode == 83) { isSPressed = false; }
    if (e.keyCode == 68) { isDPressed = false; }
});

Then in your game loop you have to check if the key is pressed.
If yes, you have to move your entity by multipling the its front vector (normal vector) with its speed.

Example (code maybe obsolete)

entity.moveWithCollisions(entity.frontVector.multiplyByFloats(entity.speed, entity.speed, entity.speed));

And this while playing your animation.

Simplified summary
if z is pressed {
    play the animation
    move the entity
} else {
    pause the animation
}

2. How do I get the character moving in the direction of the camera?

You need to set the player front vector in the same direction as the camera.

3. How do I get the run animation played, when w and shift are pressed at the same time?

Same as 1. but with the condition that shift + Z are pressed simultaneously and an other animation + speed

2 Likes

Thank you for your advices and examples.

For now I focused on the animation and movement on the same time.
Sadly, it isn’t working as it should be.

How do I check the key in my game loop?
I used the registerBeforeRender function, because in the runRenderLoop function, I can’t refere to my imported mesh.
Furthermore, only the animation of the else-statement is working, while the object is moving. And only when the if-statement doesn’t contain an animation.

I used your example like this:
   let isWPressed = false;

       document.addEventListener('keydown', (e) => {
		if (e.keyCode == 87) { isWPressed = true; }
	});
			
	document.addEventListener("keyup", (e) => {
		if (e.keyCode == 87) {isWPressed = false;}
	});
			
	scene.registerBeforeRender(function() {
		if (!scene.isReady()) return;
				
		if (isWPressed) {
            //scene.beginAnimation(skeleton, runRange.from, runRange.to, true);
			moveVector.z = movestep;
			bot.moveWithCollisions(moveVector);
		} else {
			scene.beginAnimation(skeleton, walkRange.from, walkRange.to, true);
		}
	});

I also tried the actionmanager, but the result was nearly the same.
Playground to my result:
https://www.babylonjs-playground.com/#BCU1XR#294

Well, it somehow works, but I’m sure it shouldn’t be working like it is now.
Any suggestions what I may change?

Hello mister Modos - looked at that playground - maybe the problem is like this

W NOT PRESSED = Animation is starting all over and over and over again (thus it doesnt move as it is always just its first frame)

W PRESSED = nothing happens, thus animation started before (when W was not pressed) can move forward.

Seems like that by pressing W you let it move while by W not pressed you are restarting it from very beginning each frame.

I have never used these animations so I am just guessing but it seems to behave like that.

Take a look at this playground: https://www.babylonjs-playground.com/#15EY4F#15

it uses onBeforeRenderObservable for its gameloop and an action manager and dictionary to handle keys. It only calls begin animation if it is not already animating.

1 Like

Heya,

I would rather use vectors to move around.

Example
newMeshes[0].frontVector = new BABYLON.Vector3(0,0,1);
newMeshes[0].moveSpeed = 0.05;

[...]

scene.onBeforeRenderObservable.add(()=>{

[...]

    if(inputMap["w"] || inputMap["ArrowUp"]) {
        newMeshes[0].moveWithCollisions(newMeshes[0].frontVector.multiplyByFloats(newMeshes[0].moveSpeed, newMeshes[0].moveSpeed, newMeshes[0].moveSpeed));
        keydown=true;
    }

[...]

}

But maybe I’m wrong and it’s not the right thing to do :sweat_smile:.

Hey guys.

Thank you all for your help. The moving was never the problem, more the animation at the same time.
I will also try using vectors to move.

But for my problem, the playground @trevordev posted is solving my problem…well, I think so. I just tried it with my playground and there it works fine.
I also was trying to run the animation while there is no animation, but it didn’t work as it does in this example.

Where did you find that example, @trevordev ?

So, this thread is solved, but maybe we see us in another thread, I’ll have more questions soon, I guess :smiley:

Edit:
https://www.babylonjs-playground.com/#BCU1XR#298

Instructions

W - forward
S - backward
A - left
D - right
Holding shift - running (not animated yet)
V - change of view (first-person/ third-person)

To do:

  • idle animation when not moving
  • moving forward in camera direction
  • running animation when holding shift
1 Like

I made it, i just updated this example https://playground.babylonjs.com/#15EY4F#0 (found on the examples page Babylon.js Documentation ) and mixed it with your playground.

1 Like

thank you your sample contains a much better key control system then what i had remember i asked for multiple camera key inputs this is way better thx :smiley: but how would i replace the key name with the keycode

To convert to and from keycodes? Maybe this would work: Get ASCII value of Character, Convert ASCII to Character in JavaScript