Search code examples
javaframeworksapplet

How to animate a ball grow with NoApplet?


I am trying to make a simple animation in java where a ball grows in size, then have a subclass that when I run it, it makes the ball grow in size until it reaches the end of the screen, at that point it will deflate and repeat the process. This is all in java with NoApplet. I am a begniner in frameworks and this is code of how I think should work.

import java.awt.*;
import java.awt.event.*;
import java.util.Objects;
import javax.swing.*;
import noapplet.NoApplet;

public class Balloon extends NoApplet{
//Field declarations? Not really sure what declarations would I use. 
    protected int delay = 100;
    protected Dimension dim;
    protected int x, y;
    protected Timer timer;
    protected int offset = 10;
    public Balloon() {
    }
    public void init(){
//initialization and have parameter 
        dim = getSize();
        x = dim.width;
        y = dim.height;

    }
    protected void paintComponent(Graphics g) {
        g.setColor(Color.BLACK);
//start making the screen black and then make the animation 


    }
    public static void main (String[]args){
        new Balloon().run();

I have similar code of how something like this should work but I don't know how to "translate"

package noapplet.assigment;
import java.awt.*;
import java.awt.event.*;
import java.util.Objects;
import javax.swing.*;
import noapplet.NoApplet;
import noapplet.example.Omok;

public class ScrollingBanner extends NoApplet {

    protected String text;
    protected Font font =  new java.awt.Font("Sans-serif", Font.BOLD, 24);
    protected Dimension dim;
    protected int x, y;
    protected int delay = 100; // millis
    protected int offset = 10;
    protected Timer timer; // animation timer

    public void init() {
        // get parameters "delay" and "text"
        String att = getParameter("delay");
        if (att != null) {
            delay = Integer.parseInt(att);
        }
        att = getParameter("text");
        text = Objects.requireNonNullElse(att, "Lets Go");

        // set the initial position of the text
        dim = getSize();
        x = dim.width;
        y = font.getSize();

        // initialize the animation timer
        timer = new Timer(delay, e -> repaint());
    }
    protected void paintComponent(Graphics g) {
        // get the font metrics to determine the length of the text
        g.setFont(font);
        FontMetrics fm = g.getFontMetrics();
        int length = fm.stringWidth(text);

        // adjust the position of the text from the previous frame
        x -= offset;
        // if the text is completely off to the left end
        // move the position back to the right end
        //if (x < -length) { x = -dim.width; }
        if (x < -length) { x = dim.width; }

        // set the pen color and draw the background
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, dim.width, dim.height);

        // set the pen color and then draw the text
        g.setColor(Color.GREEN);
        g.drawString(text, x, y);
    }
    public void start() {
        timer.start();
    }
    public void stop() {
        timer.stop();
    }
    public static void main (String [] args){
        new ScrollingBanner().run();
    }
}


Pic related: Shrinking and inflating ball


Solution

  • So, based on this example, I was able to simply modify it to support a circle shape (rather then a custom shape)

    enter image description here

    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Shape;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Path2D;
    import java.time.Duration;
    import java.time.Instant;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    
    public class Main {
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        class TestPane extends JPanel {
    
            private Path2D path;
    
            private Instant anchorPoint;
            private Duration playDuration = Duration.ofSeconds(2);
            private double scale = 1;
    
            private double lowerRange = 0.75;
            private double upperRange = 1.25;
    
            public TestPane() {
                super();
                setPreferredSize(new Dimension(800, 600));
                path = new Path2D.Double(new Ellipse2D.Double(-100, -100, 200, 200));
    
                Timer timer = new Timer(5, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (anchorPoint == null) {
                            anchorPoint = Instant.now();
                        }
                        Duration playTime = Duration.between(anchorPoint, Instant.now());
                        double progress = (double) playTime.toMillis() / playDuration.toMillis();
                        if (progress >= 1) {
                            anchorPoint = null;
                            progress = 1;
                        }
    
                        if (progress > 0.5) {
                            progress = 1.0 - progress;
                        }
    
                        scale = ((upperRange - lowerRange) * progress) + lowerRange;
                        repaint();
                    }
                });
                timer.start();
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
    
                AffineTransform gat = new AffineTransform();
    
                gat.scale(1.0, -1.0);
                gat.translate(getWidth() / 2.0, -getHeight() / 2.0);
                g2d.transform(gat);
    
                Shape shape = path.createTransformedShape(AffineTransform.getScaleInstance(scale, scale));
    
                g2d.setPaint(Color.PINK);
                g2d.fill(shape);
                g2d.setStroke(new BasicStroke(5.0f));
                g2d.setPaint(Color.BLACK);
                g2d.draw(shape);
                g2d.dispose();
            }
        }
    }
    

    Cavet - This will start out large and shrink, before repeating, to reverse this, just change the scale calculation to inverse the progress, for example...

    scale = ((upperRange - lowerRange) * (1d - progress)) + lowerRange;
    

    Cavet - I have no idea what NoApplet is and it scares me