I am trying to create a rectangle in Java but only with awt package classes.
I can only click two points and the program must calculate the width and height and draw a rectangle between those exact two points.
The following doesn't work for me:
package ie.iact.shapes;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Rect extends Shapes {``
private Point secondPoint;
public Rect(Point f, Point s) {
setFirstPoint(f);
setSecondPoint(s);
}
#Override
public void draw(Graphics g) {
int x1 = firstPoint.x;
int y1 = firstPoint.y;
int x2 = secondPoint.x;
int y2 = secondPoint.y;
int a;
int b;
if (x1 < x2) {
a = x1;
} else {
a = x2;
}
if (y1 < y2) {
b = y1;
} else {
b = y2;
}
int width = secondPoint.x - a;
int hight = secondPoint.y - b;
g.drawRect(getFirstPoint().x, getFirstPoint().y, secondPoint.x, secondPoint.y);
}
public Point getSecondPoint() {
return secondPoint;
}
public void setSecondPoint(Point secondPoint) {
this.secondPoint = secondPoint;
}
}
Rectangle class can already handle all of your calculations:
Rectangle rect= new Rectangle(point1);
rect.add(point2);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
Alternatively you can use setFrameFromDiagonal:
Rectangle rect= new Rectangle();
rect.setFrameFromDiagonal(point1, point2);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
Related
I am trying to make a simple screen-saver, and I think I have everything else implemented properly. I just don't know how to make the shapes move. Looking at the code a bit more, I think it has something to do with the way I might have implemented the shapes themselves (the if (line), etc.)? I have looked at other answers regarding this question, but I couldn't quite find the answer I was looking for with the way my code is implemented. Any advice is super helpful, thank you!
Also, just for a side note, is the -40 necessary for the "if" conditions? I thought I heard somewhere that it is useful to leave a little space in-between the frame, but I can't remember why.
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
public class MyScreenSaver extends JComponent
{
ArrayList <Shapes> randomShapes = new ArrayList <>();
Shapes randomShape;
public MyScreenSaver ()
{
class TimerListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event)
{
// Create random generation of colors and shapes...
Shape shape = null;
int frameWidth = 800;
int frameHeight = 500;
for (int i = 1; i <= 10; i ++)
{
Random rng = new Random();
boolean line = rng.nextBoolean();
boolean rectangle = rng.nextBoolean();
int red = ((int) (Math.random() * 255));
int green = ((int) (Math.random() * 255));
int blue = ((int) (Math.random() * 255));
Color color = new Color (red, green, blue);
int width = (10 + (int) (40 * Math.random()));
int height = (10 + (int) (40 * Math.random()));
int x = (int) (Math.random() * (getWidth() - width));
int y = (int) (Math.random() * (getHeight() - height));
int velX = 2;
int velY = 2;
int newX = velX + x;
int newY = velY + y;
if (line)
{
shape = new Line2D.Double(x, y, x + width, y + height);
}
else if (rectangle)
{
shape = new Rectangle2D.Double(x, y, width, height);
}
else
{
shape = new Ellipse2D.Double(x, y, width, height);
}
// Here, we want the shapes to stop appearing after reaching a certain size...
if (randomShapes.size() >= 20)
{
break;
}
Shapes randomShape = new Shapes (color, shape);
// Add the shapes to the randomShapes ArrayList...
randomShapes.add (randomShape);
// Here, we are moving the shapes...
for (Shapes shapeMove : randomShapes)
{
if (x < 0 || x > frameWidth - 40)
{
velX = velX * -1;
}
else
{
x = newX;
}
if (y < 0 || y > frameHeight - 40)
{
velY = velY * -1;
}
else
{
y = newY;
}
}
repaint();
}
}
}
ActionListener listener = new TimerListener();
final int DELAY = 100;
Timer t = new Timer(DELAY, listener);
t.start();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shapes shape : randomShapes)
{
System.out.println (randomShapes.size());
shape.paint(g2d);
}
g2d.dispose();
}
public static void main (String [] args)
{
// Set up the main frame...
final int FRAME_WIDTH = 800;
final int FRAME_HEIGHT = 500;
JFrame screenSaverFrame = new JFrame ();
screenSaverFrame.setTitle("Homework 6");
screenSaverFrame.setSize (FRAME_WIDTH, FRAME_HEIGHT);
screenSaverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final MyScreenSaver component = new MyScreenSaver ();
screenSaverFrame.add (component);
screenSaverFrame.setVisible (true);
}
}
Here is the loop specifically...
for (Shapes shapeMove : randomShapes)
{
if (x < 0 || x > frameWidth - 40)
{
velX = velX * -1;
}
else
{
x = newX;
}
if (y < 0 || y > frameHeight - 40)
{
velY = velY * -1;
}
else
{
y = newY;
}
}
I was thinking about placing the contents of the loop inside a void method, but I really don't think that is necessary.
Also, here is my Shape class as well.
import java.awt.*;
public class Shapes
{
private final Color color;
private final Shape shape;
public Shapes (Color color, Shape shape)
{
this.color = color;
this.shape = shape;
}
public Color getColor ()
{
return color;
}
public Shape getShape ()
{
return shape;
}
public void paint(Graphics2D g2d)
{
g2d.setColor(color);
g2d.draw(shape);
g2d.fill(shape);
}
}
The following mre is based on your code. Note the comments documenting the changes made:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
public class MyScreenSaver extends JComponent
{
private final ArrayList <ColoredShape> randomShapes = new ArrayList <>();
//define constants
private static final int FRAME_WIDTH = 800, FRAME_HEIGHT = 500, DELAY = 100, MAX_SHAPE_HEIGHT = 40,
MAX_SHAPE_WIDTH = 40, MIN_SHAPE_HEIGHT = 10, MIN_SHAPE_WIDTH = 40, MAX_SHAPE_COUNT = 20,
LINE_WIDTH = 5, X_STEP = 5, Y_STEP = 5;
//define shape types
enum ShapeType {LINE, RECTANGLE, ELIPSE};
public MyScreenSaver ()
{
ActionListener listener = new TimerListener();
Timer t = new Timer(DELAY, listener);
t.start();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(LINE_WIDTH));
for (ColoredShape shape : randomShapes) //draw stored shapes
{
shape.paint(g2d);
}
g2d.dispose();
}
//invoked repeatedly by Timer. Each time it adds a shape to the collection
//moves all shapes and repaints
class TimerListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event)
{
// Create random generation of colors and shapes and location
//up to MAX_SHAPE_COUNT
if (randomShapes.size() < MAX_SHAPE_COUNT)
{
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color color = new Color (red, green, blue);
int width = MIN_SHAPE_WIDTH + (int) (MAX_SHAPE_WIDTH * Math.random());
int height = MIN_SHAPE_HEIGHT + (int) (MAX_SHAPE_HEIGHT* Math.random());
int x = (int) (Math.random() * (getWidth() - width));
int y = (int) (Math.random() * (getHeight() - height));
//select a random shape type
int typeIndex = (int) (Math.random()* ShapeType.values().length);
ShapeType type = ShapeType.values()[typeIndex];
// Add the shapes to the randomShapes ArrayList...
randomShapes.add (new ColoredShape (type,color,x, y,width,height));
}
//move the shapes...
for (ColoredShape shape : randomShapes)
{
int x = shape.getX();//get current x position
if (x <= 0 || x > getWidth() - shape.getWidth())
{
shape.setXDirection(-1*shape.getXDirection());//change direction
}
shape.setX(shape.getX() + shape.getXDirection()*X_STEP);//increment
int y = shape.getY();
if (y <= 0 || y > getHeight()- shape.getHeight())
{
shape.setYDirection(-1*shape.getYDirection());
}
shape.setY(shape.getY() + shape.getYDirection()*Y_STEP);
}
repaint();
}
}
public class ColoredShape
{
private int x, y;
private final int width, height;
private int xDirection, yDirection;
private final Color color;
private final ShapeType type;
public ColoredShape(ShapeType type, Color color, int x, int y, int width, int height)
{
this.type = type;
this.color = color;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
xDirection = yDirection = 1; //1 means increase value, -1 decrease value
}
public Color getColor ()
{
return color;
}
private Shape constructShape ()
{
//construct new shape using updated bounds
if(type == ShapeType.LINE)
return new Line2D.Double(x, y, x + width, y + height);
else if (type == ShapeType.RECTANGLE)
return new Rectangle2D.Double(x, y, width, height);
else
return new Ellipse2D.Double(x, y, width, height);
}
public void paint(Graphics2D g2d)
{
g2d.setColor(color);
Shape shape = constructShape();
g2d.draw(shape);
g2d.fill(shape);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getXDirection() {
return xDirection;
}
public void setXDirection(int xDirextion) {
xDirection = xDirextion;
}
public int getYDirection() {
return yDirection;
}
public void setYDirection(int yDirection) {
this.yDirection = yDirection;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
public static void main (String [] args)
{
// Set up the main frame...
JFrame screenSaverFrame = new JFrame ();
screenSaverFrame.setTitle("Homework 6");
screenSaverFrame.setSize (FRAME_WIDTH, FRAME_HEIGHT);
screenSaverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screenSaverFrame.add (new MyScreenSaver ());
screenSaverFrame.setVisible (true);
}
}
I have two ImageViews in a javafx program. They both have been rotated and translated a few times. I know their initial angle and position (layoutX,layoutY) and I also have the list of transformation and rotation they went through. How can I tell if they are overlapping one another right now or not?
The images are given below:
Image of an Apple:
Image of an Arrow:
It would also be really helpful if I could determine whether the tip of the arrow is inside the apple image. However, its okay if I can just tell if the images are colliding or not.
The apple Class:
class Apple {
public double height, width, x1, x2, y1, y2;
public ImageView image;
Apple(double x1, double y1, double height, double width) {
this.x1 = x1;
this.y1 = y1;
this.height = height;
this.width = width;
}
Apple(double x1, double y1) {
height = 20;
width = 20;
this.x1 = x1;
this.y1 = y1;
}
public boolean isCollision(double ax, double ay) {
x2 = x1 + width;
y2 = y1 + height;
if (ax > x1 && ax < x2 && ay > y1 && ay < y2) {
return true;
} else {
return false;
}
}
}
The code to create apples:
Apple generateApple() {
double x1, y1, rx, ry;
x1 = 300;
y1 = 250;
rx = 150;
ry = 150;
double xa, ya;
xa = randomno(x1, x1 + rx);
ya = randomno(y1, y1 + ry);
Apple apl = new Apple(xa, ya);
createAppleImage(apl);
return apl;
}
void createAppleImage(Apple apple) {
ImageView appleImage = null;
FileInputStream inputstream5 = null;
try {
inputstream5 = new FileInputStream("C:\\Users\\MAHDI\\Documents\\NetBeansProjects\\ThreadTesting\\apple.jpg");
Image img4 = new Image(inputstream5);
appleImage = new ImageView(img4);
appleImage.setFitHeight(apple.height);
appleImage.setFitWidth(apple.width);
appleImage.setLayoutX(apple.x1);
appleImage.setLayoutY(apple.y1);
System.out.println(" " + apple.x1 + " " + apple.y1);
gameLayout.getChildren().add(appleImage);
} catch (FileNotFoundException ex) {
Logger.getLogger(AppleShooter.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
inputstream5.close();
} catch (IOException ex) {
Logger.getLogger(AppleShooter.class.getName()).log(Level.SEVERE, null, ex);
}
}
apple.image = appleImage;
}
The code to create arrow:
FileInputStream inputstream3 = new FileInputStream("C:\\Users\\MAHDI\\Documents\\NetBeansProjects\\ThreadTesting\\arrowpic.png");
Image img2 = new Image(inputstream3);
arrow = new ImageView(img2);
arrow.setFitHeight(arrowheight);
arrow.setFitWidth(arrowwidth);
arrow.setLayoutX(40);
arrow.setLayoutY(420);
arrow.setRotate(-45);
I suggest you start by having a look at Shape.intersects
I would also like to add that I know absolutely nothing about JavaFX and basically hobbled this together from reading the JavaDocs and some other examples
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
Rectangle box1 = new Rectangle(10, 10, 100, 100);
box1.setFill(Color.RED);
Rectangle box2 = new Rectangle(120, 10, 100, 100);
box2.setFill(Color.BLUE);
Pane root = new Pane();
root.getChildren().add(box1);
root.getChildren().add(box2);
Scene scene = new Scene(root, 230, 120);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
Timeline timeline = new Timeline(60, new KeyFrame(Duration.millis(500), new EventHandler<ActionEvent>() {
private double delta1 = 0.5;
private double delta2 = -5;
private double angle1 = 0;
private double angle2 = 0;
private Shape oldCollision;
#Override
public void handle(ActionEvent event) {
angle1 += delta1;
angle2 += delta2;
box1.setRotate(angle1);
box2.setRotate(angle2);
if (oldCollision != null) {
root.getChildren().remove(oldCollision);
oldCollision = null;
}
Shape collision = Shape.intersect(box1, box2);
if (collision != null) {
collision.setFill(Color.AQUA);
root.getChildren().add(collision);
}
oldCollision = collision;
// if (box1.intersects(box1.parentToLocal(box2.getBoundsInParent()))) {
// box1.setFill(Color.AQUA);
// box2.setFill(Color.AQUA);
// } else {
// box1.setFill(Color.RED);
// box2.setFill(Color.BLUE);
// }
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I just want to point out that adding and removing the collision Shape is for demonstration purposes only!
Now before you point out to me how Rectangle is not ImageView, make sure you take the time to have read of the JavaDocs for ImageView and Rectangle for the reasons why I choose it for this example
I've created an application that draws a random number of ovals (with random sizes and colors) with JPanel and JFrame (Java 8 installed in Ubuntu 16.04). Everything seems to be right... but no oval is draw when I execute the code. I receave just a blank screen (JFrame appears, but only blank).
It have 3 classes: MyOval, DrawPanel and DrawTest.
MyOval Class
package drawingovals;
import java.awt.Color;
import java.awt.Graphics;
public class MyOval {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
private boolean isFilled;
public MyOval(int x1, int y1, int x2, int y2, Color color, boolean isFilled) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.x2 = x2;
myColor = color;
this.isFilled = isFilled;
}
public int getUpperLeftX(){
return x1;
}
public int getUpperLeftY(){
return y1;
}
public int getWidth(){
return x2 - x1;
}
public int getHeight() {
return y2 - y1;
}
public String getColor() {
return myColor.toString();
}
public boolean getFilling(){
return isFilled;
}
public void setUpperLeftX(int value) {
x1 = value;
}
public void setUpperLeftY(int value) {
y1 = value;
}
public void setDownRightX(int value) {
x2 = value;
}
public void setDownRightY(int value) {
y2 = value;
}
public void drawNoFill(Graphics g) {
g.setColor(myColor);
g.drawOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
public void drawFill(Graphics g) {
g.setColor(myColor);
g.fillOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
}
DrawPanel Class
package drawingovals;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
private Random randomNumbers = new Random();
private MyOval[] ovals;
public DrawPanel() {
setBackground(Color.WHITE);
ovals = new MyOval[5 + randomNumbers.nextInt(5)];
for (int count = 0; count < ovals.length; count++) {
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color(randomNumbers.nextInt(256),
randomNumbers.nextInt(256), randomNumbers.nextInt(256));
boolean fill = randomNumbers.nextBoolean();
ovals[count] = new MyOval(x1, y1, x2, y2, color, fill);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int count = 0; count < ovals.length - 1; count++) {
ovals[count].drawFill(g);
}
}
}
DrawTest Class
package drawingovals;
import javax.swing.JFrame;
public class DrawTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(400, 400);
application.setVisible(true);
}
}
You need to take care that your oval heights and widths contain only positive values -- your code does not do this. Consider using Math.max, Math.min, or Math.abs when obtaining your oval properties to help you achieve this.
Also, this is wrong as you're duplicating setting x2 bug ignoring y2:
this.x1 = x1;
this.y1 = y1;
this.x2 = x2; // *** these are the same
this.x2 = x2; // *** these are the same
Something like this would work:
public MyOval(int x1, int y1, int x2, int y2, Color color, boolean isFilled) {
this.x1 = Math.min(x1, x2);
this.y1 = Math.min(y1, y2);
this.x2 = Math.max(x1, x2);
this.y2 = Math.max(y1, y2);;
myColor = color;
this.isFilled = isFilled;
}
In the future, the key to solving these types of issues is to use a debugger to check the fields of your program, here the oval properties, as the program runs, and then see if they don't make sense, and then why.
I am wring the bouncing ball program in java. And I Now have one bouncing ball, I would like to have at least five bouncing balls. I have tried a few ways to do it, however, I only end up with one ball or error.
Do you have any suggestions on how to proceed? This in the piece of code used for the one ball, is it possible to rewrite this piece of code to get multiple balls in a neat way?
import javafx.scene.shape.Rectangle;
public class World {
private final double width, height;
private Ball[] balls;
private final Rectangle pad;
public World(double width, double height) {
this.width = width;
this.height = height;
balls = new Ball[1];
balls[0] = new Ball(10, 10);
balls[0].setVelocity(75.0, 100.0);
pad = new Rectangle(width / 2, 0.9 * height,
width / 8, height / 32);
}
public void move(long elapsedTimeNs) {
balls[0].move(elapsedTimeNs);
constrainBall(balls[0]);
checkForCollisionWithPad(balls[0]);
}
public Ball[] getBalls() {
return (Ball[]) balls.clone();
}
public Rectangle getPad() {
return pad;
}
public void setPadX(double x) {
if (x > width) {
x = width;
}
if (x < 0) {
x = 0;
}
pad.setX(x);
}
private void constrainBall(Ball ball) {
double x = ball.getX(), y = ball.getY();
double dx = ball.getDx(), dy = ball.getDy();
double radius = ball.getRadius();
if (x < radius) {
dx = Math.abs(dx);
} else if (x > width - radius) {
dx = -Math.abs(dx);
}
if (y < radius) {
dy = Math.abs(dy);
} else if (y > height - radius) {
dy = -Math.abs(dy);
}
ball.setVelocity(dx, dy);
}
private void checkForCollisionWithPad(Ball ball) {
if (ball.intersectsArea(
pad.getX(), pad.getY(), pad.getWidth(), pad.getHeight())) {
double dx = ball.getDx();
// set dy negative, i.e. moving "up"
double newDy = -Math.abs(ball.getDy());
ball.setVelocity(dx, newDy);
}
}
}
Main
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Bounce extends Application {
private World world;
private Canvas canvas;
private AnimationTimer timer;
protected class BounceTimer extends AnimationTimer {
private long previousNs = 0;
#Override
public void handle(long nowNs) {
if (previousNs == 0) {
previousNs = nowNs;
}
world.move(nowNs - previousNs);
previousNs = nowNs;
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.WHITESMOKE);
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
Rectangle pad = world.getPad();
gc.setFill(Color.BLACK);
double x = pad.getX(), y = pad.getY(),
w = pad.getWidth(), h = pad.getHeight();
gc.fillRoundRect(x, y, w, h, h, h);
for (Ball b : world.getBalls()) {
b.paint(gc);
}
}
}
#Override
public void start(Stage stage) {
Group root = new Group();
Scene scene = new Scene(root, 300, 300, Color.WHITESMOKE);
canvas = new Canvas(scene.getWidth(), scene.getHeight());
root.getChildren().add(canvas);
stage.setTitle("Bounce");
stage.setScene(scene);
stage.setResizable(false);
stage.sizeToScene();
stage.show();
world = new World(canvas.getWidth(), canvas.getHeight());
timer = new BounceTimer();
timer.start();
canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
world.setPadX(me.getX());
}
});
}
public static void main(String[] args) {
launch(args);
}
private void showAlert(String message) {
alert.setHeaderText("");
alert.setTitle("Alert!");
alert.setContentText(message);
alert.show();
}
private final Alert alert = new Alert(Alert.AlertType.INFORMATION);
}
Ball
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class Ball {
public static final double BILLION = 1_000_000_000.0;
private double x, y; // position of the balls center
private double dx, dy; // velocity measured in pixels/second
private double radius;
private Color color;
public Ball(double x0, double y0) {
x = x0;
y = y0;
radius = 10;
color = Color.MAGENTA;
}
public Ball(double x0, double y0, double rad, Color col) {
x = x0;
y = y0;
radius = rad;
color = col;
}
Ball(int i, int i0, Color BLUEVIOLET) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void setColor(Color col) { // setColor
color = col; }
public double getX() {
return x;
}
public double getY() {
return y;
}
public void setX(double newX) {
x = newX;
}
public void setY(double newY) {
y = newY;
}
public double getRadius() {
return radius;
}
public double getDx() {
return dx;
}
public double getDy() {
return dy;
}
public void setVelocity(double newDx, double newDy) {
dx = newDx;
dy = newDy;
}
public void moveTo(double newX, double newY) {
x = newX;
y = newY;
}
public void move(long elapsedTimeNs) {
x += dx * elapsedTimeNs / BILLION;
y += dy * elapsedTimeNs / BILLION;
}
public void paint(GraphicsContext gc) {
gc.setFill(color);
// arguments to fillOval: see the javadoc for GraphicsContext
gc.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}
public boolean intersectsArea(
double rectX, double rectY,
double rectWidth, double rectHeight) {
double closestX = clamp(x, rectX, rectX + rectWidth);
double closestY = clamp(y, rectY, rectY + rectHeight);
double distanceX = x - closestX;
double distanceY = y - closestY;
return (distanceX * distanceX) + (distanceY * distanceY)
< (radius * radius);
}
private double clamp(double value, double lower, double upper) {
if (value < lower) {
return lower;
}
if (value > upper) {
return upper;
}
return value;
}
}
As Stormblessed said, you are only targeting one ball in your move method.
You should do:
public void move(Ball ball, long elapsedTimeNs) {
ball.move(elapsedTimeNs);
constrainBall(ball);
checkForCollisionWithPad(ball);
}
Edit: Since you want the handler method to accept only the elapsedTimeNs argument, do:
public void move(long elapsedTimeNs) {
for (Ball ball : balls) {
ball.move(elapsedTimeNs);
constrainBall(ball);
checkForCollisionWithPad(ball);
}
}
Edit 2: You should probably have a method that creates a new ball, for convenience:
public Ball newBall(double x, double y, double velocity1, double velocity2) {
Ball tmp = new Ball(x, y);
tmp.setVelocity(velocity1, velocity2);
balls.add(tmp);
return tmp;
}
Edit 3: The reason it throws an error is that you designated balls to have only one index position by using balls = new Ball[1]. You should use an ArrayList (java.util.ArrayList) instead, like so:
import java.util.ArrayList;
ArrayList<Ball> balls = new ArrayList<>;
You should now use balls.add and balls.get instead of = and []. References have been updated accordingly.
i have looked all over the internet and in my school books but I can't seem to slove my problem.
In my program "bouncing ball" (got the code from our teacher) i need to change the size of the ball from small to bigger and reverse. I understand that i need a boolean to do that and maybe alsow an if statment. This is what I have in the Ball class rigth now regarding the size change:
private boolean changeSize = true;
int maxSize = 10;
int minSize = 1;
public void changeSize(boolean size ){
if(size == maxSize ){
return minSize;
}
else return maxSize;
}
public void changeBallSize(int d, int f){
diameter = d*f;
This is the whole code for the class Ball:
class Ball {
static int defaultDiameter = 10;
static Color defaultColor = Color.yellow;
static Rectangle defaultBox = new Rectangle(0,0,100,100);
// Position
private int x, y;
// Speen and angel
private int dx, dy;
// Size
private int diameter;
// Color
private Color color;
// Bouncing area
private Rectangle box;
// New Ball
public Ball( int x0, int y0, int dx0, int dy0 ) {
x = x0;
y = y0;
dx = dx0;
dy = dy0;
color = defaultColor;
diameter = defaultDiameter;
}
// New color
public void setColor( Color c ) {
color = c;
}
public void setBoundingBox( Rectangle r ) {
box = r;
}
// ball
public void paint( Graphics g ) {
// Byt till bollens färg
g.setColor( color );
g.fillOval( x, y, diameter, diameter );
}
void constrain() {
// Ge absoluta koordinater för det rektangulära området
int x0 = box.x;
int y0 = box.y;
int x1 = x0 + box.width - diameter;
int y1 = y0 + box.height - diameter;
// Setting speed and angels
if (x < x0)
dx = Math.abs(dx);
if (x > x1)
dx = -Math.abs(dx);
if (y < y0)
dy = Math.abs(dy);
if (y > y1)
dy = -Math.abs(dy);
}
// movingt the ball
x = x + dx;
y = y + dy;
constrain();
}
}
I am a total rookie of java! Thanks for the help!
Add the following into your Ball class:
private int changeFlag=-1;
In your constrain() function, just before the last line, after moving the ball:
if(diameter==maxSize) {
changeFlag=-1;
}
else if (diameter==minSize) {
changeFlag=1;
}
diameter=diameter+changeFlag;
Add this code to your Ball Class
private minSize = 1;
private maxSize = 10;
public void setDiameter(int newDiameter) {
this.diameter = newDiameter;
}
public int getMinSize() {
return minSize;
}
public int getMinSize() {
return maxSize;
}
Use this when you use the ball
Ball ball = new Ball(1,1,1,1);
int newDiameter = 10;
if(newDiameter == ball.getMinSize()) {
ball.setDiameter(ball.getMaxSize());
}
id(newDiameter == ball.getMaxSize()) {
ball.setDiameter (ball.getMinSize());
}
I've edited it, is this what you mean?
Main Class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
public class Main extends JFrame {
public static void main(String[] args) {
new Main();
}
public Main() {
// configure JFrame
setSize(640, 360);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create ball
Ball ball = new Ball(this.getWidth()/2, this.getHeight()/2, 50, 100);
add(ball);
Thread t = new Thread(ball);
t.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
}
}
Ball Class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
public class Ball extends JComponent implements Runnable {
private int x, y, minDiameter, maxDiameter, currentDiameter, growRate = -1;
private Color color = Color.BLUE;
public Ball(int x, int y, int minDiameter, int maxDiameter) {
this.x = x;
this.y = y;
this.minDiameter = minDiameter;
this.maxDiameter = maxDiameter;
this.currentDiameter = minDiameter;
setVisible(true);
}
#Override
public void run() {
while (true) {
// coerce max and min size
if (this.currentDiameter + growRate > maxDiameter) {
this.currentDiameter = maxDiameter;
this.growRate = -1;
}
if (this.currentDiameter + growRate < minDiameter) {
this.currentDiameter = minDiameter;
this.growRate = 1;
}
this.currentDiameter += this.growRate;
repaint();
try {
Thread.sleep(10);
}
catch(Exception e) {
System.out.println(e.toString());
}
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2.setColor(this.color);
g2.fillOval(this.x, this.y, this.currentDiameter, this.currentDiameter);
}
}