How to stop rendering old positions when moving a picture in Java? - java

I built a small game in java in which i use a game loop. I add gameobjects which i render using render() and tick() methods. However, now the program gets bigger i encounterted a problem.
How do you solve that when i use velocity to move a picture, the object keeps rendering on old positions? For small programs this aint a problem, but when you get like 100 objects in the screen the FPS keeps dropping to the point the program doesnt work properly anymore. This is just because there are so many objects to render. Is there a way to remove the rendering of the old positions of the object? Here below is some code i have written.
The game loop i used:
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
tick();
delta--;
}
if (running) {
try {
render();
} catch (IOException e) {
e.printStackTrace();
} catch (FontFormatException e) {
e.printStackTrace();
}
}
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
stop();
}
I used the Graphics class in Java to draw the images/strings/rectangles/etc. on the JFrame.
Here below is a picture of the problem. You can see that the object began all the way to the right. I changed the x-axis every tick of the game loop which made the object go to the left. Unfortunately, the object leaves a trace behind it and keeps rendering that, while i want it to only render the newest position.
Object rendering problem picture:
How can i solve this? Thanks in advance.

Related

Delta time not working correctly in game engine - LWJGL

I'm trying to make a simple game engine and I'm trying to make delta time available to the user. This is how it is calculated and given to the user (they get it as a float):
float deltaTime;
long lastLoop = System.nanoTime();
UpdateInfo updateInfo = new UpdateInfo(0, 0, gameInstance.window.getWindowHandle());
while (!glfwWindowShouldClose(gameInstance.window.getWindowHandle()))
{
deltaTime = (float)((System.nanoTime() - lastLoop) / 1000000f);
updateInfo.setDeltaTime(deltaTime);
if (gameInstance.window.isFPSCounterEnabled())
{
if (System.currentTimeMillis() - lastFrameCount >= 1000)
{
fps = frames;
frames = 0;
lastFrameCount = System.currentTimeMillis();
}
}
else
{
fps = -1;
}
updateInfo.setFPS(fps);
gameInstance.updateGame(updateInfo);
gameInstance.drawGame(gameInstance.window.getDrawboard());
lastLoop = System.nanoTime();
glfwPollEvents();
}
But when I test the delta time value in moving a sprite across the screen, it's really choppy. This is both when VSync is enabled and disabled. Am I calculating it wrong or is my game being unstable?

Separate game loops for rendering and updating without built-in timers or separate threads

I am wondering if there is a way to update two different operations (in this case, updating and rendering) within a single thread / loop.
In my current scenario I have a TPS (ticks per second) that I want to have set to 64, and FPS (frames per second) that I want to be modifiable by the player.
The reason they cannot be in separate threads like I have been doing is because it causes a inconsistent flickering effect because of the timing between rendering and updating.
I am drawing with BufferStrategy and Canvas
This is what I was doing previously:
// The TPS = 64, the FPS = anything
public void init() {
tick_thread = new Thread(() -> {
long start, elapsed, wait;
while(alive) {
start = System.nanoTime();
input();
tick();
elapsed = System.nanoTime() - start;
wait = (1000 / TPS) - (elapsed / 1000000);
try {
Thread.sleep(wait <= 0 : 1 ? wait);
} catch(Exception e) {
e.printStackTrace(System.out);
}
}
});
render_thread = new Thread(() -> {
long start, elapsed, wait;
while(alive) {
start = System.nanoTime();
render();
elapsed = System.nanoTime() - start;
wait = (1000 / FPS) - (elapsed / 1000000);
try {
Thread.sleep(wait <= 0 : 1 ? wait);
} catch(Exception e) {
e.printStackTrace(System.out);
}
}
});
}
This works well, but I want to move from one thread to a single thread and still update them at a different rate. Like...
public void init() {
game_thread = new Thread(() -> {
long start, elapsed, wait, // etc
while(alive) {
// Some calculations
input(); // RUNS 64 TIMES A SECOND
tick(); // RUNS 64 TIMES A SECOND
render(); // Runs 30, 60, 120 times a second
// Some calculations
}
});
}
If you could help or try helping, it would mean a lot!

rare occuring nullpointer exception (game programming Java)

I am building this game in Java. Basically it is minecraft in 2D. I made it so that block objects are deleted when pressed. My block object rendering sometimes gives a nullpointerexception after clicking/deleting a block (randomly after about 200 blocks). It seems as if the object is sometimes deleted while the game is in the renderingloop. When I add a try-catch, the next render cycle does not have the error anymore. Any ideas what is causing this? Is this gameloop a solid one, I suspect that is what is causing my error.
Render method in my handler:
LinkedList<GameObject> object = new LinkedList<GameObject>();
public void render(Graphics g){
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);//sometimes nullpointer when getting the object I clicked on
tempObject.render(g);
}
}
Deleting with mouseInput
for(int i = 0; i < handler.object.size(); i++){
if(handler.object.get(i).getID() == ID.Block){
int x1 = (int) handler.object.get(i).getX();
int y1 = (int) handler.object.get(i).getY();
//if mouse is over object
if((MouseX >= x1+1 && MouseX <= (x1 +32-1)) && (MouseY >= y1+1 && MouseY <= (y1 +32-1))){
Block b = (Block) handler.object.get(i);
inventory.addInventoryBlocks(b.getType(), 1);
handler.removeObject(handler.object.get(i));
}
}
}
Gameloop:
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
//System.out.println("FPS: " + frames);
frames = 0;
}
}
stop();
}
I assume your mouse input handler runs as a seperate thread. In this case the deletion of a block can occure within your rendering loop.
A solution would be not to delete the blocks immediately in your mouse handler but to save the blocks to delete in a separate array. These blocks can be handled at a dedicated position in your main loop right before rendering.
Most likely your mouse handler is running in the AWT thread while the render is running in another thread. In this case you would be suffering of concurrency troubles.
Try using a critical section.
public static Object lock = new Object();
public void render(Graphics g){
synchronized(lock)
{
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);//sometimes nullpointer when getting the object I clicked on
tempObject.render(g);
}
}
}
void mouseInputHandler()
{
synchronized( lock )
{
code
}
}
This could be better refined knowing more about your code's structure but it should get you going in the right direction.
Assuming you are using different threads for updating the game state and rendering, this behavior does not seem that odd to me, as one thread might have deleted an object as the other tries to render it.
A good way to debug this is to force sequential execution of your code. Check if the current behavior persists. A nice introduction (Android) to game loops can be found here

Make Graphics2D Text Blink with Delay

I have a draw method drawing a String to the screen using a Graphics2D object. I set up an if statement in the draw method to make the text draw every second (blinking effect), but the text will draw for a second, then not draw only one frame and continue drawing again. I would like for it to draw for a second, then not draw for a second and so on.
Here is the method -
long elapsed = (System.nanoTime() - blinkTimer) / 1000000;
if(elapsed < 1000){
// g.drawString("",x,y); Draw String Here
}else{
blinkTimer = System.nanoTime();
}
blinkTimer is initialized in the constructor as System.nanoTime();
I would like to accomplish this without using the Java Timer object. Thanks in advance!
Added an additional timer -
long elapsed = (System.nanoTime() - blinkTimer) / 1000000;
if(elapsed < 1000){
//g.drawString("",x,y); Draw String Here
breakTimer = System.nanoTime();
}
long breakElapsed = (System.nanoTime() - breakTimer) / 1000000;
if(breakElapsed > 500){
blinkTimer = System.nanoTime();
}

Locking game update speed causing high CPU usage. How do I make thread sleep when not doing anything?

So I'm currently just learning how to do this, and someone said that the code is inefficient because the thread is still running when nothing is updating. When I look at the CPU usage in the task manager, it shoots up to 35 - 45% and 20 in the CPU column when only a black screen is being rendered. Is there a way to make the thread sleep when the CPU isn't updating anything?
Thanks!
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;
updates = 0;
frames = 0;
}
}
stop();
}
You shouldn't render on your own threads. SWING is thread unsafe so all GUI operations should happen on the SWING thread. It just happens SWING has a thread specially made for this.
timer = new javax.swing.Timer(1000 / 60, this);
timer.start();
#Override
public void actionPerformed(ActionEvent e) {
// Do your stuff (ignore 'e')
}
The only good way of doing it, is to execute the yourThread.wait() when the game stops doing stuff, and then yourThread.notify() when the game makes an action again.

Categories