add object to JPanel - java

I don't usually do this, and I hate when other does... But I found my self spending the last 6 hours to figure out where I wrong.
I rewrote those lines dozen of times, change several approaches, and still couldn't figure out what the hake is wrong!
The issue is as followed:
Clicking on the [Add] button should add additional circle to the panel (starting from x=0,y=0 - top left corner).
currently only the first circle is loaded, the rest is loaded to the arrayList but not to the panel.
Any thoughts?
BallControl:
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.event.*;
import java.awt.*;
import java.util.ArrayList;
public class BallControl extends JPanel {
private int delay = 10; // Create a timer with delay 1000 ms
private Timer timer = new Timer(delay, new TimerListener());
private ArrayList<Ball> balls = new ArrayList<Ball>();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JButton jbtAdd = new JButton("Add");
private JButton jbtRemove = new JButton("Remove");
private JButton jbtDirection = new JButton("Direction");
private JScrollBar jsbDelay = new JScrollBar();
private JPanel jplBalls = new JPanel(new BorderLayout());
public BallControl() { // Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtAdd);
panel.add(jbtRemove);
panel.add(jbtDirection);
balls.add(new Ball());
// Add panel-ball and buttons to the panel
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
setDelay(jsbDelay.getMaximum());
timer.setDelay(delay);
jplBalls.setBorder(new LineBorder(Color.blue));
jplBalls.setVisible(true);
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(jplBalls, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
timer.start();
jplBalls.add(balls.get(balls.size()-1));
// Register listeners
jbtSuspend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
jbtResume.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
jbtAdd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addNewBallToPanel();
if(jbtRemove.isEnabled()==false)
jbtRemove.setEnabled(true);
}
});
jbtRemove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeBallFromPanel();
if (balls.size()==0)
jbtRemove.setEnabled(false);
}
});
jbtDirection.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(Ball b : balls)
b.changeDirection();
}
});
jsbDelay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
setDelay(jsbDelay.getMaximum() - e.getValue());
timer.setDelay(delay);
}
});
}
public void addNewBallToPanel(){
balls.add(new Ball());
jplBalls.add(balls.get(balls.size()-1));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
for (Ball b : balls){
b.paintComponent(g);
}
}
private class TimerListener implements ActionListener {
/** Handle the action event */
public void actionPerformed(ActionEvent e) {
repaint();
}
}
public void removeBallFromPanel(){
jplBalls.remove(balls.get(balls.size()-1));
balls.remove(balls.size()-1);
}
public void setDelay(int delay) {
this.delay = delay;
}
}
Ball:
import javax.swing.Timer;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Ball extends JPanel {
//private int delay = 10; // Create a timer with delay 1000 ms
//private Timer timer = new Timer(delay, new TimerListener());
private int x = 0;
private int y = 0; // Current ball position
private int radius = 5; // Ball radius
private int dx = 2; // Increment on ball's x-coordinate
private int dy = 2; // Increment on ball's y-coordinate
private Color c;
public void setC(Color c) {
this.c = c;
}
public Ball() {
c = new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(c);
if (x < radius)
dx = Math.abs(dx); // Check boundaries
if (x > getWidth() - radius)
dx = -Math.abs(dx);
if (y < radius)
dy = Math.abs(dy);
if (y > getHeight() - radius)
dy = -Math.abs(dy);
x += dx; // Adjust ball position
y += dy;
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}
public void changeDirection(){
dx=-dx;
dy=-dy;
}
}
BounceBallApp:
import java.awt.*;
import javax.swing.*;
public class BounceBallApp extends JApplet {
public BounceBallApp() {
add(new BallControl());
}
public void init(){
this.setSize(500, 300);
}
}

Two edits seems to fix problem:
In BallControl
private JPanel jplBalls = new JPanel(null);
jplBalls.setOpaque(false);
In Ball
if (x > getParent().getWidth() - radius)
dx = -Math.abs(dx);
if (y > getParent().getHeight() - radius)
dy = -Math.abs(dy);
But i should suggest you to have one panel and draw balls from array in it's paintComponent method.
Now you have created a sandwich from multiple panels and they are overlap each other.
Another way is make ball a widget, and change it's coordinates.

Swing components use layout managers. You created your balls panel with a BorderLayout. A BorderLayout can only display a single component in the CENTER, which is where you are adding all your Balls.
When you add additional Balls you never revalidate() the panel, so by default all the Balls have a 0 size which means there is nothing to paint. Even if you did revalidate() the panel the only the last panel added with display since by default a panel is opaque so the last ball added would paint over top of the other Balls. So the simple answer to your question is that you probably need to make the Balls non-opaque.
However, that is still not a very good design because you will potentially be adding many Balls to the panel and each ball will be sized at roughly (500, 300). Since all the Balls are non-opaque the painting system will need to do a lot of work to find an opaque background which needs to be painted before all the Balls are painted.
If you want to deal with components. Then each component should be non-opaque and the size of each component should only be the size of the actual oval that you are painting. You would need to use a null layout so you can randomly position every ball on the panel. Then you need to set the size/location of every Ball so that it can be painted properly.
Or another approach is to not use components at all but instead to just keep information about every Ball in an ArrayList and then do custom painting that simply iterates through the ArrayList to paint each Ball.
For an example of this last approach check out the DrawOnComponent example from Custom Painting Approaches. The code is not exactly what you want, but the concept is the same except your user will be clicking a button to add a circle instead of using the mouse.

Your problem is that your Ball is a panel. You really only want the Ball to be a data class that holds the data of how to draw a class. The problem with your code is that you r trying to add a new ball panel when really you only want to add a ball to an existing panel. So the logic from your Ball class, you need to move that to the BallControll. Here's a running example. I tweeked your code. You can get an idea from it, what needs to be fixed.
import javax.swing.Timer;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class BounceBallApp extends JFrame {
public BounceBallApp() {
add(new BallControl());
}
public static void main(String[] args) {
JFrame frame = new BounceBallApp();
frame.setTitle("MultipleBallApp");
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JButton jbtAdd = new JButton("Add");
private JButton jbtSubtract = new JButton("Remove");
private JScrollBar jsbDelay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtAdd);
panel.add(jbtSubtract);
// Add ball and buttons to the panel
ballPanel.setBorder(
new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new Listener());
jbtResume.addActionListener(new Listener());
jbtAdd.addActionListener(new Listener());
jbtSubtract.addActionListener(new Listener());
jsbDelay.addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbtSuspend) {
ballPanel.suspend();
} else if (e.getSource() == jbtResume) {
ballPanel.resume();
} else if (e.getSource() == jbtAdd) {
ballPanel.add();
} else if (e.getSource() == jbtSubtract) {
ballPanel.subtract();
}
}
}
}
class BallPanel extends JPanel {
private int delay = 10;
private ArrayList<Ball> list = new ArrayList<Ball>();
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
#Override
/**
* Handle the action event
*/
public void actionPerformed(ActionEvent e) {
repaint();
}
});
public BallPanel() {
timer.start();
}
public void add() {
list.add(new Ball());
}
public void subtract() {
if (list.size() > 0) {
list.remove(list.size() - 1); // Remove the last ball
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < list.size(); i++) {
Ball ball = (Ball) list.get(i); // Get a ball
g.setColor(ball.color); // Set ball color
// Check boundaries
if (ball.x < 0 || ball.x > getWidth()) {
ball.dx = -ball.dx;
}
if (ball.y < 0 || ball.y > getHeight()) {
ball.dy = -ball.dy;
}
// Adjust ball position
ball.x += ball.dx;
ball.y += ball.dy;
g.fillOval(ball.x - ball.radius, ball.y - ball.radius,
ball.radius * 2, ball.radius * 2);
}
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
class Ball {
int x = 0;
int y = 0; // Current ball position
int dx = 2; // Increment on ball's x-coordinate
int dy = 2; // Increment on ball's y-coordinate
int radius = 5; // Ball radius
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
}
}
Note: I left the direction part out. Id was confusing me. You can fix that.

Related

How to use a reset button Java arkanoid game

So this is part of my game panel for my game. I got my start button to work, and created a reset button but I don't know how to reset the game every single time it is pressed. Does anyone know how to reset the game to its original position after you press "Reset"? Right now it will display the words "You have died", but it doesn't do anything when I press Reset.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class GamePanel extends JPanel
{
private Brick[][] bary;
private static final Color BACKGROUND = Color.black;
private BufferedImage myImage;
private Graphics myBuffer;
private Ball ball = new Ball();
public Bumper bumper;
private Timer t;
private int hits = 0;
private boolean isPlayingGame = false;
public GamePanel()
{
myImage = new BufferedImage(600, 800, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
myBuffer.setColor(BACKGROUND);
myBuffer.fillRect(0, 0, 600,800);
JButton sbutton = new JButton("Start");
sbutton.setFocusable(false);
sbutton.addActionListener(new Listener());
add(sbutton);
JButton rbutton = new JButton("Reset");
rbutton.setFocusable(false);
rbutton.addActionListener(new Listener());
add(rbutton);
bary = new Brick[5][14];
bumper = new Bumper(270, 775, 60, 10, Color.BLUE);
ball = new Ball(300, 400, 10, Color.RED);
t = new Timer(5, new Listener());
setFocusable(true);
//addKeyListener(new Key());
}
// tick method is called every 10ms by Arkanoid.java
// only does stuff if game is actually being played
public void tick()
{
if(isPlayingGame)
{
ball.move(600,800, 600, 800);
death(ball);
}
}
// these get called by the BumperLitsener, which is added to the whole frame
public void moveBumperLeft()
{
bumper.setX(bumper.getX()-20);
//System.out.println("moving bumper left");
}
public void moveBumperRight()
{
bumper.setX(bumper.getX()+20);
//System.out.println("moving bumper right");
}
/*
public class Key extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_A)
bumper.setX(bumper.getX()+10 );
if(e.getKeyCode() == KeyEvent.VK_S)
bumper.setX(bumper.getX()-10 );
}
}
*/
public void startGame()
{
isPlayingGame = true;
}
public void paintComponent(Graphics g)
{
// draw myBuffer, then draw that onto g
myBuffer.setColor(BACKGROUND);
myBuffer.fillRect(0,0,600,800);
setLayout(new GridLayout(5, 14));
myBuffer.setColor(Color.WHITE);
int b=1;
int d=40;
for(int r = 0; r < bary.length; r++)
{
for(int c = 0; c < bary[0].length; c++)
{
bary[r][c] = new Brick(b, d,40,20, Color.BLUE);
b=b+43;
bary[r][c].draw(myBuffer);
}
d=d+23;
b=1;
}
ball.draw(myBuffer);
bumper.draw(myBuffer);
repaint();
if(ball.getColor()==Color.BLACK)
{
myBuffer.setFont(new Font("MS Comic Sans", Font.ITALIC, 45));
myBuffer.drawString("GAME OVER!", 168, 300);
ball.move(0, 0, 0, 0);
}
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
GamePanel.this.getTopLevelAncestor().requestFocus();
startGame(); // starts game when button is pressed
System.out.println("Game is starting!");
}
}
private void death(Ball ball)
{
double d = ball.getY() + ball.getRadius();
if(d>800.0)
{
ball.setX(300);
ball.setY(400);
ball.setdx(ball.getdx()*-1);
ball.setdy(ball.getdy()*-1);
ball.setColor(Color.BLACK);
}
}
/* private void collide(Ball ball, Bumper b)
{
double d = distance(ball.getX(), ball.getY(), b.getX(), b.getY());
if(d <= 37.5)
{
ball.move();
hits++;
}
}*/
// private double distance(double x1, double y1, double x2, double y2)
// {
// return(Math.sqrt(Math.pow(x2 - x1, 2.0) + Math.pow(y2 - y1, 2.0))); // enter the calculation here.
//}
}
Thank you so much!!!
Right now, you have a single Listener class and two buttons that have registered against the listener (sbutton and rbutton). It'd be easier if you had different classes that implemented ActionListener, but let's move past that for now.
You need to make modifications to your actionPerformed method such that:
You can differentiate the source of the action - i.e. which button was pressed - Reset or the Start? Hint: use the getSource() method from ActionEvent
If the button pressed was the Reset button, you need to reset the GUI to its initial state

Multiple Ball Program that randomizes the size of the balls

I have my program running where I have a variable radius so that the balls can be of a size int, but I would like to know how to make this program more complex with adding random sizes of balls. small,medium,big etc. On line 148 I tried changing it to int radius = (int)(5*Math.random); but it did not work. Must I do something else to my code in order for this to work? And if there are any other hints you may have, they'd be much appreciated. Thanks
import javax.swing.Timer;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MultipleBallApp extends JApplet
{
public MultipleBallApp()
{
add(new BallControl());
}
class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JButton jbtAdd = new JButton("+1");
private JButton jbtSubtract = new JButton("-1");
private JScrollBar jsbDelay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtAdd);
panel.add(jbtSubtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new Listener());
jbtResume.addActionListener(new Listener());
jbtAdd.addActionListener(new Listener());
jbtSubtract.addActionListener(new Listener());
jsbDelay.addAdjustmentListener(new AdjustmentListener()
{
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbtSuspend)
ballPanel.suspend();
else if (e.getSource() == jbtResume)
ballPanel.resume();
else if (e.getSource() == jbtAdd)
ballPanel.add();
else if (e.getSource() == jbtSubtract)
ballPanel.subtract();
}
}
}
class BallPanel extends JPanel
{
private int delay = 10;
private ArrayList<Ball> list = new ArrayList<Ball>();
// Create a timer with the initial dalay
protected Timer timer = new Timer(delay, new ActionListener() {
#Override /** Handle the action event */
public void actionPerformed(ActionEvent e)
{
repaint();
}
});
public BallPanel()
{
timer.start();
}
public void add()
{
list.add(new Ball());
}
public void subtract()
{
if (list.size() > 0)
list.remove(list.size() - 1); // Remove the last ball
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int i = 0; i < list.size(); i++)
{
Ball ball = (Ball)list.get(i); // Get a ball
g.setColor(ball.color); // Set ball color
// Check boundaries
if (ball.x < 0 || ball.x > getWidth())
ball.dx = -ball.dx;
if (ball.y < 0 || ball.y > getHeight())
ball.dy = -ball.dy;
// Adjust ball position
ball.x += ball.dx;
ball.y += ball.dy;
g.fillOval(ball.x - ball.radius, ball.y - ball.radius,
ball.radius * 2, ball.radius * 2);
}
}
public void suspend()
{
timer.stop();
}
public void resume()
{
timer.start();
}
public void setDelay(int delay)
{
this.delay = delay;
timer.setDelay(delay);
}
}
class Ball
{
int x = 0;
int y = 0; // Current ball position
int dx = 10; // Increment on ball's x-coordinate
int dy = 10; // Increment on ball's y-coordinate
int radius = 5; // Ball radius
Color color = new Color((int)(Math.random() * 256),
(int)(Math.random() * 256), (int)(Math.random() * 256));
}
/** Main method */
public static void main(String[] args)
{
JFrame frame = new JFrame();
JApplet applet = new MultipleBallApp();
frame.add(applet);
frame.setTitle("MultipleBallApp");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.setLocationRelativeTo(null); // Center the frame
frame.setVisible(true);
}
}
Make sure you do not get 0 as a radius when trying to randomize the ball's radius.
int radius = (int)(4*Math.random()+1);

How to animate Rectangle in JPanel?

I want to learn some tricks about JAVA for my project.
I want to animate my Rectangle leftoright and righttoleft but I can't apply the same functions for ball animation.
In addition,how can I start my ball in different x-direction with a border of y-coordinate ?
Thanks a lot for your advices and helping.
My codes:
import javax.swing.Timer;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MultipleBall extends JApplet {
public MultipleBall() {
add(new BallControl());
}
class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton Suspend = new JButton("Suspend");
private JButton Resume = new JButton("Resume");
private JButton Add = new JButton("+1");
private JButton Subtract = new JButton("-1");
private JScrollBar Delay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(Suspend);
panel.add(Resume);
panel.add(Add);
panel.add(Subtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
Delay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(Delay.getMaximum());
setLayout(new BorderLayout());
add(Delay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
Suspend.addActionListener(new Listener());
Resume.addActionListener(new Listener());
Add.addActionListener(new Listener());
Subtract.addActionListener(new Listener());
Delay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(Delay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Suspend)
ballPanel.suspend();
else if (e.getSource() == Resume)
ballPanel.resume();
else if (e.getSource() == Add)
ballPanel.add();
else if (e.getSource() == Subtract)
ballPanel.subtract();
}
}
}
class BallPanel extends JPanel {
private int delay = 30;
private ArrayList<Ball> list = new ArrayList<Ball>();
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
/** Handle the action event */
public void actionPerformed(ActionEvent e) {
repaint();
}
});
public BallPanel() {
timer.start();
}
public void add() {
list.add(new Ball());
}
public void subtract() {
if (list.size() > 0)
list.remove(list.size() - 1); // Remove the last ball
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(185, 279, 50, 15);
g.setColor(Color.RED);
g.fillRect(185, 279, 50, 15);
for (int i = 0; i < list.size(); i++) {
Ball ball = (Ball) list.get(i); // Get a ball
g.setColor(ball.color); // Set ball color
// Check boundaries
if (ball.x < 0 || ball.x > getWidth())
ball.dx = -ball.dx;
if (ball.y < 0 || ball.y > getHeight())
ball.dy = -ball.dy;
// Adjust ball position
ball.x += ball.dx;
// ball.y += ball.dy;
g.fillOval(ball.x - ball.radius, ball.y - ball.radius,
ball.radius * 2, ball.radius * 2);
}
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
class Ball {
int x = 20;
int y = 20; // Current ball position
int dx = 2; // Increment on ball's x-coordinate
int dy = 2; // Increment on ball's y-coordinate
int radius = 15; // Ball radius
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
}
/** Main method */
public static void main(String[] args) {
JFrame frame = new JFrame();
JApplet applet = new MultipleBallApp();
frame.add(applet);
frame.setTitle("MultipleBallApp");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null); // Center the frame
frame.setVisible(true);
}
}
can't apply the same functions for ball animation
This is probably your first mistake. In fact, this is exactly what you should be trying to do. The idea is, you should be trying to devise a means by what is painted/animated is abstract so it doesn't matter what the shape is you want to paint, you can apply it to the sam basic animation process...
For example, you could start with some kind interface which describes the basic properties of an animated entity...
public interface AnimatedShape {
public void update(Rectangle bounds);
public void paint(JComponent parent, Graphics2D g2d);
}
This says that an animated entity can be updated (moved) and painted. By convention (and because I'm lazy), I like to create an abstract implementation which implements the most common aspects...
public abstract class AbstractAnimatedShape implements AnimatedShape {
private Rectangle bounds;
private int dx, dy;
public AbstractAnimatedShape() {
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public Rectangle getBounds() {
return bounds;
}
public int getDx() {
return dx;
}
public int getDy() {
return dy;
}
public void setDx(int dx) {
this.dx = dx;
}
public void setDy(int dy) {
this.dy = dy;
}
#Override
public void update(Rectangle parentBounds) {
Rectangle bounds = getBounds();
int dx = getDx();
int dy = getDy();
bounds.x += dx;
bounds.y += dy;
if (bounds.x < parentBounds.x) {
bounds.x = parentBounds.x;
setDx(dx *= -1);
} else if (bounds.x + bounds.width > parentBounds.x + parentBounds.width) {
bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
setDx(dx *= -1);
}
if (bounds.y < parentBounds.y) {
bounds.y = parentBounds.y;
setDy(dy *= -1);
} else if (bounds.y + bounds.height > parentBounds.y + parentBounds.height) {
bounds.y = parentBounds.y + (parentBounds.height - bounds.height);
setDy(dy *= -1);
}
}
}
And then start creating implementations...
public class AnimatedBall extends AbstractAnimatedShape {
private Color color;
public AnimatedBall(int x, int y, int radius, Color color) {
setBounds(new Rectangle(x, y, radius * 2, radius * 2));
this.color = color;
setDx(Math.random() > 0.5 ? 2 : -2);
setDy(Math.random() > 0.5 ? 2 : -2);
}
public Color getColor() {
return color;
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(getColor());
g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
In this manner, you can customise the way that the entity is animated and painted, but the basic logic for each instance of the entity is the same...
But what's all the point of this...
Basically, what it allows us to do is produce a "virtual" concept of all the animated objects and simplify there management, for example...
Instead of using a "tightly" coupled List, we can use a loosely couple List instead...
private ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
Then when we want the entities to be updated, we simply need to iterate the List and ask the entities to update...
protected Timer timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (AnimatedShape ball : list) {
ball.update(getBounds());
}
repaint();
}
});
And when they need to be painted...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (AnimatedShape ball : list) {
ball.paint(this, g2d);
}
}
Because the BallPane doesn't care what actually type of entity it is, but only that it's a type of AnimatedShape...makes life easier...
Now, my implementation of the AnimatedBall already randomise the direction of each instance of the ball, but you can also randomise the starting position when the ball is added using something like...
public void add() {
int radius = 15;
// Randomised position
int x = (int)(Math.random() * (getWidth() - (radius * 2))) + radius;
int y = (int)(Math.random() * (getHeight() - (radius * 2))) + radius;
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
AnimatedBall ball = new AnimatedBall(x, y, radius, color);
list.add(ball);
}
But how does this help you with adding a rectangle?
You now need to create an AnimatedRectangle that extends from AbstractAnimatedShape and implemented the required methods and add instances of this to the List of AnimatedShapes in the BallPane.
If you don't want the rectangle to be managed within the same list, you could create another list and manage it sepearatly (it create two additional methods, update(List<AnimatedShape>) and paint(List<AnimatedShape>, Graphics2D) passing in each individual list so as to reduce the duplicate code, but that's me)...
You can restrict the rectangles vertical movement by overriding the setDy method and ignoring any changes, for example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MultipleBall {
public MultipleBall() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("MultipleBallApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BallControl());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton Suspend = new JButton("Suspend");
private JButton Resume = new JButton("Resume");
private JButton Add = new JButton("+1");
private JButton Subtract = new JButton("-1");
private JScrollBar Delay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(Suspend);
panel.add(Resume);
panel.add(Add);
panel.add(Subtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
Delay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(Delay.getMaximum());
setLayout(new BorderLayout());
add(Delay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
Suspend.addActionListener(new Listener());
Resume.addActionListener(new Listener());
Add.addActionListener(new Listener());
Subtract.addActionListener(new Listener());
Delay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(Delay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Suspend) {
ballPanel.suspend();
} else if (e.getSource() == Resume) {
ballPanel.resume();
} else if (e.getSource() == Add) {
ballPanel.add();
} else if (e.getSource() == Subtract) {
ballPanel.subtract();
}
}
}
}
class BallPanel extends JPanel {
private int delay = 30;
private ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
private AnimatedRectange rectangle;
public BallPanel() {
this.rectangle = new AnimatedRectange(-25, 200, 50, 25, Color.RED);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
/**
* Handle the action event
*/
#Override
public void actionPerformed(ActionEvent e) {
for (AnimatedShape ball : list) {
ball.update(getBounds());
}
rectangle.update(getBounds());
repaint();
}
});
public void add() {
int radius = 15;
// Randomised position
int x = (int) (Math.random() * (getWidth() - (radius * 2))) + radius;
int y = (int) (Math.random() * (getHeight() - (radius * 2))) + radius;
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
AnimatedBall ball = new AnimatedBall(x, y, radius, color);
list.add(ball);
}
public void subtract() {
if (list.size() > 0) {
list.remove(list.size() - 1); // Remove the last ball
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (AnimatedShape ball : list) {
ball.paint(this, g2d);
}
rectangle.paint(this, g2d);
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
public interface AnimatedShape {
public void update(Rectangle bounds);
public void paint(JComponent parent, Graphics2D g2d);
}
public abstract class AbstractAnimatedShape implements AnimatedShape {
private Rectangle bounds;
private int dx, dy;
public AbstractAnimatedShape() {
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public Rectangle getBounds() {
return bounds;
}
public int getDx() {
return dx;
}
public int getDy() {
return dy;
}
public void setDx(int dx) {
this.dx = dx;
}
public void setDy(int dy) {
this.dy = dy;
}
#Override
public void update(Rectangle parentBounds) {
Rectangle bounds = getBounds();
int dx = getDx();
int dy = getDy();
bounds.x += dx;
bounds.y += dy;
if (bounds.x < parentBounds.x) {
bounds.x = parentBounds.x;
setDx(dx *= -1);
} else if (bounds.x + bounds.width > parentBounds.x + parentBounds.width) {
bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
setDx(dx *= -1);
}
if (bounds.y < parentBounds.y) {
bounds.y = parentBounds.y;
setDy(dy *= -1);
} else if (bounds.y + bounds.height > parentBounds.y + parentBounds.height) {
bounds.y = parentBounds.y + (parentBounds.height - bounds.height);
setDy(dy *= -1);
}
}
}
public class AnimatedBall extends AbstractAnimatedShape {
private Color color;
public AnimatedBall(int x, int y, int radius, Color color) {
setBounds(new Rectangle(x, y, radius * 2, radius * 2));
this.color = color;
setDx(Math.random() > 0.5 ? 2 : -2);
setDy(Math.random() > 0.5 ? 2 : -2);
}
public Color getColor() {
return color;
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(getColor());
g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
public class AnimatedRectange extends AbstractAnimatedShape {
private Color color;
public AnimatedRectange(int x, int y, int width, int height, Color color) {
setBounds(new Rectangle(x, y, width, height));
this.color = color;
setDx(2);
}
// Don't want to adjust the vertical speed
#Override
public void setDy(int dy) {
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(color);
g2d.fill(bounds);
}
}
/**
* Main method
*/
public static void main(String[] args) {
new MultipleBall();
}
}
Amendment
You really should avoid adding JApplet to a JFrame, an applet has a prescribed life cycle and management process which you are ignoring. Better to focus on just using the BallControl panel as the core UI element and then add this to what ever top level container you want
You may find a JSlider more piratical then a JScrollBar, not to mention, it will look better on different platforms, most uses understand what a slider is used for...
Add a static variable like ballCount and add 1 to it every time you make a ball. In the Ball class, change the definition of y to something likey = 20 + ballcount*(radius*2+distanceInBalls)
public class RandomTests extends JApplet {
public RandomTests() {
add(new BallControl());
}
static int ballCount = 0;
class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton Suspend = new JButton("Suspend");
private JButton Resume = new JButton("Resume");
private JButton Add = new JButton("+1");
private JButton Subtract = new JButton("-1");
private JScrollBar Delay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(Suspend);
panel.add(Resume);
panel.add(Add);
panel.add(Subtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
Delay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(Delay.getMaximum());
setLayout(new BorderLayout());
add(Delay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
Suspend.addActionListener(new Listener());
Resume.addActionListener(new Listener());
Add.addActionListener(new Listener());
Subtract.addActionListener(new Listener());
Delay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(Delay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Suspend) ballPanel.suspend();
else if (e.getSource() == Resume) ballPanel.resume();
else if (e.getSource() == Add) ballPanel.add();
else if (e.getSource() == Subtract) ballPanel.subtract();
}
}
}
class BallPanel extends JPanel {
private int delay = 30;
private ArrayList<Ball> list = new ArrayList<Ball>();
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
/** Handle the action event */
public void actionPerformed(ActionEvent e) {
repaint();
}
});
public BallPanel() {
timer.start();
}
public void add() {
list.add(new Ball());
ballCount++;
}
public void subtract() {
if (list.size() > 0) list.remove(list.size() - 1); // Remove the last ball
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(185, 279, 50, 15);
g.setColor(Color.RED);
g.fillRect(185, 279, 50, 15);
for (int i = 0; i < list.size(); i++) {
Ball ball = (Ball) list.get(i); // Get a ball
g.setColor(ball.color); // Set ball color
// Check boundaries
if (ball.x < 0 || ball.x > getWidth()) ball.dx = -ball.dx;
if (ball.y < 0 || ball.y > getHeight()) ball.dy = -ball.dy;
// Adjust ball position
ball.x += ball.dx;
// ball.y += ball.dy;
g.fillOval(ball.x - ball.radius, ball.y - ball.radius, ball.radius * 2, ball.radius * 2);
}
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
class Ball {
int radius = 15; // Ball radius
int x = radius;
int y = 20 + (radius * ballCount * 2 + 15); // Current ball position
int dx = 2; // Increment on ball's x-coordinate
int dy = 2; // Increment on ball's y-coordinate
Color color = new Color((int) (Math.random() * 256), (int) (Math.random() * 256), (int) (Math.random() * 256));
}
public static void main(String[] args) {
JFrame frame = new JFrame();
JApplet applet = new RandomTests();
frame.add(applet);
frame.setTitle("MultipleBallApp");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null); // Center the frame
frame.setVisible(true);
}
}

Why can't i use keyPressed anymore once the if-statement is true in the run()-methode?

I'm trying to make a kind of brickbreaker game but once I press the start button ("starten" = true). I can't use the keyPressed()-utility anymore but before i pressed the start button I could use the keyPressed()-utility. Could somebody please tell me why I suddenly can't use the keyPressed()-utility anymore and give me a possible solution too?
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class VGKernel extends JPanel implements KeyListener {
public Rectangle screen, ball, block; // The screen area and ball location/size.
public Rectangle bounds; // The boundaries of the drawing area.
public JFrame frame; // A JFrame to put the graphics into.
public VGTimerTask vgTask; // The TimerTask that runs the game.
public boolean down, right, starten = false; // Direction of ball's travel.
public JButton start;
public VGKernel(){
super();
screen = new Rectangle(0, 0, 600, 400);
ball = new Rectangle(0, 0, 20, 20);
block = new Rectangle(260, 350, 40, 10);
bounds = new Rectangle(0, 0, 600, 400); // Give some starter values.
frame = new JFrame("VGKernel");
vgTask = new VGTimerTask();
addKeyListener(this);
setFocusable(true);
start = new JButton("Start");
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
starten = true;
}
});
add(start);
}
class VGTimerTask extends TimerTask{
public void run(){
repaint();
if(starten){
moveBall();
frame.repaint();
}
}
}
// Now the instance methods:
public void paintComponent(Graphics g){
// Get the drawing area bounds for game logic.
bounds = g.getClipBounds();
// Clear the drawing area, then draw the ball.
g.clearRect(screen.x, screen.y, screen.width, screen.height);
g.fillRect(ball.x, ball.y, ball.width, ball.height);
g.fillRect(block.x, block.y, block.width, block.height);
}
public void moveBall(){
// Ball should really be its own class with this as a method.
if (right) ball.x+=1; // If right is true, move ball right,
else ball.x-=1; // otherwise move left.
if (down) ball.y+=1; // Same for up/down.
else ball.y-=1;
if (ball.x > (bounds.width - ball.width)) // Detect edges and bounce.
{ right = false; ball.x = bounds.width - ball.width; }
if (ball.y > (bounds.height - ball.height))
{ down = false; ball.y = bounds.height - ball.height;}
if (ball.x == 0) { right = true; ball.x = 0; }
if (ball.y == 0) { down = true; ball.y = 0; }
}
public void keyPressed(KeyEvent evt) {
if(evt.getKeyCode() == KeyEvent.VK_G && block.x > 0) {
block.x -= 20;
}
if(evt.getKeyCode() == KeyEvent.VK_H && block.x < 540) {
block.x += 20;
}
}
public void keyTyped(KeyEvent evt){ }
public void keyReleased(KeyEvent evt){ }
public void startActionPerformed(java.awt.event.ActionEvent evt) {
starten = true;
}
public static void main(String arg[]){
java.util.Timer vgTimer = new java.util.Timer(); // Create a Timer.
VGKernel panel = new VGKernel(); // Create and instance of our kernel.
// Set the intial ball movement direction.
panel.down = true;
panel.right = true;
// Set up our JFRame
panel.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.frame.setSize(panel.screen.width, panel.screen.height);
panel.frame.setContentPane(panel);
panel.frame.setVisible(true);
// Set up a timer to do the vgTask regularly.
vgTimer.schedule(panel.vgTask, 0, 10);
}
}
You need to make sure whatever component you're listening for KeyEvents on has the focus.
Once you click the button, that button has focus instead of your JPanel. More info here: http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html
You can use the requestFocusInWindow() method on your JPanel, or you can call setFocusable(false) on your JButton.
Or you could use key bindings instead: http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
Add VGKernel.this.grabFocus(); to the ActionListener to return focus to the VGKernel panel after clicking the button.
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
starten = true;
VGKernel.this.grabFocus();
}
});

Moving objects and timers

I have a screen with say 500 width and 400 height, and I have a vector with a bunch of shapes. let say the vector has 2 different shapes for example. I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down (similar to game fruit ninja, where the fruits are my shapes).
In my main (view) I have a vector of shapes of which i instantiate the timers, add to array and place them in the buttom of the screen using the translate function. My timer takes in an action listener which basically changes the translate of the shape to move up till ascent and then down, but my problem is that all the shapes start at the same time regardless.
Something like this:
Shape f = new Shape(new Area(new Ellipse2D.Double(0, 50, 50, 50)));
f.translate(0, 400);
f.timer = new Timer( 10 , taskPerformer);
f.timer.start();
vector.add(f);
Shape f2 = new Shape(new Area(new Rectangle2D.Double(0, 50, 50, 50)));
f2.translate(200, 400);
f2.timer = new Timer( 10 , taskPerformer);
f2.timer.setInitialDelay(5000);
f2.timer.start();
vector.add(f2);
and my action listener:
Random generator = new Random();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
for (Shape s : model.getShapes()) {
// Scale object using translate
// once reached ascent drop down
// translate to diffrenet part of the bottom of the screen
// delay its timer
}
update();
//basically repaints
}
};
I'm running into problems that all shapes follow the same timer, and begin to pop up at the same time (no delay) ...
Any suggestions on how to avoid this or if there is a different approach i should try
"I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down"
See the runnable example below. What I do is pass a radomDelayedStart to the Shape. Every tick of the timer, the randomDelayedStart decreases til it reaches 0, that's when the flag to be drawn in raised. Most of the logic is in the Shape class methods, which are called in the Timers Actionlistener. Everything is done in one Timer. For the ascent, I just used a hard coded 50, but you can also pass a random ascent to the Shape. Let me know if you have any questions. I tried to made the code as clear as possible.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class RandomShape extends JPanel {
private static final int D_HEIGHT = 500;
private static final int D_WIDTH = 400;
private static final int INCREMENT = 8;
private List<Shape> shapes;
private List<Color> colors;
private Timer timer = null;
public RandomShape() {
colors = createColorList();
shapes = createShapeList();
timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (Shape shape : shapes) {
shape.move();
shape.decreaseDelay();
repaint();
}
}
});
JButton start = new JButton("Start");
start.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
JButton reset = new JButton("Reset");
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
shapes = createShapeList();
timer.restart();
}
});
JPanel panel = new JPanel();
panel.add(start);
panel.add(reset);
setLayout(new BorderLayout());
add(panel, BorderLayout.PAGE_START);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape shape : shapes) {
shape.drawShape(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_WIDTH, D_HEIGHT);
}
private List<Color> createColorList() {
List<Color> list = new ArrayList<>();
list.add(Color.BLUE);
list.add(Color.GREEN);
list.add(Color.ORANGE);
list.add(Color.MAGENTA);
list.add(Color.CYAN);
list.add(Color.PINK);
return list;
}
private List<Shape> createShapeList() {
List<Shape> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
int randXLoc = random.nextInt(D_WIDTH);
int randomDelayedStart = random.nextInt(100);
int colorIndex = random.nextInt(colors.size());
Color color = colors.get(colorIndex);
list.add(new Shape(randXLoc, randomDelayedStart, color));
}
return list;
}
class Shape {
int randXLoc;
int y = D_HEIGHT;
int randomDelayedStart;
boolean draw = false;
boolean down = false;
Color color;
public Shape(int randXLoc, int randomDelayedStart, Color color) {
this.randXLoc = randXLoc;
this.randomDelayedStart = randomDelayedStart;
this.color = color;
}
public void drawShape(Graphics g) {
if (draw) {
g.setColor(color);
g.fillOval(randXLoc, y, 30, 30);
}
}
public void move() {
if (draw) {
if (y <= 50) {
down = true;
}
if (down) {
y += INCREMENT;
} else {
y -= INCREMENT;
}
}
}
public void decreaseDelay() {
if (randomDelayedStart <= 0) {
draw = true;
} else {
randomDelayedStart -= 1;
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new RandomShape());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Categories

Resources