Jump to content

Learning Java - Simple Animation Problem

Arcapse
Go to solution Solved by Nuluvius,
5 minutes ago, Arcapse said:

I'm unsure how to do this and where? I'm really new to java :P

Ah you can accomplish that in a very simple way by drawing your background over everything as the first thing... then render everything else.

5 minutes ago, Arcapse said:

I thought I was already doing this with the following code?

Sorry that I missed it, screaming kids, distracted... Ugh.

I'm learning Java and I've encountered a problem with animation. I've set up this program to open a window and then display text. I was hoping it would move down the page, however the way this is working right now, it does this.

 

Few seconds after starting..

heNRvQm.jpg

 

A while after starting..

1OsrxG6.jpg

 

Something's not right there, the logic of Java hasn't clicked with me yet so if someone could help figure out why my program is doing this (repeatedly calling the text instead of just moving it down) and give me guidance on how to fix it, will be much appreciated :)

 

Game Class

Spoiler

 

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

public class Game extends Canvas implements Runnable{
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 640;
    public static final int HEIGHT = 480;
    public final String TITLE = "Learning Java";
    
    private boolean running = false;
    private Thread thread;
    
    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    
    private Word w;
    
    private void init(){
        w = new Word(200, 20, this);
    }
    
    private synchronized void start(){
        if(running)
            return;
        running = true;
        thread = new Thread(this);
        thread.start();
    }
    
    private synchronized void stop(){
        if(!running)
            return;
        
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(1);
    }
    
    
    public void run(){
        init();
        long lastTime = System.nanoTime();
        final double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        int updates = 0;
        int frames = 0;
        long timer = System.currentTimeMillis();
        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            if (delta >= 1){
                tick();
                updates++;
                delta--;
            }
            render();
            frames++;
            
            if(System.currentTimeMillis() - timer > 1000){
                timer +=1000;
                System.out.println(updates + " Ticks, FPS " + frames);
                updates = 0;
                frames = 0;
            }
            
        }
        stop();
    }
    
    private void tick(){
        w.tick();
    }
    
    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(2);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        ////
        g.fillRect(0,400,getWidth(),20);
        w.render(g);
        ////
        g.dispose();
        bs.show();
    }
    public static void main(String args[]){
        Game game = new Game();
        
        game.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        game.setMaximumSize(new Dimension(WIDTH, HEIGHT));
        game.setMinimumSize(new Dimension(WIDTH, HEIGHT));

        
        JFrame frame = new JFrame(game.TITLE);
        
        frame.add(game);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);;
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        
        game.start();
    }
}

 

Word Class:

Spoiler

 

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

public class Word {

    private double x;
    private double y;
    
    public Word(double x, double y, Game game){
        this.x = x;
        this.y = y;
    }
    
    public void tick(){
        y++;
    }
    
    public void render(Graphics g){
        //set up text style
        Font font = new Font("Serif", Font.BOLD, 36);
        g.setFont(font);
        g.setColor(Color.black);
        
        g.drawString("Hello", (int)x, (int)y);
    }
}

 

 

Cheers & Best Regards,

Arcapse

Link to comment
Share on other sites

Link to post
Share on other sites

I'm reposting the code so it's easier to see

 

Game Class

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage; 
import javax.swing.JFrame; 
public class Game extends Canvas implements Runnable{
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 640;
    public static final int HEIGHT = 480;
    public final String TITLE = "Learning Java";
    
    private boolean running = false;
    private Thread thread;
    
    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    
    private Word w;
    
    private void init(){
        w = new Word(200, 20, this);
    }
    
    private synchronized void start(){
        if(running)
            return;
        running = true;
        thread = new Thread(this);
        thread.start();
    }
    
    private synchronized void stop(){
        if(!running)
            return;
        
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(1);
    }
    
    
    public void run(){
        init();
        long lastTime = System.nanoTime();
        final double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        int updates = 0;
        int frames = 0;
        long timer = System.currentTimeMillis();
        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            if (delta >= 1){
                tick();
                updates++;
                delta--;
            }
            render();
            frames++;
            
            if(System.currentTimeMillis() - timer > 1000){
                timer +=1000;
                System.out.println(updates + " Ticks, FPS " + frames);
                updates = 0;
                frames = 0;
            }
            
        }
        stop();
    }
    
    private void tick(){
        w.tick();
    }
    
    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(2);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        ////
        g.fillRect(0,400,getWidth(),20);
        w.render(g);
        ////
        g.dispose();
        bs.show();
    }
    public static void main(String args[]){
        Game game = new Game();
        
        game.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        game.setMaximumSize(new Dimension(WIDTH, HEIGHT));
        game.setMinimumSize(new Dimension(WIDTH, HEIGHT)); 
        
        JFrame frame = new JFrame(game.TITLE);
        
        frame.add(game);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);;
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        
        game.start();
    }
} 
  

World Class

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics; 
public class Word { 
    private double x;
    private double y;
    
    public Word(double x, double y, Game game){
        this.x = x;
        this.y = y;
    }
    
    public void tick(){
        y++;
    }
    
    public void render(Graphics g){
        //set up text style
        Font font = new Font("Serif", Font.BOLD, 36);
        g.setFont(font);
        g.setColor(Color.black);
        
        g.drawString("Hello", (int)x, (int)y);
    }
} 

 

Judge a product on its own merits AND the company that made it.

How to setup MSI Afterburner OSD | How to make your AMD Radeon GPU more efficient with Radeon Chill | (Probably) Why LMG Merch shipping to the EU is expensive

Oneplus 6 (Early 2023 to present) | HP Envy 15" x360 R7 5700U (Mid 2021 to present) | Steam Deck (Late 2022 to present)

 

Mid 2023 AlTech Desktop Refresh - AMD R7 5800X (Mid 2023), XFX Radeon RX 6700XT MBA (Mid 2021), MSI X370 Gaming Pro Carbon (Early 2018), 32GB DDR4-3200 (16GB x2) (Mid 2022

Noctua NH-D15 (Early 2021), Corsair MP510 1.92TB NVMe SSD (Mid 2020), beQuiet Pure Wings 2 140mm x2 & 120mm x1 (Mid 2023),

Link to comment
Share on other sites

Link to post
Share on other sites

Sorry dude. I got nothing :(.

 

Although I will say that I think it's tied to the framerate checker somehow.

Judge a product on its own merits AND the company that made it.

How to setup MSI Afterburner OSD | How to make your AMD Radeon GPU more efficient with Radeon Chill | (Probably) Why LMG Merch shipping to the EU is expensive

Oneplus 6 (Early 2023 to present) | HP Envy 15" x360 R7 5700U (Mid 2021 to present) | Steam Deck (Late 2022 to present)

 

Mid 2023 AlTech Desktop Refresh - AMD R7 5800X (Mid 2023), XFX Radeon RX 6700XT MBA (Mid 2021), MSI X370 Gaming Pro Carbon (Early 2018), 32GB DDR4-3200 (16GB x2) (Mid 2022

Noctua NH-D15 (Early 2021), Corsair MP510 1.92TB NVMe SSD (Mid 2020), beQuiet Pure Wings 2 140mm x2 & 120mm x1 (Mid 2023),

Link to comment
Share on other sites

Link to post
Share on other sites

In every graphic programing api I have used i need to clear the draw buffer at start of each frame. I havnt looked through code but looks like every frame is being drawn over the last

             ☼

ψ ︿_____︿_ψ_   

Link to comment
Share on other sites

Link to post
Share on other sites

9 hours ago, SCHISCHKA said:

i need to clear the draw buffer at start of each frame

I'm unsure how to do this and where? I'm really new to java :P

 

4 hours ago, Nuluvius said:

You should also implement double buffering.

I thought I was already doing this with the following code?


    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(2);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        ////
        g.fillRect(0,400,getWidth(),20);
        w.render(g);
        ////
        g.dispose();
        bs.show();
    }

Cheers & Best Regards,

Arcapse

Link to comment
Share on other sites

Link to post
Share on other sites

5 minutes ago, Arcapse said:

I'm unsure how to do this and where? I'm really new to java :P

Ah you can accomplish that in a very simple way by drawing your background over everything as the first thing... then render everything else.

5 minutes ago, Arcapse said:

I thought I was already doing this with the following code?

Sorry that I missed it, screaming kids, distracted... Ugh.

The single biggest problem in communication is the illusion that it has taken place.

Link to comment
Share on other sites

Link to post
Share on other sites

13 minutes ago, Nuluvius said:

Ah you can accomplish that in a very simple way by drawing your background over everything as the first thing

It's working now (I created a rectangle and sized it as the window)

 

    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(2);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        ////
        g.setColor(Color.white);
        g.fillRect(0,0,getWidth(),getHeight());
        g.setColor(Color.red);
        g.fillRect(0,400,getWidth(),20);
        w.render(g);

        ////
        g.dispose();
        bs.show();
    }

 

But I'm curious, will those objects still be rendered, so overtime performance will decrease?

 

Cheers & Best Regards,

Arcapse

Link to comment
Share on other sites

Link to post
Share on other sites

4 minutes ago, Arcapse said:

But I'm curious, will those objects still be rendered, so overtime performance will decrease?

Whatever has has been drawn previously will be obliterated by what is drawn over the top; it doesn't remain in memory and performance will not be affected. An optimisation would be to deal with the canvas in parts... Pragmatically however, that's probably too much aggravation and simply unnecessary for what you are doing.

The single biggest problem in communication is the illusion that it has taken place.

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, Nuluvius said:

Whatever has has been drawn previously will be obliterated by what is drawn over the top; it doesn't remain in memory and performance will not be affected. An optimisation would be to deal with the canvas in parts... Pragmatically however, that's probably too much aggravation and simply unnecessary for what you are doing.

Alright. Thanks for the help :)

Cheers & Best Regards,

Arcapse

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, Arcapse said:

Alright. Thanks for the help :)

don't forget to mark the answer which helped you as solved

Judge a product on its own merits AND the company that made it.

How to setup MSI Afterburner OSD | How to make your AMD Radeon GPU more efficient with Radeon Chill | (Probably) Why LMG Merch shipping to the EU is expensive

Oneplus 6 (Early 2023 to present) | HP Envy 15" x360 R7 5700U (Mid 2021 to present) | Steam Deck (Late 2022 to present)

 

Mid 2023 AlTech Desktop Refresh - AMD R7 5800X (Mid 2023), XFX Radeon RX 6700XT MBA (Mid 2021), MSI X370 Gaming Pro Carbon (Early 2018), 32GB DDR4-3200 (16GB x2) (Mid 2022

Noctua NH-D15 (Early 2021), Corsair MP510 1.92TB NVMe SSD (Mid 2020), beQuiet Pure Wings 2 140mm x2 & 120mm x1 (Mid 2023),

Link to comment
Share on other sites

Link to post
Share on other sites

27 minutes ago, Arcapse said:

But I'm curious, will those objects still be rendered, so overtime performance will decrease?

the way i think about is the draw buffer is like a sheet of paper. theres no performance effect because that buffer can only be the size of your window. If you do not start with a clean buffer on every frame then it will re-use the image that is already there

             ☼

ψ ︿_____︿_ψ_   

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×