LibGDX - bad FPS

Hey guys,

I’m trying to learn more about LibGDX, Slick2D and LWJGL. To compare those 3, I’ve done my own Snake-Game with own graphics and so on.
Slick2D works fine. And in generally in LibGDX it works finde, too… But i’ve done some tests with big snakes… And the FPS with LibGDX goes down with a Snake-size over 280. It goes down to 20!
Is it because of bad code?
To compare it to my Slick2D project, it is fast til snake size of 1600!

Here is my Code for the GameScreen in which the snake is drawn

package com.mygdx.view;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.mygdx.game.Snake2D;
import com.mygdx.model.Food;
import com.mygdx.model.Highscore;
import com.mygdx.model.Snake;
import com.mygdx.model.Body;

public class GameScreen implements Screen{
	private Snake2D game;
	
	CharSequence string;
	
	private Highscore hs;
	private Snake snake;
	private Food food;
	public int points;
	private float time;
	private float multi;
	private String name;
	private int richtung; // 0 = Rechts , 1 = Runter, 2 = Links, 3 = Hoch
	
	public GameScreen(Snake2D game, String name){
		this.game = game;
		
		hs = new Highscore();
		
		this.name = name;

		time = 0;
		multi = (float) 1.25;
		
		richtung = 0;
		points = 0;
		
		//Schlange und Essen initialisieren
		snake = new Snake();
		food = new Food();
	
		game.font.setColor(Color.BLACK);
	}

	@Override
	public void show() {

		
	}

	@Override
	public void render(float delta) {
		//Update part
		time += delta;
		time *= multi;
		if(snake.getSnake().get(0).getTangle().overlaps(food.getFood())){
			food = new Food();
			points += 10;
			if(snake.getSnake().size() % 3 == 0){
				multi += 0.025;
			}
		}
		if(time >= 1){
			if(richtung == 0){
				snake.snakeRight(food);
			}
			else if(richtung == 1){
				snake.snakeDown(food);
			}
			else if(richtung == 2){
				snake.snakeLeft(food);
			}
			else{
				snake.snakeUp(food);
			}
			time = 0;
		}
		
		testOver();
		
		handleInput();
		
		//Render Part
		for(Body b: snake.getSnake()){
			game.batch.begin();
			game.font.draw(game.batch,"Punkte: "+points, Gdx.graphics.getWidth()-100, Gdx.graphics.getHeight()-10);
			game.font.draw(game.batch,"FPS: " + Gdx.graphics.getFramesPerSecond(), 100, Gdx.graphics.getHeight()-10);
			game.batch.draw(b.getImg(),b.getTangle().getX(), b.getTangle().getY());
			game.batch.draw(food.getImg(), food.getFood().getX(), food.getFood().getY());
			game.batch.end();
		}
		
	}

	@Override
	public void resize(int width, int height) {
		
	}

	@Override
	public void pause() {
		
	}

	@Override
	public void resume() {
	
	}

	@Override
	public void hide() {
		
	}

	@Override
	public void dispose() {
		for(Body b : snake.getSnake()){
			b.getImg().dispose();
		}
		hs.addScore(name, points);
		game.setScreen(new HighscoreScreen(game));
	}
	
	public void handleInput() {
		if(Gdx.input.isKeyJustPressed(Keys.UP) && richtung != 1){
			richtung = 3;
		}
		if(Gdx.input.isKeyJustPressed(Keys.RIGHT) && richtung != 2){
			richtung = 0;
		}
		if(Gdx.input.isKeyJustPressed(Keys.DOWN) && richtung != 3){
			richtung = 1;
		}
		if(Gdx.input.isKeyJustPressed(Keys.LEFT) && richtung != 0){
			richtung = 2;
		}
		if(Gdx.input.isKeyJustPressed(Keys.ESCAPE)){
			game.setScreen(new MenuScreen(game));
		}	
	}
	
	public void testOver(){
		for(int i = 1; i < snake.getSnake().size(); i++){
			if(snake.getSnake().get(0).getTangle().overlaps(snake.getSnake().get(i).getTangle())){
				if(name != null){
					dispose();
				}
			}
		}
		if(snake.getSnake().get(0).getTangle().getX() >= 600 || snake.getSnake().get(0).getTangle().getX() < 0){
			if(name != null){
				dispose();
			}
		}
		if(snake.getSnake().get(0).getTangle().getY() >= 4600 || snake.getSnake().get(0).getTangle().getY() < 0){
			if(name != null){
				dispose();
			}
		}
	}

}

This is my Snake class.

package com.mygdx.model;

import java.util.ArrayList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;

public class Snake {
	
	private ArrayList<Body> snake;
	private Texture headR, headL, headO, headU, body;
	
	public Snake(){
		snake = new ArrayList<Body>();
		headR = new Texture(Gdx.files.internal("Schlangenkopf.png"));
		headL = new Texture(Gdx.files.internal("SchlangenkopfL.png"));
		headU = new Texture(Gdx.files.internal("SchlangenkopfU.png"));
		headO = new Texture(Gdx.files.internal("SchlangenkopfO.png"));
		body = new Texture(Gdx.files.internal("Snakebody.png"));
		Rectangle one = new Rectangle(20,Gdx.graphics.getHeight()/2,10,10);
		Rectangle two = new Rectangle(10,Gdx.graphics.getHeight()/2,10,10);
		
		snake.add(new Body(one,one.getX(), one.getY(), headR));
		snake.add(new Body(two,two.getX(), two.getY(), body));
	}
	
	public void snakeRight(Food food){
		//Dem Kopf das richtige Bild zuweisen
		snake.get(0).setImg(headR);
		//Die alte X Position speichern, für die nachfolgenden Teile
		snake.get(0).setOldX(snake.get(0).getTangle().getX());
		snake.get(0).setOldY(snake.get(0).getTangle().getY());
		snake.get(0).getTangle().setX(snake.get(0).getTangle().getX()+10);
		testAdd(food);
		snakeVor();
	}
	
	public void snakeLeft(Food food){
		snake.get(0).setImg(headL);
		snake.get(0).setOldX(snake.get(0).getTangle().getX());
		snake.get(0).setOldY(snake.get(0).getTangle().getY());
		snake.get(0).getTangle().setX(snake.get(0).getTangle().getX()-10);
		testAdd(food);
		snakeVor();
	}
	
	public void snakeUp(Food food){
		snake.get(0).setImg(headO);
		snake.get(0).setOldX(snake.get(0).getTangle().getX());
		snake.get(0).setOldY(snake.get(0).getTangle().getY());
		snake.get(0).getTangle().setY(snake.get(0).getTangle().getY()+10);
		testAdd(food);
		snakeVor();
	}
	
	public void snakeDown(Food food){
		snake.get(0).setImg(headU);
		snake.get(0).setOldX(snake.get(0).getTangle().getX());
		snake.get(0).setOldY(snake.get(0).getTangle().getY());
		snake.get(0).getTangle().setY(snake.get(0).getTangle().getY()-10);
		testAdd(food);
		snakeVor();
	}
	
	public void snakeVor(){
		for(int i=1; i < snake.size();i++){
			snake.get(i).setOldX(snake.get(i).getTangle().getX());
			snake.get(i).setOldY(snake.get(i).getTangle().getY());
			snake.get(i).getTangle().setX(snake.get(i-1).getOldX());
			snake.get(i).getTangle().setY(snake.get(i-1).getOldY());
		}
	}
	
	public void testAdd(Food food){
		if(snake.get(0).getTangle().overlaps((food.getFood())) || snake.size() < 800){
			Rectangle tangle = new Rectangle(snake.get(snake.size()-1).getTangle().getX(), snake.get(snake.size()-1).getTangle().getY(),10,10);
			snake.add(new Body(tangle,tangle.getX(),tangle.getY(), body));
		}
	}
	
	public ArrayList<Body> getSnake() {
		return snake;
	}

	public void setSnake(ArrayList<Body> snake) {
		this.snake = snake;
	}

}

Sorry for my bad english. Maybe you’ll see some “german words” in my comments. It’s because I’m from germany :wink: Hope you can help me!



 for(Body b: snake.getSnake()){
         game.batch.begin();
         game.font.draw(game.batch,"Punkte: "+points, Gdx.graphics.getWidth()-100, Gdx.graphics.getHeight()-10);
         game.font.draw(game.batch,"FPS: " + Gdx.graphics.getFramesPerSecond(), 100, Gdx.graphics.getHeight()-10);
         game.batch.draw(b.getImg(),b.getTangle().getX(), b.getTangle().getY());
         game.batch.draw(food.getImg(), food.getFood().getX(), food.getFood().getY());
         game.batch.end();
      }

You are starting the batch and ending it with every body part. As well as drawing the FPS counter x amount of times in the same loop iteration, as well as the food.

It should be like this:


game.batch.begin();
game.font.draw(game.batch,"Punkte: "+points, Gdx.graphics.getWidth()-100, Gdx.graphics.getHeight()-10);
game.font.draw(game.batch,"FPS: " + Gdx.graphics.getFramesPerSecond(), 100, Gdx.graphics.getHeight()-10);
game.batch.draw(food.getImg(), food.getFood().getX(), food.getFood().getY());
 for(Body b: snake.getSnake()){
         game.batch.draw(b.getImg(),b.getTangle().getX(), b.getTangle().getY());
      }
game.batch.end();

You only need to call batch.begin and batch.end once, anything inbetween will be drawn.

EDIT: Your English is fine! Relax :smiley:

Oh yeah you’re right.
Don’t know how this could happen.

Big thanks to you!! Now it works finde! :))

willkommen :slight_smile:

No problem :smiley: Have a welcome medal :slight_smile:

Dankeschön :slight_smile: Thank you