2016-08-31 42 views
1

我一直在嘗試使運行渲染(圖形g)和邏輯()但不起作用的canvas遊戲循環。如何使Java Canvas遊戲循環

我已經嘗試製作一個腳本來運行這兩個函數,然後再次調用自己來創建一個循環。

在此先感謝。

我嘗試這樣做:

public class Canvas extends JPanel { 
static GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); 
static int width = gd.getDisplayMode().getWidth(); 
static int height = gd.getDisplayMode().getHeight(); 
//Get the system time 
long lastTime = System.nanoTime(); 
//Specify how many seconds there are in a minute as a double 
//store as a double cause 60 sec in nanosec is big and store as final so it can't be changed 
final double ticks = 60D; 
//Set definition of how many ticks per 1000000000 ns or 1 sec 
double ns = 1000000000/ticks;  
double delta = 0; 

public static void main(String[] args) { 
    JFrame frame = new JFrame("Zombie Run"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.add(new Canvas()); 
    frame.setSize(width, height); 
    frame.setVisible(true); 
    loop(); 
} 

public static void loop() { 
    logic(); 
    render(g); 
    loop(); 
} 
public static void render(Graphics g) { 
    System.out.println("Running Render"); 
    g.setColor(Color.BLUE); 
    g.fillRect(0, 0, 800, 500); 

} 
public static void logic() { 
    System.out.println("Logic"); 

} 

}

我從日食得到的錯誤是:

Logic 
Running Render 
Exception in thread "main" java.lang.NullPointerException 
    at ZombieGame.Canvas.render(Canvas.java:41) 
    at ZombieGame.Canvas.loop(Canvas.java:36) 
    at ZombieGame.Canvas.main(Canvas.java:31) 
+2

你可以使用[Swing'Timer'](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)。如果這沒有幫助,請發佈您以[MCVE]形式嘗試過的內容。 –

+0

「一個運行這兩個函數的腳本會再次調用它自己來創建一個循環」 - 腳本不應該在java代碼中。如果它調用自己的方法,你正在運行一個stackoverflow。我想知道你是否沒有聽說過強大的「while」循環。如果不是不想寫電腦遊戲。 – ArcticLord

+0

是的,我沒有嘗試雖然真正的循環,但它拋出了錯誤,並不會工作 –

回答

1

你可以使用一個Swing Timer。 while循環和Thread.sleep只會導致GUI凍結。

我使用Timer類做了一個例子。它會創建一個延遲爲42毫秒的計時器。每次延遲後,它都會執行ActionListener中的代碼。這個例子在面板上繪製了隨機矩形,就像那個linux屏幕保護程序一樣:P我不認爲你必須擔心我特別是如何做得太多,這只是爲了說明如何使用Timer

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Random; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

public class Foo { 

    public static void main(String[] args) throws IOException { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Foo().createAndShowGUI(); 
      } 
     }); 
    } 

    public void createAndShowGUI() { 
     DrawingPanel panel = new DrawingPanel(); 

     Timer timer = new Timer(42, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       panel.addNewRectangle(); 
       panel.repaint(); 
      } 
     }); 
     timer.start(); 

     JFrame frame = new JFrame("Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setContentPane(panel); 
     frame.setSize(800, 600); 
     frame.setVisible(true); 
    } 

    private class GameRectangle extends Rectangle { 
     private Color color; 

     public GameRectangle(int x, int y, int width, int height, Color color) { 
      setBounds(x, y, width, height); 
      setColor(color); 
     } 

     public void draw(Graphics2D context) { 
      context.setColor(getColor()); 
      context.fill(this); 
     } 

     public Color getColor() { 
      return color; 
     } 

     public void setColor(Color color) { 
      this.color = color; 
     } 
    } 

    private class DrawingPanel extends JPanel { 
     private final Random RANDOM = new Random(); 
     private ArrayList<GameRectangle> rectangles; 

     public DrawingPanel() { 
      setRectangles(new ArrayList<>()); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2 = (Graphics2D) g.create(); 
      for (GameRectangle rectangle : getRectangles()) { 
       rectangle.draw(g2); 
      } 
      g2.dispose(); 
     } 

     public void addNewRectangle() { 
      getRectangles().add(createRandomRectangle()); 
     } 

     private Color createRandomColor() { 
      return new Color(RANDOM.nextInt(255), RANDOM.nextInt(255), RANDOM.nextInt(255)); 
     } 

     private GameRectangle createRandomRectangle() { 
      return new GameRectangle(RANDOM.nextInt(getWidth()), RANDOM.nextInt(getHeight()), RANDOM.nextInt(420), 
        RANDOM.nextInt(420), createRandomColor()); 
     } 

     public ArrayList<GameRectangle> getRectangles() { 
      return rectangles; 
     } 

     public void setRectangles(ArrayList<GameRectangle> rectangles) { 
      this.rectangles = rectangles; 
     } 
    } 

} 
+0

謝謝,但你可以改變它只顯示一個正方形,因爲我真的不需要多彩色的方形垃圾郵件 –

+0

@JacobGoddard嗯,它只是一個我提供的例子演示了一個計時器如何工作。如果你瞭解這些基礎知識,你也可以實現你想要做的事情。當然,只需將'loop'方法的代碼放在定時器的'actionPerformed'方法內,不需要遞歸調用。 –

0

使用java.lang.Threadjava.lang.Runnable

在您的班級中實施Runnable並創建一個線程。 記得實現run()方法。

public class Canvas extends JPanel implements Runnable{ 
    Thread mainThread = new Thread(this); //Creates a new thread with Canvas runnable object. 

    //code 

    @Override 
    public void run(){} 
} 

因此,在主要方法中,我們啓動線程。

public static void main(String[] args){ 
    //your frame creation and initialization code. 

    mainThread.start(); //starts the thread. 
} 

所以你已經開始了線程。現在線程將進入run()方法。

boolean isStarted = false; 
public void run(){ 
    isStarted = true; 
    while(isStarted){ 
     logic(); 
     render(g); 
    } /* The thread will return in this loop each has finished a task */ 
     // It's useless to call this method because the thread does all. 
     // Leave it to the thread. 
} 

使用線程,因爲swing不是線程安全的!!!!!!!!

由於圖形未初始化,因此拋出了NullPointerException。