Hot questions for Using Lightweight Java Game Library in game engine

Question:

I'm trying to make a Window class to abstract all the GLFW stuff. The thing is that I don't know how to use glfwSetWindowUserPointer in LWJGL.

I've used the function before, but in C++. Now I'm moving to Java, using LWJGL.

In C++, I would do something like:

    glfwSetWindowUserPointer(myWindow, &myData)

But in LWJGL the function takes 2 long, where the first argument is the window handle, but I don't know what to do with the second one.

How can I pass a pointer to my object containing all the data I need inside the callbacks?

Thanks in advance


Answer:

To expand on @elect's comment about JNINativeInterface and memGlobalRefToObject:

import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jni.JNINativeInterface;

class JavaObject {
    String message;

    JavaObject(String message) {
        this.message = message
    }
}

final long pointer = JNINativeInterface.NewGlobalRef(new JavaObject("Hello"));
JavaObject object = MemoryUtil.memGlobalRefToObject(pointer);
JNINativeInterface.DeleteGlobalRef(pointer);

System.out.println(object.message) // => "Hello"

// Already deleted the strong reference held by the native part of the application.
object = MemoryUtil.memGlobalRefToObject(pointer);
System.out.println(object) // => null

On a bit of advice: I'd only use the GLFW user pointer for the callbacks set with glfwSetMonitorCallback and glfwSetErrorCallback. You don't need it for the window callbacks, as you set one callback per window, so you already have a reference to each Java wrapper class.

class Window {
    final long handle;

    int width;
    int height;

    WindowObserver observer;

    Window(final long handle, final int width, final int height) {
        this.handle = handle;
        this.width = width;
        this.height = height;

        glfwSetWindowSizeCallback(handle, (handle, w, h) -> {
            if (observer != null) {
                observer.windowDidResize(this, this.width, this.height, w, h);
            }

            this.width = w;
            this.height = h;
        });
    }
}

Question:

So me and my friends are deciding to make a game, so I decided to create an engine for the game. And all was going well, I implemented a collision type I call "Push Collision" which basically means: When the player is moving towards and object take the speed it is moving at the object with and subtract it to the position, so say I am pressing W or the up arrow and I am moving into a wall, the wall will take my Horizontal speed or ysp (Y Speed) and subtract it to my y position. And it started working until I added a second box, know it worked when I went to collide with the boxes one by one, but when I got in the middle of the two wall objects, and my player would start bouncing back and forth from the walls. Now I know whats going on, since it's colliding with one wall it is subtracting my speed to my y or x position, but since I am colliding with two it will subtract twice the speed I am moving at to my x or y, I was thinking that I could just increase the x or y speed of the object/player but then the objects will just subtract twice was I am moving, so I'm in a bit of a pickle. Here is the code that I made for the "Push Collision type" and the Game class along with the Player class and TestBox class or Wall class.

Collision Class:

package engine.test.core;

public class Collision {
    public static void PushCollision(BaseObject obj1, BaseObject obj2) {
        if (obj1.box.CollideWOB(obj2.box)) {

            if (obj1.MoveDir == 2) {
                obj1.Position.x -= obj1.xsp;
            } else if (obj1.MoveDir == 1) {
                obj1.Position.x += obj1.xsp;
            } else if (obj1.MoveDir == 3) {
                obj1.Position.y += obj1.ysp;
            } else if (obj1.MoveDir == 4) {
                obj1.Position.y -= obj1.ysp;
            }
        }
    }
}

Player Class:

package engine.test.game;

import org.lwjgl.input.Keyboard;

import engine.test.core.BaseObject;
import engine.test.core.Renderer;

public class Player extends BaseObject {

    public Player(int x, int y, int w, int h) {
        super(x, y, w, h);
    }

    @Override
    public void Init() {
        xsp = 5;
        ysp = 5;
    }

    @Override
    public void Update() {
        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            MoveDir = 2;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            MoveDir = 1;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            MoveDir = 4;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
            MoveDir = 3;
        } else {
            MoveDir = 0;
        }

        if (MoveDir == 1) {
            Position.x -= xsp;
        } else if (MoveDir == 2) {
            Position.x += xsp;
        } else if (MoveDir == 3) {
            Position.y -= ysp;
        } else if (MoveDir == 4) {
            Position.y += ysp;
        }

        box.UpdateBox(Position, Size);
    }

    @Override
    public void Draw() {
        Renderer.Quad(Position, Size);
    }
}

TestBox Class:

package engine.test.game;

import engine.test.core.BaseObject;
import engine.test.core.Renderer;

public class TestBox extends BaseObject {

    public TestBox(int x, int y, int w, int h) {
        super(x, y, w, h);
    }

    @Override
    public void Init() {

    }

    @Override
    public void Update() {
        box.UpdateBox(Position, Size);
    }

    @Override
    public void Draw() {
        Renderer.Quad(Position, Size);
    }
}

Game Class:

package engine.test.game;

import java.util.ArrayList;
import java.util.List;

import engine.test.core.BaseGame;
import engine.test.core.Collision;

public class Game extends BaseGame {

    Player p;
    TestBox tb;
    TestBox tb2;

    List<TestBox> TestBoxes = new ArrayList<TestBox>();


    boolean Debug = false;

    @Override
    public void Init() {
        p = new Player(0, 0, 32, 32);

        p.Init();

        tb = new TestBox(100, 100, 32, 32);
        tb2 = new TestBox(132, 100, 32, 32);

        tb.Init();
        tb2.Init();

        TestBoxes.add(tb);
        TestBoxes.add(tb2);
    }

    @Override
    public void Update() {

        p.Update();

        for (TestBox box : TestBoxes) {
            Collision.PushCollision(p, box);
        }
    }

    @Override
    public void Draw() {
        p.Draw();

        for (TestBox box : TestBoxes) {
            box.Draw();
        }
    }
}

Answer:

One approach you could take to solve this is:

  • When a collision is detected, add it to a queue of "detected collisions" which should hold the collision box data.
  • After all collisions have been detected and added to the queue, iterate through the queue and after each push, check to see if the object is still colliding with that object. If it is, calculate a new push and apply that. Otherwise, ignore the original collision.

This is the first solution that comes to mind for me. Let me know if you have any questions about this! :)

Question:

I am currently working on a 2D Game that uses LWJGL, but I have stumbled across some serious performance issues. When I render more than ~100 sprites, the window freezes for a very small amount of time. I did some tests and I found out the following:

  • The problem occurs with both Vsync enabled or disabled
  • The problem occurs even if I cap the frames at 60
  • The program is not just rendering less frames for a short time, the Rendering seems to actually pause
  • There are no other operations like Matrix-Calculations that slow down the program
  • I already have implemented batch rendering, but it does not seem to improve the performance
  • The frequency of the freezes increases with the amount of Sprites
  • My Graphics Card driver is up to date
  • The problem occurs although the framerate seems to be quite acceptable, with 100 rendered sprites at the same time, I have ~1500 fps, with 1000 sprites ~200 fps

I use a very basic shader, the transformation matrices are passed to the shader via uniform variables each rendering call (Once per sprite per frame). The size of the CPU/GPU bus shouldn't be an issue.

I have found a very similar issue here, but none of the suggested solutions work for me.

This is my first question here, please let me know if I am missing some important information.


Answer:

It's probably GC.

Java is sadly not the best language for games thanks to GC and lack of any structures that can be allocated at stack, from languages similar to Java - c# is often better choice thanks to much more tools to control memory, like stack alloc and just structures in general. So when writing game in languages with GC you should make sure your game loop does not allocate too many objects, in many cases in other languages people often try to go for 0 or near 0 allocations in loop. You can create objects pools for your entities/sprites, so you don't allocate new ones, just re-use existing ones.

And if it's simple 2d game, then probably just avoiding allocating objects when there is no need to should be enough (like passing just two ints instead of object holding location on 2d map).

And you should use profiler to confirm what changes are worth it. There are also more tricky solutions, like using off heap manually allocated memory to store some data without object overhead, but I don't think simple game will need such solutions. Just typical game-dev solutions like pooling and avoiding not needed objects should be enough.

Question:

I am trying to display a texture of a window (in 3d) This is my code

try {
        texture = TextureLoader.getTexture("PNG", new FileInputStream(new File("res\\window.png")));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    texture.bind();
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(0, 0, 0);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(10, 0, 0);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(10, 10, 0);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(0, 10, 0);
    GL11.glEnd();
    GL11.glDisable(GL11.GL_TEXTURE_2D);

This is the real image:

And now here's the problem: lwjgl or what ever is doing it, is totally changing the color of the texture? this is how the image get's displayed:

No errors, no nothing.


Answer:

The color you set multiplies with the color of your image. Set your color to white before drawing the image:

GL11.glColor3f(1.0, 1.0, 1.0);