Jump to content

Custom controls based on grid


foumfo
 Share

Recommended Posts

I'm developing a game that will have grid based maps - levels and the player will be moving through it one block per keystroke. I'll be using the keyboard as input just for the start, I'll add others later on.

Every level is generated from a double array filled with 1 & 0.

So I want to do here is for example: if I press W the player will move one block forward. if I press Q the player will rotate anticlockwise by 45 degrees.

 

Link to comment
Share on other sites

3 minutes ago, Deltakosh said:

You may want to read this first:

http://doc.babylonjs.com/how_to/customizing_camera_inputs

based on that you can either create your own input or hijack the keyboard one :)

I've read that already but its a bit difficult for me to follow.

What I actually need is a small and simple example just for one control, pressing W and moving forward a specific amount of space

Link to comment
Share on other sites

I think I've had it all wrong from the start. Would it be possible to create my own function for controlling the camera without actually attaching it to the camera object?

After I've detached the default keyboard controls ofcourse

Link to comment
Share on other sites

Hi guys.

Hey forumfo... here's a goofy playground that somebody once made.  

https://www.babylonjs-playground.com/#23PDP1#4

It uses WASD keys to trigger 90-degree rotations of the box.  Kind of fun.

The code size could be massively reduced.  The rotations were done with "parenting to an invisible gizmo"... before I knew about setPivotPoint() for mesh.

AND... this thing uses old DOM-like keypress-checking... when really... we should use BabylonJS ActionManager instead.  Sooo...

https://www.babylonjs-playground.com/#1MK1Y4#3

A little more modern... with WASDQE keys all working... but... the box is not moving in "steps".   This is because the translation and rotation anims...  is done in the render loop area (lines 70-75).

Really, we need a few little "animation functions"... and remove stuff from the render loop.

See lines 26, 29, 32, 35, 38, 41?  We could replace those lines... with... moveMesh(whichmesh axis, amount);  [amount could be positive or negative])  We would MAKE our own 'custom' mesh-mover function. 

Same with rotate.  rotateMesh(whichmesh, axis, amount)  (amount can be negative or positive).  Custom mesh rotater func... by Captain Foumfo!  Alright!  :)

What would go inside these 2 mover and rotater funcs?  Well, let's go check out another playground.

https://www.babylonjs-playground.com/#HH1U5#72

See the stuff at the top?  Mainly, notice the spinTo, and moveTo functions.  Inside those... is an amazing one-liner super-animator call... BABYLON.Animation.CreateAndStartAnimation().

It's amazing.  I really like it.  Anyway, steal some animation code from there... for your functions.  Use the entire spinTo and moveTo functions... for your thing.  With a little hacking and playing... I think you now have the tools to take over the world.  :)  Our Animation docs might be helpful. 

Ohhhh... you REALLY wanted to talk about moving a CAMERA, step by step?   Just parent the camera to the box.  Easy.  You might want to remove camera.inputs, if you want to disable cursor keys and mouse... moving the camera.

AND, finally, yes, as Deltakosh states... you could write a custom camera input... that moves the camera in grid-steps.  I'm not sure that anyone has ever done that, yet.  You would need to wear a hard-hat and safety goggles, for sure.  :D  My "parent to the invisible box" method... might be easier... safer... less tumor-causing.  :)

Did you know that cameras... can have animations directly upon them, too?  hmm.  BABYLON.Animation.CreateAndStartAnimation() can animate the camera, instead of a mesh.  hmm.  A little note:  pay attention to camera.setTarget, .target, and .lockedTarget properties.  Changing THOSE values... often setting them == box.position... CAN be handy for basic 'followCamera'.  AND, even camera.target or .lockedTarget can be animated, with easing.  hmm.   Talk soon, be well. 

Link to comment
Share on other sites

9 hours ago, Wingnut said:

Hi guys.

Hey forumfo... here's a goofy playground that somebody once made.  

...............

Thanks for the answer, I should have stated from the start that I'm talking about a First Person Camera game.

If I understand correctly, you're talking about adding an invisible mesh as the player and have a FollowCamera attached to it, right?

Link to comment
Share on other sites

Yeah.  Maybe not a followCam, though.  Maybe just parent the cam to the invisible box.  Notice John's demo also uses a 'cambox'.

With FPS... there's no player mesh, right?  (I'm not much of a shoot-em-up player.  Too old and slow.)  :)

Yeah, you would want to use parenting, not .target/setTarget()/.lockedTarget  (those are all 'follow-ish' things).

Universal or free cam...  clear its camera.input so the camera has no controls of its own.  Then just drive-around the tiny/invisible cam-parent box... should work fine.  Cam 'gizmo' or 'handle' thing.

Step one... make code to drive-around a box with wasdqe.  Make it act just like you want your camera to act... later... when you parent it to the box.  Goof around, see what you like or don't... have good fun.

Perhaps, a fun thing... familiarize yourself with BabylonJS GUI "simpleButton".  Then maybe...  create two buttons onscreen and two cameras.  One is parentedToBoxFreeCam... the other is wideViewCam.  Make your buttons choose which camera to view-from.  *shrug*.  A nice testing feature, eh?  WideViewCam keeps normal .inputs (possibly use an ArcRotateCam)... and the parentedToBoxFreeCam has its .inputs cleared.  *shrug*

Link to comment
Share on other sites

4 hours ago, Wingnut said:

Yeah.  Maybe not a followCam, though.  Maybe just parent the cam to the invisible box.  Notice John's demo also uses a 'cambox'.

With FPS... there's no player mesh, right?  (I'm not much of a shoot-em-up player.  Too old and slow.)  :)

Yeah, you would want to use parenting, not .target/setTarget()/.lockedTarget  (those are all 'follow-ish' things).

Universal or free cam...  clear its camera.input so the camera has no controls of its own.  Then just drive-around the tiny/invisible cam-parent box... should work fine.  Cam 'gizmo' or 'handle' thing.

Step one... make code to drive a box with wasdqe.  Make it act just like you want your camera to act... later... when you parent it to the box.  Goof around, see what you like or don't... have good fun.

Ok then I'll create a box with my controls and then see how to make it a parent to a camera. I didn't know I could do that.

The game I'm developing will be like the old school rpgs that players roam in dungeons step by step using a FPS cam

Link to comment
Share on other sites

Hi Foumfo.  I want to remind you... that just because Wingnut has an idea, doesn't mean it's good or right.  :)  It's simply one way to do it.

After some tests, you might find better ways.  More comments may come, too.  I'm certainly no expert in game programming.

Here's another demo... with 'spin' and 'move' functions installed/used.

https://www.babylonjs-playground.com/#1MK1Y4#7

Issues:

- After Q/E 45-degree turns, cambox still wants to WASD-move in WORLDSPACE directions, but cambox SHOULD move in cambox's LOCALSPACE directions.  (if box is turned 45 degrees, all cam/cambox WASD moves should be rotated 45 degrees, too.)

- Held-down keys do not repeat.  Probably should.

- Hemispheric light's .groundColor (line 36) might not be working.  Sides of cones SHOULD be lit/colored, and not black, I think.

------------------------------

Lines 109-111 parent the camera to the box and remove any old positions or far targets.  Even though I did not set cambox.visibility = 0, you can't see it... even if you tilt the camera downward with the mouse.  By setting camera.minZ to something like .01... you might be able to see it again.

I did NOT clear the .input of this camera.  I wanted to keep being able to look around... with mouse or cursors, for now.

Also, animations are not required.  We could "snap" the camera to new positions and rotations... instantly.  I think the keys would repeat when held, that way, automatically.  There might be ways to tell the animations to do LOCAL SPACE animating instead of WORLD SPACE, but I'm not sure how to do that.   Maybe others will help with that.

Anyway, now you have an example... of what a camera... parented to a box... looks-like/acts-like.  Not too bad, eh?  Something to play-with.  Talk soon.

Link to comment
Share on other sites

//player
window.player = BABYLON.MeshBuilder.CreateBox("player", {size: 1}, scene);

var playerMovement = function(key) {
    console.log(key);
    switch(key.charCode) {
        //up
        case 119:
        case 87:
            player.position.z += 1;
            break;
        //down
        case 115:
        case 83:
            player.position.z -= 1;
            break;
        //left
        case 97:
        case 65:
            player.position.x -= 1;
            break;
        //right
        case 100:
        case 68:
            player.position.x += 1;
            break;
        //rotate anticlockwise
        case 113:
            player.rotation.y -= Math.PI / 2;
            break;
        //rotate clockwise
        case 101:
            player.rotation.y += Math.PI / 2;
            break;
    }
}

document.addEventListener('keypress', playerMovement, false);

I just created this small piece of code, but all the transforms are instant. How can I animate them?

 

Link to comment
Share on other sites

https://www.babylonjs-playground.com/#1MK1Y4#10

There ya go.  Your code is lines 102-146.  Spin() and move() animation funcs are lines 2-11.

I can't get the keypress repeating (held keypress) to work, yet.  And I am seeing a move on keypress UP, too.  Not sure why.  Still thinking/studying.

My tumbler demo https://www.babylonjs-playground.com/#23PDP1#4  performs/allows held keypresses, but it uses different animation methods (not using spin() or move() or CreateAndStartAnimation().  hmm.

Perhaps you or others can help me find my mistakes.

Link to comment
Share on other sites

38 minutes ago, Wingnut said:

https://www.babylonjs-playground.com/#1MK1Y4#9

There ya go.  Your code is lines 102-146.  Spin() and move() animation funcs are lines 2-11.

I can't get the keypress repeating (held keypress) to work, yet.  And I am seeing a move on keypress UP, too.  Not sure why.  Still thinking/studying.

My tumbler demo https://www.babylonjs-playground.com/#23PDP1#4  performs/allows held keypresses, but it uses a different animation methods (not using spin() or move() or CreateAndStartAnimation().  hmm.

Perhaps you or others can help me find my mistakes.

Your first example works but only if add

window.addEventListener("keypress", playerMovement, false); instead of keydown.
By the way, your first lines are awesome!

BABYLON.AbstractMesh.prototype is how we add properties to the mesh class correct?

Link to comment
Share on other sites

Is it possible to rotate a meshes pivot axis when we rotate the mesh?

For example, when we rotate the mesh clockwise, rotate the X axis clockwise also. So when you move the mesh forward, it will move rightwards compared to the global axis

Link to comment
Share on other sites

Yeah, that's possible.  Remember when I talked about LOCALspace and WORLDspace... and I wasn't sure how to use animation to move an object in along localspace axes?

That's what I was talking about.  And I still don't know how.  I'm not very helpful.  :(

Let's make sure you and I are understanding each other.

Visit here, please.

http://playground.babylonjs.com/#6FHKHC#9

This is a playground where we activated the mousewheel... on a freeCamera (normally, not activated).

Pretend that the mousewheel == YOUR W and S keys. 

Notice that... no matter WHICH WAY the camera (box) is rotated/aimed, the mousewheel (W/S keys)... moves the camera along cam's LOCAL z-axis... and not along the WORLD z-axis.

I think that is what you want.  (verify, if you wish)

I think you want translations to move along the box's LOCALspace z-axis.  (sometimes called the box's "forwardVector", I believe... but I could be wrong on that.)

I don't think mesh.setPivotPoint() will work for this. 

I don't know how to move a mesh along its "forwardVector" (its localSpace z-axis)... with animation.  Not yet, anyway.  Still thinking.

Although it is a weekend (sleepy forum)... let's wait for more comments/help.

Link to comment
Share on other sites

Even though I didn't understand much of your example, I do want the camera box's movement to be based on its locaspacel axis and not the globalspace.

I could do it programmatically I suppose but it would take a lot of lines of code.

I asked this in case there was a built-in way / method to handle local translations

Link to comment
Share on other sites

*nod*.  https://www.babylonjs-playground.com/#1MK1Y4#12

Quite a bit of change in lines 2-13.

Using .rotate() and .translate() funcs... instead of .rotation and .position properties... gives us the localSpace stuff we want.

But I still don't know how to apply animation to it.  Help welcome, from anyone.

Note:  When we used the .rotate() function in line 3, that is called a Quaternion rotation.  The mesh sort-of turns-off the .rotation property, and instead uses .rotationQuaternion to store it's rotation values.  We'll talk more about that, someday.  Main thing is... after a rotate() happens on a mesh, mesh.rotation property is no longer used, and mesh.rotationQuaternion property is added to the mesh, and used instead.

Okay, how about it, fellow forumers?  Anyone know how to use animations like those seen in line 4-6 and 10-12... but with localSpace animations instead of worldSpace?  Help!  :)

Stay tuned, foumfo.  SOMEBODY will know how to animate these localSpace moves/turns.  (Wingnut crosses his fingers).

Link to comment
Share on other sites

18 hours ago, Wingnut said:

*nod*.  https://www.babylonjs-playground.com/#1MK1Y4#12

Quite a bit of change in lines 2-13.

Using .rotate() and .translate() funcs... instead of .rotation and .position properties... gives us the localSpace stuff we want.

But I still don't know how to apply animation to it.  Help welcome, from anyone.

Note:  When we used the .rotate() function in line 3, that is called a Quaternion rotation.  The mesh sort-of turns-off the .rotation property, and instead uses .rotationQuaternion to store it's rotation values.  We'll talk more about that, someday.  Main thing is... after a rotate() happens on a mesh, mesh.rotation property is no longer used, and mesh.rotationQuaternion property is added to the mesh, and used instead.

Okay, how about it, fellow forumers?  Anyone know how to use animations like those seen in line 4-6 and 10-12... but with localSpace animations instead of worldSpace?  Help!  :)

Stay tuned, foumfo.  SOMEBODY will know how to animate these localSpace moves/turns.  (Wingnut crosses his fingers).

What If we did this animation using another framework, like jquery for example.

Would it be too taxing performance-wise?

Link to comment
Share on other sites

:)  Yeah, you're sort-of on the right track.  We can use BJS built-in 'LERP'.  Goofy term, eh?  "linear interpolation".  You can think of it as a "derived" (math-generated) array of vector3 positions... just like an animation might be.  It is pre-"grown" before the animation starts, and then this array is "delivered" to the 'animatable'... at a frame rate.

https://github.com/BabylonJS/Babylon.js/search?utf8=✓&q=lerp&type=

The BJS animation system and easings system... uses lerp now.

So, yes, the power to make your own eased animations... is already built-into BJS.

Do I know how to use it?  Heck no.  heh. 

Let's try a playground search for 'lerp'...  http://doc.babylonjs.com/playground?code=lerp

Plenty of examples.  Is any of it easy?  Maybe, but... MUCH smarter lerp-masters than I... are nearby.  Hopefully, you, or one of them will wave their magic lerp-wand, and make it all better.  :)

important afterthought:  I said that a lerp array might be an array of vector3 .positions.  THAT... might not be true.  Each value MIGHT BE... "amount of change to apply since last change".  Not sure.  For building your own animation (interpolation array) to apply-to mesh.translate() repeatedly...  an "amount of change since last change" array... would be better for you. 

Conversely, an array of vector3 positions... would be better for using mesh.position... instead of mesh.translate().  I think EITHER METHOD would work for you.  Maybe.  *shrug* 

I think you can "grow" lerps... using either method.  Scary.  :o  I really have no idea what I am talking about, though.  Mostly speculation.

MAYBE... the move() function could be made "smarter"... able to recognize WHEN/IF a box has been rotated, and change its animation methods... to compensate for that (such as running two animations at the same time).  Hmm.

It would be good to know WHY animations like these ... do keypress-held repeating, but no hold/repeat for our BABYLON.Animation.CreateAndStartAnimation().  Might be something about the CreateAndStartAnimation's onFinished callback (or lack-of callback?), or something.  I need more learning.  :)

Notice the 'itEnded' callback in line 192 of that playground.  It calls the itEnded() function... upon ending.  OUR style of animating (CreateAndStartAnimation)... doesn't use that, as best I can tell.  *shrug*  Perhaps THAT is why one kind of animation/keypress-events allow held/repeating keys, and the other doesn't.  Not sure.

Link to comment
Share on other sites

Wingnut check this out:

https://www.babylonjs-playground.com/#1MK1Y4#15

you only have to use

this.translate(axis, amt, BABYLON.Space.LOCAL);

When you use

BABYLON.Animation.CreateAndStartAnimation('at4', this, 'rotation.' + axis, speed, 120, this.rotation[axis], this.rotation[axis]+rads, 0, ease);

and then translate, the mesh moves along the local axis that has been rotated by the above rotation

Link to comment
Share on other sites

For simple movement try adding this code:

BABYLON.AbstractMesh.prototype.moveTo = function (targetPos, fps, frames, done) {
    var ease = new BABYLON.QuadraticEase();
    ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
    this.activeAnimation = BABYLON.Animation.CreateAndStartAnimation('at5', this, 'position', fps, frames, this.position, targetPos, 0, ease, done);
};

This will attach a moveTo method to every mesh in your scene, and then you can simply call the function like so:

myMesh.moveTo(new BABYLON.Vector3(x,y,z),24,96,function(){
    console.log("Movement complete!");
});

You can extend the function to accept the easing type in the method call if you intend to have different ease effects according to situation.

For rotation you may wish to look in to Quaternions, as they in general provide much smoother and more reliable results. The following is an example implementation for slerping between two quaternions, however there are probably other methods you can use for this.

// set up the initial Quaternion on your mesh, as they are not created automatically
myMesh.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(
	myMesh.rotation.y, 
	myMesh.rotation.x, 
	myMesh.rotation.z
);

// add an "indicator" mesh to your main mesh. This will be used to look at the target location, and the different between its quaternion and your mesh's quaternion then slerped to match
var indicatorMesh=BABYLON.Mesh.CreateBox("meshIndicator", 0.1, scene);

// add quaternion for this new mesh too
indicatorMesh.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(
	indicatorMesh.rotation.y, 
	indicatorMesh.rotation.x, 
	indicatorMesh.rotation.z
);

// parent the indicator mesh to your main mesh
indicatorMesh.parent = myMesh;

// now, in a registerAfterRender function (called automatically), adjust the two quaternions. change the world/local space to suit. targetPosition it the Vector3 you want to look at
scene.registerAfterRender(function () {
    if(myMesh.isRotating=true){
        // make the indicator mesh look to the target position. This will update its quaternion.
        indicatorMesh.lookAt(targetPosition,0,0,0,BABYLON.Space.WORLD);
        // now get an integer value representing the difference between the main mesh quaternion value and the indicator mesh's quaternion value.
        var diff = myMesh.rotationQuaternion.subtract(indicatorMesh.rotationQuaternion).length();

        // registerAfterRender fires after ever frame render, so here we can check the difference between the two quaternions and decide to do something once we meet a certain threshold.
	    if(diff > 0.05){

             // if we are still above the threshold, adjust the mesh quaternion a little. You can adjust the amount to suit. The higher the number the quicker the rotation and the faster the rotation will pass the threshold. We use Slerp here because this will spherically interpolate a value in directional vectors
             myMesh.rotationQuaternion = BABYLON.Quaternion.Slerp(
					                myMesh.rotationQuaternion,
					                indicatorMesh.rotationQuaternion,
					                0.035
					            );
        else {
            // set the rotating flag to false to stop this loop for firing again
            myMesh.isRotating=false;
            // optionally call a function to continue processing
            done && done();
        }
    }
});

// somewhere in your code, start the process away
targetObject=new BABYLON.Vector3(x,y,z);
myMesh.isRotating=true;

var done = function(){
console.log("done rotating");
};

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...