libgdx – Java Efficient way to reduce a vector’s value gradually until it reaches 0,0

I can manage to achieve this but the code seems to be much longer than it should be. Velocity is given an initial value, either positive or negative and then is gradually reduced until it is 0,0.

Vector2 velocity = new Vector2(4,-3);
private float decSpeed = .2f;

public void update(float delta) {
velocity.x = setVel(velocity.x);
velocity.y = setVel(velocity.y);
}


private float setVel(float vel) {
    if (vel > 0) {
        if (vel - decSpeed <= 0)
            vel = 0;
        else
            vel -= decSpeed;
    } else if (vel < 0)
        if (vel + decSpeed >= 0)
            vel = 0;
        else
            vel += decSpeed;
    return vel;
}

I simply want to decrease the vector value for both x and y by a fixed amount, but of course you have to take into account that the vector can be either positive or negative.

java – (LibGDX) Set actor to fixed position on TiledMap

How can I set an actor to an absolute / fixed position on my TiledMap, such that it does not follow the camera when I pan around?enter image description here

enter image description here

Currently my code looks like:

camera = new OrthographicCamera();
rootGroup = new Group();

castleMap = new TmxMapLoader().load("castleMap.tmx");
isoMapRenderer = new IsometricTiledMapRenderer(castleMap, 1/32f);

...

final FitViewport fitViewport = new FitViewport(worldWidth, worldHeight);
stage = new Stage(fitViewport);
rootGroup.setSize(stage.getWidth(), stage.getHeight());
stage.addActor(rootGroup);

barracks = new Barracks(barracksIcon, self);
rootGroup.addActor(barracks);

From there, whether I try to position the barracks actor using

barracks.setPosition(x, y);

or using

Vector2 vector = new Vector2(x, y);
vector = stage.screenToStageCoordinates(vector);
vector = rootGroup.stageToLocalCoordinates(vector);
barracks.setPosition(vector.x, vector.y);

I get the same result.

I emphatically do not want to use Tables.

Thanks in advance!

java – How to make camera move with the player in 3D Libgdx

Iam trying to create a 3D game in Libgdx, so I created a 3d World with physics, and added just a small terrain and capulse (the Player) .

I want to make the game first person, so I created a player class and managed to move the player (Capulse) by joystick.

Like this :-

@Override
    public void create() {
        // load enviroment
        environment = new Environment();
        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
        environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
        // setup camera
        cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        cam.position.set(10f, 10f, 10f);
        cam.lookAt(0, 0, 0);
        cam.near = 0.001f;
        cam.far = 3000f;
        cam.update();
        // setup controller for camera
        camController = new CameraInputController(cam);
        Gdx.input.setInputProcessor(camController);
        // load the models
        assets = new AssetManager();
        assets.load("ground_stairs.g3db", Model.class);
        assets.load("gathering_node.g3db", Model.class);
        loading = true;
        modelBatch = new ModelBatch();

        // setup bulletphysics
        Bullet.init();
        collisionConfig = new btDefaultCollisionConfiguration();
        dispatcher = new btCollisionDispatcher(collisionConfig);
        broadphase = new btDbvtBroadphase();
        constraintSolver = new btSequentialImpulseConstraintSolver();
        dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);
        dynamicsWorld.setGravity(new Vector3(0, -10f, 0));
        contactListener = new MyContactListener();
        loadPlayer();
        
    }

    private void loadPlayer() {
     
        // setup player/camera movement
        pc = new PlayerController(instances,cam,dynamicsWorld);
    }

    private void doneLoading() {
        loading = false;
        onDoneLoadingStatic("ground_stairs.g3db", GROUND);
        onDoneLoadingStatic("gathering_node.g3db", GATHERING_NODE);
        gatheringNode = instances.get(instances.size() - 1);
    }

    public btRigidBody onDoneLoadingStatic(String fileName, int id) {
        Model model = assets.get(fileName, Model.class);
        ModelInstance instance = new ModelInstance(model);
        instances.add(instance);

        btBvhTriangleMeshShape shape = new btBvhTriangleMeshShape(instance.model.meshParts);
        btRigidBody body = new btRigidBody(0, null, shape, new Vector3(0, 0, 0));
        body.proceedToTransform(instance.transform);
        // set id to find with collision detection
        body.setUserValue(id);
        dynamicsWorld.addRigidBody(body);
        
        return body;
    }

    @Override
    public void render() {
        if (loading && assets.update()) {
            doneLoading();
        }
        camController.update();

        pc.update();
       
        
        final float delta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
        dynamicsWorld.stepSimulation(delta, 5, 1f / 60f);

        
        Gdx.gl20.glClearColor(0, 0.5f, 1, 1);
        Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        modelBatch.begin(cam);
        modelBatch.render(instances, environment);
        modelBatch.end();
    }

    @Override
    public void dispose() {
        modelBatch.dispose();
    }

    

    private class MyContactListener extends ContactListener {

        @Override
        public void onContactStarted(int userValue0, int userValue1) {
            if (userValue0 == PLAYER && userValue1 == GATHERING_NODE) {
                ((ColorAttribute) gatheringNode.materials.first().get(ColorAttribute.Diffuse)).color.set(Color.RED);
            }
            if (userValue0 == PLAYER && userValue1 == GROUND) {
                PlayerController.canJump = true;
            }
        }

        @Override
        public void onContactEnded(int userValue0, int userValue1) {
            if (userValue0 == PLAYER && userValue1 == GATHERING_NODE) {
                ((ColorAttribute) gatheringNode.materials.first().get(ColorAttribute.Diffuse)).color.set(Color.BLUE);
            }
        }
    }
}




PlayerController

public class PlayerController
 {
    private btRigidBody playerBody;
    private ModelInstance player;
    private float speed = 1f;
    public static boolean canJump = true;
    private PerspectiveCamera cam;
    private List<ModelInstance> instances = new ArrayList<ModelInstance>();
    private static final int PLAYER = 1;
    public static float xposition;
    public static float yposition;
    private btDynamicsWorld dynamicsWorld;
    public static float angleX;
    
    public PlayerController(List<ModelInstance> instances,PerspectiveCamera cam,btDynamicsWorld dynamicWorld) {
        this.instances = instances;
        this.cam = cam;
        this.dynamicsWorld = dynamicWorld;
        
        player = new ModelInstance(new ModelBuilder()
                                   .createCapsule(0.25f, 3, 10, new Material(ColorAttribute.createAmbient(Color.BLACK)), Usage.Normal | Usage.Position)
                                   );
        player.transform.translate(5, 7, 0);
        instances.add(player);
        // load player rigid body
        btCapsuleShape playerShape = new btCapsuleShape(0.25f, 2.5f);
        float mass = 10;
        Vector3 localInertia = new Vector3();
        playerShape.calculateLocalInertia(mass, localInertia);
        playerBody = new btRigidBody(mass, null, playerShape, localInertia);
        playerBody.proceedToTransform(player.transform);
        playerBody.setCollisionFlags(playerBody.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
        // set id to find with collision detection
        playerBody.setUserValue(PLAYER);
        dynamicsWorld.addRigidBody(playerBody);
        
        
    }

    public void update() {
        // make sure to activate the player body so bullet doesnt put it to sleep
        playerBody.activate();
        // prevent the capsule from falling over
        playerBody.setAngularFactor(new Vector3(0, 0, 0));
        playerBody.getWorldTransform(player.transform);
        
        
        Vector3 velocity = new Vector3(0, playerBody.getLinearVelocity().y, 0);
        velocity.x = xposition;
        velocity.z = yposition;
        player.transform.rotate(Vector3.Y,angleX);
        
        
        cam.update();
        
        playerBody.setLinearVelocity(velocity);
        

    }
}

And this is the output :-

the Player move perfectly with joystick

Now I want the camera to be at the top of the player (the Capulse) , and move with the player, so I added this

cam.position.add(velocity);

In update method in PlayerController

And this the output : just a blue screen
So, my question how to make the camera move we it the player like first person?

enter image description here

Libgdx – How to set labels on the same “Line”?

I have a code snippet like:

    float sw = Gdx.graphics.getWidth();
    float sh = Gdx.graphics.getHeight();

    float cw = sw * 0.7f;
    float ch = sh * 0.5f;

    tableContainer.setSize(cw, ch);
    tableContainer.setPosition((sw - cw) / 2.0f, (sh - ch) / 2.0f);
    tableContainer.fillX();

    Table table = new Table(skin);

    Label topLabel = new Label("PREFERENCES", skin);
    Label levelLabel = new Label("LEVEL", skin);
    Label thirdLabel = new Label("number of robots", skin);
    Label forthLabel = new Label("max. health", skin);
    Label fifthLabel = new Label("max. energy", skin);
    Label sixthLabel = new Label("rocket impact", skin);
    
    topLabel.setAlignment(Align.center);
    //levelLabel.setAlignment(Align.center);
    
    Slider slider = new Slider(0, 100, 1, false, skin);
    
    Label robotLabel = new Label("ROBOT", skin);
    //robotLabel.setAlignment(Align.center);

    Table buttonTable = new Table(skin);

    TextButton buttonA = new TextButton("ACCEPT", skin);
    TextButton buttonB = new TextButton("CANCEL", skin);

    table.row().colspan(3).expandX().fillX();
    table.add(topLabel).align(Align.center).padBottom(100f);
    table.row().colspan(3).expandX().fillX();
    table.add(levelLabel).align(Align.center).padBottom(20f);
    table.row().colspan(3).expandX().fillX();
    table.row();
    table.add(thirdLabel);
    table.add(blaSlider).width(100);
    table.add(volumeValue).width(40);
    table.row().colspan(3).expandX().fillX();
    table.add(robotLabel).align(Align.center).padBottom(20f).padTop(80f);
    table.row();
    table.add(forthLabel);
    table.add(healthSlider).width(100);
    table.add(volumeHealthValue).width(40);
    table.row().colspan(3).expandX().fillX();
    table.row();
    table.add(fifthLabel);
    table.add(energySlider).width(100);
    table.add(volumeEnergyValue).width(40);
    table.row().colspan(3).expandX().fillX();
    table.row();
    table.add(sixthLabel);
    table.add(rocketSlider).width(100);
    table.add(volumeRocketValue).width(40);
    table.row().colspan(3).expandX().fillX();
    table.row().expandX().fillX();
    table.add(buttonTable).colspan(3).padTop(80f);

    buttonTable.pad(16);
    buttonTable.row().fillX().expandX();
    buttonTable.add(buttonA).width(cw/3.0f);
    buttonTable.add(buttonB).width(cw/3.0f);

    tableContainer.setActor(table);
    stage.addActor(tableContainer);

    Gdx.input.setInputProcessor(stage);

And what I get is:

enter image description here

as you can see,
max. health, max. energy, and the number of robots are not in the same “Line”.

I want, that the alignment will be the same for the labels, like it is for the “number of robots”.

Does anyone has an idea how to fix it?

Thanks

java – LibGDX Change mouse cursor to custom image……and keep it there

I’m able to create a custom cursor no problem using the following code running in my GameScreen’s Show method:

Pixmap pixmap = new Pixmap(Gdx.files.internal("ui/cursor.png"));
Cursor cursor = Gdx.graphics.newCursor(pixmap, pixmap.getWidth() / 2, pixmap.getHeight() / 2);
Gdx.graphics.setCursor(cursor);
pixmap.dispose();

The problem is…if I deselect the game window and return back…the cursor has returned back to the default one. At least that happens for me on Mac desktop. If I move the cursor out of the screen (without deselecting) and then back again I get the custom cursor image back but I don’t think people would know to do that.

But after searching I couldn’t find any way for LibGDX to detect when the game window is deselected? I thought I would be able to find that since it would seem useful for something like automatically pausing when deselecting the game window and such.

That would seem to be the way to reset the cursor every time returning to the game window, unless there’s some other way to make it more permanent?

java – Libgdx how to resize game screen without flickering?

My top down shooter game works in any resolution that results in exact pixels like 1200×800 or 1800×1200 without flicker. With zoom 0.25, 0.5 and 1 it is also fine since that will still yield whole pixels. But if I make it full screen then it has to be the resolution of my monitor which is not so exact. When zoomed in there is obvious flickering on the textures as the player and camera move.

When setting to full screen, everything is enlarged rather than just revealing more of the map, which is how it should be, but causes flicker when moving about the map.

public GameScreen(Game game) {
vp = new FitViewport(1200, 800, cam);
etc

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.setProjectionMatrix(cam.combined);
    batch.begin();
    rendup.renderAll(batch, control.grid);
    batch.end();

@Override
public void resize(int width, int height) {
    cam.viewportWidth = width;
    cam.viewportHeight = height;
    vp.update(width, height);
}

To be clear, I’m not talking about the lines you get around tiles since I have padding which solved that. I downloaded many other LibGDX games and noticed most also have this problem, but there were notably several that didn’t…so there must be a way around it.

I tried making the player’s speed, position and camera position all pixel perfect but surprisingly that made no difference. It must be something else.

networking – Smoke-Testing (BVT) for libgdx games?

I’m wondering how to test my client server game or how to test games in general.

Currently I’m able to run unit tests using https://github.com/TomGrill/gdx-testing but I thing most of the critical parts in my game are the interactions of a of different ECS systems.

So I thing the best approach would be using a smoke tests-system (aka Build Verification Testing). But I’m not sure and I have no idea how to realize something like that.

There is an article from Riot Games about how they will do testing in LOL-Game. They will use RPC calls to control the game.
Is this the way how to implement smoke-tests for network-games in libgdx?

Best way to make a Side Panel UI with Libgdx? (Java)

Take this image for example, the game is called Realm of the mad god, and it has this side panel filling the whole screen height with the player info.

To reproduce it, Is there any way to make the game “view” smaller so I can fit the side panel to its right without literally overlaying the game, PROBABLY like this game did, or is the only way out to overlay the game?

(Tibia might also be an example of a game smaller then its UI)

Side Panel example

libgdx – How to use multiple animations?

convert an animated model:

3dsMax(CAT) -> Export FBX -> fbx-conv -> model.g3dj

my code:

...
val model = modelLoader.loadModel(Gdx.files.getFileHandle("model.g3dj", Files.FileType.Internal))
val modelInstance = ModelInstance(model)
val controller = AnimationController(modelInstance)
controller.setAnimation("Take 001", -1, 0.5f, null)
...

docs:

setAnimation(java.lang.String animationId)

Set the active animation, replacing any current animation.

How to set animationId in the source file (FBX) ?

my research:

model.g3dj

{…, animation: { id: ‘Take 001’, … } }

format: https://github.com/libgdx/fbx-conv/wiki/Version-0.2-%28draft%29

model.fbx

AnimationStack ‘Take 001’

format: http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=files/GUID-E5C89F5F-09D1-4C32-BA83-28F63D0B2A6C.htm,topicNumber=d30e11661

my question: How to set AnimationStack.name in 3dsMax?

https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2017/ENU/3DSMax/files/GUID-26323F8D-3CC2-4918-A60D-C9D6C558584E-htm.html

enter image description here

enter image description here

libgdx – Java LERP but with integer values

I have a formula which returns a Lerp Vector3 value in integers but the problem is it never reaches the desired target value. It’s converting to pixel values first by multiplying by PPM which is float 32f.

private Vector3 lerp(final Vector3 source, final Vector3 target, float alpha) {
    Vector3 sourcePPM = new Vector3(source.x * PPM, source.y * PPM, 0);
    Vector3 targetPPM = new Vector3(target.x * PPM, target.y * PPM, 0);
    sourcePPM.x += Math.round(alpha * (targetPPM.x - sourcePPM.x));
    sourcePPM.y += Math.round(alpha * (targetPPM.y - sourcePPM.y));
    source.x = sourcePPM.x / PPM;
    source.y = sourcePPM.y / PPM;
    source.z = 0;
    return source;
}

So for example with lerp(new Vector3(0.0, 0.0, 0.0), new Vector3(26.0, 29.0, 0.0), 0.06f), the final result is:

Target destination: (26.0,29.0,0.0)
Actual final destination: (25.75,28.75,0.0)

Falling short of the target destination. If I don’t round the values then it gets there fine but I need it to be in whole pixels.

The final line of intermediate values (too many to add all of them):

(25.0,27.90625,0.0)
(25.0625,27.96875,0.0)
(25.125,28.03125,0.0)
(25.1875,28.09375,0.0)
(25.25,28.15625,0.0)
(25.28125,28.21875,0.0)
(25.3125,28.28125,0.0)
(25.34375,28.3125,0.0)
(25.375,28.34375,0.0)
(25.40625,28.375,0.0)
(25.4375,28.40625,0.0)
(25.46875,28.4375,0.0)
(25.5,28.46875,0.0)
(25.53125,28.5,0.0)
(25.5625,28.53125,0.0)
(25.59375,28.5625,0.0)
(25.625,28.59375,0.0)
(25.65625,28.625,0.0)
(25.6875,28.65625,0.0)
(25.71875,28.6875,0.0)
(25.75,28.71875,0.0)
(25.75,28.75,0.0)