com.badlogic.gdx.utils.Array OR java ArrayList ? Performance

Hey guys!!
I have a question, which should i use in libgdx projects?
arrows = new com.badlogic.gdx.utils.Array();
or ArrayList from java?

Im having performance issues… And i think it started after i changed that but idk if i should change everything again…

Could you explain some more about the performance issues?

I don’t know what does the libgdx array does, but if you just want to use it like ArrayList, just use ArrayList.

Gdx Array exists to replace ArrayList. Same with their other collection utils. They are marginally faster and tend to use less allocations. It’s a non-issue on desktop since the performance differences are negligible. On mobile the performance differences are still pretty minor, relatively speaking. In either case it’s probably not the cause of your slowdown.

Alright! I will create a new topic explaining everything :stuck_out_tongue:

No don’t make a new topic just for that. Just ask here.

Use Gaplist

Also, to find the source of you performance issues, use JVisualVM.

One of the problems that i face is when i shoot arrows, things go way slower.
In desktop its ok, but in my android… jesus… It goes slow.

Video of Profile Analyzer of Netbeans

And here are the Arrow Classes…

package br.weapons;

import br.enemies_aux.SmokeEffect;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public class Arrow {

    private static int xVertice = -1;

    public int type_Arrow;
    public int posX, posY, shotPosX;
    public int damage;
    public double shotAngle, movingAngle;
    public Sprite sprite;
    public int manaWaste = 0;

    public int shotToQuadrant = -1;

    public double frameTime;

    public Vector3 touch;
    public Vector2 vector;

    public boolean isInsideWindow;

    public boolean hit = false;
    public boolean toRemoveThis = false;
    public SmokeEffect smokeEffect;

    private TiledMapTileLayer.Cell Cell_Temp;

    public Arrow(double posX, double posY, double angle, int quadrant) {
        shotPosX = (int) posX;

        this.posX = (int) posX;
        this.posY = (int) posY;
        this.shotAngle = angle;

        frameTime = 0;
        isInsideWindow = true;

        smokeEffect = new SmokeEffect();
        damage = 0;
        shotToQuadrant = quadrant;
        touch = new Vector3();
        vector = new Vector2();
        //System.out.println("Shot To Quadrant : " + shotToQuadrant);
    }

    public void render(SpriteBatch sb) {
        if (hit) {
            smokeEffect.render(sb, posX, posY);
            if (smokeEffect.isFinished()) {
                toRemoveThis = true;
            }
        } else {
            if (toRemoveThis == false) {
                //System.out.println("Sprite Rotation" + (float) toDegrees(shotAngle));

                sprite.setPosition(posX, posY);
                sprite.draw(sb);

            }
        }
    }

    public void update(TiledMapTileLayer collisionLayer, Camera camera) {
        if (hit == false) {

            lookNearbyCells(collisionLayer);

            posX = (int) ArrowBallistic.getSX(posX, posY, ArrowBallistic.vo, ArrowBallistic.gravity, shotAngle, frameTime);
            posY = (int) ArrowBallistic.getSY(posY, ArrowBallistic.vo, ArrowBallistic.gravity, shotAngle, frameTime);

            //Will Fix this soon.
            //movingAngle = ArrowBallistic.getMovingAngle(shotAngle, shotPosX, posX, shotToQuadrant);

            sprite.setRotation((float) Math.toDegrees(shotAngle));

            frameTime += 0.1;    //0.001

            touch.set(posX, posY, 0);
            camera.project(touch);
            vector.set(touch.x, touch.y);

            isInsideWindow = (vector.x > (-Gdx.graphics.getWidth()) && vector.x < (Gdx.graphics.getWidth() * 2)) && (vector.y > (-Gdx.graphics.getHeight()));

            if (!isInsideWindow) {

                toRemoveThis = true;

            }

        }
    }

    public boolean isIsInsideWindow() {
        return isInsideWindow;
    }

    public void lookNearbyCells(TiledMapTileLayer collisionLayer) {

        boolean blocked = false;
        boolean slope = false;

        for (int i = 0; i < 3; i++) {
            Cell_Temp = collisionLayer.getCell((int) (((posX + ((sprite.getWidth() / 2) * i)) / 16)), (int) (((posY + ((sprite.getHeight() / 2) * i)) / 16)));

            if (Cell_Temp != null) {
                blocked = Cell_Temp.getTile().getProperties().containsKey(ArrowInfo.BLOCKED);
                slope = Cell_Temp.getTile().getProperties().containsKey(ArrowInfo.SLOPED);
                if (blocked || slope) {
                    toRemoveThis = true;
                }

            }

            for (int j = 0; j < 3; j++) {
                Cell_Temp = collisionLayer.getCell((int) (((posX + ((sprite.getWidth() / 2) * i)) / 16)), (int) (((posY + ((sprite.getHeight() / 2) * j)) / 16)));
                if (Cell_Temp != null) {
                    blocked = Cell_Temp.getTile().getProperties().containsKey(ArrowInfo.BLOCKED);
                    slope = Cell_Temp.getTile().getProperties().containsKey(ArrowInfo.SLOPED);

                    if (blocked || slope) {
                        toRemoveThis = true;
                    }
                }
            }
        }
    }

    public boolean isToRemoveThis() {
        return toRemoveThis;
    }

    public void setArrowHitSomething() {
        hit = true;
    }

    public Rectangle getFrameRectangle() {
        Rectangle frameRectangle = new Rectangle();

        frameRectangle.height = sprite.getRegionHeight();
        frameRectangle.width = sprite.getRegionWidth();

        frameRectangle.x = posX;
        frameRectangle.y = posY;

        return frameRectangle;
    }

    public void dispose() {
        smokeEffect.dispose();

    }

}

package br.weapons.arrows;

import br.dir.DirectoriesWeapons;
import br.weapons.Arrow;
import br.weapons.ArrowInfo;
import com.badlogic.gdx.math.Rectangle;
import static java.lang.Math.toDegrees;

public class LightArrow extends Arrow {

    public LightArrow(double posX, double posY, double angle, int quadrant) {
        super(posX, posY, angle, quadrant);
        damage = 20;
        type_Arrow = ArrowInfo.light_Arrow;

        DirectoriesWeapons directoriesWeapons = new DirectoriesWeapons();
        sprite = directoriesWeapons.getLightArrow();

        sprite.setRotation((float) toDegrees(shotAngle));
        directoriesWeapons = null;
    }

    @Override
    public Rectangle getFrameRectangle() {
        Rectangle frameRectangle = new Rectangle();

        frameRectangle.width = 40;
        frameRectangle.height = 6;

        frameRectangle.x = posX;
        frameRectangle.y = posY;

        return frameRectangle;
    }

    @Override
    public void dispose() {
        try {

            sprite.getTexture().dispose();
            smokeEffect.setFinished();
            smokeEffect.dispose();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

}

World Update

 public void updateAndRenderArrows(SpriteBatch spriteBatch, float delta) {

        camera = current_Level.camera;
        for (int i = 0; i < arrows.size; i++) {
            Arrow arrow_TEMP = arrows.get(i);

            for (int k = 0; k < enemies.size; k++) {
                if (!arrow_TEMP.hit) {
                    Rectangle arrowRect = arrow_TEMP.getFrameRectangle();
                    Rectangle enemyRect = enemies.get(k).getFrameRectangle();

                    if (arrowRect.overlaps(enemyRect)) {
                        enemies.get(k).beingHit(arrow_TEMP.damage);
                        arrow_TEMP.setArrowHitSomething();
                    }
                }
            }

            if (!arrow_TEMP.isToRemoveThis()) {
                arrow_TEMP.update(collisionLayer, camera);
                arrow_TEMP.render(spriteBatch);

            } else {

                arrows.removeIndex(i);
                arrow_TEMP.dispose();
                arrow_TEMP = null;

            }

        }
    }

Do you update with the delta time?

Not really.Should i ? Im really confused, its my first game,so im sorry in advance.
Any suggestions , i will try them!
Should i use delta? How should i insert it? I feel the ArrowBallistic is not perfect plus, the music plays without lag, so im thinking its just the arrows not moving fast enough…

Heres the ArrowBallistic…

package br.weapons;

/**
 *
 */
public class ArrowBallistic {

    private static int normal = 1; //TEST
    public static double vo = 20 / normal;
    public static double gravity = 2 / normal;

    public static int FIRST_QUADRANT = 1;
    public static int SECOND_QUADRANT = 2;
    public static int THIRD_QUADRANT = 3;
    public static int FOURTH_QUADRANT = 4;

    private static double atan = 0;
    private static double dx, dy;

    public static double getAngle(double posXplayer, double xClick, double posYPlayer, double yClick) {

        if (xClick < posXplayer && yClick < posYPlayer) {
            atan = Math.PI + (Math.atan((posYPlayer - yClick) / (posXplayer - xClick)));
        } else if (xClick >= posXplayer && yClick >= posYPlayer) {

            atan = Math.atan((posYPlayer - yClick) / (posXplayer - xClick));
        } else if (xClick < posXplayer && yClick >= posYPlayer) {

            atan = Math.PI - (Math.atan((yClick - posYPlayer) / (posXplayer - xClick)));

        } else if (xClick > posXplayer && yClick < posYPlayer) {
            atan = (2 * Math.PI) - (Math.atan((yClick - posYPlayer) / (posXplayer - xClick)));
        } else {
            atan = 0;
        }

        return atan;
    }

    public static double getSX(double xo, double yo, double vo, double gravity, double angle, double time) {
        dx = (xo) + vo * Math.cos(angle) * time;

        return dx;
    }

    public static double getSY(double yo, double vo, double gravity, double angle, double time) {

        dy = yo + vo * (Math.sin(angle) * time) - ((gravity / 2) * (time * time));

        return dy;
    }

    public static double getMovingAngle(double angle, double xo, double sx, int shotToQuadrant) {

        double tanO = 0;

        if (shotToQuadrant == FIRST_QUADRANT) {
            tanO = Math.atan(Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo));
        } else if (shotToQuadrant == SECOND_QUADRANT) {
            tanO = Math.atan(Math.PI / 2 + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        } else if (shotToQuadrant == THIRD_QUADRANT) {
            tanO = Math.atan(Math.PI + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        } else if (shotToQuadrant == FOURTH_QUADRANT) {
            tanO = Math.atan(Math.PI * 2 + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        }

        //Change quadrant Calculations
        if (shotToQuadrant == FIRST_QUADRANT && sx <= getXVertice(angle, gravity, vo, xo, sx)) {
            shotToQuadrant = FOURTH_QUADRANT;
        } else if (shotToQuadrant == SECOND_QUADRANT && sx <= getXVertice(angle, gravity, vo, xo, sx)) {
            shotToQuadrant = THIRD_QUADRANT;
        }

        return tanO;
        
        
        
    }

    public static double getXVertice(double angle, double gravity, double velocity, double xo, double dx) {
        double xv = 0;
        double b = 0;
        double a2 = 0;

        //-b
        b = -((xo * gravity) / ((velocity * velocity) * (Math.cos(angle) * Math.cos(angle))));

        //2a
        a2 = 2 * (-gravity / ((2 * (velocity * velocity)) * Math.cos(angle) * Math.cos(angle)));

        xv = b / a2;

        return xv;
    }

}

Like already mentioned, the kind of collection class is not the problem.

It its probably not the cause of bad performance, but you create way too many rectangles for no reason.

Method lookNearbyCells() is unclear and probably not efficient. Why inspect all surrounding cells each and every time ? Method name does not imply what it does.

Well because i must see if the arrow is hitting a wall :slight_smile:

How should i do it then? Plus the rectangles… How should i make them?

The fps stays in 40~~

Heres how im loading the .tmx

TmxMapLoader.Parameters params = new TmxMapLoader.Parameters();
        params.textureMagFilter = Texture.TextureFilter.Nearest;
        params.textureMinFilter = Texture.TextureFilter.Nearest;
        map = new TmxMapLoader().load("imagens/Levels/One/LevelOne.tmx", params);