I am creating a game, how to implement a pause menu?

Asked

Viewed 392 times

0

I am creating a game in Android studio using the Surfaceview class that is instantiated in Mainactivity and a thread that is instantiated in Surfaceview, the problem is when I turn on and off the screen it goes back to the initial state, ie it does not save the positions/state, actually, I was wondering how to implement a break menu ...

IMAGERY

before pressing the Off Screen button (I tapped the screen to [circle/bird] jump) inserir a descrição da imagem aqui

after pressing the button on screen (the [circle/bird] back to fall position) inserir a descrição da imagem aqui

Source code below

Mainactivity

public class MainActivity extends Activity {

private Game game;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FrameLayout container = findViewById(R.id.container);
    game = new Game(this);
    container.addView(game);
}
@Override
protected void onPause() {
    super.onPause();
    game.cancela();
}

@Override
protected void onResume() {
    super.onResume();
    game.inicia();
    new Thread(game).start();
      }
   }

Game Class (Gameview)

public class Game extends SurfaceView implements Runnable,View.OnTouchListener{
private final SurfaceHolder holder = getHolder();
private boolean isRunning = true;
private Player passaro;
private Bitmap background;
private Tela tela;


public Game(Context context) {
    super(context);
    setOnTouchListener(this);
    inicializaElementos();
}

private void inicializaElementos() {
    tela = new Tela(getContext());
    this.passaro = new Player();
    Bitmap back = BitmapFactory.decodeResource(getResources(),
            R.drawable.background);
    this.background = Bitmap.createScaledBitmap(back,
            tela.getLargura(), tela.getAltura(), false);

}

public void update() {
    passaro.update();
}

@Override
public void run() {
    while (isRunning) {
        if (!holder.getSurface().isValid()) continue;
        //Neste loop vamos gerenciar os elementos do Jumper.
        //
        Canvas canvas = holder.lockCanvas();
        update();
        //
        //Aqui vamos desenhar os elementos do jogo!
        canvas.drawBitmap(background, 0, 0, null);
        passaro.desenhaNo(canvas);
        //
        holder.unlockCanvasAndPost(canvas);
    }
}

public void cancela() {
    this.isRunning = false;
}

public void inicia() {
    this.isRunning = true;
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
    passaro.pula();
    return false;
     }
  }

Player class(bird)

public class Player {
private static final Paint vermelho = Cores.getCorDoPassaro();
private int x;
private static final int RAIO = 50;
private int y, velY = 0;
private int gravity = 1;
//private float fric = 0.3f;
//private boolean jump = false;

public Player() {
    this.y = 0;
    this.x = 100;
}

public void pula() {
    this.velY = -30;
    cai();
}

public void update() {
    if (chao()) {
        this.y = 1080 - RAIO;
        this.velY = 0;//(int) (-this.velY*this.fric);
    } else {
        cai();
    }
}


private boolean chao() {
    if (this.y >= 1080 - RAIO) {
        return true;
    }
    return false;
}

private void cai() {
    this.y += this.velY;
    this.velY += this.gravity;
}


public void desenhaNo(Canvas canvas) {
    canvas.drawCircle(x, y, RAIO, vermelho);
   }
}

Screen Class

public class Tela {
private DisplayMetrics metrics;

public Tela(Context context) {
    WindowManager wm = (WindowManager) context.getSystemService(
            Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    metrics = new DisplayMetrics();
    display.getMetrics(metrics);
}

public int getAltura() {
    return metrics.heightPixels;
}

public int getLargura() {
    return metrics.widthPixels;
   }
}

Class Colors

public class Cores {
public static Paint getCorDoPassaro() {
    Paint vermelho = new Paint();
    vermelho.setColor(0xFFFF0000);
    return vermelho;
   }
}
  • Be more specific in your question, put what you already have of code. Screenshots of the problem on the screen, etc.

  • @hugocsl I just put

1 answer

1


To pause within the game a simple way would be to create any variable and check inside the loop of your game.

Ex:

@Override
public void run() {
    while (isRunning) {
        if(isPaused) continue; // Aqui checa de o jogo esta pausado ou não;
        if (!holder.getSurface().isValid()) continue;
        //Neste loop vamos gerenciar os elementos do Jumper.
        //
        Canvas canvas = holder.lockCanvas();
        update();
        //
        //Aqui vamos desenhar os elementos do jogo!
        canvas.drawBitmap(background, 0, 0, null);
        passaro.desenhaNo(canvas);
        //
        holder.unlockCanvasAndPost(canvas);
    }
}

Now to pause the game and exit it and then come back you need to save the information from it before. You can use the onSaveInstanceState to save and then into onCreate you recharge them.

static final String Tag_intQualquer = "tint";
static final String Tag_stringQualquer = "tstring";

int intQualquer;
String stringQualquer;

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
    savedInstanceState.putInt(Tag_intQualquer, intQualquer);
    savedInstanceState.putString(Tag_stringQualquer, stringQualquer);

    super.onSaveInstanceState(savedInstanceState);
}

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    // verifica se existe algo salvo para ser recarregado
    if (savedInstanceState != null) 
    {
        carrega os dados do jogo anterior
        intQualquer = savedInstanceState.getInt(Tag_intQualquer);
        stringQualquer = savedInstanceState.getInt(Tag_stringQualquer);
        // com os dados carregados você gera um Player e manda para para a classe Game
    } 
    else 
    {
        // recomeçar o jogo do inicio           
    }
}

then just make some modifications in the constructor of your class Game so that he can receive an object Player

public Game(Context context, Player old) 
{
    super(context);
    setOnTouchListener(this);
    inicializaElementos(old);
}

private void inicializaElementos(Player old)
{
    tela = new Tela(getContext());
    if(old == null)
    {
        this.passaro = new Player();
    }
    else
    {
        this.passaro = old;
    }
    Bitmap back = BitmapFactory.decodeResource(getResources(),
            R.drawable.background);
    this.background = Bitmap.createScaledBitmap(back,
            tela.getLargura(), tela.getAltura(), false);
}
  • I disagree on the if (isPaused) continue;, because ends up spending processing and battery unnecessarily

  • 1

    I agree with you disagreeing, hahaha. Some better simple solution? @Jeffersonquesado

  • I’d like to know what the most Android would be, but I don’t know. This solution would be based on implementing a function that would redesign the screen, which would not be in a loop. From experience needing to manipulate "real-time action interfaces", I have Python expectations with Tkinter and Pygame. In the case of Tkinter (an interface that was made to be programmed based on events), after drawing the frame, I scheduled another frame design for a quick time, I think 60 FPS, hence drawing again took into account the time elapsed from the beginning of the drawing of the previous frame...

  • ... until the beginning of the current frame (interval between two ticks), making the moves based on this time window. In the case of Pygame, which was already more of a "real-time interface", I made an infinite loop sleeping around 17ms before starting the next iteration; to make the moves, I also took into account the difference between two ticks, not the time I had asked to sleep.

  • In that scheme there, I would particularly do something like this: while (running) { long tick = getTick(); getNextFrameUpdater().updateFrame(tick); sleep(4); }. I could have put it to be sleep(17) for 60 FPS, but then any fluctuation between the sleep() and the next action would make Android lose a frame, so I prefer to have a greater guarantee that I will draw fluidly. Note to the getNextFrameUpdater(): it takes into account the internal state of the program (type by variable isPaused that you quoted) and select how you will update the screen; if you have it in pause, it will not be the game

Browser other questions tagged

You are not signed in. Login or sign up in order to post.