有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java这个小程序gameloop有什么问题?

这个小程序似乎只会在窗口调整大小或最小化时绘制和更新绘制。因此,小程序不会一直重新绘制,而只是在操作窗口时

我做错什么了吗

我遵循这里介绍的游戏循环:http://www3.ntu.edu.sg/home/ehchua/programming/java/J8d_Game_Framework.html

代码如下:

package newapplet;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GameApplet extends JApplet {     // main class for the game as a Swing application

// Define constants for the game
static final int CANVAS_WIDTH = 493;    // width and height of the game screen
static final int CANVAS_HEIGHT = 411;
static final int UPDATE_RATE = 4;    // number of game update per second
static final long UPDATE_PERIOD = 1000000000L / UPDATE_RATE;  // nanoseconds

static int DRAWS = 0;
// ......

// Enumeration for the states of the game.
public enum gameState {
  INITIALIZED, CONNECTING, PLAYING, DISCONNECTED
}

private gameState state;

// Define instance variables for the game objects
// ......
// ......

// Handle for the custom drawing panel
private GameCanvas canvas;

// Constructor to initialize the UI components and game objects
public GameApplet() {
  // Initialize the game objects
  gameInit();

  // UI components
  canvas = new GameCanvas();
  canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
  this.setContentPane(canvas);

  // Other UI components such as button, score board, if any.
  // ......

  this.setVisible(true);
}

// All the game related codes here

// Initialize all the game objects, run only once in the constructor of the main class.
public void gameInit() {
  // ...... 
  state = gameState.INITIALIZED;
}

// Shutdown the game, clean up code that runs only once.
public void gameShutdown() {
  // ...... 
   state = gameState.DISCONNECTED;
}

// To start and re-start the game.
public void gameStart() { 
  // Create a new thread
  Thread gameThread =  new Thread() {
     // Override run() to provide the running behavior of this thread.
     @Override
     public void run() {
        gameLoop();
     }
  };
  // Start the thread. start() calls run(), which in turn calls gameLoop().
  gameThread.start();
}

// Run the game loop here.
private void gameLoop() {
  // Regenerate the game objects for a new game
  // ......
  //state = State.PLAYING;

  // Game loop
  long beginTime, timeTaken, timeLeft;
  while (true) {
     beginTime = System.nanoTime();
     if (state == gameState.DISCONNECTED) break;  // break the loop to finish the current play
     if (state == gameState.PLAYING) {
        // Update the state and position of all the game objects,
        // detect collisions and provide responses.
        gameUpdate();
     }
     // Refresh the display
     repaint();
     // Delay timer to provide the necessary delay to meet the target rate
     timeTaken = System.nanoTime() - beginTime;
     timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000L;  // in milliseconds
     if (timeLeft < 10) timeLeft = 10;   // set a minimum
     try {
        // Provides the necessary delay and also yields control so that other thread can do work.
        Thread.sleep(timeLeft);
     } catch (InterruptedException ex) { }
  }
}

// Update the state and position of all the game objects,
// detect collisions and provide responses.
public void gameUpdate() { 

}

// Refresh the display. Called back via rapaint(), which invoke the paintComponent().
private void gameDraw(Graphics2D g2d) {
  switch (state) {
     case INITIALIZED:
    g2d.setColor (Color.red); 
    g2d.drawString ("init",20,20);
    break;
     case PLAYING:
    g2d.setColor (Color.red); 
    g2d.drawString ("play",20,20);
    break;
  case CONNECTING:
    g2d.setColor (Color.red); 
    g2d.drawString ("connecting",20,20);
    break;
  case DISCONNECTED:
    g2d.setColor (Color.red); 
    g2d.drawString ("disconnect",20,20);
    break;
  }

  g2d.setColor (Color.GREEN); 
  g2d.drawString ("Re-paint: " + DRAWS,30,30);
  this.DRAWS++;
  // ...... 
}

// Process a key-pressed event. Update the current state.
public void gameKeyPressed(int keyCode) {
  switch (keyCode) {
     case KeyEvent.VK_UP:
        // ......
        break;
     case KeyEvent.VK_DOWN:
        // ......
        break;
     case KeyEvent.VK_LEFT:
        // ......
        break;
     case KeyEvent.VK_RIGHT:
        // ......
        break;
  }
}

// Process a key-released event.
public void gameKeyReleased(int keyCode) {  }

// Process a key-typed event.
public void gameKeyTyped(char keyChar) {  }

// Other methods
// ......

// Custom drawing panel, written as an inner class.
class GameCanvas extends JPanel implements KeyListener {
  // Constructor
  public GameCanvas() {
     setFocusable(true);  // so that can receive key-events
     requestFocus();
     addKeyListener(this);
  }

  // Override paintComponent to do custom drawing.
  // Called back by repaint().
  @Override
  public void paintComponent(Graphics g) {
     Graphics2D g2d = (Graphics2D)g;
     super.paintComponent(g2d);   // paint background
     setBackground(Color.BLACK);  // may use an image for background

     // Draw the game objects
     gameDraw(g2d);
  }

  // KeyEvent handlers
  @Override
  public void keyPressed(KeyEvent e) {
     gameKeyPressed(e.getKeyCode());
  }

  @Override
  public void keyReleased(KeyEvent e) {
     gameKeyReleased(e.getKeyCode());
  }

  @Override
  public void keyTyped(KeyEvent e) {
     gameKeyTyped(e.getKeyChar());
  }
}

// main
public static void main(String[] args) {
  // Use the event dispatch thread to build the UI for thread-safety.
  SwingUtilities.invokeLater(new Runnable() {
     @Override
     public void run() {
        new GameApplet();
     }
  });
}
}

共 (2) 个答案

  1. # 1 楼答案

    GameApplet

    有关一些更正,请参阅此代码

    // <applet code='GameApplet' width=400 height=50></applet>
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class GameApplet extends JApplet {     // main class for the game as a Swing application
    
    // Define constants for the game
    static final int CANVAS_WIDTH = 493;    // width and height of the game screen
    static final int CANVAS_HEIGHT = 411;
    static final int UPDATE_RATE = 4;    // number of game update per second
    static final long UPDATE_PERIOD = 1000000000L / UPDATE_RATE;  // nanoseconds
    Timer timer;
    
    static int DRAWS = 0;
    // ......
    
    // Enumeration for the states of the game.
    public enum gameState {
      INITIALIZED, CONNECTING, PLAYING, DISCONNECTED
    }
    
    private gameState state;
    
    // Define instance variables for the game objects
    // ......
    // ......
    
    // Handle for the custom drawing panel
    private GameCanvas canvas;
    
    // Constructor to initialize the UI components and game objects
    public GameApplet() {
      // Initialize the game objects
      gameInit();
    
      // UI components
      canvas = new GameCanvas();
      // set the size of the applet in HTML, not the content pane!
      canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
      this.setContentPane(canvas);
    
      // Other UI components such as button, score board, if any.
      // ......
    
      //this.setVisible(true);
    }
    
    // All the game related codes here
    
    // Initialize all the game objects, run only once in the constructor of the main class.
    public void gameInit() {
      // ......
      state = gameState.INITIALIZED;
      gameStart();
    }
    
    // Shutdown the game, clean up code that runs only once.
    public void gameShutdown() {
      // ......
       state = gameState.DISCONNECTED;
    }
    
    @Override
    public void destroy() {
        timer.stop();
    }
    
    // To start and re-start the game.
    public void gameStart() {
      // Create a new thread
      //Thread gameThread =  new Thread() {
         // Override run() to provide the running behavior of this thread.
      //   @Override
      //   public void run() {
            gameLoop();
      //   }
      //};
      // Start the thread. start() calls run(), which in turn calls gameLoop().
      //gameThread.start();
    }
    
    // Run the game loop here.
    private void gameLoop() {
      // Regenerate the game objects for a new game
      // ......
      //state = State.PLAYING;
    
      // Game loop
      ActionListener al = new ActionListener() {
    
          long beginTime, timeTaken, timeLeft;
    
          public void actionPerformed(ActionEvent ae) {
             beginTime = System.nanoTime();
             if (state == gameState.DISCONNECTED) {
                 //break;  // break the loop to finish the current play
                 System.out.println("do SOMETHING here..");
             }
             if (state == gameState.PLAYING) {
                // Update the state and position of all the game objects,
                // detect collisions and provide responses.
                gameUpdate();
             }
             // Refresh the display
             repaint();
             // Delay timer to provide the necessary delay to meet the target rate
             timeTaken = System.nanoTime() - beginTime;
             timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000L;  // in milliseconds
             if (timeLeft < 10) timeLeft = 10;   // set a minimum
         }
     };
     timer = new Timer(40,al);
     timer.start();
    }
    
    // Update the state and position of all the game objects,
    // detect collisions and provide responses.
    public void gameUpdate() {
    
    }
    
    // Refresh the display. Called back via rapaint(), which invoke the paintComponent().
    private void gameDraw(Graphics2D g2d) {
      switch (state) {
         case INITIALIZED:
        g2d.setColor (Color.red);
        g2d.drawString ("init",20,20);
        break;
         case PLAYING:
        g2d.setColor (Color.red);
        g2d.drawString ("play",20,20);
        break;
      case CONNECTING:
        g2d.setColor (Color.red);
        g2d.drawString ("connecting",20,20);
        break;
      case DISCONNECTED:
        g2d.setColor (Color.red);
        g2d.drawString ("disconnect",20,20);
        break;
      }
    
      g2d.setColor (Color.GREEN);
      g2d.drawString ("Re-paint: " + DRAWS,30,30);
      this.DRAWS++;
      // ......
    }
    
    // Process a key-pressed event. Update the current state.
    public void gameKeyPressed(int keyCode) {
      switch (keyCode) {
         case KeyEvent.VK_UP:
            // ......
            break;
         case KeyEvent.VK_DOWN:
            // ......
            break;
         case KeyEvent.VK_LEFT:
            // ......
            break;
         case KeyEvent.VK_RIGHT:
            // ......
            break;
      }
    }
    
    // Process a key-released event.
    public void gameKeyReleased(int keyCode) {  }
    
    // Process a key-typed event.
    public void gameKeyTyped(char keyChar) {  }
    
    // Other methods
    // ......
    
    // Custom drawing panel, written as an inner class.
    class GameCanvas extends JPanel implements KeyListener {
      // Constructor
      public GameCanvas() {
         setFocusable(true);  // so that can receive key-events
         requestFocus();
         addKeyListener(this);
      }
    
      // Override paintComponent to do custom drawing.
      // Called back by repaint().
      @Override
      public void paintComponent(Graphics g) {
         Graphics2D g2d = (Graphics2D)g;
         super.paintComponent(g2d);   // paint background
         setBackground(Color.BLACK);  // may use an image for background
    
         // Draw the game objects
         gameDraw(g2d);
      }
    
      // KeyEvent handlers
      @Override
      public void keyPressed(KeyEvent e) {
         gameKeyPressed(e.getKeyCode());
      }
    
      @Override
      public void keyReleased(KeyEvent e) {
         gameKeyReleased(e.getKeyCode());
      }
    
      @Override
      public void keyTyped(KeyEvent e) {
         gameKeyTyped(e.getKeyChar());
      }
    }
    }
    

    请注意,在源代码顶部添加单行注释意味着(编译后)可以使用..从命令行启动它

    > appletviewer GameApplet.java