How to pause and resume a simple game in Java

时光怂恿深爱的人放手 提交于 2019-12-11 04:07:30

问题


i made simple game by java , it's about "tennis background" and "tennis ball" , and the ball is randomally move automatically ,

my game consist of two file , 1st file fore Jpanel , and 2nd file for JFrame ,

my question is : i need to control of "stopping and resuming" the ball by clicking the mouse , i tried to put wait() during thread running loop , but it's faild , i don't know what is the reason ! , so please review my code and then tell me what is the wrong , and what is the true method of "pause&resume" thread in my simple game !

tennis.java file (which contain the thread):

/*
 * tennis.java
 *
 * Created on Nov 15, 2011, 3:35:28 PM
 */
package io;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;


public class tennis extends javax.swing.JPanel implements Runnable{

    BufferedImage ball;
    BufferedImage bg;
    int ball_h = 0;
    int ball_w = 0;
    int height = 0;
    int width  = 0;
    int yPos   = -1;
    int xPos   = 10;
    int pause  = 20;

    // Move Speed
    int xMov   = 5;
    int yMov   = 10;
    boolean clicked = false;
    int play    =   0;

    Thread runner;

    /** Creates new form tennis */
    public tennis() throws IOException {

        ball = ImageIO.read(new File("tennis/ball.png"));
        bg = ImageIO.read(new File("tennis/bg.jpg"));
        ball_h = 50;
        ball_w = 50;
        height = 600 - ball_h;
        width  = 800  - ball_w;

        runner = new Thread(this);
        runner.start();

    }

    public void start(){
       if(play == 0){

           play     =   1;
           clicked = true;

       }else{
           play    =  0;
           clicked = true;
       }

       System.out.println(play);
    }

    public void stop(){
        runner = null;
    }




    @Override
    public void paint(Graphics g){
        Graphics2D g2D  =   (Graphics2D) g;

        g2D.drawImage(bg, 0, 0, 800,600, this);
        g2D.drawImage(ball, xPos, yPos,50,50, this);
    }


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>                        
    // Variables declaration - do not modify                     
    // End of variables declaration                   

    @Override
    public void run() {

        while(runner == runner){



                    if(xPos >= (width))
                        {
                           xMov   *= -1;   
                        }



                           xPos   += xMov;

                    if(xPos < 1)
                        {
                           xMov   *= -1;   
                        }                

                    if(yPos >= (height-ball_h))
                        {
                            yMov    *= -1 ;
                        }



                            yPos    += yMov;

                     if(yPos < 1)
                        {
                            yMov    *= -1 ;
                        }

                    repaint();



                    try {
                        if(play == 1){
                            Thread.sleep(pause);
                        }else{
                            synchronized(this){
                                while(play == 0){
                                wait();
                              }
                            }
                        }

                    } catch (InterruptedException ex) {
                        Logger.getLogger(tennis.class.getName()).log(Level.SEVERE, null, ex);
                    }

        }  
    }

}

Tennis3D.java file(frame for starting the game and define the thread) :

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Tennis3D.java
 *
 * Created on Nov 15, 2011, 3:42:42 PM
 */
package io;

import io.tennis;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Tennis3D extends javax.swing.JFrame implements MouseListener{

    tennis tennis;

    /** Creates new form Tennis3D */
    public Tennis3D() {
        super("Tennis3D");
        setSize(800,600);


        try {
            tennis = new tennis();
            add(tennis);
            tennis.addMouseListener(this);
        } catch (IOException ex) {
            Logger.getLogger(Tennis3D.class.getName()).log(Level.SEVERE, null, ex);
        }


        setVisible(true);

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
       Tennis3D tennis = new Tennis3D();
    }
    // Variables declaration - do not modify                     
    // End of variables declaration                   

    @Override
    public void mouseClicked(MouseEvent e) {
       tennis.start();
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}

Thank you for your help :)


回答1:


This is piggy-backing on what Nerdtron wrote in the comment above. Typically a game loop looks like this

 while (!game.isOver())
 {
      if (!game.isPaused())
           game.update()  // this moves your ball, players, etc
 }



回答2:


Your approach is strange. Most games have a sort of main loop where methods update(deltaTime) and draw() are called sequentially.

Typical main loop:

initGame();
while(!gameOver)
{
    readInput();
    update(deltaTime);
    draw();
}

update(dt) is something like

for(GameObject go : myObjectList)
{
    go.update(deltaTime);
}

If you want to skip some objects you could use something like:

for(GameObject go : myObjectList)
{
    if(go.isActive())
    {
        go.update(deltaTime);
    }
}

So your task would be trivial if you use game-loop structure like that.




回答3:


To stop a thread wait()ing you need to call notifyAll() on the same object.

From the Javadoc for Object.wait()

Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

I would suggest you call notifyAll() in a synchronized block when you set play = 1;




回答4:


A common way to achieve this is by using different states. So when you would put the game on pause it would go in PAUSE state. When resumed it would go back in RUNNING state or some other (more specific) state.
This is done by keeping the state in a variable. The C-way is to define integers like follows:

final int PAUSE = 1;
final int RUNNING = 2;

The Java-way is more like this: (using enums)

public enum State {
    RUNNING,
    PAUSE
}

Then, in your main loop (run method) you check the state in which the game is at that moment, and perform actions accordingly.

switch(state){
    case PAUSE:
        Thread.sleep(100);
        break;
    case RUNNING:
        // do something entertaining
        break;
}


来源:https://stackoverflow.com/questions/8299010/how-to-pause-and-resume-a-simple-game-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!