i am newbie for libgdx,
How to create very simple pause/resume game in libgdx??
I'm trying to implement simple game using libgdx. I have want to create pause the game but don't know how to pause and resume game based on user input.Kindly suggest idea as well as some practical code to implement the same.I am using simple game code demonstrated in libgdx library. Thank you.
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
float x;
float y;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
x= x+4;
if(Gdx.input.isKeyPressed(Input.Keys.P)){
// pause
}
batch.begin();
batch.draw(img, x, y);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
}
}
Press P key to press the game
if(Gdx.input.isKeyPressed(Input.Keys.P)){
// if(game.pause()){
game.resume();
}else{
game.pause();
}
}
any idea??? thanks
Your render method is called repeatable and what "paused" means is up to you. You have to implement your logic that handles "paused" state because that doesn't mean anything to libGDX.
If you want everything to freeze when game is paused but still to be drawn best way is (IMHO) to fully separate drawing from calculating (movements and stuff). So i.e. when your render method is called you will call your drawing method once (to draw the graphics) but you will also calculate how many times your calculation method should be call (to have same game speed independently on frame rate) and call it that many times.
Then when your game is paused you will just skip calling your calculation method and call only drawing method. So nothing will move and until you end your pause the same graphics will be drawn.
And to keep paused state you can have some boolean variable. Every time p key is pressed you should invert it, like:
if(Gdx.input.isKeyPressed(Input.Keys.P)){
paused = !paused;
}
or something (as #Tenfour04 suggested).
Related
I am having a problem in with this part of the code, I am creating a very simple game in Java with the implementation of LibGDX.
I have three different game states that are handled in three different classes:
StateCreation
MenuState
PlayState
They all work perfectly except for one thing. The music that I have inserted and that is created in the StateCreation should start over, when the player gets to the gameover and the state changes the mode to start over or go back to the menu. This does not happen and the music overlaps
public class GameBarbo extends ApplicationAdapter {
//impostazioni base dell'applicazione
public static final int WIDTH = 480;
public static final int HEIGHT = 800;
public static final String TITLE = "Cavaliere";
private GameStateManager gsm = new GameStateManager();
private SpriteBatch batch;
private Music music;
#Override
public void create () {
batch = new SpriteBatch();
music = Gdx.audio.newMusic(Gdx.files.internal("sound.mp3"));
music.setVolume(0.1f);
music.play();
Gdx.gl.glClearColor(1, 0, 0, 1);
gsm.push(new MenuState(gsm));
}
#Override
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gsm.update(Gdx.graphics.getDeltaTime());
gsm.render(batch);
}
#Override
public void dispose() {
super.dispose();
music.dispose();
}
}
You code looks very much like what I found in this guide (though they don't include super.dispose().)
Is it possible that when your game state changes, the dispose() method does not execute? I haven't used libgdx in ages, but it could be the case that dispose() only executes when you exit the program.
I see from this wiki that the Music class has a stop() method. Perhaps that needs to be called directly when the game ends. But IDK if stopping the file and executing a reload for another iteration is asking for a memory leak or not.
Hopefully someone with more experience will answer, but maybe these thoughts will help you figure something out in the meantime.
Hardly, do I understand multithreading stuff. And beginning look into it , I faced one issue, that came in my mind. I have recently wrote one simple application, and as soon as I get some new knowledge about Java I wish to improve my app with that I’ve learned.
It looks like simple swing GUI that updates images every period of time. I implemented ActionListener and overrode actionPerformed method. Timer with 15ms delay, repainted JPanelclass and everything worked fine. But I thought that updating my GUI using timer directly in actionPerformed (I presume that it’s another thread, but I’m barely sure) is bad idea. So I decided to change code and use SwingWorker. I called all my methods for my animation inside process() .. and again app working fine but it became extremely slow.
Now I’m thinking what’s wrong? Why it acts slower then before ? My timer delay is actually not waiting 15ms , it’s much slower even though delay the same. Am I made mistake with multithreading ?
Help me understand this stuff. Thanks in advance
public class GameEngine() extends SwingWorker<Void, Drawable>
GamePanel gp; // ref to JPanel class
{
public GameEngine(GamePanel gp)
{
this.gp = gp;
}
}
protected void doInBackground()
{
publish();
}
protected void process(List<Drawable> chunks)
{
Timer timer = new Timer(15, e ->
{
//methods for animation
fall();
animate();
checkTouch();
});
}
Some code I left beyond. If you need it I can write...
EDITION
Just for clarity of my issue I provide some more examples and addition explanation.
**Used to be: **
public class GamePanel extends JPanel
{
public void GamePanel()
{
GameEngine engine = new GameEngine(this);
}
//some images , variables etc...
protected void paintComponent(Graphics g)
super.paintComponent(g)
g.drawImage(image1, x, y, null);
g.drawImage(image2, w, z,null);
...
}
public class GameEngine () implements ActionListener
{
GamePanel gp;
Timer timer;
public void GameEngine(GamePanel gp)
{
this.gp = gp;
timer = new Timer( 15 , this );
}
public void actionPerformed()
{
//these methods repaint my GamePanel every 15ms.
fall(); // make object (image) increment on Y Axis
animate(); // make another object (image) decrement on X Axis
checkTouch(); // check if objects collided
}
}
**Became: **
public class GamePanel extends JPanel
{
public void GamePanel()
{
GameEngine engine = new GameEngine(this);
}
//some images , variables etc...
protected void paintComponent(Graphics g)
super.paintComponent(g)
g.drawImage(image1, x, y, null);
g.drawImage(image2, w, z,null);
...
}
public class GameEngine () extends SwingWorker<Void, Drawable>
{
GamePanel gp;
Timer timer;
public void GameEngine(GamePanel gp)
{
this.gp = gp;
}
protected void doInBackground()
{
process();
}
protected void progress()
{
timer = new Timer (15, e->
{
new ActionListener(new actionPerformed)
{
//these methods repaint my GamePanel every 15ms.
fall(); // make object (image) increment on Y Axis
animate(); // make another object (image) decrement on X Axis
checkTouch(); // check if objects collided
}
});
}
protected void done()
{
};
}
When I created it first I implemented ActionListener and updated my panel through timer declared in constructor.. I presumed that it’s thread-unsafe.
That’s why I transfer everything in progress method where I declared timer which ActionListener as lambda argument.
In other words I call all methods for animation in another thread.
Finally it became slower, comparing with first example..
I don’t understand
Is Timer from first example EDT or it’s another thread ?
My first example is thread safe ?
Why my second example goes much slower then first one ?
I heard about NOT update your GUI outside EDT, is it that case?
There is not enough information in your question to answer it, but I will take your queries about multi-threading and the implied question about Swing and rendering and see if I can help you out.
I think the most likely reason for your slowdown is unnecessary screen updating. Once a pixel has been drawn onto the canvas or whatever in your application, usually your application does not need to redraw it unless it is supposed to change; either a sprite moves or some other image in your app obscures a part of the drawing temporarily and then needs to be restored.
It is common for a novice repainting to ignore this, and just repaintng the entire painted surface. Although this will work, it is slow; if you're doing it a number of times in a loop, then the loop will seem slow.
The better way to do this is to use the rectangle passed into the redrawing routine and only repaint its intersection with the entire surface redrawn by your routine -- this cuts way down on the part that needs to be redrawn, and therefore on the time it takes to redraw it.
As for multithreading, I think it's helpful to think of it the way we used to think of things in a single-processor world -- the computer does something for a while, then stops in a place you cannot predict and does something in the other thread for a while, etc. You cannot assume the order in which things are going to get done, or how long it will spend on each thing, etc.
With modern multi-core computers, it is possible that these things in fact get done at the same time, but I don't know that trying to envision that helps you any.
Is there a way to check if my sprite is visible? For instance I have a specific sprite I want to appear only IF this other sprite isn't visible. Example "You Win" will only appear if you win the game and the "You Lose" sprite isn't already on the screen. Thanks!
Visibility of sprite can be maintained by extending Sprite class. Add data member in your extended Sprite Class and at run-time check your sprite is visible of not.
you can also fulfill your requirement by this :
private Sprite win,loose;
private SpriteBatch spriteBatch;
private DialogType dialogType;
#Override
public void create () {
dialogType=DialogType.NONE;
spriteBatch=new SpriteBatch();
win=new Sprite(...);
loose=new Sprite(...);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
...
...
if(dialogType==WIN){
win.draw(spriteBatch);
}else if(dialogType==LOOSE){
loose.draw(spriteBatch);
}
spriteBatch.end();
}
public enum DialogType {
NONE,WIN,LOOSE
}
Seems like an overwhelm to do what you are trying to do, like I said in the comment with a simple boolean win,loose; you pretty much cover your example, or like other comment said you should not track the game state according with some sprite visibility make a enum and track the game state instead, like the other answer, BUT ima give you a solution
Use Image instead...
Image image = new Image(texture);
image.setBounds(0,0,100,100); // set x,y,width,height
stage.add(image); //add to stage
image.setVisible(false); //make it invisible
image.setVisible(true); //make it visible
image.isVisible(); //check if is visible
i'm making a game in libgdx but i'm new and i don´t know if my code is the correct form or the best way to do it.
i'm trying to make the basis of the game:
a screen manager to implement a Menu,
an option screen
a loading screen
a game screen
a pause Screem
a game over screen
In the loading screen I like to do something like Dragon Ball when the loading screen allow us to make goku eat rice, the pause screen needs to draw some statistics and options something like Megaman or Castlevania, the menu do something when the player touch a button something like move the camera or open a door, or move to another "scenario" showing another options, and the game over screen needs to previously gives the player the opportunity to win some life to not lose the game.
I try to make this in this form:
I have the main class of the game with the constructor, and the overriden metods create(), render(), resize() and dispose(), the variables for a camera, a viewport, a Spritebatch, a int to store the current screen, and a manager for the screens.
public class BOS_Project extends Game {
OrthographicCamera camera;
Viewport viewport;
SpriteBatch batch;
AssetManager manager = new AssetManager();
int actualScreen = 0;
public BOS_Project(){
camera = new OrthographicCamera();
camera.setToOrtho(false, screenWidth, screenHeight);
viewport = new FitViewport(screenWidth, screenHeight);
}
#Override
public void create(){
batch = new SpriteBatch();
}
#Override
public void render(){
actualScreen = 1;
ScreenManager.getInstance().showScreen(1, this);
super.render();
}
#Override
public void resize(int width, int height){
viewport.update(width, height);
}
#Override
public void dispose(){
batch.dispose();
}
}
Also the class ScreenManager is singleton, and
public class ScreenManager{
private static ScreenManager instance;
private Game game;
Screen screen;
private ScreenManager(){
super();
}
public static ScreenManager getInstance(){
if(instance == null){
instance = new ScreenManager();
}
return instance;
}
public void initialize(Game game){
this.game = game;
}
public void showScreen(int currentscreen, BOS_Project game){
if(currentscreen == 1){
if(screen!=null)
screen.dispose();
screen = new LoadingScreen(game, game.actualScreen);
game.setScreen(screen);
}else if(currentscreen == 2){
if(screen!=null)
screen.dispose();
screen = new GameScreen(game);
game.setScreen(screen);
}else{
if(screen!=null)
screen.dispose();
screen = new MenuScreen(game);
game.setScreen(screen);
}
}
The other classes are the MenuScreen, GameScreen and Loading Screen.
Loading Screen:
public LoadingScreen(BOS_Project game2, int screen2){
game = game2;
screen = screen2;
game.manager.load("button.png", Texture.class);
game.manager.finishLoadingAsset("button.png");
sprite1 = new Sprite(game.manager.get("button.png", Texture.class));
sprite1.setPosition(0, 0);
//This is a method to load the assets for the especific screen
game.load(screen);
}
#Override
public void render(float delta){
if(game.manager.getProgress()==1) {
if (time < 3) {
Gdx.app.log("Loading: ", "90.0");
}
}else {
Gdx.app.log("Loading: ", String.valueOf(game.manager.getProgress() * 100));
}
game.manager.update();
batch = game.batch;
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite1.draw(batch);
if(game.manager.getProgress()==1 && time > 3){
if(screen==1) {
ScreenManager.getInstance().showScreen(2, game);
}else{
ScreenManager.getInstance().showScreen(3, game);
}
}else{
time += delta;
}
batch.end();
super.render(delta);
}
The Menu and Game classes are similar to loading, only call the assets and draw some sprite on the render method.
This code function well to change screens but I don't know if is the correct form, and another big question is how to manage the pause screen, because I manage this only storing a variable if the variable is pause the render method draw something, if not draw the normal game, but if I want to change the options and images of the pause I need to check variables to know what the pause needs to draw.
if(pause){
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
spritePause.draw(batch);
batch.end();
}else if(game){
batch.begin();
spriteGame.draw(batch);
batch.end();
}
So, am i doing it right? or what would you recommend me? Some examples or maybe specific tutorials to achieve this would be great.
There is not only one correct way of managing screens. Libido gives you the freedom to do it exactly how you please. You can extend the Screen class to make screens for the different needs of your project. You can manage your screens as states and manage them with a state manager.
Regarding the Pause and Game Over screen, you can do that in different ways too.
You can have a dedicated screen to switch to or you can have a Pause and GameOver state in your Game state/screen and show the Pause/GameOver elements on top of your gamescreen while the game is still in the background.
So there is not a single correct way of doing it. The correct way is what works for your game.
For some inspiration:
pixnbgames.com : How to manage screens
Brent Aureli : Game State Manager
As #IronMonkey has answered, there is no "correct" way.
I do it with one GameScreen class only, and have a lot of different states inside the GameScreen class. The GameScreen class is very simple and short (100-200 LOC), and is responsible for switching between states. States are similar to the GameScreen class, but they can be entered and exited without the need to instantiate new objecs.
class GameScreen extends ScreenAdapter implements Disposable {
GameState menuState;
GameState playState;
GameState currentState;
public GameScreen(final MyGame game) {
menuState = new MenuState(this);
playState = new PlayState(this);
}
public void setState(GameState state) {
if(currentState == state) return;
// states have a method 'exit' where you can pause them or finalize something
if(currentState != null)
currentState.exit();
currentState = state;
// also states have 'enter' where you can unpause or init something when entering
currentState.enter();
}
public void render(float delta) {
currentState.render(delta);
}
}
First, this is very resource efficient, because the needed states are created only once when the game is started. Second, because you never destroy the states, but just change them and call enter/exit, they always retain perfectly their current state, i.e. variables, objects and everything and when you go back to a state, it is exactly as it was before you left it.
GameState is interface and you are free to implement it as you wish.
public interface GameState
{
public void enter();
public void exit();
public void update(float delta);
public void render(SpriteBatch batch, float delta);
public String toString();
public void dispose();
}
I recently started to learn about android and java and to practice I started to make a space invader-type game.
In order to draw all the images(player/enemy/etc) I've been using an overridden onDraw method and canvas.DrawBitmap(..). This is where my problem starts. Whenever I draw the images with their new X,Y coordinates, the previous bitmap is still on the canvas which makes everything overlap. Is there some way to refresh the canvas or just get rid of the "leftovers"(I don't even know what to call them). When I made this I was under the impression that I just move the 1 image across the screen but it looks like I was wrong.
This is the code I use to draw the player bitmap:
public void render(Canvas canvas){
//draw the player image
canvas.drawBitmap(_bmPlayerImg, (float) (_dX - (_iHalfWidth)),
(float)(_dY - (_iHalfHeight)), null);
}
The onDraw() method:
#Override
protected void onDraw(Canvas canvas) {
//draw the player
_player.render(canvas);
}//end method
The onDraw() method is called in a thread I use as my game timer every 50ms:
public Runnable runnable = new Runnable() {
#Override
public void run() {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder){
//update the state of all objects in the game
gamePanel.update(canvas);
gamePanel.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}//end if
}//end finally
handler.postDelayed(this, _iRepeatTime);
}
};
Any help is appreciated...I tried looking it up but I couldn't find anything.
Before you draw anything on the canvas:
//clear the canvas
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
And now your canvas is clear and you can draw your character.
If your onDraw method was in an expanded view class and was triggered by you calling invalidate(), then the canvas would automatically clear itself. But you are manually calling it (looks like you are using a surface/texture view?), so you have to clear it manually.