Как приостановить и возобновить простую игру на Java - PullRequest
2 голосов
/ 28 ноября 2011

я сделал простую игру от java, это про "теннисный фон" и "теннисный мяч", и мяч автоматически перемещается случайно,

моя игра состоит из двух файлов, 1-го файла на Jpanel и 2-гофайл для JFrame,

мой вопрос: мне нужно контролировать «остановку и возобновление» шара, щелкая мышью, я пытался поставить wait () во время цикла выполнения потока, но это не удалось, я нене знаю в чем причина!, пожалуйста, просмотрите мой код, а затем скажите мне, что не так, и каков истинный метод ветки «приостановить и возобновить» в моей простой игре!

файл tennis.java (который содержит ветку):

/*
 * 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 (рамка для запуска игры и определения темы):

/*
 * 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) {

    }
}

Спасибо за помощь:)

Ответы [ 4 ]

2 голосов
/ 28 ноября 2011

Это поддержка того, что Нердтрон написал в комментарии выше.Обычно игровой цикл выглядит следующим образом

 while (!game.isOver())
 {
      if (!game.isPaused())
           game.update()  // this moves your ball, players, etc
 }
1 голос
/ 28 ноября 2011

Ваш подход странный.Большинство игр имеют своего рода основной цикл, где методы update (deltaTime) и draw () вызываются последовательно.

Типичный основной цикл:

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

update (dt) - это что-то вроде

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

Если вы хотите пропустить некоторые объекты, вы можете использовать что-то вроде:

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

Так что ваша задача будет тривиальной, если вы будете использовать такую ​​структуру игрового цикла.

0 голосов
/ 28 ноября 2011

Распространенным способом достижения этого является использование разных состояний. Поэтому, когда вы ставите игру на паузу, она переходит в состояние PAUSE. После возобновления он вернется в состояние RUNNING или в другое (более конкретное) состояние.
Это делается путем сохранения состояния в переменной. C -путь должен определять целые числа следующим образом:

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

Путь Java больше похож на это: (используя enum s)

public enum State {
    RUNNING,
    PAUSE
}

Затем в своем основном цикле (метод run) вы проверяете состояние, в котором игра находится в данный момент, и соответственно выполняете действия.

switch(state){
    case PAUSE:
        Thread.sleep(100);
        break;
    case RUNNING:
        // do something entertaining
        break;
}
0 голосов
/ 28 ноября 2011

Чтобы остановить ожидание потока (), необходимо вызвать notifyAll () для того же объекта.

Из Javadoc для Object.wait ()

Заставляет текущий поток ждать, пока другой поток не вызовет метод notify () или метод notifyAll () для этого объекта.

Я бы посоветовал вам вызывать notifyAll () в синхронизированном блоке, когда вы устанавливаете play = 1;

...