2015-03-05 2 views
1

Я слежу за другим руководством по разработке java-игры, чтобы получить базовое представление о потоковой передаче, я взял these учебники и объединил их с программированием openGL, которое я узнал ранее. Кроме того, я думаю, что, возможно, что-то пропустил, потому что при вызове engine.stop() (это включает в себя thread.join()) окно закрывается, и программа зависает в фоновом режиме, и вы должны завершить ее процесс.Java OpenGL - Thread Hangs When It Shouldnt

Вот мой код:

package com.daboom.threadgl; 

import org.lwjgl.LWJGLException; 
import org.lwjgl.input.Keyboard; 
import org.lwjgl.input.Mouse; 
import org.lwjgl.opengl.Display; 
import org.lwjgl.opengl.DisplayMode; 
import org.lwjgl.opengl.GL11; 

import com.daboom.threadgl.graphics.Camera; 

public class EngineMain implements Runnable { 

    private boolean running; 
    private Thread thread; 
    private Camera cam; 


    /** 
    * Starts the Dual Threaded System, does not need to be called, 
    * already called upon application beginning 
    */ 
    @Override 
    public void run() { 
     initDisplay(); 
     long lastTime = System.nanoTime(); 
     long timer = System.currentTimeMillis(); 
     final double ns = 1000000000.0/60.0; 
     double delta = 0; 
     int frames = 0; 
     int updates = 0; 
     while (running) { 
      long now = System.nanoTime(); 
      delta += (now - lastTime)/ns; 
      lastTime = now; 
      while (delta >= 1) { 
       update(); 

       updates++; 
       delta--; 
      } 

      render(); 
      if (Display.isCloseRequested()) 
       break; 
      frames++; 

      if (System.currentTimeMillis() - timer > 1000) { 
       timer += 1000; 
       System.out.println(updates + " u/sec " + frames + " f/sec"); 
       Display.setTitle(Game.gameName + " || " + updates + " u/sec " + frames 
         + " f/sec ||"); 
       updates = 0; 
       frames = 0; 
      } 

     } 
     stop(); 
    } 

    private void update() { 
     game.update(); 
    } 

    Game game; 

    private void render() { 
     GL11.glLoadIdentity(); 
     GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); 
     cam.useView(); 
     game.render3D(); 
     cam.setProjection2D(Display.getWidth(), Display.getHeight()); 
     game.render2D(); 
     Display.update(); 
     cam.resetTo3D(); 
    } 

    public EngineMain() { 
     cam = new Camera(); 
     game = new Game(this, cam); 
    } 

    private void initDisplay() { 
     try { 
      Display.setDisplayMode(new DisplayMode(800, 600)); 
      Display.setTitle(Game.gameName); 
      Display.create(); 
     } catch (LWJGLException e) { 
      e.printStackTrace(); 
     } 

     GL11.glEnable(GL11.GL_BLEND); 
     GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 
     GL11.glClearColor(0, 0, 0, 1); 
     cam.setProjection3D(63,(float) Display.getWidth()/(float)Display.getHeight(), 0.3f, 
       1000); 


     try { 
      Keyboard.create(); 
      Mouse.create(); 
     } catch (LWJGLException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Starts the Multi-Threading and the Game 
    * 
    */ 
    public synchronized void start() { 
     running = true; 
     thread = new Thread(this, "Display"); 
     thread.start(); 
    } 
    /** 
    * Safely Stops the program 
    * Call this to exit the game 
    */ 
    public synchronized void stop() { 
     running = false; 
     Mouse.destroy(); 
     Keyboard.destroy(); 
     Display.destroy(); 

     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     EngineMain main = new EngineMain(); 
     main.start(); 
    } 

} 

Когда я использовать свои учебники, с из модификации использовать свой код, процесс завершается должным образом.

Я не могу для жизни меня идентифицировать проблему.

P.S Если вам нужно больше комментариев, просто спросите.

EDIT: Вот исходный код перед модификацией

package com.thecherno.rain; 

import java.awt.Canvas; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferStrategy; 
import java.awt.image.BufferedImage; 
import java.awt.image.DataBufferInt; 

import javax.swing.JFrame; 

import com.thecherno.rain.graphics.Screen; 
import com.thecherno.rain.input.Keyboard; 

public class Game extends Canvas implements Runnable { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    public static int width = 300; 
    public static int height = width/16 * 9; 
    public static int scale = 3; 
    public static String title = "Rain"; 
    private Thread thread; 
    private JFrame frame; 
    private Keyboard key; 
    private boolean running = false; 

    private Screen screen; 

    private BufferedImage image = new BufferedImage(width, height, 
      BufferedImage.TYPE_INT_RGB); 
    private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()) 
      .getData(); 

    public Game() { 
     Dimension size = new Dimension(width * scale, height * scale); 
     setPreferredSize(size); 
     screen = new Screen(width, height); 
     frame = new JFrame(); 
     key = new Keyboard(); 
     addKeyListener(key); 
    } 

    public synchronized void start() { 
     running = true; 
     thread = new Thread(this, "Display"); 
     thread.start(); 
    } 

    public synchronized void stop() { 
     running = false; 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    public void run() { 
     long lastTime = System.nanoTime(); 
     long timer = System.currentTimeMillis(); 
     final double ns = 1000000000.0/60.0; 
     double delta = 0; 
     int frames = 0; 
     int updates = 0; 
     while (running) { 
      long now = System.nanoTime(); 
      delta += (now - lastTime)/ns; 
      lastTime = now; 
      while (delta >= 1) { 
       update(); 
       updates++; 
       delta--; 
      } 
      render(); 
      frames++; 

      if (System.currentTimeMillis() - timer > 1000) { 
       timer += 1000; 
       System.out.println(updates + " u/sec " + frames + " f/sec"); 
       frame.setTitle(title + " | " + updates + " u/sec " + frames 
         + " f/sec"); 
       updates = 0; 
       frames = 0; 
      } 

     } 
     stop(); 
    } 

    int x, y; 

    public void update() { 
     key.update(); 

     if (key.up) 
      y--; 
     if (key.down) 
      y++; 
     if (key.left) 
      x--; 
     if (key.right) 
      x++; 
    } 

    public void render() { 
     BufferStrategy bs = getBufferStrategy(); 
     if (bs == null) { 
      createBufferStrategy(3); 
      return; 
     } 
     screen.clear(); 
     screen.render(x, y); 

     for (int i = 0; i < pixels.length; i++) { 
      pixels[i] = screen.pixels[i]; 
     } 

     Graphics g = bs.getDrawGraphics(); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     g.drawImage(image, 0, 0, getWidth(), getHeight(), null); 
     g.dispose(); 
     bs.show(); 
    } 

    public static void main(String[] args) { 
     Game game = new Game(); 
     game.frame.setResizable(false); 
     game.frame.setTitle(Game.title); 
     game.frame.add(game); 
     game.frame.pack(); 
     game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     game.frame.setLocationRelativeTo(null); 
     game.frame.setVisible(true); 

     game.start(); 
    } 

} 
+1

Я не эксперт по Java, но остановка в ваш случай вызван из самой нити. Так что в основном поток ждет, когда он остановится, что, вероятно, не работает. – BDL

ответ

1

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

private static void dumpThreads() { 
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); 
    for (Thread thread : threadSet) { 
     System.out.println(String.format("threadName = '%s', daemon = %b", 
       thread.getName(), thread.isDaemon())); 
    } 
} 

см Также в этом: What is Daemon thread in Java?

+0

Хорошо, это странно .. Я поместил ваш метод 'dumpThreads()' в функцию 'stop()' (прямо перед 'running' установлено значение false), и по какой-то причине программа закрывается, а' stop() 'функция даже не вызвана немодифицированным кодом, но все же программа выходит из строя, между тем мой код' stop() 'вызывает вызов и программа зависает после закрытия окна. –

+0

Ok только два разных потоков, которые ARENT работает в моем модифицированном коде: 'threadName = 'АВТ-Windows', демон = true' ' threadName = 'Java2D Disposer', демон = true' , которые как представляется, AWT, поэтому я не думаю, что это –

+0

, но ваш код полезен для определения того, какие потоки все еще работают, поэтому не помню этого. –

0

ОК, так что я понял это ... как сказал BDL, я не могу call join, находясь в активной ветке, к сожалению, из-за неумолимого характера LWJGL, потребовалась реструктуризация основного класса.

Для будущей ссылки (для меня и кто-либо другой) Вот текущий код:

package com.daboom.threadgl; 

import org.lwjgl.LWJGLException; 
import org.lwjgl.opengl.Display; 
import org.lwjgl.opengl.DisplayMode; 
import org.lwjgl.opengl.GL11; 
import com.daboom.threadgl.graphics.Camera; 

public class EngineMain implements Runnable { 

    private boolean running; 
    private Thread thread; 
    private Camera cam; 
    public boolean isLogicThreadRunning = false; 

    /** 
    * Starts the Dual Threaded System, does not need to be called, already 
    */ 
    @Override 
    public void run() { 
     while (running) { 
      update(); 
      Display.sync(60); 
     } 
    } 

    private void update() { 
     game.update(); 
    } 

    Game game; 

    private void render() { 
     GL11.glLoadIdentity(); 
     GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); 
     cam.useView(); 
     game.render3D(); 
     cam.setProjection2D(Display.getWidth(), Display.getHeight()); 
     game.render2D(); 
     Display.update(); 
     cam.resetTo3D(); 
    } 

    public EngineMain() { 

     cam = new Camera(); 
     game = new Game(this, cam); 

    } 

    private void initDisplay() { 
     try { 
      Display.setDisplayMode(new DisplayMode(800, 600)); 
      Display.setTitle(Game.gameName); 
      Display.create(); 
     } catch (LWJGLException e) { 
      e.printStackTrace(); 
     } 

     GL11.glEnable(GL11.GL_BLEND); 
     GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 
     GL11.glClearColor(0, 0, 0, 1); 
     cam.setProjection3D(63, 
       (float) Display.getWidth()/(float) Display.getHeight(), 0.3f, 
       1000); 

    } 

    /** 
    * Starts the Game engine 
    * 
    */ 
    public synchronized void start() { 
     running = true; 
     if (Runtime.getRuntime().availableProcessors() > 1) { 

      thread = new Thread(this, "Update"); 
      thread.start(); 
      isLogicThreadRunning = true; 

     } 
     else 
     { 
      isLogicThreadRunning = false; 
      System.out.println("WARNING: SINGLE CORE SYSTEM DETECTED, FPS LIMITED TO 60"); 
     } 
     initDisplay(); 
     gameLoop(); 
    } 

    /** 
    * Stops the program. Call this to exit the game 
    */ 
    public synchronized void stop() { 
     running = false; 
     System.out.println(Thread.currentThread().getName()); 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     // dumpThreads(); 
    } 

    public void gameLoop() { 
     while (running) { 
      if (!isLogicThreadRunning) { 
       update(); 
       Display.sync(60); 
      } 

      render(); 
      if (Display.isCloseRequested()) 
       running = false; 
     } 
    } 

    public static void main(String[] args) { 
     EngineMain main = new EngineMain(); 
     main.start(); 
    } 

} 

Принимал навсегда, чтобы понять это, и я до сих пор не имеют ни малейшего представления о том, как исходный код в учебнике работал, но кажется, что попытка реализовать LWJGL в нем, похоже, нарушает его, из-за того, что контекст openGL носит однопоточный характер.

Конечно, если я делаю то, что не рекомендуется или не прав, пожалуйста, скажите мне, потому что я любитель, когда дело доходит до резьбы. (на самом деле, я все еще любитель с openGL ... мне нужен новый компьютер, чтобы получить лучшие/новые функции, вздох .. все еще застрял с 3.1)