2
\$\begingroup\$

I am a mildly experienced programmer who has created several game engine templates and small 2D games in Java. I am currently expanding to 3D game engines and I am re-writing a previous engine to be more adaptive and Object-oriented.

My issue is, and has been periodically, that the objects are only sometimes rendered. This causes me to have to constantly re-run the program just to display any images.

I have not found any direct answers to this question, and nobody else seems to have this same issue (even when observing sources with the exact same code setup). The problem apparently lies within the render() method sometimes not properly creating or utilizing the Graphics & BufferStrategy objects while inside a thread called from the main method.

Here is some code of the 'Main' class:

public Main() {
    addScreenAndFrame();
}

public static void main(String[] args) {
     main = new Main();
     frame.add(main);    
     thread = 

new Thread(main);
         running = true;
         thread.start();
     }
public void run() {
    while (running) {
        render();
        tick();
    }
}
public void tick() {
    screen.tick();
}
public void render() {
    bs = getBufferStrategy();
    if (bs == null) {
        createBufferStrategy(3);
        return;
    }
    g = bs.getDrawGraphics();
    screen.paintComponent(g);
    g.dispose();
    bs.show();
}

Here is some code from the Screen class:

public Screen(int width, int height) {
    this.width = width;
    this.height = height;
    addEntities();
}
public void paintComponent(Graphics g) {
    p.render(g);
}
public void tick() {
    KeyInput.tick();
    renderInput();
}
public void addEntities() {
    p = new PolygonObject(new double[] {50,200,50}, new double[] {50,200, 200} );
}

And finally here is the PolygonObject class:

    public PolygonObject(double x[], double y[]) {
        Screen.polygonSize ++;
        polygon = new Polygon();
        for (int i=0; i < x.length; i++) {
            polygon.addPoint((int)x[i], (int)y[i]);
        }
    }
    public void render(Graphics g) {
        g.fillPolygon(polygon);
        g.setColor(Color.black);
        g.drawPolygon(polygon);
    }

I don't know why calling render() while within a thread would yield inconsistent results when drawing images to the screen. I have seen many source codes for game templates and tutorials with the exact same code without any rendering issues. The only way rendering works consistently is when I draw images with the paintComponent() method of the Canvas class outside of a thread which limits my program functionality and is poor design of a game engine.

I would like an explanation of this and any possible solutions. There is NO accurate way for me to build the game engine without the use of a thread in order to have controlled time-based functionality.

\$\endgroup\$
  • \$\begingroup\$ This is just a guess, but it seems like since the thread doesn’t create the screen and the frame, instead getting passed them from the main thread, the accesses to them might not be thread-safe/atomic, occasionally causing problems but sometimes working by chance. I assume you don’t need to access the screen and frame from the main thread anyway, so keeping them entirely on one thread would be better encapsulation. \$\endgroup\$ – Ryan1729 Nov 18 '17 at 21:15
  • \$\begingroup\$ Using the main method thread to run the entire program produces the same results. After re-structuring the way the frame is setup I found that calling the JPanel class method paintComponent() rendered the image to the screen with 100% success until attempting to call 'frame.request(true);' in the Main class constructor. Input stopped working, and after fixing input the rendering chance has been reduced to ~70%. It seems the amount of threads present (including the Swing thread used during the uses of the repaint() and paintComponent() methods) is causing random encapsulation & focus errors. \$\endgroup\$ – Ryan Nov 19 '17 at 0:59
  • \$\begingroup\$ Swing (and AWT) is not designed for multithreading. Weird things can happen when you use multithreading with Swing. If you want multithreading don't use Swing. If you want Swing don't use multithreading. \$\endgroup\$ – user253751 Sep 7 '18 at 1:20
1
\$\begingroup\$

The run() method called by the 3rd thread was unstable and sometimes did not properly construct each object due to encapsulation issues.

I have removed the extra thread and have re-structured the engine to do all rendering within the JPanel's paintComponent() method in the Screen class. The Main class has been re-structured to only create the frame then add the Screen and KeyInput objects to the frame while managing the game logic and input.

The engine now renders with 100% success and all objects work as they should.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.