What does Vector2.scl method do in LibGdx - java

I've been following a a tutorial recently and really new to game development. There is a method called scl of the Vector2 class in LibGdx. Here is the fragment of my code. My question is. What does it do. If you can do a detailed explanation. Please add some.
public void update(float dt){
if(position.y > 0)
velocity.add(0, GRAVITY);
velocity.scl(dt);
Gdx.app.log("scl dt 1", Float.toString(velocity.y));
position.add(0, velocity.y, 0);
if(position.y < 0)
position.y = 0;
velocity.scl(1/dt);
}

scl() is overloaded method of Vector2 class.
1. public Vector2 scl(float scalar)
Scales your vector by a scalar quantity and return.
2. public Vector2 scl(float x,float y)
Multiplies your vector by a scalar and return itself.
3. public Vector2 scl(Vector2 v)
Scales your vector by another vector and return itself.
In above your code you are scaling your vector by dt unit.
What is dt ?
dt is the time between the start of the previous and the start of the current call to render(). It just takes the current time and subtracts the previous time from it. The unit of this value is seconds.

Related

Calculate the bouncing angle for a ball/point

I'm building my own small game engine for learning. So basically pure Java. I have Lines which are defined by a start and endpoint (x and y coordinates)
Now I have a ball with a velocity vector. I want to "bounce" off the wall, which could positioned in any possible angle. How do I find out the new velocity vector after the collision happend? I know the point S, P1 and P2 (see image)
I thought about calculating the angle, and change the x and y components. But I can't find a way how to do this for all possible angles.
I could find many solutions for walls which are parallel to the canvas borders, but no general solution. How do "big" game engines handle this common problem?
edit:
My updated Vector class methods:
public static Vector bounce(Vector normal, Vector velocity) {
Vector tmp = Vector.multiplication(2*Vector.dot(normal,velocity), normal);
return Vector.addition(tmp, velocity);
}
public static Vector multiplication(double multi, Vector n) {
Vector new_vector = new Vector(n.x * multi, n.y * multi);
return new_vector;
}
public static double dot(Vector a, Vector b) {
return a.x*b.x + a.y*b.y; // + a.z*b.z if you're in 3D
}
My test function:
#Test
public void testBounce() {
Vector normal_vector_corrected = new Vector(0, 1);
Vector start_velocity = new Vector(3, -3);
Vector bounced_vector = Vector.bounce(normal_vector_corrected, start_velocity);
System.out.println("normal vector: "+normal_vector_corrected);
System.out.println("start_velocity: "+start_velocity);
System.out.println("bounced_vector "+bounced_vector);
}
The output is this:
normal vector: <Vector x=0,00, y=1,00>
start_velocity: <Vector x=3,00, y=-3,00>
bounced_vector <Vector x=3,00, y=-9,00>
According to my calculations, bounced_vector should be x=3,y=3 instead. Where is my mistake? (My example as picture:)
edit2:
I found that it has to be return Vec.add(tmp, v);. Furthermore, I had to inverse the velocity vector.
The "bounced velocity vector" v' is obtained from the original velocity v and the surface normal unit vector n with 2(n . v)n + v where . stands for the vector dot product. This is usually called a reflection; the velocity vector is reflected across the surface normal.
In case you're not familiar with the terminology, the surface normal is a vector that is perpendicular (at 90-degree angle) to the surface. A unit vector is a vector with length 1.
I assume you already have a class to represent vectors, called Vec, with methods to multiply a vector with a scalar and to add two vectors. You could write the bounce operation as:
static Vec bounce(Vec n, Vec v) {
Vec tmp = Vec.scalarMultiply(-2*Vec.dot(n,v), n);
return Vec.add(tmp, v);
}
static double dot(Vec a, Vec b) {
return a.x*b.x + a.y*b.y; // + a.z*b.z if you're in 3D
}
As for how to get the surface normal, that will depend on if you're in 2D or 3D. Assuming 2D, it's simple: if (x,y) is the vector from P1 to P2, then (-y,x) is perpendicular to it, and one unit normal would be:
n = (-y/sqrt(x*x+y*y), x/sqrt(x*x+y*y))
The other possible unit normal is -n. You would use one or the other depending on which side of the surface you are.
You should store the normal vector with the geometry of the scene so you don't have to calculate it every time.

How to make LibGDX Actions moveTo() animate from one point to another in a curved line?

I am working on a project in LibGDX, and I am using Scene2D actors for some of my sprites. In this regard, I have a sprite, which is spawning somewhere on the screen and needs to move to another position on the screen. To do this I am using the moveTo(xPos, yPos, duration, interpolation) method in the Actions, to make the move animation.
However, when I use this approach, the actor moves like I told it to, but it only moves in a straight line, from point A to B. I have tried several Interpolation options, like Circle interpolation and such, but it seems only to impact the speed of the animation line.
So now my question: How do I make my animation make a smooth curved line (See picture), from A to B?
I am currently using this code to make the Actions animation:
adultCustomerPointActor.addAction(Actions.sequence(
Actions.moveTo(300, 200, 2f, Interpolation.circle)
));
Thanks in advance for your help :)
It's a geometry problem. Using vectors, find the point halfway between the two points:
vec1.set(bx, by).sub(ax, ay).scl(0.5f).add(ax, ay);
Get another vector that is 90 or 270 to from the vector between the points:
vec2.set(bx, by).sub(ax, ay).rotate90().add(vec1);
This vec2 can be scaled to adjust how extreme curvature of the arc is. If you leave it alone, you'll have a quarter circle. You can also scale it negative to reverse the curvature.
Then add the second vector to the first to find the center point of your arc, which we can call point C.
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
float angle = vec1.angle(vec3);
Now you need a vector that points from point C to point A. You will rotate this vector until it reaches point B. So you need the angle between CA and CB.
So here's a very simplistic class that implements this. It doesn't account yet for deciding if you want the arc to go up or down and if you want to scale how extreme it looks. You could add those as additional parameters with getters/setters. I haven't tested it, so it may need some debugging.
public class ArcToAction extends MoveToAction {
private float angle;
private final Vector2 vec1 = new Vector2(), vec2 = new Vector2(), vec3 = new Vector2();
#Override
protected void begin () {
super.begin();
float ax = target.getX(getAlignment()); // have to recalculate these because private in parent
float ay = target.getY(getAlignment());
vec1.set(getX(), getY()).sub(ax, ay);
vec2.set(vec1).rotate90();
vec1.scl(0.5f).add(ax, ay);
vec2.add(vec1);
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
angle = vec1.angle(vec3);
}
protected void update (float percent) {
if (percent >= 1){
target.setPosition(getX(), getY(), getAlignment());
return;
}
vec1.set(vec3).rotate(percent * angle);
target.setPosition(vec1.x, vec1.y, getAlignment());
}
}
If you want to support automatic pooling, you can add a method like this:
static public ArcToAction arcTo (float x, float y, float duration, Interpolation interpolation) {
ArcToAction action = Actions.action(ArcToAction .class);
action.setPosition(x, y);
action.setDuration(duration);
action.setInterpolation(interpolation);
return action;
}

Firing projectiles in a circle

So I can't seem to find an answer to this, but I am trying to fire bullets into a circle. I have a simple class for a circular path that I attach to a bullet and it reads from that class a position when given a time value. The bullet simply increments this time value, constantly updating its position to the next. This can be improved but until I get the logic down this is what I have. I know this method works because I tried it with a linear path. The problem is applying it to a circular path.
I want the bullet to circle around a point (say Point 'Center') with a given radius and speed. I want all bullets to travel at the same speed no matter the radius of the circle so a larger circle will take longer to complete than a shorter one. Currently what is happening is I have the CircularPath object giving saying x = r * cos(t) and y = r * sin (t) where t is in radians, but this is making a circle that increases in speed as the radius increases and the radius and center of this circle is completely off. The bullets are starting in the correct position, except the radius and speeds are off. I hope I am describing this adequately. I will post the code for anyone to inspect.
package io.shparki.tetris.go;
import io.shparki.tetris.util.Point2D;
import java.awt.Color;
import java.awt.Graphics2D;
public class CircularPath extends Path{
private double radius;
// Where Start is the center and end is the location of mouse
// Radius will be distance between the two
public CircularPath(Point2D start, Point2D end) {
super(start, end);
radius = normalToEnd.getLength();
color = Color.YELLOW;
}
public Point2D getPointAtTime(double time){
double px = start.getX() + radius * Math.cos(Math.toRadians(time));
double py = start.getY() - radius * Math.sin(Math.toRadians(time));
return new Point2D(px, py);
}
public double getFinalTime() { return 0; }
public CircularPath getClone() { return new CircularPath(start.getClone(), end.getClone()); }
public void update(){
super.update();
radius = normalToEnd.getLength();
}
public void render(Graphics2D g2d){
super.render(g2d);
g2d.drawLine((int)start.getX(), (int)start.getY(), (int)end.getX(), (int)end.getY());
//g2d.drawOval((int)(start.getX() - radius), (int)(start.getY() - radius), (int)radius * 2, (int)radius * 2);
}
}
x = r * cos(t/r)
y = r * sin(t/r)
The other solution is to model 2d momentum and impose a "gravitational force" toward the center point (or ellipsoidal focus, more generally) that you want the moving object to orbit around.
(The classic Space Wars game was implemented on a machine too slow to handle the trig computations in realtime, so they precomputed a 2d array each for the x and y components of the gravity field; they could then just do a table lookup based on the ship's last position and use that to update its momentum, which was then used to update its position. Slower machines forced more clever solutions.)

LibGDX render and update calling speed

In the ApplicationAdapter class, I override the render() method and draws my game from there.
I also have an own method: update() inside the render method which is where I want to update everything.
The render() method is as I know called ~60 times a second.
I dont want my update method to be dependent on how many times the render method is called.
I want the render method to render as much as the device can handle below 60 FPS.
I also want the update method to get called at a fixed rate: 60 times a second.
I´ve tried to call my update method 60 times a second in my render method like this:
double beforeMillis;
double FPS=4; //test
double millisPassed=0;
int x=0;
#Override
public void render () {
beforeMillis=System.currentTimeMillis();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(tex, x, 10);
batch.end();
millisPassed+=(System.currentTimeMillis()-beforeMillis);
if(millisPassed>=1000/FPS){
update();
millisPassed=0;
}
}
...but it updates like once every four seconds.
Any good way of doing this? Thanks in advance!
The code you posted won't compare accurate time, because it ignores all the time spent doing things between batch.end() and the next call to render(), some of which occurs in the libgdx backend. And if you update after drawing in the render method, you will always have at least one visual frame of lag.
A basic implementation of a fixed timestep update in libgdx would be like this:
static final double DT = 1/60.0;
static final int MAX_UPDATES_PER_FRAME = 3; //for preventing spiral of death
private long currentTimeMillis;
public void create() {
currentTimeMillis = System.currentTimeMillis();
}
public void render() {
long newTimeMillis = System.currentTimeMillis();
float frameTimeSeconds = (newTimeMillis - currentTimeMillis) / 1000f;
currentTimeMillis = newTimeMillis;
int updateCount = 0;
while (frameTimeSeconds > 0f && updateCount <= MAX_UPDATES_PER_FRAME) {
float deltaTimeSeconds = Math.min(frameTimeSeconds, DT);
update(deltaTimeSeconds);
frameTimeSeconds -= deltaTimeSeconds;
++updateCount;
}
draw();
}
This does result in update occurring more than 60 times a second, because it gets updated with the "leftovers" to keep the visuals current (no stuttering). The update(float delta) method must be designed to use a variable delta time.
You can do a truly fixed update as described here in the last two sections, but that has the disadvantage of visual stuttering or needing to implement a one-frame delay and interpolating ahead.

derive the trajectory by a vector with libgdx?

Hello everyone ,
I am developing a game where two points, one is A, and the other is B , the point A is a cannon and the other is the point where there is a touch of the user.
how can I do to get the line , say infinite to proceed with the bullet starting from point A ?
My math skills are a bit scarce : /
Someone who can recommend a way to do it with libgdx / java ?
You need the vector position of B minus the vector position of A, which will give the vector pointing from A to B. Try having a read through this, a basic knowledge of vectors is indispensible if you are going to be making games
To represent state, you can use something like following.
public class Bullet extends Actor {
private Vector2 position;
private Vector2 velocity;
public Bullet(Vector2 position, Vector2 velocity) {
this.position = position;
this.velocity = velocity;
}
#Override
public void act(float delta) {
super.act(delta);
// Since newPosition = oldPosition + velocity * time elapsed
this.position.mulAdd(this.velocity, delta / 1000);
}
// Override draw method to handle rendering.
}
Now, you can initialize a new Bullet at each touch event (or whenever you wish)
Bullet createBullet(Vector2 canonPosition, Vector2 touchPosition) {
return new Bullet(canonPosition.cpy(), //Initial position of bullet.
touchPosition.sub(canonPosition).nor()); // Velocity
}
Now just add the Bullet to the stage and have fun.
Hope this helps.
Good luck.

Categories