Hello,
I am working on a homework assignment to represent a java applet with some bouncing balls inside. So far so good. The balls bounce and behave as they are supposed. The only thing is that I want to make 2 buttons, Start and Stop (this is not part of the assignment, but my free will to provide some extra stuff :) ) . I am implementing Runnable for the animation and ActionListener for the buttons. I did research on threading, but somehow I am still not getting quite the result I want. The applet is not displaying my buttons (I guess I am not implementing them correctly) and I dont know whether I have synchronized the threads correctly as well. So, I am asking for some guidance how can I do this? Thanks in advance!
As a remark, I am new to Java, as I am just starting to learn it and this is my first assignment.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Balls extends JApplet implements Runnable, ActionListener
{
Thread runner = null;
Image img;
Graphics gr;
BallCollision ball[];
Balls can;
JButton stopButton;
JButton startButton;
JPanel controls;
boolean stop,start;
//field for 10 balls
static final int MAX=10;
public void init()
{
setSize(800,600);
img = createImage(size().width,size().height);
gr = img.getGraphics();
startButton = new JButton("Start");
stopButton = new JButton("Stop");
stopButton.addActionListener(this);
startButton.addActionListener(this);
controls = new JPanel();
controls.setLayout(new FlowLayout());
controls.add(startButton);
controls.add(stopButton);
//new Thread(this).start();
ball = new BallCollision[MAX];
int w=size().width;
int h=size().height;
//creation of balls, which have different coordinates,
//speed, direction and colors
ball[0] = new BallCollision(w,h,50,20,1.5,7.5,Color.orange);
ball[1] = new BallCollision(w,h,60,210,2.0,-3.0,Color.red);
ball[2] = new BallCollision(w,h,15,70,-2.0,-2.5,Color.pink);
ball[3] = new BallCollision(w,h,150,30,-2.7,-1.0,Color.cyan);
ball[4] = new BallCollision(w,h,210,30,2.2,-12.5,Color.magenta);
ball[5] = new BallCollision(w,h,360,170,2.2,-1.5,Color.yellow);
ball[6] = new BallCollision(w,h,210,180,-1.2,-2.5,Color.blue);
ball[7] = new BallCollision(w,h,330,30,-2.2,-1.8,Color.green);
ball[8] = new BallCollision(w,h,180,220,-2.2,-1.8,Color.white);
ball[9] = new BallCollision(w,h,330,130,-2.2,9.0,Color.gray);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == startButton) start = true;
can.start();
if(e.getSource() == stopButton) start = false;
can.stop();
}
public void start()
{
if (runner == null)
{
runner = new Thread (this);
runner.start();
}
}
public void stop()
{
if (runner != null)
{
runner.stop();
runner = null;
}
}
public void run()
{
while(true)
{
try {Thread.sleep(15);}
catch (Exception e) { }
//move our balls around
for(int i=0;i<MAX;i++)
ball.move();
handleCollision();
repaint();
}
}
boolean collide(BallCollision b1, BallCollision b2)
{
double wx=b1.getCenterX()-b2.getCenterX();
double wy=b1.getCenterY()-b2.getCenterY();
//the distance between 2 colling balls' centres is
//calculated by the theorem of Pythagoras
double distance=Math.sqrt(wx*wx+wy*wy);
if(distance<b1.diameter)
return true;
return false;
}
private void handleCollision()
{
//ecah ball is checked for possible collisions
for(int i=0;i<MAX;i++)
for(int j=0;j<MAX;j++)
{
if(i!=j)
{
if(collide(ball[i], ball[j]))
{
ball[i].hit(ball[j]);
ball[j].hit(ball[i]);
}
}
}
}
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g)
{
gr.setColor(Color.black);
gr.fillRect(0,0,size().width,size().height);
//paint the balls
for(int i=0;i<MAX;i++)
ball[i].paint(gr);
g.drawImage (img,0,0, this);
}
}
class BallCollision
{
int width, height;
int diameter=30;
//balls' coordinates and values to be incremented for directions
double x, y, xIncremented, yIncremented, coll_x, coll_y;
boolean collide;
Color color;
Graphics g;
//constructor
public BallCollision(int w, int h, int x, int y, double xInc, double yInc, Color c)
{
width=w;
height=h;
this.x=x;
this.y=y;
this.xIncremented=xInc;
this.yIncremented=yInc;
color=c;
}
public double getCenterX() {return x+diameter/2;}
public double getCenterY() {return y+diameter/2;}
public void move()
{
if (collide)
{
double xvect=coll_x-getCenterX();
double yvect=coll_y-getCenterY();
if((xIncremented>0 && xvect>0) || (xIncremented<0 && xvect<0))
xIncremented=-xIncremented;
if((yIncremented>0 && yvect>0) || (yIncremented<0 && yvect<0))
yIncremented=-yIncremented;
collide=false;
}
x+=xIncremented;
y+=yIncremented;
//if the ball reaches a wall, it bounces to the opposite direction
if(x<1 || x>width-diameter)
{
xIncremented=-xIncremented;
x+=xIncremented;
}
if(y<1 || y>height-diameter)
{
yIncremented=-yIncremented;
y+=yIncremented;
}
}
public void hit(BallCollision b)
{
if(!collide)
{
coll_x=b.getCenterX();
coll_y=b.getCenterY();
collide=true;
}
}
public void paint(Graphics graphics)
{
g=graphics;
g.setColor(color);
//the coordinates in fillOval have to be int, so we cast
//explicitly from double to int
g.fillOval((int)x,(int)y,diameter,diameter);
}
}