// ===========================================================================//	BallApp.java	1996 Yushin Hozumi All rights reserved.//					Author:Yushin Hozumi// ===========================================================================package	StudioRAIN;import StudioRAIN.*;import StudioRAIN.geometry.*;import StudioRAIN.MMI.ColorPicker.*;import StudioRAIN.MMI.Broadcast.*;import java.awt.*;import java.applet.*;import java.util.*;public class BallApp extends Applet{	private TestRoom mTestRoom = null;	private BallAppControls mControls = null;	private Scrollbar mGravityBar = null;	private Scrollbar mRestitutionBar = null;	public void init()	{		setLayout( new BorderLayout() );		String at = getParameter("wait");		int wait = (at != null) ? Integer.valueOf(at).intValue() : 10;		at = getParameter("width");		int width = (at != null) ? Integer.valueOf(at).intValue() : 400;		at = getParameter("height");		int height = (at != null) ? Integer.valueOf(at).intValue() : 400;		mTestRoom = new TestRoom( 0.95F, 2.0F );		add( "Center", mTestRoom );		add( "North", mControls = new BallAppControls( mTestRoom ) );		add( "West", mGravityBar = new Scrollbar( Scrollbar.VERTICAL, 20, 10, 0, 100  ) );		add( "East", mRestitutionBar = new Scrollbar( Scrollbar.VERTICAL, 95, 10, 0, 100 ) );	}	public void start()	{		mTestRoom.start();		mControls.enable( true );//		mGravityBar.enable( true );//		mRestitutionBar.enable( true );	}	public void stop()	{		mControls.disable();		mTestRoom.stop();	}    public boolean handleEvent( Event ev )    {//    	System.out.println( ev.target.toString() );		if( ev.target instanceof Scrollbar )		{			if( ev.target == mGravityBar )			{//    			System.out.println( String.valueOf( mGravityBar.getValue() ) );				mTestRoom.setGravity( ( float )mGravityBar.getValue() / 10.0F );				return true;			}			else if( ev.target == mRestitutionBar )			{//    			System.out.println( String.valueOf( mRestitutionBar.getValue() ) );				mTestRoom.setRestitution( ( float )mRestitutionBar.getValue() / 100.0F );				return true;			}		}				return false;    }}class BallAppControls extends Panel implements Listener{	private TestRoom mTestRoom = null;	private TextField mSize;	private Color mColor = Color.black;	private ColorCheck mColorCheck = null;    public BallAppControls( TestRoom inRoom )    {		setLayout(new FlowLayout());		mTestRoom = inRoom;		mColorCheck = new ColorCheck();		mColorCheck.addListener( this );		mColor = mColorCheck.getColor();		add( mColorCheck );		add( mSize = new TextField("10", 4) );		add( new Button( "Enter a New Ball" ) );		add( new Button( "Clear all Balls" ) );    }	public void	listenToMessage( Object inClient, BroadcastingMessage inMessage )	{		if( inMessage == ColorPicker.MessageColorChanged && inClient == mColorCheck )			mColor = mColorCheck.getColor();	}	public void setColor( Color inColor )	{		mColor = inColor;	}    public boolean action( Event ev, Object arg )    {		if( ev.target instanceof Button )		{		    if( "Enter a New Ball".equals( arg ) )		    {				mTestRoom.entryBall( Integer.parseInt( mSize.getText().trim() ), mColor );				return true;		    }		    else if( "Clear all Balls".equals( arg ) )		    {				mTestRoom.clearAllBalls();				return true;		    }		}		return false;    }}class TestRoom extends Canvas implements Runnable {	private Vector mBalls = new Vector();	private Thread kicker = null;	private float restitution = 0.95F;	private float gravity = 2.0F;	private int wait = 50;	public TestRoom( float r, float g )	{		restitution = r;		gravity = g;	}		// query functions	public int getWidth() { return size().width; }	public int getHeight() { return size().height; }	public float getRestitution() { return restitution; }	public float getGravity() { return gravity; }	public void setRestitution( float inR ) { restitution = inR; }	public void setGravity( float inG) { gravity = inG; }	void clearAllBalls()	{		for( int i = 0; i < mBalls.size(); i++ )		{			BoundingBall theBall = ( BoundingBall )mBalls.elementAt( i );			theBall.stop();		}		mBalls.removeAllElements();		repaint();	}			synchronized void entryBall( int inSize, Color inColor )	{		float rx = ( float )inSize;		float ry = ( float )inSize;		float x = ( float )Math.random() * ( ( float )getWidth() - rx - rx ) + rx;		float y = ( float )Math.random() * ( ( float )getHeight() - ry - ry ) + ry;		float vx = ( float )Math.random() * 80F - 40F;		float vy = ( float )Math.random() * 80F - 40F;		BoundingBall theBall =  new BoundingBall( this, new Vector2D( x, y ), new Vector2D( vx, vy ), new Vector2D( rx, ry ), inColor );		theBall.start();		mBalls.addElement( theBall );	}	public void paint( Graphics g )	{//		System.out.println( "TestRoom.paint() called." );		if( !mBalls.isEmpty() )		{			try			{				for( int i = 0; i < mBalls.size(); i++ )				{					BoundingBall theBall = ( BoundingBall )mBalls.elementAt( i );					g.setColor( theBall.getColor() );					Vector2D theOrigin = theBall.getPosition().sub( theBall.getRadious() );					Vector2D theSize = theBall.getRadious().schalarMultiple( 2.0F );					g.fillOval( ( int )theOrigin.getX(), ( int )theOrigin.getY(), ( int )theSize.getX(), ( int )theSize.getY() );				}			}			catch( Exception e )			{				System.out.println( e.getMessage() );//				throw( e );			}		}	}	public void start()	{		if( kicker == null)		{			kicker = new Thread( this );			kicker.start();		}	}	public void stop()	{		if( kicker != null )		{			kicker.stop();//			kicker.destroy();			kicker = null;		}	}	public void run()	{//		Thread.currentThread().setPriority( Thread.NORM_PRIORITY-1 );		while( kicker != null )		{			repaint();			try			{				kicker.sleep( wait );			}			catch( InterruptedException e )			{				System.out.println( e.getMessage() );				break;			}		}	}}class BoundingBall extends Thread{	private	Vector2D mPosition = null;	private	Vector2D mRadious = null;	private	Vector2D mVelocity = null;	private TestRoom container = null;	private Color color = null;	private static int wait = 50;	public synchronized Vector2D getPosition() { return new Vector2D( mPosition ); }	public synchronized Vector2D getVelocity() { return new Vector2D( mVelocity ); }	public synchronized Vector2D getRadious() { return new Vector2D( mRadious ); }	public Color getColor() { return color; }		public static void setWait( int inW ) { wait = inW; } 	public BoundingBall( TestRoom inContainter, Vector2D inPosition, Vector2D inVelocity, Vector2D inRadious, Color inColor )	{		container = inContainter;		mPosition = inPosition;		mVelocity = inVelocity;		mRadious = inRadious;		color = inColor;	}		public void run()	{//		System.out.println( "X = " +  x + "Y = " +  y);		for( ; ; )		{			tick();			try			{				sleep( wait );			}			catch( InterruptedException e )			{				System.out.println( e.getMessage() );				break;			}		}	}	public synchronized void tick()	{		mPosition.add( mVelocity );		mPosition.addToY( 0.5F * container.getGravity());				if( mPosition.getX() - mRadious.getX() < 0.0F )		{			mVelocity.setX( -mVelocity.getX() * container.getRestitution() );			mPosition.setX( -mPosition.getX() + mRadious.getX() + mRadious.getX() );		}		else if( mPosition.getX() + mRadious.getX() >= ( float )container.getWidth() )		{			mVelocity.setX( -mVelocity.getX() * container.getRestitution() );			mPosition.setX( ( float )container.getWidth() + ( float )container.getWidth() - mPosition.getX() - mRadious.getX() - mRadious.getX() );		}				if( mPosition.getY() - mRadious.getY() < 0.0F )		{			mVelocity.setY( -mVelocity.getY() * container.getRestitution() );			mPosition.setY( -mPosition.getY() + mRadious.getY() + mRadious.getY() );		}		else if( mPosition.getY() + mRadious.getY() >= ( float )container.getHeight() )		{			mVelocity.setY( -mVelocity.getY() * container.getRestitution() );			mPosition.setY( ( float )container.getHeight() + ( float )container.getHeight() - mPosition.getY() - mRadious.getY() - mRadious.getY() );		}						mVelocity.addToY( container.getGravity() );	}	}