Setting Linear Velocity for a body using TouchPad in LIBGDX - libgdx

I have been following tutorial from this link for implementing touchpad in LIBGDX. I want to set the linear velocity for a body using touchpad . I tried updating the position as per this tutorial but the body is not moving smoother.
This is my code for setting up linear velocity,
public void knobinput(float dt)
{
if(touchpad.getKnobPercentX()>0)
{
gamehero.heroBody.setLinearVelocity(1.4f, 0);
}
else
{
gamehero.heroBody.setLinearVelocity(-1.4f, 0);
}
}
When I implement this logic, the body started moving though I didn't give any inputs through touchpad.
I want to set the linear velocity as per the above code when the knob is turned right and left but, I didn't know how to check if the knob is turned right or left. Please help. Thanks in advance.

You do not handle the situation when the touchpad is in it's zero position - I mean you have no code for stopping body there. Take a look at this fragment:
else
{
gamehero.heroBody.setLinearVelocity(-1.4f, 0);
}
Even if you do not move the touchpad body has some velocity set.
The best approach would be to set velocity directly based on touchpad position without any conditions like:
gamehero.heroBody.setLinearVelocity(SPEED * touchpad.getKnobPercentX(),
SPEED * touchpad.getKnobPercentY());
It will handle zero position of touch pad (and body will have (0, 0) velocity set as it should) and it's speed will be based on touchpad's position value also (what does mean that if you move a touchpad a little body will move slowly and if you will move touchpad to the edge it will move with maximum speed - also as it should I guess).
SPEED variable should be the max speed that you need. In this case you can set SPEED = 1.4f for example.

Related

LibGDX ModelInstance - can't reset scale, setting the transform while scaled deforms the model

Is there any way to reset a modelInstance's scale or set a modelInstances position without using transform.set? I'm making a 3D monster maker, When a part is selected a set of 3D arrows move to the part and become visible allowing the part to be dragged around. It's come to my attention that setting an arrow's position while scaled heavily deforms the arrow for whatever reason. This is a huge problem as I need the arrows to be different sizes depending on the size of the part. Without setting position, with setting position. Using transform.set on a non-scaled ModelInstance (or one scaled by 1) works fine.
I thought a solution would be to reset the size of the arrow before moving it and then re-scaling it after it was moved but there doesn't seem to be any method to do this and using transform.scale(-currentScale, -currentScale, -currentScale) inverts the arrow and increases its size rather than decreasing it.
Here is how I change the arrow's position: arrow[j].transform.set(modelInstance[i].transform.getTranslation(new Vector3(), arrow[j].transform.getRotation(new Quaternion());
Ok, I did some logging and found that scaling changes all values within the matrix4 not just the size of the modelInstance. I didn't find a way to only scale rotation but I figured a way around this: I created an empty Matrix4 and set that to a copy of the arrows matrix before scaling. When the arrows need to be positioned at a part I set the arrow's matrix to the baseMatrix, used transform.set to change the arrows' position, and then rescaled the arrow.
if(Intersector.intersectRayBoundsFast(pickRay, modelInstance[i].boundingBox)) {
modelInstance[i].transform.getTranslation(modelInstance[i].position);//get the part's position and store it
for(int j = 0 ; j < 3 ; j++) {
arrow[j].transform = arrow[j].baseTransform.cpy();//reset the arrows transform
arrow[j].transform.getRotation(arrow[j].rotation);//get the arrow's (unscaled) rotation and store it
arrow[j].transform.set(modelInstance[i].position, arrow[j].rotation);//set the arrow's position and rotation
arrow[j].changeSize('S');//rescale the arrow
}
break;
}
You can use transform.scale(1f/currentScale, 1f/currentScale, 1f/currentScale) to revert the scaling or the function ModelInstance.calculateTransforms()

libGDX zoom implementation isn't working right

I would like to achieve a zoom effect that is similar to "Clash of Clans". I'm currently implementing zoom in a way that pretty much all the tutorials online do. There are of course a my camera specific constants to make it zoom at good speeds for my camera.The code DOES WORK.
#Override
public boolean zoom(float initialDistance, float distance) {
float zoomAmount = -1*(distance - initialDistance)/10000;
cameraHelper.addZoom(zoomAmount);
return true;
}
The camera helper class does this simple stuff:
public void addZoom(float amount) {
setZoom(zoom + amount);
}
public void apply(OrthographicCamera camera) {
camera.zoom = zoom;
camera.update();
}
So this does work. When I fling two fingers in one continuous motion and then stop moving the fingers on the screen, let's say I zoom in with zoomAmount = x, zoom gets called once and the zoom is done.
Problem:
However, if I then wiggle one, or both, of the fingers just a tiny bit, zoom gets called again with that same value for zoomAmount = x. So by wiggling a finger, it will simply keep adding to zoom and keep zooming in or out (depending on the current state of zoomAmount).
Question:
How do I make libgdx or java remember my original camera.zoom much like initialDistance in the zoom() method. OR, is there any other trick that I can do to have a responsive and smooth zoom (without removing fingers from the screen) much like the game "Clash of Clans".
Extra info:
I have tried pinch, same effect. I have thought about having a base zoom value and then some kind of percentage multiplier, however because I have to update the camera by setting its zoom (camera.zoom = zoom;) I can't think of a clever trick with adding or subtracting any values that will not be effected by zoom() being constantly called. Any thoughts anyone?

Rotating a Model in Away3D

Here's what i want to do:
I want to load a model (most likely .3ds) into my .swf and be able to rotate it with the mouse.
This works fine at first glance, but there's problem, the rotations 'switch' over. Or to say it differently:
Imagine we have a model in the shape of a pipe.
If we drag the mouse to the right, the model rotates along its X-Axis to the left, mouse to the left, X-Axis rotation to the right, moving the mouse up, Y-Axis rotation downward, mouse down, Y-Axis rotation upward.
Now, lets say we turn the pipe to the right or left, until we face the (former) 'backside' of the pipe, and then we move the mouse down. The model will rotate downward instead of upward.
I hope you understand what i mean with this. I've been looking around for a good while now and never found a satisfying solution. There was talk about quaternions, but i can't grasp them.
Another suggestion i read somewhere is the following:
create a Matrix3D object, apply rotation on it, then multiply it with the desired Matrix3D of my 3d-Model.
I tried to do it, but the result stays the same, the directions of rotation switches depending on what side i'm facing.
private function update(e:Event):void
{
xCalc = (0.3*(stage.mouseX - lastMouseX));
yCalc = (0.3*(stage.mouseY - lastMouseY));
if(move)
{
var objTransform:Matrix3D = new Matrix3D();
objTransform.prependRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.prependRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = multiply3DMatrices(mesh.transform, objTransform);
}
lastMouseX = stage.mouseX;
lastMouseY = stage.mouseY;
view.render();
}
multiply3DMatrices simply multiplies two 4x4 Matrices together.
objC is the ObjectContainer3D that holds my model. For some reason i cannot rotate it properly, unless i manipulate the rotationX/Y/Z properties.
mesh is the mesh inside of the Model (which is very simple, a single mesh).
Also, i'm aware that i could try another Framework for this (like papervision) but this project requires me to use Away3D.
Solved it by myself, the problem was that i created a new Matrix3D Object every time. The fixed code looks like this:
private function update(e:Event):void
{
...
if(move)
{
var objTransform:Matrix3D = mesh.transform;
objTransform.appendRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.appendRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = objTransform;
}
...
}
And yes, the user bwroga was actually right, i should've used appendRotation instead of prependRotation, as well.

AS3 smooth rotation direction

I'm not very good with radial calculations, I can't imagine thus I can't be sure. I need some explanation of Math.atan2() thing, please.
Usual task - to make an object rotate after the mouse. I get the differences, get the angle, I see angles in the text areas and DIRECTLY the object does follow the mouse. What I need now is everything to be smooth. I need angles to be 0-360 but after 180 object rotation becomes -180 and counts backwards, and mouse rotation becomes -90 after 270 and also counts back to 0.
More deeply, I want a smooth rotation, it means a set speed of say 2 per frame, to meet the mouse angle the shortest way. It takes to set conditions and I can't do that cause I don't even understand the logic of these values. They are almost random! I don't need it to be done or copied, I need to understand to move on so if you could please explain how does it work and what I do wrong...
Code is simple:
angle = Math.atan2(deltaY,deltaX)/(Math.PI/180) + 90; //+90 cause it lacks it to look at the mouse//
Object01.rotation = angle;
So the problem is I don't even get how it works... if 2 values are different the object can't point at the mouse but it does. Numbers lie and if I need something based on these numbers it will be wrong. Very wrong... Need organization. Meaning I want everything to be ready for further coding that will be based on the rotations to not jump up and down cause of misfit ends.
Add: Explanation of how does it happen, what I described above. Why such a chaos of the values? And an advice on how could I arrange it for further coding, just as I said. Animation alone wont work if I want to make rotation an element of important events such as shooting direction and aiming speed. Or changes of speed rotation of a lockpicked lock. Or anything much more complicated that wont work if I don't make straight and clear values: from A to Z, from 1 to 10, no 8s between 2 and 3, no R before B, no mouse angle 270 when object facing it -90 when they both started from 0 and reached 180 together.
Oh, and as I said, mouse facing works but when I try to make a certain speed of chasing mouse the shortest way it turns the object wrong directions in all 4 quarters. I assume it's also about this arctangens thing that has issues with delta values becoming negative in different quarters. And when I change it, some other value goes wrong... So I need to know exactly what I'm doing to know what's wrong and how to fix it. So yep. Need explanation. Please.
Add2: angleZ = Math.atan2(oppSide,adjSide)/(Math.PI/180);
So I divided rotation to 4 quarters, for each I count atan as opp. side to adj. side, then add 90, 180 and 270 respectively. My mouse rotation does 360, but the object that follow through simple object.rotation = angleZ; still goes to 180, then from -180 to 0 on the left side. Why does it ignore the simple command? The rotation fits but I need it to be equal, no surprises! Why is it happening? How can a number I directly set to be equal to another number as a base of the action change itself to the one of same rotation but completely different number? It doesn't even know it's degrees! It's as simple as "object.rotation, please be equal to the number I choose!"
It's just different coordinate systems. Like how x starts at 0 at the left of the stage, goes +x to the right, and -x to the left, object rotation starts at 0˚ pointing up, and goes +180˚ clockwise and -180˚ anti-clockwise.
Math.atan2 happens to start at 0 pointing left (-x), and go +270˚ clockwise and -90˚ anti-clockwise, which is annoying, but it just means you have to convert between coordinate systems by adding 90˚.
You can spin something around over and over of course, so the numbers jump so that they always stay within the same range, because 361˚ is the same as 1˚, and -270˚ is the same as 90˚. You can tell an object to rotate outside of the -180˚ to 180˚ range, and it will normalise the rotation to within those values.
As mitim described, to smoothly animate rotation you'll either need to use Event.ENTER_FRAME, a Timer, or a tweening library like TweenLite. Most tweening libraries can work out the shortest rotation direction for you, but otherwise you can simply calculate both and see which is smaller.
As an idea, since it seems like you know the angle you need to rotate towards and it's direction, would it be easier to just animate towards that angle to get your smooth rotation? Basically treat it like any other animatable property and just add on your rotation speed (2 degrees it looks like) per frame tick, until it reaches the desired rotation.
Find angle amount needed to rotate by
Figure out if clockwise or counter clockwise direction and set the rotation amount. This can be figured out by checking if the angle is great then 180 / positive or negative
Add the rotation amount * direction every frame tick, until the desired rotation is less then or equal to the rotation amount per frame
Set rotation to desired rotation

Help with velocity vectors

I have a velocity vector that is V(233, 188).
It makes an object moves toward the right-bottom side of the screen in 300 pixels per second when the origin is V(0, 0).
When the position of the object is, for instance, (592, 334), I set the velocity vector to V(294, 55) but the object does not start moving toward that direction... It keeps moving the same direction, but it seems that it makes a small curve of 10 degrees...
What I'm doing is:
objectLocation += velocity * elapsedTime;
What am I doing wrong?
The difference between (233,188) and (294,55) is not that much, in the grand scheme of things. To verify your code is working, try a vector such as (200,-200). That will cause it to actually bounce off the point in the y-direction.
If that code works, then it's just your values that aren't working.