Search code examples
javaswingpaintcomponentkeylistener

Can't figure out how to repaint


So I have this little project where I make the mario jump. But I can't figure out how to repaint it. If I do it in the Main class after a click, then the whole jumping will be very jerky.

I tried to do it at the end of my jump function but that did not work too.

Here is my code:

Main:

package klassid;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;


public class Main extends JComponent implements KeyListener, ActionListener{
    static Hero hero;
    Timer t = new Timer(500,this);

    public static void main(String[] args) {
        JFrame aken = new JFrame("Simple jumping simulator");
        aken.setSize(600, 600);
        aken.getContentPane().setBackground(new Color(255,255,255));
        aken.getContentPane().add(new Main());
        aken.setVisible(true);
        aken.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        hero.the_jump();
    }

    public Main(){
        addKeyListener(this);
        setFocusable(true);
        t.start();
        hero = new Hero(0, 320);
    }

    public void paintComponent(Graphics g){
        hero.render(g, this);
        g.setColor(Color.GREEN);
        g.fillRect(0, 550, 600, 2);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        hero.move(e.getKeyCode());
    }
    public void keyReleased(KeyEvent e) {
        hero.move2(e.getKeyCode());
    }
    public void keyTyped(KeyEvent e) {}
    public void actionPerformed(ActionEvent e) {}
}

And my Hero class:

package klassid;

import java.awt.Toolkit;
import java.awt.Image;
import java.awt.Graphics;

public class Hero {
    static Main main;
    int y;
    Image pilt = Toolkit.getDefaultToolkit().getImage("../mario.png");
    private double height = 0, speed = 4;
    public static final double gravity = 9.81;
    private double x = 25;
    private boolean left = false, right = false, up = false;


    public Hero(int x, int y){
        this.x = x;
        this.y = y;
    }

    public void render(Graphics g, Main pohiKlass){
        g.drawImage(pilt, (int) (x), (int) (500-(height*100)), 50, 50, pohiKlass);
    }

    public void the_jump() {
        long previous = 0, start = 0;

        while(true){
            start= System.nanoTime();  
            if(previous != 0 && up){
                double delta = start - previous;

                height += (delta/1000000000) * speed;        
                speed -= (delta/1000000000)  * gravity; 
            }  
            if(left)
                x -= 3;
            if(right)
                x += 3; 
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(height < 0){
                height = 0;
                speed = 4; 
                up = false;
            }      
            previous = start;
            repaint();
        }
    }
    public void move(int i){
        if(i == 38)
            up=true;
        if(i == 37)
            left=true;
        if(i == 39)
            right=true;
    }
    public void move2(int i){
        if(i == 37)
            left=false;
        if(i == 39)
            right=false;
    }
}

I also tried to access the paintComponent in the_jump function but it did not work as I have no idea what kind of a parameter it expects.

How is this mess solvable?


Solution

  • The first line in your paintComponent method should be:

    super.paintComponent(g);
    

    JComponent will do a lot of things for you, but you need to explicitly call the super class method to do so. Take a look at the Oracle Documentation here.

    You could call repaint() in your actionPerformed method, if you decrease the timer value to something very low. This will give you "continuous" repainting (as many times a second as you can reasonably perform).