After creating a few bodies and a map with collisions, the app performance clearly goes down. However, RAM and CPU don't seem fully stuck, but the game experience is horrible nonetheless.
GameScreen class:
public class GameScreen implements Screen {
Main main;
Joystick joystickL, joystickR;
public static Player player;
public static Array<Bullet> bullets;
public static float angle;
private Text ammo_view;
public static Array<Enemy> enemies;
private TiledMap map;
private OrthogonalTiledMapRenderer mapRenderer;
public static World world;
private Box2DDebugRenderer b2dr;
private HitContactListener hcl = new HitContactListener();
public GameScreen(Main main){
this.main = main;
}
@Override
public void show() {
loadActors();
Gdx.input.setInputProcessor(new InputProcessor() {
@Override
public boolean keyDown(int keycode) {
return false;
}
@Override
public boolean keyUp(int keycode) {
return false;
}
@Override
public boolean keyTyped(char character) {
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenY = (Gdx.graphics.getHeight() - screenY);
multitouch( screenX, screenY, true, pointer);
return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
screenY = (Gdx.graphics.getHeight() - screenY);
multitouch(screenX, screenY, false, pointer);
return false;
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
screenY = (Gdx.graphics.getHeight() - screenY);
multitouch(screenX, screenY, true, pointer);
return false;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
@Override
public boolean scrolled(float amountX, float amountY) {
return false;
}
}
);
}
public void loadActors() {
bullets = new Array<Bullet>();
enemies = new Array<Enemy>();
//MAP
b2dr = new Box2DDebugRenderer();
world = new World(new Vector2(0, 0), false);
world.setContactListener(hcl);
map = new TmxMapLoader().load("map/kartapapka/суперготовая карта.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map, 1.5f);
MapLoader.buildShapes(map.getLayers().get("Obstacles").getObjects(), world);
//PLAYER
player = new Player(Main.mainChar_ak, new Vector2(52.8f, 7.5f).scl(PPM), 7, world);
player.getGun(new Ak(player));
//GRIPS
joystickR = new Joystick(Main.joystickImg, Main.gripImg, new Vector2((float) (Main.WIDTH - (Main.WIDTH * 0.15)), (Main.HEIGHT / 3) / 2 + (Main.HEIGHT / 3) / 4), Main.HEIGHT / 3);
joystickL = new Joystick(Main.joystickImg, Main.gripImg, new Vector2((float)(Main.WIDTH - (Main.WIDTH * 0.85)), (Main.HEIGHT / 3) / 2 + (Main.HEIGHT / 3) / 4), Main.HEIGHT / 3);
//FIRST BULLET TO AVOID SPAWN TROUBLES
bullets.add(new Bullet(new Vector2(), new Vector2(), 0, 0, world));
//world.destroyBody(bullets.get(0).body);
//ENEMIES GENERATION
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(21.6f,27f).scl(PPM), 6, world));
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(61.4f,18f).scl(PPM), 6, world));
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(80.6f,35f).scl(PPM), 6, world));
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(58f, 38.4f).scl(PPM), 6, world));
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(31.5f, 39f).scl(PPM), 6, world));
enemies.add(new Enemy(new Sprite(new Texture(Gdx.files.internal("main_sprites/enemy_handgun.png"))), new Vector2(39.2f, 54f).scl(PPM), 6, world));
//GIVING GUNS TO ENEMIES
for (int i = 0; i < enemies.size; i++) {
enemies.get(i).getGun(new Enemy_handgun(enemies.get(i)));
}
//FONT GENERATION
ammo_view = new Text("fonts/ammo.ttf",(float) Main.WIDTH - 100, (float) Main.HEIGHT - 80);
//ADDING ACTORS
Main.stage.addActor(joystickR);
Main.stage.addActor(joystickL);
Main.stage.addActor(ammo_view);
Main.stage.addActor(fm);
}
@Override
public void render(float delta) {
world.step(1 / 45f, 6, 2);
Gdx.gl.glClearColor(1,0,1,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gameUpdate(delta);
main.shapeRenderer.setProjectionMatrix(main.camera.combined);
main.camera.update();
main.camera.position.set(player.body.getPosition().x * PPM, player.body.getPosition().y * PPM, 0);
//MAP RENDERING
mapRenderer.setView(main.camera);
mapRenderer.render();
b2dr.render(world, new Matrix4(main.camera.combined).scl(PPM));
Main.batch.setProjectionMatrix(main.camera.combined);
Main.batch.begin();
gameRender(Main.batch);
Main.batch.end();
//STAGE DRAW
Main.stage.act(delta);
Main.stage.draw();
main.shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
main.shapeRenderer.setColor(Color.GRAY);
for (int i = 0; i < bullets.size; i++) {
main.shapeRenderer.circle(bullets.get(i).position.x, bullets.get(i).position.y, bullets.get(i).size);
}
main.shapeRenderer.end();
}
@Override
public void resize(int width, int height) {
main.camera.viewportWidth = width;
main.camera.viewportHeight = height;
main.camera.update();
}
@Override
public void dispose() {
map.dispose();
mapRenderer.dispose();
main.dispose();
}
public void gameRender(SpriteBatch batch) {
//PLAYER ROTATION
if (joystickL.direction.angleDeg() != 0) angle = joystickL.direction.angleDeg();
if (joystickR.direction.angleDeg() != 0) angle = joystickR.direction.angleDeg();
player.img.setRotation(angle);
ammo_view.update(player);
//ENEMY ROTATION
for(int i = 0; i < enemies.size; i++) {
enemies.get(i).img.setRotation(enemies.get(i).direction.angleDeg());
enemies.get(i).draw(batch);
}
player.draw(batch);
}
private void sweepDeadBodies() {
Array<Body> bodiesToDestroy = new Array<>(hcl.getBodiesToDestroy());
Set<Body> bodiesToDestroySet = new HashSet<>();
for (Body body : bodiesToDestroy) {
if (body.getUserData() != null && body != null) {
bodiesToDestroySet.add(body);
}
}
//System.out.println(bodiesToDestroySet);
for (Body body : bodiesToDestroySet) {
world.destroyBody(body);
}
}
public void gameUpdate(float delta){
for(int i = 0; i < enemies.size; i++) {
//enemies.get(i).player_detection(player);
enemies.get(i).update();
enemies.get(i).handgun.update(joystickR);
bullets.addAll(enemies.get(i).handgun.getBulletsArray());
}
bullets.addAll(player.gun.getBulletsArray());
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
sweepDeadBodies();
}
});
player.update();
//sc.update();
player.direction.set(joystickL.direction);
player.gun.update(joystickR);
for (int i = 0; i < bullets.size; i++) {
//bullets.get(i).direction.rotateDeg(bullets.get(i).direction.angleDeg() + (float)getRandomDoubleBetweenRange(-10, 10));
bullets.get(i).update();
}
if (player.gun.isFire && player.gun.ammo > 0) {
if (Rumble.getRumbleTimeLeft() > 0){
Rumble.tick(delta);
main.camera.translate(Rumble.getPos());
}
}
hit_detection();
}
private void multitouch(float x, float y, boolean isDownTouched, int pointer) {
for (int i = 0; i < 5; i++) {
joystickL.update(x, y, isDownTouched, pointer);
joystickR.update(x, y, isDownTouched, pointer);
}
}
private void hit_detection() {
for (int j = 0; j < enemies.size; j++) {
for (int i = 0; i < bullets.size; i++) {
//HIT DETECTION
if (bullets.get(i).bounds.overlaps(enemies.get(j).bounds) && enemies.get(j).isAlive) {
bullets.removeIndex(i--);
enemies.get(j).die();
}
}
}
}
}
I want to increase efficiency or follow any other suggestions. I can append any other classes, if necessary.
hit_detection
function. Doing checks in O(n^2) like that may be very inefficient compared to using a better spacial partition approach. Also, I don't know how this works in details in Java, but removing the bullets the way it is done now may cause another performance issue; in c++ you would swap the object to remove with the last object in the vector, then you'd remove it from the last position; this avoid having to shift all the objects repeatedly. \$\endgroup\$