我一直在关注另一个java游戏开发教程,以便对线程有一个基本的了解,我已经学习了these教程并将它们与我之前学到的openGL编程相结合。除了我认为我可能错过了一些内容,因为在调用engine.stop()
(包括thread.join()
)时,窗口关闭,程序在后台挂起,你必须结束它的过程。
这是我的代码:
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();
}
}
当我使用他的教程,没有使用他的代码的修改时,过程正确结束。
我无法为我的生活找到问题。
如果您需要更多评论,请询问。
编辑:这是修改前的原始代码
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();
}
}
答案 0 :(得分: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()));
}
}
答案 1 :(得分:0)
好的,所以我已经弄清楚了...就像BDL说的那样,我不能在活动线程中调用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的业余爱好者...我需要一台新PC来获得最佳/新功能,感叹......仍然坚持使用3.1)