Set an image as button on Android Studio Gdx library - java

I am trying to put a button using a play image. I have followed some tutorials and cannot find the documentation to complete my project. The game is actually done, and I just need to connect the gameover screen to the game screen so I can replay the game by pushing the play image. I got stuck in this longer than I expected. I cannot change the methods because I will mess up my code. Code and images below.
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class GameOverScreen extends BaseScreen {
private Image background;
private Stage stage;
private Image gameOver;
private Image replay;
public GameOverScreen(final MainGame game) {
super(game);
stage = new Stage(new FitViewport(640, 320));
//Preparing actors
background = new Image(game.getManager().get("bg.png", Texture.class));
gameOver = new Image(game.getManager().get("gameover.png", Texture.class));
replay = new Image(game.getManager().get("plybtn.png", Texture.class));
replay.addCaptureListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(game.gameScreen);
}
});
//Giving their positions and sizes
background.setPosition(0,0);
gameOver.setPosition(320 - gameOver.getWidth()/2, 180 - gameOver.getHeight()/2);
replay.setPosition(320 - replay.getWidth()/2, 60 -replay.getHeight()/2);
//Set them in stage
stage.addActor(background);
stage.addActor(gameOver);
stage.addActor(replay);
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void hide() {
Gdx.input.setInputProcessor(null);
}
#Override
public void dispose() {
stage.dispose();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.4f, 0.5f, 0.8f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
}
[This is the screen that I get, it does not change the screen when I touch the button][1]
[1]: https://i.stack.imgur.com/GxVLM.png
Update:
This is the solution to my problem in case you need it.
// Declare statements at the beginning of the class
private Texture myTexture;
private TextureRegion myTextureRegion;
private TextureRegionDrawable myTexRegionDrawable;
private ImageButton pbutton;
// Make a texture out of the image in the MenuScreen constructor
myTexture = new Texture(Gdx.files.internal("plybtn.png"));
myTextureRegion = new TextureRegion(myTexture);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
pbutton = new ImageButton(myTexRegionDrawable);

The event doesn't look like its being received. Change
replay.addCaptureListener(new ChangeListener() {
to
replay.addListener(new ChangeListener() {
or even use ClickListener instead. CaptureListener is to intercept events to disable them, not for handling and you need to return true in the capture handler to not break event handling down the tree.
https://gamedev.stackexchange.com/questions/151505/what-is-the-difference-between-a-listener-and-a-capturelistener-in-libgdx-scene2

Related

I am using Libgdx to build a mobile game. Can someone please show me how set the screen to one size?

package com.test.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Splash implements Screen {
private Sprite splash;
private SpriteBatch batch;
private float height = 1920;
private float width = 1080;
private float aspectratio = width/height;
#Override
public void render(float delta){
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
splash.draw(batch);
batch.end();
}
#Override
public void resize(int width, int height){
}
#Override
public void show(){
batch = new SpriteBatch();
Texture splashTexture = new Texture("zeuswallpaperphone1.jpg");
splash = new Sprite(splashTexture);
//splash.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
splash.rotate(90);
splash.setPosition(Gdx.graphics.getWidth()/2 - splashTexture.getWidth()/2, Gdx.graphics.getHeight()/2 - splashTexture.getHeight()/2);
}
#Override
public void hide(){
}
#Override
public void pause(){
}
#Override
public void resume(){
}
#Override
public void dispose(){
}
}
This is the splash screen of my game. I am trying to get the splash screen image to adjust for different screen sizes. Is there a way that I set the screen to one size? I want to set the screen to a size of 1280 x 720. And also will this keep the touch inputs the same? I do not understand why this is so hard in android. I have searched the internet vigorously trying to find a solution. I am also sorry if this question was already answered in another post. It seems that most answers to this problem are really old. I have not been able to find an answer the the problem that I have. I am looking for any help so please someone help me out. I have tried various methods and nothing seems to be working. Thank you in advance for your help. I hate that stack overflow makes you type a certain amount. There are a few libgdx tutorials out there. So if someone could watch one and get back to me that would be great. I have tried playing with the Viewport and Orthographic camera but when I run the game it will not adjust. On iOS you just set the screen size and you are good to go on all devices. They need that in android studio. Nothing seems to be working.
This is the code I have. Thanks for your help. This is crazy they still want me to type more.
I think you need to use a camera and viewport:
OrthographicCamera hudCamera = new OrthographicCamera();
Viewport hudViewport = new ScreenViewport(hudCamera);
public void create {
// Your code
hudViewport.apply(true);
}
public void render(float delta){
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(hudCamera.combined);
batch.begin();
splash.draw(batch);
batch.end();
}
public void resize(int width, int height) {
hudViewport.update(width, height);
hudViewport.apply(true);
}
Make sure you are setting the correct size in your main method.

Assets wont get rendered after disposing and reloading them

In my game I have currently two screens. The MenuScreen and the GameScreen. Through the Play option in the menu the player can switch to the GameScreen and start the Gameplay and with Escape he can get back to the MenuScreen. I dispose the used Assets when I switch to the other Screen in the hide() method and load the needed Assets for the new Screen in the constructor of the Screen I switch to. The problem is that the Textures and Sound Effects aren't rendered/played when I switch back.
For example when I start the game in the MenuScreen, then switch to the GameScreen everything is fine. But when I switch back to the MenuScreen the MenuScreen is just a black window. When I then switch to the GameScreen again it's black too except for the BitmapFont.
Maybe there is a fundemental flaw in the way I handle this. I tried to leave out as much unnecessary things as I can from the code I post here, but I fear that it's still too much.
RessourceLoader Class:
public class RessourceLoader {
public static AssetManager manager;
public static void create() {
manager = new AssetManager();
}
public static void loadMenuScreen() {
manager.load("gfx/menuBackground.png", Texture.class);
}
public static void getMenuScreen() {
menuBackground = manager.get("gfx/menuBackground.png", Texture.class);
}
public static void disposeMenuScreen() {
menuBackground.dispose();
}
public static void loadGameScreen() {
// load GameScreen Assets through AssetManager
}
public static void getGameScreen() {
// get GameScreen Assets through AssetManager
}
public static void disposeGameScreen() {
// dispose all GameScreen Assets
}
public static void dispose() {
manager.dispose();
}
}
MenuScreen Class:
public class MenuScreen implements Screen {
// Game starts in the MenuScreen
// Instance of game
private PHGame game;
// Orthographic camera
private OrthographicCamera cam;
public MenuScreen(PHGame phGame) {
game = phGame;
RessourceLoader.loadMenuScreen();
RessourceLoader.manager.finishLoading();
RessourceLoader.getMenuScreen();
cam = new OrthographicCamera();
cam.setToOrtho(true, 640, 480);
game.batcher.setProjectionMatrix(cam.combined);
}
#Override
public void render(float delta) {
// Fills background with black to avoid flickering
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Begin Drawing
game.batcher.begin();
// Draw Menu
// Stop drawing
game.batcher.end();
// Pressing Space confirms currently selected menu item
if (GameKeys.isPressed(GameKeys.SPACE)) {
game.setScreen(new GameScreen(game));
}
// Update Key Presses
GameKeys.update();
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
RessourceLoader.disposeMenuScreen();
}
}
GameScreen Class:
public class GameScreen implements Screen {
// Instance of game
private PHGame game;
private GameWorld world;
private GameRenderer renderer;
private float runTime;
public GameScreen(PHGame phGame) {
game = phGame;
RessourceLoader.loadGameScreen();
RessourceLoader.manager.finishLoading();
RessourceLoader.getGameScreen();
world = new GameWorld(game, this);
renderer = new GameRenderer(world, game);
}
#Override
public void render(float delta) {
// runTime is the amount of time the game is running
runTime += delta;
// Updates the Game World
world.update(delta);
// Renders everything
renderer.render(runTime);
// Update Key Presses
GameKeys.update();
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
RessourceLoader.disposeGameScreen();
}
}
GameRenderer Class:
public class GameRenderer {
// Instance of PHGame
PHGame game;
// Instance of Game World
private GameWorld world;
// Orthographic Camera
private OrthographicCamera cam;
// If true hitbox's will be shown
private boolean showHitbox;
// Game Objects
private Player player;
public GameRenderer(GameWorld world, PHGame game) {
this.game = game;
this.world = world;
player = world.getPlayer();
cam = new OrthographicCamera();
cam.setToOrtho(true, 640, 480);
showHitbox = false;
game.batcher.setProjectionMatrix(cam.combined);
}
public void render(float runTime) {
// draw objects and hud
}
}
If there are any questions regarding my problem I'll try to answer then as good as I can.
Refer to the github article 'managing your assets'. AssetManagers should not be static. 'This typically would cause black/missing textures or incorrect assets.'
After you dispose your asset manager it can no londer be used. Instead use manager.unload to unload assets. manager.unload("gfx/menuBackground.png");
EDIT:
I also didn't see any overriden show() methods. If you want your assets back you will need to load your assets in the screen's show method every time.

ActorGestureListener Fling does not register

I can't get my app to register a fling action on a specific actor. I have no problem when adding a simple tap to the actor and checking for a tap on the table. Doing the same thing for flick but it does not work. Am I missing something? Looked everywhere online and not much info on the ActorGestureListener's fling.
my Code:
mainLeftTable.setTouchable(Touchable.enabled);
mainLeftTable.addListener(new ActorGestureListener(){
#Override
public void fling(InputEvent event, float velocityX, float velocityY, int button) {
System.out.println(velocityX + " - " + velocityY);
}
});
Nothing happens using this code, I can't see what I'm missing
For reference, setting up tap works with this code:
mainLeftTable.setTouchable(Touchable.enabled);
mainLeftTable.addListener(new ActorGestureListener(){
#Override
public void tap(InputEvent event, float x, float y, int count, int button) {
System.out.println("tapped");
}
I have my stage as the input processor.
Update:
Apparently it is something in ScrollPane that messes it up, if I disable the ScrollPane on my table, the fling works. Why is this? I need the scroll
Are you telling the Gdx app about the listener? that is, calling:
Gdx.input.setInputProcessor(yourListener)
to tell the app about your new listener? And if you have multiple listeners, you'll likely need to use an InputMultiplexer. Not sure how the rest of your code is setup with your "tap" listener.
I did a quick search and ran across the following tutorial which may give an example you can repurpose to your code:
http://www.gamefromscratch.com/post/2013/10/24/LibGDX-Tutorial-5-Handling-Input-Touch-and-gestures.aspx
Edit:
Based on the comments, here is a sample app that works. I think this is what you're trying to do.
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
public class Fling implements ApplicationListener {
private Texture music;
private SpriteBatch batch;
private OrthographicCamera camera;
private Stage stage;
#Override
public void create() {
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
batch = new SpriteBatch();
music = new Texture(Gdx.files.internal("img/sprites/buttons/music_off.png"));
Image image = new Image(music);
Table actor = new Table();
actor.debug();
actor.add(image).width(105).height(105);
actor.setX(100);
actor.setY(100);
actor.setTouchable(Touchable.enabled);
actor.addListener(new ActorGestureListener(){
#Override
public void fling(InputEvent event, float velocityX, float velocityY, int button) {
System.out.println(velocityX + " - " + velocityY);
}
#Override
public void tap(InputEvent event, float x, float y, int count, int button) {
System.out.println("tapped");
}
#Override
public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("touchdown");
}
});
stage = new Stage();
stage.addActor(actor);
Gdx.input.setInputProcessor(stage);
}
#Override
public void render() {
stage.draw();
}
#Override
public void dispose() {
music.dispose();
batch.dispose();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
And when I run it, I see:
I had the same issue and after checking the source code for the ScrollPane, I noticed that the ActorGestureListener already handles the fling event and automatically cancels the touch focus.
Simply call setCancelTouchFocus(false) on your ScrollPane and you will be able to handle the fling event yourself. At least this solved the problem for me.

Why does my TextButton that switches screens cause my application to crash?

I'm currently trying my hand at LibGDX to create a simple game. Currently I have finished working on the main menu and have tried to program the Level Selection menu. I have the following code in my LevelSelection class but my application crashes when I try to click on the "start" button in my main menu to bring up the Level Selection menu:
import java.util.ArrayList;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
public class LevelSelect implements Screen {
private Stage stage;
private TextureAtlas atlas;
private Table table;
private ArrayList<TextButton> buttons;
private Skin skin;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
public void initButtons(){
buttons = new ArrayList<TextButton>();
for(int i=1;i<=5;i++){
TextButton b = new TextButton(("" + i),skin);
buttons.add(b);
}
}
#Override
public void resize(int width, int height) {
/*stage.getViewport().update(width, height, false);
table.invalidateHierarchy();*/
}
#Override
public void show() {
stage = new Stage();
Gdx.input.setInputProcessor(stage);
atlas = new TextureAtlas(Gdx.files.internal("ui/button.pack"));
skin = new Skin(Gdx.files.internal("ui/menuSkin.json"),atlas);
table = new Table(skin);
this.initButtons();
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
stage.dispose();
skin.dispose();
}
}
It seems that the initButtons method isn't the issue either as even without that the application crashes. The application reports no errors, rather I get a Java Platform SE binary has stopped working issue when I click the 'start' button that loads this new screen class.
Thank you for your help!

LIBGDX creating a main menu

So i want to create a mainmenu for my game and i'm stuck on what to do next i have all the art done and it's all in layers and packed in a .pack
public class MainMenu implements Screen {
CrazyZombies game;
Stage stage;
BitmapFont font;
TextureAtlas MainMenu;
Texture road;
Skin skin;
SpriteBatch batch;
public MainMenu(CrazyZombies game){
this.game = game;
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0.09f, 0.28f, 0.2f, 1);
stage.act(delta);
batch.begin();
stage.draw();
batch.end();
}
#Override
public void resize(int width, int height) {
if(stage == null)
stage = new Stage(width, height, true);
stage.clear();
Gdx.input.setInputProcessor(stage);
}
#Override
public void show() {
batch = new SpriteBatch();
skin = new Skin();
MainMenu = new TextureAtlas("data/mainmenu/MainMenu.pack");
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
skin.dispose();
MainMenu.dispose();
stage.dispose();
}
}
If anyone could give me some guidelines or tutorials on what to do now it would be great i've looked in a lot of places but they have not given me the required answers.
Have a look at this tutorial which sums up what you want exactly:
LibGDX: Using a Splash Screen or Menu
i think it will be easy if u use scene2D that will handle all the complexity and help you to create a nice looking UI with a little bit of code .
you may need to check this link
https://github.com/libgdx/libgdx/wiki/Scene2d.ui
Basically, you need to
create a skin, and
we need to add buttionTextureStyle to it.
Don't forget to add fonts, it took me a hour to figure out that fonts are not set by default like other parameters of buttonTextureStyle
and then you create a button with created skin
and then add that button to the stage.

Categories