package net.jaitec.applet1;
import javax.swing.JApplet;
import net.jaitec.applet1.Ball;
import net.jaitec.applet1.Config;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
public class Applet1 extends JApplet implements Runnable {
/**
*
*/
private static final long serialVersionUID = 5637177354165225750L;
private Graphics2D graphic;
private Image canvasImage;
private ArrayList<Ball> balls;
//private int t;
private int dir;
private boolean move = true;
private boolean process = true;
private Thread thread = null;
boolean threadSuspended;
//Called when this applet is loaded into the browser.
public void init() {
setSize(Config.WIDTH, Config.HEIGHT);
setBackground( Config.BGCOLOR );
canvasImage = createImage(Config.WIDTH, Config.HEIGHT);
graphic = (Graphics2D)canvasImage.getGraphics();
balls = new ArrayList<Ball>();
int numballs = 9;
Ball ball;
Color[] color = { Color.orange, Color.gray, Color.cyan,
Color.green, Color.lightGray, Color.yellow,
Color.magenta, Color.pink, Color.red,
Color.white
};
int dx = 65;
int dy = 65;
int y = Config.MARGIN + 15;
int x = Config.MARGIN + 15;
// now generating the random balls
for (int i=0;i<numballs;i++){
int radius = 20 - ((int) Math.random() * 10);
ball = new Ball(color[i%color.length], radius);
ball.setCoords( x , y );
x += dx;
if( x > Config.WIDTH_E - dx){
x = Config.MARGIN + 15;
y += dy;
}
ball.setAngle(45 + Math.toRadians( (int) (Math.random() * 90) ));
ball.setSpeed(1 + (int) (Math.random()*10));
addBall(ball);
}
//run();
}
public void paint( Graphics g ) {
g.drawImage(canvasImage, 0, 0, this);
}
private void erase()
{
Color original = graphic.getColor();
graphic.setColor(Config.BGCOLOR);
graphic.fill(new Rectangle(0, 0, Config.WIDTH, Config.HEIGHT));
graphic.setColor(original);
}
public void addBall(Ball ball)
{
balls.add(ball);
}
public void eraseBall(Ball ball){
balls.remove(ball);
}
public void redraw()
{
erase();
// work frame where balls bounce
Color antes = graphic.getColor();
graphic.drawRect(Config.MARGIN, Config.MARGIN,
Config.WIDTH-(2*Config.MARGIN)-1, Config.HEIGHT-(2*Config.MARGIN)-1);
graphic.setColor(Color.black);
// angle guide
if(Config.DEBUG)
{
for(int a=0;a<=360;a+=15)
{
int x = Config.CENTERX + (int) (Math.cos(Math.toRadians(a)) * Config.WIDTH_E / 2);
int y = Config.CENTERY + (int) (Math.sin(Math.toRadians(a)) * Config.HEIGHT_E / 2);
graphic.drawLine(Config.CENTERX, Config.CENTERY, x,y);
graphic.drawString(""+a+"�", x, y);
}
}
graphic.setColor(antes);
// now draw each ball
for(Iterator<Ball> i= balls.iterator(); i.hasNext(); ) {
Ball b = (Ball) i.next();
b.draw(graphic);
// data from each ball
if(Config.DEBUG)
{
graphic.drawString("a="+(int) Math.toDegrees(b.getAngle()), b.getX(), b.getY());
graphic.drawString("s="+b.getSpeed(), b.getX(), b.getY()+15);
graphic.drawString("r="+b.getRadius(), b.getX(), b.getY()+30);
}
}
repaint();
}
public boolean move(Ball ball)
{
int dist = ball.getSpeed();
double angle = ball.getAngle();
int xx = ball.getX();
int yy = ball.getY();
int r = ball.getRadius();
// checks if the ball has exit the work frame
if (xx + r > Config.WIDTH_E - r) xx = Config.WIDTH_E - 2*r - 1;
if (xx < Config.MARGIN ) xx = Config.MARGIN +1;
if (yy + r > Config.HEIGHT_E - r) yy = Config.HEIGHT_E - 2*r - 1;
if (yy < Config.MARGIN) yy = Config.MARGIN + 1;
if(xx!=ball.getX() || yy!=ball.getY()){
ball.setCoords(xx,yy);
ball.setSpeed(2);
return true;
}
// now calculates the new position
xx = ball.getX() + (int) (Math.cos(angle) * dist);
yy = ball.getY() + (int) (Math.sin(angle) * dist);
ball.setCoords(xx,yy);
// checks if the balls bounce with border
int x = ball.getCenterX();
int y = ball.getCenterY();
int ang = (int) (360 + Math.toDegrees(angle)) % 360;
double a = 9999; // this controls that not changes are necessary
int var = (int) (Math.random() * 30) - 15; // to introduce little variation in bounce angle
if( ( (ang > 90) && (ang <270) && (x - r <= Config.MARGIN) ) ||
( (ang >270 || ang < 90) && (x + r >= Config.WIDTH_E) ) ){
a = 180 - ang + var;
if(Config.DEBUG)
System.out.print(">");
}else{
if( ( (ang >180) && (ang <360) && (y - r <= Config.MARGIN) ) ||
( (ang > 0 ) && (ang< 180) && (y + r >= Config.HEIGHT_E) ) ) {
a = 360 - ang + var;
if(Config.DEBUG)
System.out.print("V");
}
}
for(Iterator<Ball> i= balls.iterator(); i.hasNext(); ) {
Ball b = ((Ball) i.next());
if(b!=ball){
int distance = ball.distance(b);
int r2 = b.getRadius();
if(distance <= r + r2){
// two balls are bounced
// we play with speeds, checked ball lost one point of speed
// and crashed ball win one point of speed
int v1 = ball.getSpeed();
if(v1>3) ball.setSpeed(v1-1);
int v2 = b.getSpeed();
if(v2<10) b.setSpeed(v2+1);
// check if the balls are mounted to calculate dist to separate them
dist = distance<r+r2?r+r2-distance+1:dist;
if(Config.DEBUG)
System.out.println("distance: "+distance+",bounce between "+b.getNumber()+" & "+ball.getNumber());
// now angle interchange except that balls goes in the same direction
a = (180 + ang) % 360;
b.setAngle(angle);
}
}
}
if(a!=9999){
a = (360 + a) % 360;
a = Math.toRadians(a);
int xDest = ball.getX() + (int) (Math.cos(a) * dist);
int yDest = ball.getY() + (int) (Math.sin(a) * dist);
ball.setAngle(a);
ball.setCoords(xDest, yDest);
if(Config.DEBUG)
System.out.println(ball.getNumber()+": bounce, entry angle ("+ang+"), exite angle ("+((int)Math.toDegrees(a))+")");
return false;
}
return true;
}
public void run(){
while(process){
long t1 = System.currentTimeMillis();
if(move) // this is controlled by user with spacebar
{
for(Iterator<Ball> it = balls.iterator(); it.hasNext(); ) {
Ball b = (Ball) it.next();
if(b.getNumber()==1 && dir>0) b.setAngle(0);
if(b.getNumber()==1 && dir<0) b.setAngle(Math.PI);
if(Config.DEBUG)
System.out.println(">:"+b.getNumber());
move(b);
}
}
redraw();
long t2 = System.currentTimeMillis();
long t = Config.FRAME-(t2-t1);
if(t>0){
try{
Thread.sleep(t);
} catch (InterruptedException ex) { }
}
}
System.exit(0);
}
// Executed after the applet is created; and also whenever
// the browser returns to the page containing the applet.
public void start() {
System.out.println("start(): begin");
if ( thread == null ) {
System.out.println("start(): creating thread");
thread = new Thread( this );
System.out.println("start(): starting thread");
threadSuspended = false;
thread.start();
}
else {
if ( threadSuspended ) {
threadSuspended = false;
System.out.println("start(): notifying thread");
synchronized( this ) {
notify();
}
}
}
System.out.println("start(): end");
}
// Executed whenever the browser leaves the page containing the applet.
public void stop() {
System.out.println("stop(): begin");
threadSuspended = true;
}
public String getAppletInfo() {
return "Title: Bouncing Balls v1.0, 8 Ago 2012\n"
+ "Author: Joseluis Laso\n"
+ "A simple experiment with animation.";
}
public static void main(String[] args) {
//... Create an initialize the applet.
Applet1 theApplet = new Applet1();
theApplet.setSize(Config.WIDTH,Config.HEIGHT);
theApplet.setVisible(true);
}
}