Output grafico: animazioni multiple.

Nella pagina precedente si è mostrato come simulare il moto di una figura. In questa si useranno metodi analoghi per simulare il moto di più figure identiche. A questo scopo si una la classe java.util.ArrayList<E> dove <E> rappresenta la classe di oggetti da considerare insieme.

Nell'esempio proposto gli oggetti, come nella pagina precedente, saranno di classe Palla che quindi andrà descritta nel sorgente del progetto.
Data la classe Palla, si può definire la classe Palle come estensione di ArrayList<Palla> in cui andranno immessi gli oggetti di classe Palla creati di volta in volta.

Ogni oggetto Palla è dotato di coordinate x e y che ne registrano la posizione ad ogni passo dell'animazione. Questi oggetti si muovono con velocità costante in intensità v e direzione a, che vengono fissate a caso dal costruttore e da cui si ricavano le componenti vx e vy della velocità. Ad ogni passo x viene incrementato di vx e y viene incrementato di vy. Quando x e y diventano negative o quando superano le corrispondenti dimensioni del rettangolo che delimita la simulazione si ha un urto contro una parete e vx o vy cambiano di segno.

La sequenza di preparazione dell'applicazione è la seguente.

Questa è la grafica del progetto.

fig01.gif

Questo può essere un passo dell'animazione.

fig02.gif

 


Esempio.

/*
Applicazione Rimbalzi
Pallina rimbalzano contro le pareti
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.MemoryImageSource;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.ImageIcon;
import javax.swing.BoxLayout;
import javax.swing.BorderFactory;
import javax.swing.Timer;

import javax.swing.border.*;

import java.util.ArrayList;

//=========================================================================
public class Rimbalzi
extends JFrame
implements ActionListener

{
  PannelloGrafica pannello_grafica;
  JLabel lbl_n, label_angolo;
  JTextField tf_n, tf_angolo;
  JButton button_start, button_stop;
  Timer timer;
  Palle palle;
  ImageIcon imgp;
  final static int dim_img = 12;
  boolean movimento;
  int dp;

//---------------------------------------------------------------------- 
  Rimbalzi()
    {
      setTitle("Rimbalzi");
      setLocation(0,0);
      int n_lingua = 0;

      Container container = getContentPane();
      container.setPreferredSize(new Dimension(800,500));
      container.setLayout(new BoxLayout(container,BoxLayout.Y_AXIS));

      pannello_grafica = new PannelloGrafica();
      imgp = iconPalla(pannello_grafica);
      dp = imgp.getIconWidth();
      container.add(pannello_grafica);

      JPanel pannello_dati = new JPanel();
      pannello_dati.setBorder(BorderFactory.createRaisedBevelBorder());
      pannello_dati.setBackground(Color.yellow);
      pannello_dati.setPreferredSize(new Dimension(300,40));
      
      String input = (n_lingua==0)? " quante palle ":" how many balls ";
      lbl_n = new JLabel(input);
      pannello_dati.add(lbl_n);

      tf_n = new JTextField("10");
      tf_n.setPreferredSize(new Dimension(80,24));
      pannello_dati.add(tf_n);

      container.add(pannello_dati);

      JPanel pannello_bottoni = new JPanel();
      pannello_bottoni.setBorder(BorderFactory.createRaisedBevelBorder());
      pannello_bottoni.setBackground(Color.green);
      pannello_bottoni.setPreferredSize(new Dimension(300,40));

      button_start = new JButton("START");
      button_start.setActionCommand("cm_start");
      button_start.addActionListener(this);
      pannello_bottoni.add(button_start);

      button_stop = new JButton("STOP");
      button_stop.setActionCommand("cm_stop");
      button_stop.addActionListener(this);
      pannello_bottoni.add(button_stop);

      container.add(pannello_bottoni);
      timer = new Timer(5,this);
      palle = new Palle();
    }

//---------------------------------------------------------------------- 
  static ImageIcon iconPalla(PannelloGrafica pg)
    {
      int bianco = (255<<24)|(255<<16)|(255<<8)|255;
      int rosso = (255<<24)|(255<<16);
      int d = dim_img;
      double dm = d/2;
      int px[] = new int[d*d];
      int ix = 0;
      for (int i = 0; i < d; i++)
        for (int j = 0; j < d; j++)       
          {
            if (hypot(i-dm,j-dm) < dm)
              px[ix] = rosso;
            else
              px[ix] = bianco;
            ix++;
          }
      Image mem = pg.createImage(new MemoryImageSource(d,d,px,0,d));
      return new ImageIcon(mem);
    } 
//----------------------------------------------------------------------  
  static double hypot(double x, double y)
    {
      return Math.sqrt(x*x+y*y);
    } 

//---------------------------------------------------------------------- 
  void inizioAnimazione()
    {
      if (timer.isRunning()) timer.stop();
      int n_palle = 0;
      try
        {
          n_palle = Integer.parseInt(tf_n.getText());
        }
      catch(Exception exc)
        {
          return;
        }
      if (n_palle < 1)
        return;

      palle = new Palle();
 
      for (int i=0; i < n_palle; i++)
        palle.add(new Palla());

      movimento = true;
      timer.start();
    }

//---------------------------------------------------------------------- 
  void fineAnimazione()
    {
      movimento = false;
      if (timer.isRunning()) timer.stop();
    }

//---------------------------------------------------------------------- 
  public void actionPerformed(ActionEvent e)
    {
      String comando = e.getActionCommand();
      if (comando=="cm_start")
        inizioAnimazione();
      if (comando=="cm_stop")
        fineAnimazione();
      if (movimento) pannello_grafica.repaint();     
    }

//----------------------------------------------------------------------
  public static void main(String args[])
    {
      Rimbalzi r = new Rimbalzi();
      r.pack();
      r.setVisible(true);
    }


//=========================================================================
class PannelloGrafica
extends JPanel

{
  LineBorder bordo;
  Palla palla;

//---------------------------------------------------------------------- 
  PannelloGrafica()
    {
      setBackground(Color.white);
      bordo = new LineBorder(Color.blue,2);
      setPreferredSize(new Dimension(400,400));
    }

//----------------------------------------------------------------------
  public void paint(Graphics g)
    {
      super.paintComponent(g);
      bordo.paintBorder(this,g,0,0,getWidth(),getHeight());
      g.setXORMode(Color.white);
      Palla p;
      for (int i=0; i < palle.size(); i++)
        {
          p = palle.get(i);
          p.spostamento();
          imgp.paintIcon(this,g,p.sn,p.alto);
        }
    }
}

//=========================================================================
class Palla
{
  double x,y,v,vx,vy,a;
  int sn, ds, alto, basso;
  PannelloGrafica pannello;

//----------------------------------------------------------------------  
  public Palla()
    {
      x = 0;
      y = 0;
      posizioneGrafica();
      v = 5*Math.random();
      a = 0.5*Math.PI*Math.random();
      vx = v*Math.cos(a);
      vy = v*Math.sin(a);
    }

//----------------------------------------------------------------------
  public void spostamento()
    {
      if ((sn < 0) || (ds>pannello_grafica.getWidth())) vx = -vx;
      if ((alto < 0) || (basso>pannello_grafica.getHeight())) vy = -vy;
      x += vx;
      y += vy;
      posizioneGrafica();
    }

//----------------------------------------------------------------------
  public void posizioneGrafica()
    {
      sn = (int)Math.round(x);
      alto = (int)Math.round(y);      
      ds = sn+dp;
      basso = alto+dp;
    }
//----------------------------------------------------------------------
  
}

//=========================================================================
class Palle
extends ArrayList< Palla>
{

}

//=========================================================================
}

Il sorgente può essere scaricato da Rimbalzi.zip e scompattato in una cartella del proprio sistema.