0

Is there a way in Java swing to give a sprite the effect like it is live? Like moving randomly it around its center and having a fluctuating effect?

I tried something like the following (but the result is horrible):

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main extends JFrame {

    private static final int W = 800;
    private static final int H = 400;
    private int last = -1;

    public Main() {
        super("JFrame");
        this.add(new ImagePanel());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        setSize(W, H);
        this.setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Main();
            }
        });
    }

    class ImagePanel extends JPanel {

        Timer movementTimer;
        int x, y;

        public ImagePanel() {
            x = 58;
            y = 58;
            movementTimer = new Timer(12, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    moveImage();
                    repaint();
                }
            });
            movementTimer.start();
        }

        public void moveImage() {
            if (last < 0) {
                last = random();
                x += last;
                y += last;
            } else {
                x -= last;
                y -= last;
                last = -1;
            }
            if (x > W) {
                x = 0;
            }
            if (y > H) {
                y = 0;
            }
        }

        private int random() {

            Random r = new Random();
            int Low = 2;
            int High = 14;
            int Result = r.nextInt(High - Low) + Low;
            return Result;
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            long start = System.nanoTime();
            g.setColor(Color.RED);
            g.fillRect(0, 0, W, H);
            g.setColor(Color.BLUE);
            g.fillRect(x, y, 50, 50);

        }
    }
}

The result is not smooth at all, do you have any suggestion ?

navy1978
  • 1,411
  • 1
  • 15
  • 35
  • The short answer is yes, but you're going to need to do some work. The Graphics2D API has a number of classes and functionality which could facilitate this quite easily – MadProgrammer Mar 19 '17 at 19:40
  • Thank you, but the short answer is too short... :) is there some example you can provide or some internet's resource from which I can start? Please let me know. – navy1978 Mar 19 '17 at 20:36
  • Yes, there are thousands of examples and no, I shouldn't need to be searching for them for you ;) – MadProgrammer Mar 19 '17 at 20:51
  • Just a tip, if you're looking for realistic movement, such as how the movement of a house fly fluctuates in a fluid manner, you may want to look into [perlin noise](https://en.wikipedia.org/wiki/Perlin_noise) rather than use raw RNG – Vince Mar 19 '17 at 21:29

2 Answers2

1

Short answer is yes, it can be done. The long answer is, you'll never find a single example/solution which meets your exact needs, you will need to dissect them and remove those elements which you need. This is a mark of a professional developer, believe me, I spend 90% of my time doing things I've never done before (or have no initial idea of how to complete).

When presented with a problem/idea, you need to take a step back and break it down into manageable components

From my perspective you have two basic requirements, animation and transformation.

Animation

Animating is simply the illusions of change over time. On the surface, it seems very simple to achieve, in reality, it becomes very complex, very quickly

In Swing, the simplest solution is to use a Swing Timer, which generates regular updates, triggered within the context of the Event Dispatching Thread, making it safe to update the UI from (Swing, like most UI frameworks, been not thread safe).

Because of the way this works, it's not very precise, meaning you could end up with a variable frame rate. You can overcome this by using a time based animation approach, , where the movement is based on a duration of time, rather then the number of times the timer triggers.

Another solution is to use a thread, calculate the amount of time each update cycle takes and wait the remaining amount of time you need in order to maintain the FPS. This is more complicated as you run into threading issues (dirty updates) and it doesn't take into account the amount of time it might take to actually render the graphics on the UI (when using Swing's passive rendering engine)

Transformation

Transforming graphics (moving/rotating) will ultimately come down to "what" you're transforming.

The Graphics2D API has the capacity to rotate images, for example, example, example, example, example, example.

It can also rotate the Graphics context itself, which can be messy, or rotate "shapes", which generally easier to manage.

You should have a look at Working with Geometry and Transforming Shapes, Text and Images and 2D Graphics generally.

You can also move an object between points and change their orentation, as demonstrated here and here or you can use path based animation so that then object follows a pre-defined path for movement or even something more complex, like a time line based animation, for example, example, example

So, the long answer is, it depends

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
-1

You could implement delta time in your project. With delta time your project will run smoothly, because the image can only move as much as it is allowed to move per second. So your program is not dependent on the performance of your CPU. You can read how to calculate delta time here: https://gamedev.stackexchange.com/questions/111741/calculating-delta-time

Video: https://www.youtube.com/watch?v=3lSzfidowTE

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 04 '22 at 05:24