Libgdx adding a UI button separated from the gamescreen - java

I've got a GameScreen where I have 100 "dots" randomly bounce around the screen. I'm currently adding a UI button in order to rotate the screen; one on the left and one on the right. The button works, however, the button is "linked" to the camera because as the screen rotates (the playing field for the dots spins because the camera rotates), the button rotates with it. I want the button(s) to be fixed to the device screen, and not rotate with the underlying field of dots.
Do I have to unproject the button somehow, or create a separate stage for any UI elements (buttons, statusbar title alone the top, etc)? Many thanks.
Here's my code:
public class GameScreen implements Screen {
final jGdxDots game;
final MyGestureListener myGestureListener;
OrthographicCamera camera;
private Skin skin;
final int NUMBER_OF_DOTS = 100;
int dotTotal;
private Stage stage;
FPSLogger fpsLogger;
float cameraRotate = 0f;
public GameScreen(final jGdxDots gam) {
this.game = gam;
fpsLogger = new FPSLogger();
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480); //boolean = YDOWN or YUP axis.
//create stage
stage = new Stage(Gdx.graphics.getWidth(),Gdx.graphics.getHeight(),true);
//set stage to handle the inputs
//Gdx.input.setInputProcessor(stage);
stage.setCamera(camera);
//stage.setViewport(800, 480, true);
//multiplex the gesture listeners (both for stage and my listener)
myGestureListener = new MyGestureListener();
GestureDetector gd = new GestureDetector(myGestureListener);
InputMultiplexer im = new InputMultiplexer(gd, stage); // Order matters here!
Gdx.input.setInputProcessor(im);
//UI button
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
final TextButton button = new TextButton("Rotate", skin, "default");
button.setWidth(100f); //200f
button.setHeight(100f); //20f
button.setPosition(10f, 10f);
button.addListener(new ClickListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
cameraRotate = 1f;
return super.touchDown(event, x, y, pointer, button);
}
#Override
public void touchUp(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
super.touchUp(event, x, y, pointer, button);
cameraRotate = 0f;
}
});
stage.addActor(button);
spawnDots(stage);
}
private void spawnDots(Stage theStage) {
//Rectangle raindrop = new Rectangle();
for (int i=0; i < NUMBER_OF_DOTS; i++) {
DotActor dot = new DotActor();
dot.setOrigin(8,8); //(dot.getWidth()/2, dot.getHeight()/2);
dot.vector.set(MathUtils.random(1,4), MathUtils.random(1,4));
dot.actorX = MathUtils.random(0, 800 - dot.getWidth());
dot.actorY = MathUtils.random(0, 480 - dot.getHeight());
stage.addActor(dot);
}
dotTotal = NUMBER_OF_DOTS;
}
#Override
public void dispose() {
stage.dispose();
}
#Override
public void render(float delta) {
//clear screen
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//logger
fpsLogger.log();
//camera.zoom += 0.005f;
camera.rotate(cameraRotate); //(1.0f);
camera.update();
//run act() method of each actor
stage.act(Gdx.graphics.getDeltaTime());
//run each actor's draw() method who are members of this stage
stage.draw();
}
}

I had this problem too. Create a separate stage, or you might just want to draw directly with a sprite batch in a 'renderer' class
Mine looks something like this:
public OverlayRenderer()
{
this.spriteBatch = new SpriteBatch();
this.loadTextures();
}
public void render(String _message)
{
this.spriteBatch.begin();
this.spriteBatch.draw(TEXTURES.UI, 0, 0);
....
}
and directly after your
stage.draw();
line, I would add
overLayRenderer.render();

Related

LibGDX Button not responding on touch

My first problem is that the textfield is not showing up and the second is that the button is not responding. My idea is when image 'vault1' is touched the textfield should show 5.
This is what I have come up with and I can't figure out what I am doing wrong.
(I have only cut out neseccary code)
public void render(float delta) {
drawSprite("vault1", 600, 450);
}
public void show() {
Gdx.input.setInputProcessor(stage);
skin = new Skin(Gdx.files.internal("ui/menuSkin.json"), new TextureAtlas("ui/atlas.pack"));
vaultInput = new TextField("", skin);
vaultInput.setPosition(300, 250);
vaultInput.setSize(300, 40);
vaultInput.setText(text2);
vault1Button = new Image(vault1);
vault1Button.addListener(new ClickListener() {
public boolean touchDown(InputEvent e, float x, float y, int point, int button) {
System.out.println("133");
vaultInput.setText(score);
return false;
}});
}
private void drawSprite(String name, float x, float y) {
Sprite sprite = textureAtlas.createSprite(name);
sprite.setPosition(x, y);
sprite.draw(batch);
vault1 = sprite;
}
It's hard to tell when you've left out code but you are adding the stage to the input processor:
Gdx.input.setInputProcessor(stage);
The stage and actors added to the stage is now the only things that responds to input. But you are never adding anything to the stage and neither drawing the stage, you are drawing your sprites seperately in the drawSprite method.
If you instead add your button to the stage all you need to do is call stage.draw():
public void render(float delta) {
stage.draw();
stage.act(delta);
}
public void show() {
Gdx.input.setInputProcessor(stage);
skin = new Skin(Gdx.files.internal("ui/menuSkin.json"), new TextureAtlas("ui/atlas.pack"));
vaultInput = new TextField("", skin);
vaultInput.setPosition(300, 250);
vaultInput.setSize(300, 40);
vaultInput.setText(text2);
vault1Button = new Image(vault1);
vault1Button = new Image(vault1);
vault1Button.addListener(new ClickListener() {
public boolean touchDown(InputEvent e, float x, float y, int point, int button) {
System.out.println("133");
vaultInput.setText(score);
return false;
}});
vaultInput.setPosition(x1, y1);
vault1Button.setPosition(x2, y2);
stage.addActor(vaultInput);
stage.addActor(vault1Button);
}
Everything added to the stage will be drawn when calling stage.draw()
The value of the vault1 field is still null when show() is called. So your actual button that you added your listener to has zero size and nothing to draw.
Also, since render() is called continuously in the game loop, you are creating new sprites to draw on every frame and reassigning the vault1 variable every frame.
You need to create your image for the button in show() and add the button to the stage. Then you only need to draw the stage.

problems with multiple cameras and viewports in libgdx

so I am doing what is suppose to be a simple game but I think I might be complicating things. I have a camera for the GameScreen and a viewPort which follow the position of the player and when it reaches to points on the sides, the camera stops following the player and stays in one point.
This by itself works fine, but then I wanted to add the pause menu and some other features in the game, creating a hud class with its own camera and viewport as well as a Stage and a shapeRenderer.
The problem comes when I create the instance of this hud inside my gameScreen, the camera that I am looking while I am playing looks like is the hudCam, which does not follow the player and basically does not let me see the player when it reaches the edges of the screen.
This is my GameScreen Class:
public class GameScreen implements Screen {
WowInvasion game;
ScrollingBackground background;
private OrthographicCamera gameCam;
private Viewport gameViewPort;
/*
Basically I wanna keep the same sprites running while in the menu, playing and till dead
therefore, I'll have a switch statement with cases on where the games at, inside the functions needed. That way I'll keep
the game has a background for the menu and there's no need for running a second screen.
*/
public static final int MAIN_MENU = 0;
public static final int GAME = 1;
private static int state = 1; //current state. starts with MAIN_MENU //DEBUGGING GAME SCREEN
//STAGES
private GameStage gameStage; //game ui
private menuStage mainMenu; //Main menu of the game
private Hud hud;
//Resources
private TextureAtlas atlas; //for the textures most
private Skin skin; //for the styles and fonts
//Sprites
private Player player;
//Shapes
private float progressPower; //for the power to build up
private final float POWER_CHARGED = 1000; //limit to get power
private final float DECREASING_POWER = 20; //limit to get power
public GameScreen(WowInvasion game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
gameViewPort = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, gameCam);
progressPower = 0f;
game.wowAssetManager.loadTexturesGameScreen(); // tells our asset manger that we want to load the images set in loadImages method
game.wowAssetManager.loadSkins(); //load the needed skins
game.wowAssetManager.manager.finishLoading(); // tells the asset manager to load the images and wait until finsihed loading.
skin = game.wowAssetManager.manager.get("ui/menuSkin.json");
}
#Override
public void show() {
game.batch.setProjectionMatrix(gameCam.combined);
background = new ScrollingBackground();
atlas = game.wowAssetManager.manager.get(WowAssetManager.GAME_ATLAS); //declaring atlas
mainMenu = new menuStage(gameViewPort, game.batch, skin, game); //pass it so that we only use one batch and one same viewport
gameStage = new GameStage(gameViewPort, game.batch, skin, game);
hud = new Hud(game.batch, skin);
player = new Player(atlas.findRegion("player"), (int) gameCam.viewportWidth / 2, (int) gameCam.viewportHeight / 2);
switch(state){
case MAIN_MENU:
Gdx.input.setInputProcessor(mainMenu);
break;
case GAME:
background.setFixedSpeed(false); //does not work in here
}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(state == GAME) {
background.setFixedSpeed(false);
player.update(delta, gameCam.viewportWidth, gameCam.viewportHeight); //updating player for movement
//really cheap way to charge power with velocity
if(progressPower != POWER_CHARGED) {
progressPower += Math.abs(player.getVelocity().x) + Math.abs(player.getVelocity().y);
progressPower -= DECREASING_POWER;
}
else
progressPower = POWER_CHARGED / 4;
}
mainMenu.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); //updating while making sure delta won't be more than 1/30f.
gameStage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
game.batch.begin();
background.updateAndRender(delta, game.batch); //updating scrolling background
player.draw(game.batch);
game.batch.end();
mainMenu.draw(); //draw the menu stage
gameStage.draw(); //draw the ui stage for the game
hud.getStage().draw();
hud.renderRotateMeter();
updateCamera(0, WowInvasion.WIDTH);
System.out.println(player.getPosition().x);
}
public void updateCamera(float startX, float endX){
Vector3 position = gameCam.position;
//linear interpolation : a + (b - a) * lerp
//b = player position
//a = current camera position
//lerp = interpolation factor
position.x = gameCam.position.x + (player.getPosition().x - gameCam.position.x) * .1f;
//making the camera stay when the player gets to close to the sides
if(position.x < startX) {
position.x = startX;
}
if(position.x > endX){
position.x = endX;
}
gameCam.position.set(position);
gameCam.update();
}
#Override
public void resize(int width, int height) {
gameViewPort.update(width, height);
//hud.getViewport().update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
mainMenu.dispose();
gameStage.dispose();
game.dispose();
hud.dispose();
}
public static void setState(int state) {
GameScreen.state = state;
}
}
And this is my HUD:
public class Hud implements Disposable{
private Stage stage;
private Viewport viewport;
Button buttonPause, buttonResume;
private OrthographicCamera hudCam;
private ShapeRenderer sp; //like a batch for shapes
public Hud(SpriteBatch sb, Skin skin){
hudCam = new OrthographicCamera();
hudCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
viewport = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, hudCam);
stage = new Stage(viewport, sb);
sp = new ShapeRenderer();
Table table = new Table();
table.top();
//this makes the table the size of the stage
table.setFillParent(true);
buttonPause = new Button(skin, "pause");
buttonPause.setTransform(true);
buttonPause.addListener(new ClickListener(){ //listener to handle event
#Override
public void clicked(InputEvent event, float x, float y) {
}
});
buttonResume = new Button(skin, "resume");
buttonResume.setTransform(true);
buttonResume.setScale(0.5f);
buttonResume.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
buttonResume.setVisible(false);
}
});
table.add(buttonPause);
table.row();
table.add(buttonResume);
stage.addActor(table);
}
public void renderRotateMeter(){
sp.setProjectionMatrix(hudCam.combined);
sp.begin(ShapeRenderer.ShapeType.Filled);
sp.setColor(Color.YELLOW);
sp.rect(hudCam.position.x,hudCam.position.y, WowInvasion.WIDTH / 2, 20);
sp.end();
}
public Viewport getViewport() {
return viewport;
}
public Stage getStage() {
return stage;
}
#Override
public void dispose() {
stage.dispose();
sp.dispose();
}
}
thanks in advance!
EDIT
so I tried passing the gameCam has a parameter to the hud and instead of making a new OrthographicCamera I used that one has the hudCamara as well and well, the movement with the player is perfect except now the thins from the Hud do not move at all..
It looks like you only set projectionMatrix to only HUD camera as seen in
sp.setProjectionMatrix(hudCam.combined);
Try to set it the same to other stuff outside of the HUD class prior to draw call too.
Another thing to keep in mind is that, when you involve using multiple Viewport and Camera in the game as most of the time it will be 1 Viewport matching with 1 Camera and work with another set as in your case. In draw call, you need to call apply() or apply(true) of Viewport class too to tell the system that you will draw based on which viewport thus in turn it will adhere to screen coordinate that was set up by viewport's attaching camera.
So assume you have 2 objects that needed to be called in different viewport consecutively, do it like the following code. The methods call is correct according to libgdx API but variable names are fictional.
// draw objA adhering to viewportA (thus cameraA) <-- assume it's player cam
sb.setProjectionMatrix(cameraA.combined);
viewportA.apply();
objA.draw();
// draw objB adhering to viewportB (thus cameraB) <-- assume it's HUD cam
sb.setProjectionMatrix(cameraB.combined);
viewportB.apply(true); // send in true as for HUD, we always want to center the screen
objB.draw();
In summary, 2 things to keep in mind when drawing objects that use multiple of camera and viewport in consecutive draw call.
Set projection matrix to either SpriteBatch or ShapeRenderer.
Call apply() or apply(true) of Viewport class to let it know you work with this viewport.

LibGDX application crash: "batch cannot be null"

i'm creating a 2D platform game with Android Studio and LibGDX.
Right now, I'm implementing an on-screen controller to move the character, but when I start the launcher, it closes automatically.
When I run the launcher, this is what the console shows:
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
at com.globapps.supermarioclon.Screens.PantallaJuego.<init>(PantallaJuego.java:57)
at com.globapps.supermarioclon.MarioBros.create(MarioBros.java:34)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
This is the code from the controller class:
public class Controles {
Viewport viewport;
Stage stage;
boolean salto, izquierda, derecha;
OrthographicCamera cam;
public Controles() {
cam = new OrthographicCamera();
viewport = new FitViewport(800, 480, cam);
stage = new Stage(viewport, PantallaJuego.batch);
Gdx.input.setInputProcessor(stage);
Table table1 = new Table();
Table table2 = new Table();
table1.left().bottom();
table2.right().bottom();
Image flechaizquierda = new Image(new Texture("flechaIzquierda.png"));
flechaizquierda.setSize(50, 50);
flechaizquierda.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
izquierda = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
izquierda = false;
}
});
final Image flechaderecha = new Image(new Texture("flechaDerecha.png"));
flechaderecha.setSize(50, 50);
flechaderecha.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
derecha = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
derecha = false;
}
});
Image flechasalto = new Image(new Texture("flechaIzquierda.png"));
flechasalto.setSize(50, 50);
flechasalto.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
salto = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
}
});
table1.add();
table1.add(flechaizquierda).size(flechaizquierda.getWidth(), flechaizquierda.getHeight());
table1.add();
table1.row().pad(0, 5, 0, 5);
table1.add();
table1.add(flechaderecha).size(flechaderecha.getWidth(), flechaderecha.getHeight());
table2.add();
table2.add(flechasalto).size(flechasalto.getWidth(), flechasalto.getHeight());
table2.row().padRight(5);
table2.add();
stage.addActor(table1);
stage.addActor(table2);
}
public void draw() {
stage.draw();
}
public boolean isDerecha() {
return derecha;
}
public boolean isIzquierda() {
return izquierda;
}
public boolean isSalto() {
return salto;
}
public void resize(int ancho, int alto) {
viewport.update(ancho, alto);
}
}
And this is the PlayScreen class:
public class PantallaJuego extends ApplicationAdapter implements Screen {
private MarioBros game;
public static SpriteBatch batch;
private TextureAtlas atlas;
private OrthographicCamera gamecam, cam;
private Viewport gamePort, viewport;
private HUD hud;
private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private World world;
private Box2DDebugRenderer b2dr;
Controles controles;
private Mario player;
private Music musica;
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
controles = new Controles();
batch = new SpriteBatch();
maploader = new TmxMapLoader();
map = maploader.load("nivel1mario.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 1/MarioBros.PPM);
gamecam.position.set(gamePort.getWorldWidth()/2, gamePort.getWorldHeight()/2, 0);
world = new World(new Vector2(0,-10), true);
b2dr = new Box2DDebugRenderer();
player = new Mario(world, this);
new B2WorldCreator(world, map);
world.setContactListener(new WorldContactListener());
musica = MarioBros.manager.get("Audio/Música/Super Mario World - Overworld Theme Music (FULL VERSION).mp3", Music.class);
musica.setLooping(true);
musica.play();
}
public TextureAtlas getAtlas() {
return atlas;
}
#Override
public void show() {
}
public void handleInput(float dt) {
if(controles.isDerecha())
player.b2body.applyLinearImpulse(new Vector2(0.1f, 0), player.b2body.getWorldCenter(), true);
if(controles.isSalto())
MarioBros.manager.get("Audio/Sonidos/Super Mario Bros- Mario Jump Sound Effect.mp3", Sound.class).play();
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
if(controles.isIzquierda())
player.b2body.applyLinearImpulse(new Vector2(-0.1f, 0), player.b2body.getWorldCenter(), true);
}
public void update(float dt) {
handleInput(dt);
world.step(1 / 60f, 6, 2);
gamecam.position.x = player.b2body.getPosition().x;
cam.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);
player.update(dt);
hud.update(dt);
if(Gdx.app.getType() == Application.ApplicationType.Android)
controles.draw();
gamecam.update();
cam.update();
renderer.setView(gamecam);
}
#Override
public void render(float delta) {
update(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, cam.combined);
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
player.draw(game.batch);
game.batch.end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
If someone could help me, I'd be very grateful. Thank you.
I think you should instantiate your batch in PantallaJueago class before instantiating controles field.
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
batch = new SpriteBatch();
controles = new Controles();
Because it is null while you instantiating your "controles". You are getting this error for your line
stage = new Stage(viewport, PantallaJuego.batch);
PantallaJuego.batch is null.
Well you should learn some more of the basics before you continue. This is related to a a NullPointerException and is usually very easy to fix. It tells you that you are trying to access a method or variable in nothing since you did not initialize it. Let's take your stack and find whats wrong.
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
//Great! So let's fix this.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
//This is a LibGDX class so there is probably nothing wrong with this
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
//This is your class so let's go to this specific line, you can double click it.
stage = new Stage(viewport, PantallaJuego.batch);
//So either viewport or batch is null in this line.
//You can put a breakpoint here and run a debug,
//your program will stop on this line and you can hover
//to see what is in the variables. You will see that batch
// is null. Why, you may ask.
In the constructor of your main class you first set new Controles()
controles = new Controles();
Now the constructor of Controles will run and comes to this line:
stage = new Stage(viewport, PantallaJuego.batch);
And since your code did not reach batch = new SpriteBatch(); in PantallaJuego batch is still null and since stage does not accept that it will throw a NullPointer. A quick fix is to turn around new SpriteBatch() and new Controles().
The reason I say you should start learning the basics first is because your code is very poorly formed. You should format your code in a neat way and use much smaller methods since right now certain methods and constructors do all kind of stuff and it is very hard to read. Apart from this you are picking up very bad habits like making a global from that SpriteBatch (public static). There is really no need for this and it is partly responsible for your failure here.
Have a look at What is a NullPointerException, and how do I fix it? although your error is not a NullPointerException it is very related. Stage() does a check of it's own for it to be null and throws another exception before it tries to access it and get a nullpointer then.

Issue with sounds in libgdx

I am having issues with libgdx sound inside a ClickListener for my button.
I am getting the error Syntax error on token "PlayButtonSound", Identifier expected after this token
SoundManager:
import utils.Constants;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
public class SoundManager {
private static Sound buttonSound = Gdx.audio.newSound(Constants.buttonSound);
private static Music song = Gdx.audio.newMusic(Constants.song);
public static void PlayMusic() {
song.setLooping(true);
song.setVolume(0.2f);
song.play();
}
public static void PlayButtonSound() {
buttonSound.play();
}
public void DestryoAudio() {
buttonSound.dispose();
song.dispose();
}
}
And MainMenu:
public class MainMenu implements Screen {
private Stage stage;
private Sprite sprite;
private TextureRegion menuBackgroundImg;
private TextureAtlas menuButton;
private Skin skin;
private BitmapFont font;
private Table table;
private TextButton playButton;
#Override
public void show() {
// Set stage
stage = new Stage();
Gdx.input.setInputProcessor(stage);
SoundManager.PlayMusic();
// Set menu baggrund
menuBackgroundImg = new TextureRegion(new Texture(Gdx.files.internal(Constants.menuBackgroundImg)));
sprite = new Sprite(menuBackgroundImg);
sprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Set menuknapper
menuButton = new TextureAtlas(Constants.menuButton);
skin = new Skin(menuButton);
// Set font
font = new BitmapFont(Constants.font, false);
// Set table
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Create button styling
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("menuButtonUp");
textButtonStyle.down = skin.getDrawable("menuButtonPressed");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = font;
textButtonStyle.fontColor = Color.BLACK;
// Create buttons
playButton = new TextButton(Constants.play, textButtonStyle);
playButton.addListener(new InputListener() {
SoundManager.PlayButtonSound(); // This is the error
});
// Button padding
playButton.pad(20, 100, 20, 100);
// Setting the table
table.add(playButton).row();
// Setting stage actor
stage.addActor(table);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Tegn baggrund
stage.getBatch().begin();
sprite.draw(stage.getBatch());
stage.getBatch().end();
// Tegn resten
stage.act(delta);
stage.draw();
}
...
#Override
public void dispose() {
stage.dispose();
menuButton.dispose();
skin.dispose();
font.dispose();
}
}
I can't really grasp what I am doing wrong and a search for the error gives vague answers that dosen't really solves my issue.
P.S. I have imported SoundManager but left it out due to length of the code snippet.
You need to implement one of the InputListener interface methods, most likely touchDown(InputEvent event, float x, float y, int pointer, int button).
Check out the API for InputListener. It lists all the methods and gives a pretty good example.
playButton.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
SoundManager.PlayButtonSound();
return false;
}
});

libgdx drag and drop

Im trying to add drag and drop functionality to several images in Libgdx. I have looked at this example: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/DragAndDropTest.java but Its still not working. The images do not drag and drop. Would anyone be able to give me some pointers in why its not working?
Thanks
private void createButton() {
stage = new Stage();
Gdx.input.setInputProcessor(stage);
skin = new Skin();
skin.add("up", new Texture(Gdx.files.internal("assets/data/up.png")));
skin.add("def", new Texture(Gdx.files.internal("assets/data/Goal.png")));
final Image up = new Image(skin, "up");
up.setBounds(1090, 630, 40, 40);
stage.addActor(up);
Image def = new Image(skin, "def");
def.setBounds(1090, 585, 40, 40);
stage.addActor(def);
DragAndDrop dragAndDrop = new DragAndDrop();
dragAndDrop.addSource(new Source(up) {
public Payload dragStart (InputEvent event, float x, float y, int pointer) {
Payload payload = new Payload();
payload.setObject(payload);
payload.setDragActor(up);
payload.setDragActor(new Label("up", skin));
Label validLabel = new Label("up", skin);
validLabel.setColor(0, 1, 0, 1);
payload.setValidDragActor(validLabel);
return payload;
}
});
dragAndDrop.addTarget(new Target(def) {
public boolean drag (Source source, Payload payload, float x, float y, int pointer) {
getActor().setColor(Color.GREEN);
return true;
}
public void reset (Source source, Payload payload) {
getActor().setColor(Color.WHITE);
}
public void drop (Source source, Payload payload, float x, float y, int pointer) {
System.out.println("Accepted: " + payload.getObject() + " " + x + ", " + y);
}
});
render();
}
public void render () {
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
Table.drawDebug(stage);
}
I implemented your code on a project of mine.
I removed your render and used the one below. Also, you shouldn't need the assets/ prefix to your image import.
skin.add("up", new Texture(Gdx.files.internal("images/coin.png")));
skin.add("def", new Texture(Gdx.files.internal("images/coin.png")));
#Override
public void render(float delta) {
super.render(delta);
stage.draw();
stage.act(Gdx.graphics.getDeltaTime());
}
Another way to do drag in a better way...
public class CaveInterection implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture bgTexture;
private Sprite sprite;
private Stage stage;
private Texture mirrTexture;
private MyActor mirrorActor;
Sprite img1,img2;
#Override
public void create() {
camera = new OrthographicCamera(1024, 550);
camera.position.set(1024 / 2, 550 / 2, 0);
batch = new SpriteBatch();
stage = new Stage(1024, 550, false);
//bgTexture = new Texture(Gdx.files.internal("data/cave.jpg"));
//bgTexture = new Texture(Gdx.files.internal("data/bg.jpg"));
mirrTexture = new Texture(Gdx.files.internal("data/mirror.png"));
mirrTexture
.setFilter(TextureFilter.Linear, TextureFilter.Linear);
mirrorActor = new MyActor(new TextureRegion(mirrTexture));
mirrorActor.setPosition(700, 400);
mirrorActor.setOrigin(mirrorActor.getWidth()/2, mirrorActor.getHeight()/2);
stage.addActor(mirrorActor);
// finally stage as the input process
Gdx.input.setInputProcessor(stage);
}
#Override
public void dispose() {
batch.dispose();
//bgTexture.dispose();
}
#Override
public void render() {
// clear the screen, update the camera and make the sprite batch
// use its matrices.
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
//batch.draw(bgTexture, 0,0);
// Gdx.app.log("arvind","X :"+mirrorActor.getX()+ " Y :"+mirrorActor.getY());
//batch.draw(bgTexture, 0, 0);
batch.end();
// tell the stage to act and draw itself
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
public class MyActor extends Actor {
TextureRegion region;
float lastX;
float lastY;
public MyActor (TextureRegion region) {
this.region = region;
setWidth(region.getRegionWidth());
setHeight(region.getRegionHeight());
addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("arv", "pointer1+"+pointer);
// we only care for the first finger to make things easier
if (pointer != 0) return false;
// record the coordinates the finger went down on. they
// are given relative to the actor's corner (0, 0)
Gdx.app.log("arvind", "touchDown");
Gdx.app.log("arv", "pointer2+"+pointer+""+x+"::::"+y);
lastX = x;
lastY = y;
return true;
}
public void touchDragged (InputEvent event, float x, float y, int pointer) {
// we only care for the first finger to make things easier
if (pointer != 0) return;
Gdx.app.log("arv", "touchDragged");
// adjust the actor's position by (current mouse position - last mouse position)
// in the actor's coordinate system.
translate(x - lastX, y - lastY);
// rotate(2);
// save the current mouse position as the basis for the next drag event.
// we adjust by the same delta so next time drag is called, lastX/lastY
// are in the actor's local coordinate system automatically.
lastX = x - (x - lastX);
lastY = y - (y - lastY);
}
});
}
#Override
public void draw (SpriteBatch batch, float parentAlpha) {
//batch.draw(region, getX(), getY());
batch.draw(region, getX(), getY(), mirrorActor.getOriginX(), mirrorActor.getOriginY(), mirrorActor.getWidth(), mirrorActor.getHeight(), 1, 1,getRotation(), true);
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}

Categories

Resources