Saturday, June 7, 2014

Java elastic collision of two balls

Pseudo elastic collision of two balls in java. Quick and dirty solution to implement elastic collision in java. There is better solution but this can serve good as well. Two balls are moving with different speed. One is heavier then the other, so we expect on collision the lighter ball to pick up some speed. Also if smaller ball hit bigger ball with certain amount of speed we expect bigger ball to pick some speed as well.

Here is ball class:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package realball;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

/**
 *
 * @author Anak1n
 */
public class ball {

    private float x;
    private float y;
    private float diametar;
    Color color;
    private double xSpeed;
    private double ySpeed;

    public ball(float x, float y, float diameter, Color color) {
        this.x = x;
        this.y = y;

        this.diametar = diameter;
        this.color = color;
    }

    public void draw(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        Ellipse2D.Double circle = new Ellipse2D.Double(getX() - getDiametar() / 2, getY() - getDiametar() / 2, getDiametar(), getDiametar());
        g2d.fill(circle);
    }

    public void move() {
        setX((float) (getX() + getxSpeed()));

        if (getX() - getDiametar() / 2 < 0) {
            setX(getDiametar() / 2);
            setxSpeed(-getxSpeed());
        } else if (getX() + getDiametar() / 2 > 390) {
            setxSpeed(-getxSpeed());
        }

        setY((float) (getY() + getySpeed()));

        if (getY() - getDiametar() / 2 < 0) {
            setySpeed(-getySpeed());
        } else if (getY() + getDiametar() / 2 > 360) {
            setY(360 - getDiametar() / 2);
            setySpeed(-getySpeed());
        }
    }

    /**
     * @return the xSpeed
     */
    public double getxSpeed() {
        return xSpeed;
    }

    /**
     * @param xSpeed the xSpeed to set
     */
    public void setxSpeed(double xSpeed) {
        this.xSpeed = xSpeed;
    }

    /**
     * @return the ySpeed
     */
    public double getySpeed() {
        return ySpeed;
    }

    /**
     * @param ySpeed the ySpeed to set
     */
    public void setySpeed(double ySpeed) {
        this.ySpeed = ySpeed;
    }

    /**
     * @return the x
     */
    public float getX() {
        return x;
    }

    /**
     * @param x the x to set
     */
    public void setX(float x) {
        this.x = x;
    }

    /**
     * @return the y
     */
    public float getY() {
        return y;
    }

    /**
     * @param y the y to set
     */
    public void setY(float y) {
        this.y = y;
    }

    /**
     * @return the diametar
     */
    public float getDiametar() {
        return diametar;
    }

    /**
     * @param diameter
     */
    public void setDiametar(float diameter) {
        this.diametar = diameter;
    }
}


gui class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package realball;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

/**
 *
 * @author Anak1n
 */
public class gui extends JPanel implements Runnable {

    ball b1;
    boolean going = true;

    Thread animator;
    ball b2;
    double deltaX;
    double deltaY;
    double distance;

    public gui() {
        b1 = new ball(50, 80, 40, Color.red);
        b1.setX(50);
        b1.setY(80);
        b1.setxSpeed(4);
        b1.setySpeed(2);

        b2 = new ball(50, 80, 70, Color.red);
        b2.setX(150);
        b2.setY(80);
        b2.setxSpeed(4);
        b2.setySpeed(2);

        

        animator = new Thread(this);
        animator.start();

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        b1.draw(g);
        b2.draw(g);
        g.setColor(Color.red);

        // draw center of circle
        g.fillOval((int) b1.getX() - 5, (int) b1.getY() - 5, 10, 10);
        g.fillOval((int) b2.getX() - 5, (int) b2.getY() - 5, 10, 10);

    }

    @Override
    public void run() {
        while (going) {
            b1.move();
            b2.move();

            checkCollision();

            repaint();

            try {
                Thread.sleep(20);
            } catch (InterruptedException ex) {
            }
        }
    }

    public void checkCollision() {

        deltaX = Math.abs(b1.getX() - b2.getX());
        deltaY = Math.abs(b1.getY() - b2.getY());
        distance = deltaX * deltaX + deltaY * deltaY;
        
        if (distance < (b1.getDiametar() / 2 + b2.getDiametar() / 2) * (b1.getDiametar() / 2 + b2.getDiametar() / 2)) {

            double newxSpeed1 = (b1.getxSpeed() * (4 - 7) + (2 * 7 * b2.getxSpeed())) / 11;

            double newxSpeed2 = (b2.getxSpeed() * (7 - 4) + (2 * 4 * b1.getxSpeed())) / 11;

            double newySpeed1 = (b1.getySpeed() * (4 - 7) + (2 * 7 * b2.getySpeed())) / 11;

            double newySpeed2 = (b2.getySpeed() * (7 - 4) + (2 * 4 * b1.getySpeed())) / 11;

            b2.setxSpeed(newxSpeed2);
            b2.setySpeed(newySpeed2);
            b1.setxSpeed(newxSpeed1);
            b1.setySpeed(newySpeed1);

        }
    }

}


main class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import javax.swing.JFrame;

/**
 *
 * @author Anak1n
 */
public class RealBall {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       JFrame frame = new JFrame ();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gui balls = new gui ();
        frame.setSize(400,400);
        frame.add(balls);
        frame.setVisible(true);
    }
    
}


If you want to improve this collision I would suggest calculating angle of impact and new direction after impact.

Video:

Tuesday, June 3, 2014

Java Swing enlarge image

Enlarge images in java with mouse clicked on image, and return to previous state when clicked on blank space. Maybe there is some more elegant solution, but I did this with java swing timer.

ImageEnlarge class:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
*
* @author Anak1n
*/

public class ImageEnlarge extends JPanel implements ActionListener,
  MouseListener {

 private ImageIcon imageIcon;
 private Image image;

 private int width;
 private int heigth;
 private int imageHeigth;
 private int imageWidth;

 boolean mouseClickedInImageArea = false;

 Rectangle boundsOfImage;

 public ImageEnlarge() {
  
  imageHeigth = 174;
  imageWidth = 170;

  heigth = (600 - imageHeigth) / 2;
  width = (600 - imageWidth) / 2;

  imageIcon = new ImageIcon("images/one.jpg");
  image = imageIcon.getImage();

  boundsOfImage = new Rectangle(width, heigth, imageWidth, imageHeigth);

  addMouseListener(this);

  Timer timer = new Timer(5, this);

  timer.start();
 }

 public void paintComponent(Graphics g) {
  super.paintComponent(g);
  g.drawImage(image, heigth, width, imageWidth, imageHeigth, this);

 }

 @Override
 public void actionPerformed(ActionEvent arg0) {

  if (mouseClickedInImageArea) {
   if (imageHeigth < 494) {
    ++imageHeigth;
    heigth = (600 - imageHeigth) / 2;
   }
   if (imageWidth < 450) {
    ++imageWidth;
    width = (600 - imageWidth) / 2;
    
   }
   boundsOfImage = new Rectangle(width, heigth, imageWidth, imageHeigth);
   
   repaint();
  }

  else if (!mouseClickedInImageArea ) {
   if (imageHeigth > 174) {
    --imageHeigth;
    heigth = (600 - imageHeigth) / 2;
   }
   if (imageWidth > 170) {
    --imageWidth;
    width = (600 - imageWidth) / 2;
   }
   boundsOfImage = new Rectangle(width, heigth, imageWidth, imageHeigth);
   
   repaint();
  }

 }

 @Override
 public void mouseClicked(MouseEvent e) {

  if (boundsOfImage.contains(e.getX(), e.getY())) {
   mouseClickedInImageArea = true;
  } else
   mouseClickedInImageArea = false;
 }

 @Override
 public void mouseEntered(MouseEvent e) {

 }

 @Override
 public void mouseExited(MouseEvent e) {

 }

 @Override
 public void mousePressed(MouseEvent e) {
  

 }

 @Override
 public void mouseReleased(MouseEvent e) {
  

 }

}

Main class:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import javax.swing.JFrame;

/**
*
* @author Anak1n
*/

public class ImageMain {

 public static void main(String[] args) {

  JFrame frame = new JFrame();
  frame.setTitle("Image enlarge");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setSize(600, 600);
  ImageEnlarge enlarge = new ImageEnlarge();
  frame.add(enlarge);
  frame.setVisible(true);

 }

}

If it is too slow and you wish to enlarge image faster you can play with values on lines 63, 67 in ImageEnlarge class, and for restoring to previous state you can change values on lines 76,80, to speed up the process or to slow it, or to change timer value on line 47.

Note: You can create folder images and put in it image named one.jpg or chose path to image. Or you can load images on other ways.

Video:

Monday, June 2, 2014

Java clock always on top

For the first blog post I will post code for clock coded in java that is always on top. It is not finished project needs some improvements and features added, like options to turn on or off always on top, change themes and so on. So here is the code:

class gui is getting system time and display it:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
package clock;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 *
 * @author Anak1n
 */
public class gui extends JPanel implements ActionListener {

    int hour, minutes, seconds;
    String a, b, c;

    Calendar time;
    ImageIcon zero = new ImageIcon("images/zero.png");
    ImageIcon one = new ImageIcon("images/one.png");
    ImageIcon two = new ImageIcon("images/two.png");
    ImageIcon three = new ImageIcon("images/three.png");
    ImageIcon four = new ImageIcon("images/four.png");
    ImageIcon five = new ImageIcon("images/five.png");
    ImageIcon six = new ImageIcon("images/six.png");
    ImageIcon seven = new ImageIcon("images/seven.png");
    ImageIcon eight = new ImageIcon("images/eight.png");
    ImageIcon nine = new ImageIcon("images/nine.png");

    Image[] numbers;

    public gui() {
        setOpaque(false);
        Timer timer = new Timer(1000, this);
        numbers = new Image[]{
            zero.getImage(),
            one.getImage(),
            two.getImage(),
            three.getImage(),
            four.getImage(),
            five.getImage(),
            six.getImage(),
            seven.getImage(),
            eight.getImage(),
            nine.getImage()};

        a = "";
        b = "";
        c = "";
        timer.start();

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        time = Calendar.getInstance();
        hour = time.get(Calendar.HOUR_OF_DAY);
        minutes = time.get(Calendar.MINUTE);
        seconds = time.get(Calendar.SECOND);
        if (hour < 10) {
            b = String.valueOf("0" + hour);
        } else {
            b = String.valueOf(hour);
        }

        if (seconds < 10) {
            a = String.valueOf("0" + seconds);
        } else {
            a = String.valueOf(seconds);
        }
        if (minutes < 10) {
            c = String.valueOf("0" + minutes);
        } else {
            c = String.valueOf(minutes);
        }

        repaint();

    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        for (int i = 0; i < a.length(); i++) {
            g.drawImage(numbers[a.charAt(i) - '0'], 180 + (40 * i), 5, this);

        }
        for (int i = 0; i < b.length(); i++) {
            g.drawImage(numbers[b.charAt(i) - '0'], 0 + (40 * i), 5, this);
        }

        for (int i = 0; i < c.length(); i++) {
            g.drawImage(numbers[c.charAt(i) - '0'], 90 + (40 * i), 5, this);
        }
    }
 }

Main class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package clock;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JOptionPane;

/**
 *
 * @author Anak1n
 */
public class ClockMain {

    public static void main(String[] args) {
        final JDialog window = new JDialog();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int left = (int) screenSize.getWidth();

        Image trayImage;
        ImageIcon trayIconImage;
        trayIconImage = new ImageIcon("images/tray.jpg");
        trayImage = trayIconImage.getImage();
        window.setLocation(left / 2 - 140, 0);
        if (!SystemTray.isSupported()) {
            System.out.println("SystemTray is not supported");
            return;
        }
        final PopupMenu popup = new PopupMenu();
        final TrayIcon trayIcon
                = new TrayIcon(trayImage);
        final SystemTray tray = SystemTray.getSystemTray();

        MenuItem exitItem = new MenuItem("Exit");
        MenuItem aboutItem = new MenuItem("About");
        exitItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        aboutItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, " Autor: Kostic Goran" + "\n E-mail: red.zmaja@gmail.com"
                        + "\n Verzija: 1.0", "About", JOptionPane.INFORMATION_MESSAGE);
            }
        });

        popup.add(aboutItem);
        popup.add(exitItem);

        trayIcon.setToolTip("Clock");
        trayIcon.setPopupMenu(popup);

        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.out.println("TrayIcon could not be added.");
        }
        window.setSize(280, 50);
        window.setResizable(false);
        gui clockGui = new gui();
        window.setUndecorated(true);

        window.add(clockGui);
        window.setAlwaysOnTop(true);

        window.setBackground(new Color(0, 0, 0, 0));
        window.setVisible(true);
    }

}
Note: This code will  display nothing if you don't have folder named images with images named one.png, two.png, tray.jpg and so on. You can change images name and extension if you change it in code also. If you have any questions I will be glad to answer them.

Screenshot: