BufferStrategy Causing Flickering? - java

I am new to Java Game Programming and I am having trouble with my game. I am making this for my class in school and for fun so I transfer my code from my computer at school and my computer at home.
Recently, when I run my program at home, the window flashes extremely fast and I cant tell what is going on. I use a buffer-strategy and have tested some values and nothing changes. When I run the code on my school computer, it runs fine.
I am wondering if my problem is in fact the buffer-strategy or maybe my Nvidia graphics card is doing something to my display.
I have also recorded my screen showing the "flickering" so you can see what I am talking about in this YouTube video.
Here is my Game class the uses the buffer-strategy.
public class Game implements Runnable{
public int width, height;
public String title;
private Display display;
private BufferStrategy bs;
private Graphics g;
private Thread thread;
private boolean running = false;
//States
private State menuState;
private State gameState;
//Input
private KeyManager keyManager;
public Game(String title, int width, int height){
this.title = title;
this.width = width;
this.height = height;
keyManager = new KeyManager();
}
private void init(){
display = new Display(title, width, height);
display.getFrame().addKeyListener(keyManager);
Assets.init();
menuState = new MenuState(this);
gameState = new GameState(this);
State.setState(menuState);
}
private void update(){
keyManager.update();
if(State.getState() != null){
State.getState().update();
}
}
private void render(){
bs = display.getCanvas().getBufferStrategy();
if(bs == null){
display.getCanvas().createBufferStrategy(1);
return;
}
g = bs.getDrawGraphics();
// Clear
g.clearRect(0, 0, width, height);
// Draw
if(State.getState() != null){
State.getState().render(g);
}
// End Draw
bs.show();
bs.dispose();
}
public void run() {
init();
int fps = 60;
double timePerTick = 1000000000 / fps; // 1 second (in nanoseconds)
double delta = 0;
long now;
long lastTime = System.nanoTime();
long timer = 0;
int ticks = 0;
while (running){
now = System.nanoTime();
delta += (now - lastTime) / timePerTick;
timer += now - lastTime;
lastTime = now;
if(delta >= 1){
update();
render();
ticks++;
delta--;
}
if(timer >= 1000000000){
System.out.println("Ticks and frames:" + ticks);
ticks = 0;
timer = 0;
}
}
stop();
}
public synchronized void start(){
if (running)
return;
running = true;
thread = new Thread(this);
thread.start(); // Call run()
}
public synchronized void stop(){
if (!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public KeyManager getKeyManager(){
return keyManager;
}
}

Related

Problems with thread and bufferstrategy: IllegalStateException: Component must have a valid peer

Here is the code that I tried to execute, but failed:
public class Game extends Canvas implements Runnable,KeyListener {
private static final long serialVersionUID = 1L;
private static Thread thread ;
private int width = 240;
private int height = 120;
private int scale = 3;
private boolean isRunning = true;
private BufferedImage image;
public static Spritesheet spritesheet;
private Player player;
Game(){
Dimension dimension = new Dimension(width*scale,height*scale);
this.setPreferredSize(dimension);
image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
}
void initframe() {
JFrame f = new JFrame("Game");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
f.setLocationRelativeTo(null);
f.setResizable(false);
}
public synchronized void start() {
thread = new Thread(this);
isRunning = true;
thread.start();
}
public synchronized void stop() {
isRunning = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Game game = new Game();
game.start();
}
void tick() {
}
void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = image.getGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, width, height);
g.dispose();
g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, width*scale,height*scale,null);
bs.show();
}
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = (10^9)/amountOfTicks ;
int frames = 0;
double delta;
double timer = System.currentTimeMillis();
while(isRunning) {
long now = System.nanoTime();
delta = (now - lastTime)/ns ;
lastTime = now;
if(delta >= 1) {
tick();
render();
frames++;
delta--;
}
if(System.currentTimeMillis() - timer >= 1000) {
System.out.println(" A taxa de fps e: "+frames);
frames = 0;
timer+=1000;
}
}
stop();
}
And the error that appears to me is:
Exception in thread "Thread-0" java.lang.IllegalStateException: Component must have a valid peer
at java.desktop/java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:4105)
at java.desktop/java.awt.Component$FlipBufferStrategy.<init>(Component.java:4079)
at java.desktop/java.awt.Component$FlipSubRegionBufferStrategy.<init>(Component.java:4611)
at java.desktop/java.awt.Component.createBufferStrategy(Component.java:3942)
at java.desktop/java.awt.Canvas.createBufferStrategy(Canvas.java:195)
at java.desktop/java.awt.Component.createBufferStrategy(Component.java:3866)
at java.desktop/java.awt.Canvas.createBufferStrategy(Canvas.java:170)
at com.main.Game.render(Game.java:83)
at com.main.Game.run(Game.java:115)
at java.base/java.lang.Thread.run(Thread.java:834)
I checked out every line of this code and I don't know why show that the problem is with thread or bufferStrategy, the method render or method run that I used.

Why is my GPU over 75°C when I run an undemanding Java game?

I have recently moved to Linux Mint 19.3 and run my Java game. In one hand I have FPS that's higher than on Windows 10 (~150 FPS VS ~4000 FPS). But in another hand my game is very lag. And I don't understand why because I don't have this problem in Windows 10. Actually, I am not good at computer graphics, but I think it's problem in VSync or so. That's the screenshot of my GPU temperature and FPS.
GameContainer.java
import javax.swing.JFrame;
import java.awt.*;
import java.awt.image.*;
public class GameContainer {
public static int width = 320;
public static int height = 240;
public static int scale = 3;
public static String title = "Space Adventure";
public Window window;
public BufferStrategy bs;
public Graphics2D g;
public GameManager gm;
public KeyInput ki;
public void start() {
window.canvas.requestFocus();
long previous = System.currentTimeMillis();
long current = 0;
double elapsed = 0;
double timePerTick = 1000.0 / 60;
int ticks = 0;
int frames = 0;
long timer = previous;
while (true) {
current = System.currentTimeMillis();
elapsed += (current - previous) / timePerTick;
previous = current;
while (elapsed >= 1) {
tick(timePerTick);
ticks++;
elapsed -= 1;
}
render();
frames++;
if (System.currentTimeMillis() - timer >= 1000) {
System.out.printf("UPS: %3d, FPS: %3d%n", ticks, frames);
timer += 1000;
ticks = 0;
frames = 0;
}
}
}
public void tick(double delta) {
gm.tick(delta);
}
public void render() {
bs = window.canvas.getBufferStrategy();
if (bs == null) {
window.canvas.createBufferStrategy(2);
return;
}
g = (Graphics2D) bs.getDrawGraphics();
g.scale(scale, scale);
gm.render(g);
g.dispose();
bs.show();
}
public void init(GameManager gm) {
window = new Window();
window.create(width , height, scale, title);
this.gm = gm;
ki = new KeyInput();
window.canvas.addKeyListener(ki);
}
}

Why is this game loop implementation getting a lower framerate than one that does more calculations per iteration?

I attempted to create my own implementation of a "game loop" using javax.swing and java.awt, but when my target fps was 60, I only got 49-52 fps on my implementation, while another implementation got 59-61 fps. Why would my implementation get a lower framerate if it's doing fewer calculations?
My Implementation:
public class MainContainer implements Runnable {
public Thread thread;
private final String title = "Window";
private int width = 800, height = 600;
private float scale = 1f;
private GameWindow window;
private final int FPS = 60;
private final long NS_PER_UPDATE = (long)((1.0d/FPS) * 1000000000);
private int current_total = 0;
private boolean running;
public MainContainer(){
running = true;
start();
}
public void start(){
window = new GameWindow(this);
thread = new Thread(this);
thread.run();
}
public void stop(){
}
#Override
public void run() {
long old = System.nanoTime();
long counterOld = System.nanoTime();
long missedTime;
double frames = 0;
long current;
long delta;
long counterDelta;
while(running){
current = System.nanoTime();
delta = current - old;
counterDelta = current - counterOld;
if(counterDelta >= 1000000000){
System.out.println(frames / (counterDelta/1000000000.0));
frames = 0;
counterOld = System.nanoTime();
}
if(delta >= NS_PER_UPDATE){
render();
missedTime = delta - NS_PER_UPDATE;
old = System.nanoTime() - missedTime;
frames++;
}else{
try {
thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void render(){
window.update();
}
public static void main(String[] args) {
MainContainer main = new MainContainer();
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
public float getScale(){
return scale;
}
public void setScale(float s){
scale = s;
}
public String getTitle(){
return title;
}
public GameWindow getWindow(){
return window;
}
}
Other Implementation:
public class MainContainer implements Runnable {
public Thread thread;
private final String title = "Window";
private int width = 800, height = 600;
private float scale = 1f;
private final int FPS = 60;
private final long NS_PER_UPDATE = (long)((1.0d/FPS) * 1000000000);
private boolean running;
private GameWindow window;
public MainContainer(){
running = true;
start();
}
public void start(){
window = new GameWindow(this);
thread = new Thread(this);
thread.start();
}
public void stop(){
}
#Override
public void run() {
long unprocessedTime = 0;
long frameTime = 0;
double frames = 0;
boolean render = false;
long current;
long delta;
long old = System.nanoTime();
while(running){
current = System.nanoTime();
delta = current - old;
old = current;
unprocessedTime += delta;
frameTime += delta;
while(unprocessedTime >= NS_PER_UPDATE){
old = System.nanoTime();
unprocessedTime -= NS_PER_UPDATE;
render = true;
if(frameTime >= 1000000000){
System.out.println(frames / (frameTime/1000000000.0));
frameTime = 0;
frames = 0;
}
}
if(render){
render();
frames++;
render = false;
}else{
try {
thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void render(){
window.update();
}
public static void main(String[] args) {
MainContainer main = new MainContainer();
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
public float getScale(){
return scale;
}
public void setScale(float s){
scale = s;
}
public String getTitle(){
return title;
}
public GameWindow getWindow(){
return window;
}
}
GameWindow Class:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class GameWindow {
private JFrame frame;
private BufferedImage image;
private Canvas canvas;
private BufferStrategy bs;
private Graphics g;
private boolean blue;
private MainContainer mc;
public GameWindow(MainContainer mc) {
this.mc = mc;
image = new BufferedImage(mc.getWidth(), mc.getHeight(), BufferedImage.TYPE_INT_RGB);
canvas = new Canvas();
Dimension s = new Dimension((int)(mc.getWidth() * mc.getScale()), (int)(mc.getHeight() * mc.getScale()));
canvas.setPreferredSize(s);
canvas.setMinimumSize(s);
canvas.setMaximumSize(s);
frame = new JFrame(mc.getTitle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(canvas, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
canvas.createBufferStrategy(2);
bs = canvas.getBufferStrategy();
g = bs.getDrawGraphics();
}
public void update(){
int[] p = ((DataBufferInt)(this.getImage().getRaster().getDataBuffer())).getData();
for(int i = 0; i < p.length; i++){
p[i] += i;
}
g.drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight(), null);
bs.show();
}
public BufferedImage getImage(){
return image;
}
}
Because in the "Other Implementation" its calculating the old time before the rendering process and in your implentation it is calculating it after the rendering process which make the value bigger because it is now also including the time it takes to render. So if you flip the code in your if statement around to look like this it will run at around 60 fps:
if(delta >= NS_PER_UPDATE){
missedTime = delta - NS_PER_UPDATE;
old = System.nanoTime() - missedTime;
render();
frames++;
}

MouseEvent canceling

I am creating a MouseEvent and it seems to be cancelling a few ticks after it starts as I can sometimes get a small response before it stops responding. Does anyone see why?
Here is where I initialize in init()
public class Game implements Runnable {
private Display display;
private int width, height;
public String title;
private boolean running = false;
private Thread thread;
private BufferStrategy bs;
private Graphics g;
//Input
Mouse mouse;
//Handler
private Handler handler;
public Game(String title, int width, int height){
this.title = title;
this.width = width;
this.height = height;
mouse = new Mouse();
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
}
catch (InterruptedException e){ e.printStackTrace(); }
}
public void run() {
init();
int fps = 60;
double timePerTick = 1000000000 / fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
long timer = 0;
int ticks = 0;
while(running){
now = System.nanoTime();
delta += (now - lastTime) / timePerTick;
timer += now - lastTime;
lastTime = now;
if(delta >= 1){
tick();
render();
ticks++;
delta--;
}
if(timer >= 1000000000){
ticks = 0;
timer = 0;
}
}
stop();
}
private void init() {
display = new Display(title, width, height);
display.getFrame().addMouseListener(mouse);
Assets.init();
handler = new Handler(this);
}
private void tick() {
Tile tile = new Tile();
tile.tick();
}
private void render() {
bs = display.getCanvas().getBufferStrategy();
if(bs == null){
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.clearRect(0, 0, width, height); //Clears the Screen
//Start of Drawing
ChessBoard cb = new ChessBoard(64);
cb.render(g);
cb.tick();
//End of Drawing
bs.show();
g.dispose();
}
}
And here is the MouseEvent
public class Mouse implements MouseListener {
public void mousePressed(MouseEvent e) {
System.out.println("1");
}
public void mouseReleased(MouseEvent e) {
System.out.println("2");
}
public void mouseEntered(MouseEvent e) {
System.out.println("3");
}
public void mouseExited(MouseEvent e) {
System.out.println("4");
}
public void mouseClicked(MouseEvent e) {
System.out.println("5");
}
}

My Java Picture won't show up correctly

I am trying to make a simple side-scrolling game and my background color won't work. It should fill the entire page, with an fps counter, but it only has a small line of color at the top of the pop up.
Here is my entire code so far (I had to copy and paste because I'm "not a level 10").
public static final int WIDTH = 640;
public static final int HIGHT = WIDTH / 4 * 3;
public static final String TITLE = "Sploocher's Epic Quest";
private static Game game = new Game();
private boolean running = false;
private Thread thread;
public void init(){
}
public void tick(){
}
public void renderBackground(Graphics g){
}
public void renderForeground(Graphics g){
}
public void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,WIDTH,HEIGHT);
//////////////////////////////////////////////////
renderBackground(g);
renderForeground(g);
g.dispose();
bs.show();
}
#Override
public void run() {
init();
long lastTime= System.nanoTime();
final double numTicks = 60.0;
double n = 1000000000 / numTicks;
double delta = 0;
int frames = 0;
int ticks = 0;
long timer = System.currentTimeMillis();
while(running){
long currentTime = System.nanoTime();
delta += (currentTime - lastTime) / n;
lastTime = currentTime;
if(delta >= 1){
tick();
ticks++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer+=1000;
System.out.println(ticks + "Ticks, FPS: " + frames);
ticks = 0;
frames = 0;
}
}
stop();
}
public static void main(String args[]){
JFrame frame = new JFrame(TITLE);
frame.add(game);
frame.setSize(WIDTH, HIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
frame.pack();
game.start();
}
private synchronized void start(){
if(running)
return;
else
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop(){
if(!running)
return;
else
running = false;
try {
thread.join();
} catch (InterruptedException e){
e.printStackTrace();
}
System.exit(1);
}
}
If anyone could help me figure out how to fix my code, I'd really appreciate it.

Categories

Resources