I am creating a 3d game in libGDX. For some reason my game keeps printing
DefaultShaderProvider: Creating new shader
in the terminal. This is driving me absolutely insane because I can not debug my program with the terminal because of the spamming of that line. I checked my code for anything that would print this but I can not find anything that would.
Could anyone tell me why this is happening?
Here is my code:
public class puppetDemo implements ApplicationListener {
public PerspectiveCamera camera;
public ModelBatch modelBatch;
public ModelInstance box;
public ModelInstance sphere;
public Array<ModelInstance> instances = new Array<ModelInstance>();
public AssetManager assets;
public Lights lights;
public CameraInputController camController;
public boolean loading = true;
#Override
public void create() {
camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
camera.position.set(10f, 0f, -100f);
camera.lookAt(0, 0, 0);
camera.near = 0.1f;
camera.far = 300f;
camera.update();
lights = new Lights();
lights.ambientLight.set(0.4f, 0.4f, 0.4f, 1f);
lights.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f,
-0.2f));
assets = new AssetManager();
assets.load("data/box.obj", Model.class);
assets.load("data/sphere.obj", Model.class);
}
#Override
public void resize(int width, int height) {
}
#Override
public void render() {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
modelBatch = new ModelBatch();
modelBatch.begin(camera);// Begin Rendering
modelBatch.render(instances, lights);
modelBatch.end();// End Rendering
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
modelBatch.dispose();
}
}
When you call new ModelBatch() in your render method, this is creating a new instance of the DefaultShaderProvider:
public ModelBatch() {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
new DefaultShaderProvider(),
new DefaultRenderableSorter());
}
Looking at the source for DefaultShaderProvider you'll notice logging output in the createShader method:
#Override
protected Shader createShader(final Renderable renderable) {
Gdx.app.log("DefaultShaderProvider", "Creating new shader");
// ...
}
Instantiate modelBatch in the create method instead of in render and I suspect you'll only see the output once. If not, it might be worth filing an issue to have logging statement removed as it seems unnecessary.
Related
I'm kind of new to LibGdx and android studio.
I'm trying to create clickable textures, one for play and one for credits.
Both should be opening a new empty screen/event.
public void create() {
batch = new SpriteBatch();
img = new Texture("Main_Screen.png");
music = Gdx.audio.newMusic(Gdx.files.internal("bgmusic.wav"));
music.play();
music.setLooping(true);
credits = new Texture("credits.png");
play = new Texture("play.png");
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.draw(play, 340, 1400);
batch.draw(credits, 340, 400);
batch.end();
}
However i'm unsure on how to do this since i'm also creating the background with a texture, so i'd be very happy if someone could assist me with helping me out.
Use Sprite instead of Texture, that holds the geometry, color, and texture information for drawing 2D sprites.
MyGdxGame
public class MyGdxGame extends Game {
public Screen menuScreen,creditsScreen,playScreen;
#Override
public void create () {
menuScreen=new MenuScreen(this);
creditsScreen=new CreditsScreen();
playScreen=new PlayScreen();
setScreen(menuScreen);
}
}
MenuScreen
public class MenuScreen extends InputAdapter implements Screen {
SpriteBatch batch;
Texture background,play,credits;
Sprite backgoundSprite,playSprite,creditsSprite;
private ExtendViewport extendViewport;
OrthographicCamera cam;
private float w=480;
private float h=800;
private Vector3 vector3;
MyGdxGame game;
Music music;
public MenuScreen(MyGdxGame game){
this.game=game;
}
#Override
public void show() {
batch = new SpriteBatch();
cam = new OrthographicCamera();
extendViewport=new ExtendViewport(w,h,cam);
vector3=new Vector3();
background = new Texture("Main_Screen.png");
play=new Texture("play.png");
credits=new Texture("credits.png");
backgoundSprite=new Sprite(background);
backgoundSprite.setSize(w,h); // If resources are not in context of your viewport
backgoundSprite.setPosition(0,0); //Default Position
playSprite=new Sprite(play);
playSprite.setSize(100,100);
playSprite.setPosition(w/2-playSprite.getWidth()/2,h/2+100);
creditsSprite=new Sprite(credits);
creditsSprite.setSize(100,100);
creditsSprite.setPosition(w/2-creditsSprite.getWidth()/2,h/2-100);
Gdx.input.setInputProcessor(this);
music = Gdx.audio.newMusic(Gdx.files.internal("bgmusic.wav"));
music.play();
music.setLooping(true);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.begin();
backgoundSprite.draw(batch);
playSprite.draw(batch);
creditsSprite.draw(batch);
batch.end();
}
#Override
public void resize(int width, int height) {
extendViewport.update(width,height);
cam.position.x = w /2;
cam.position.y = h/2;
cam.update();
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
vector3.set(screenX,screenY,0);
Vector3 position=cam.unproject(vector3);
if(playSprite.getBoundingRectangle().contains(position.x,position.y)) {
game.setScreen(game.playScreen);
}
if(creditsSprite.getBoundingRectangle().contains(position.x,position.y)){
game.setScreen(game.creditsScreen);
}
return super.touchDown(screenX, screenY, pointer, button);
}
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() {
batch.dispose();
background.dispose();
play.dispose();
credits.dispose();
}
}
CreditsScreen
public class CreditsScreen implements Screen {
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void resize(int width, int height) { }
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() { }
}
PlayScreen
public class PlayScreen implements Screen {
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void resize(int width, int height) { }
#Override
public void pause() { }
#Override
public void resume() { }
#Override
public void hide() { }
#Override
public void dispose() { }
}
Welcome to libGDX!
If I understand your question correctly, you are trying to figure out how to change screens in your game. At a high level, this is what you'd need to do:
Draw your button texture on the screen.
Use Gdx.input to detect when the player lifts their mouse button (and if it's over one of your buttons when they do it)
Switch to the new screen (presumably with a new background) when this happens.
I would recommend that you first complete the "A Simple Game" and "Extending the Simple Game" tutorials in order to familiarize yourself with the basics of libGDX and the Game and Screen classes.
Next, try using Scene2D.UI (there are links at the bottom of the second tutorial) to add a Stage and TextButtons to your main menu.
Hopefully that helps you get started- there is a lot of helpful information on that libGDX wiki which I think you will find helpful.
I am making a 2d game using libgdx and am adding hexagon shaped actors to a group which is then added to a stage. For a normal camera you can use camera.zoom in the render method to zoom in and out along with camera.translate to pan around the world.
I have been getting the camera used by the stage using stage.getCamera() and I can still call stage.getcamera().translate however there is no stage.getCamera().zoom option.
Here is my code:
//import statements
public class HexGame implements ApplicationListener{
private Stage stage;
private Texture hexTexture;
private Group hexGroup;
private int screenWidth;
private int screenHeight;
#Override
public void create() {
hexTexture = new Texture(Gdx.files.internal("hex.png"));
screenHeight = Gdx.graphics.getHeight();
screenWidth = Gdx.graphics.getWidth();
stage = new Stage(new ScreenViewport());
hexGroup = new HexGroup(screenWidth,screenHeight,hexTexture);
stage.addActor(hexGroup);
}
#Override
public void dispose() {
stage.dispose();
hexTexture.dispose();
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
handleInput();
stage.getCamera().update();
}
private void handleInput() {
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
stage.getCamera().translate(-3, 0, 0);
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
stage.getCamera().translate(3, 0, 0);
}
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
stage.getCamera().translate(0, -3, 0);
}
if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
stage.getCamera().translate(0, 3, 0);
}
//This is the part that doesn't work
/*
if (Gdx.input.isKeyPressed(Input.Keys.Z)) {
stage.getCamera().zoom += 0.02;
}
*/
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
Any help is appreciated, and if there is anything else wrong with my code please let me know, I'm new to libgdx. Thanks
Zoom is available in OrthographicCamera class and by default Stage class create a OrthographicCamera
/** Creates a stage with a {#link ScalingViewport} set to {#link Scaling#stretch}. The stage will use its own {#link Batch}
* which will be disposed when the stage is disposed. */
public Stage () {
this(new ScalingViewport(Scaling.stretch, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), new OrthographicCamera()),
new SpriteBatch());
ownsBatch = true;
}
So what you need is to cast your camera to OrthographicCamera:
((OrthographicCamera)stage.getCamera()).zoom += 0.02f;
When I run the application my menu screen shows, but when I click the screen to begin playing the game the game begins playing but the menu screen is still their overlaying the game. I know this because the game has music playing. I'm also going to add a splash screen in the future but I'm not concerned about that right now. I'm new at this so please explain things as best as you can. Below are the 3 classes used to make this happen.
public class SlingshotSteve extends Game {
public SpriteBatch batch;
public BitmapFont font;
public void create() {
batch = new SpriteBatch();
//Use LibGDX's default Arial font.
font = new BitmapFont();
this.setScreen(new Menu(this));
}
public void render() {
super.render(); //important!
}
public void dispose() {
batch.dispose();
font.dispose();
}
}
Here is the main menu screen
public class Menu implements Screen {
final SlingshotSteve game;
OrthographicCamera camera;
public Menu(final SlingshotSteve gam) {
game = gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.font.draw(game.batch, "Welcome to Slingshot Steve!!! ", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) {
game.setScreen((Screen) new GameScreen(game));
dispose();
}
}
Here is the game screen
public class GameScreen implements Screen {
final SlingshotSteve game;
OrthographicCamera camera;
// Creates our 2D images
SpriteBatch batch;
TextureRegion backgroundTexture;
Texture texture;
GameScreen(final SlingshotSteve gam) {
this.game = gam;
camera = new OrthographicCamera(1280, 720);
batch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("background.jpg"));
backgroundTexture = new TextureRegion(texture, 0, 0, 500, 500);
Music mp3Sound = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
mp3Sound.setLooping(true);
mp3Sound.play();
}
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundTexture, 0, 0);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
texture.dispose();
}
In addition to Phonbopit's answer. You should probably #Override the render function at GameScreen.
Not sure but I think your render() method on GameScreen not called. you must implement method render(float delta) that use delta time for parameter.
replace
public void render() {
// your code
}
with
public void render(float delta) {
// your code
}
I am having some issues with loading button.pack made in TexturePacker. I really can't find where is the problem. If someone can see it from my GameScreen class please let me know. Thank you very much.
public class GameScreen implements Screen {
Stage stage;
TextureAtlas buttonAtlas;
TextButtonStyle buttonStyle;
TextButton button;
Skin skin;
SpriteBatch batch;
private GameWorld world;
private GameRenderer renderer;
private float runTime;
// This is the constructor, not the class declaration
public GameScreen() {
float screenWidth = Gdx.graphics.getWidth();
float screenHeight = Gdx.graphics.getHeight();
float gameWidth = 544;
float gameHeight = screenHeight / (screenWidth / gameWidth);
world = new GameWorld();
renderer = new GameRenderer(world, (int) gameHeight, (int) gameWidth);
Gdx.input.setInputProcessor(new InputHandler(world));
}
#Override
public void render(float delta) {
runTime += delta;
world.update(delta);
renderer.render(runTime);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act();
batch.begin();
stage.draw();
batch.end();
}
#Override
public void resize(int width, int height) {
System.out.println("GameScreen - resizing");
}
#Override
public void show() {
System.out.println("GameScreen - show called");
stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),
true);
skin = new Skin();
buttonAtlas = new TextureAtlas("button.pack");
skin.addRegions(buttonAtlas);
}
#Override
public void hide() {
System.out.println("GameScreen - hide called");
}
#Override
public void pause() {
System.out.println("GameScreen - pause called");
}
#Override
public void resume() {
System.out.println("GameScreen - resume called");
}
#Override
public void dispose() {
// Leave blank
}
}
Every time, no matter what change I make, it says "Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: File not found: button.pack (Internal)"
I checked in assets folder, button.pack and button.png are there :/
Use AssetManager for your game.
Code:
AssetManager am = new AssetManager();
am.load("buttons.pack", TextureAtlas.class);
am.finishLoading();
buttonAtlas = am.get("buttons.pack");
Then you can use your atlas.
And don't forget to put your atlas to game-android/assets directory.
I just started learning libGDX, and was following the example from http://steigert.blogspot.in/2012/02/2-libgdx-tutorial-game-screens.html (the second link on libGdx help page).
As of now, I just display a logo of 512x512. There is nothing else happening in the application but when I run the application in desktop mode,I get a FPS of 15-16. When I remove the image, I get 60fps for the blank screen. For android its even worse, I get 3-4 fps in Galaxy SL - GT-i9003 (Temple Run runs on playable speed on the device).
My laptop plays World of Warcraft without any hiccups in high quality so its baffling that such a small app would only achieve 15fps.
public class SplashScreen extends AbstractScreen {
private Texture splashTexture;
private TextureRegion splashTextureRegion;
public SplashScreen(MyGDXGame game){
super(game);
}
#Override
public void show()
{
super.show();
// load the splash image and create the texture region
splashTexture = new Texture("splash.png");
// we set the linear texture filter to improve the stretching
splashTexture.setFilter( TextureFilter.Linear, TextureFilter.Linear );
// in the image atlas, our splash image begins at (0,0) at the
// upper-left corner and has a dimension of 512x301
splashTextureRegion = new TextureRegion( splashTexture, 0, 0, 512, 382 );
}
#Override
public void render(float delta ) {
super.render( delta );
// we use the SpriteBatch to draw 2D textures (it is defined in our base
// class: AbstractScreen)
batch.begin();
// we tell the batch to draw the region starting at (0,0) of the
// lower-left corner with the size of the screen
batch.draw( splashTextureRegion, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
// the end method does the drawing
batch.end();
}
#Override
public void dispose()
{
super.dispose();
splashTexture.dispose();
}
}
Here is the relevant section of AbstractScreen class:
public class AbstractScreen implements Screen {
protected final MyGDXGame game;
protected final BitmapFont font;
protected final SpriteBatch batch;
public AbstractScreen(MyGDXGame game ){
this.game = game;
this.font = new BitmapFont();
this.batch = new SpriteBatch();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
}
...
}
And the desktop app:
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "First Game";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(new MyGDXGame(), cfg);
}
MyGDXGame is as follows:
public class MyGDXGame extends Game {
private FPSLogger fpsLogger;
public SplashScreen getSplashScreen() {
return new SplashScreen( this );
}
#Override
public void create() {
fpsLogger = new FPSLogger();
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
super.render();
setScreen(getSplashScreen());
fpsLogger.log();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
I have read so many good things about libGdx, so this issue seems baffling to me. What am I doing wrong to get such a low frame rate?
I think setScreen(getSplashScreen()); in your render() method might be the problem. Move it to the create() method of MyGDXGame.
Right now you are switching the screen in every single frame and recreate a SpriteBatch every single time which is a very heavy object (see my comment to your question).