I would like to be able to have the user change the color and radius of the ball, I would also like to be able to change the color of the ball when it has already been created.
I have tried using the setColor but I does not get it to work.
Here is my code:
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.YELLOW;
}
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 setColor(Color col) {
color = col;
}
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;
}
}
Any tips on how to proceed?
Thanks!
My guess is that you do not call paint after setting the color, you need to redraw to have the color changed
Related
I was trying to draw a hexagon on a canvas. But I have not found something that could help me. I wasn't able to do it on my one. My problem is that the hexagon line points aren't drawing.
The green dots are the circles I want to draw and the black lines should be the hexagon when I draw it with lines
My Hexagon class
public class Hexagon extends Rotateables {
public float radius;
public Hexagon(Game game, Vector2 position, float radius) {
super(game, position.x, position.y, 0, 0, 0);
this.radius = radius;
}
public void drawHexagon(Canvas canvas) {
for (int angle = 0; angle < 360;angle += 45) {
setAngle(angle);
Vector2 drawPos = getMovement();
Paint paint;
paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawCircle(drawPos.getX(), drawPos.getY(), radius, paint);
}
}
}
My Rotateables class
public abstract class Rotateables {
protected double x ,y , angle; // angle
protected int w, h; // width and height
// constructor
public Rotateables(double x, double y, double angle, int w, int h) {
this.x = x;
this.y = y;
this.angle = angle;
this.w = w;
this.h = h;
}
// returning all the necessary value of this class
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getAngle() {
return angle;
}
public int getW() {
return w;
}
public int getH() {
return h;
}
// setting the angle
public void setAngle(int aa) {
angle = Math.toRadians(aa);
}
// move toward the angle
// //forward
public void moveForward() {
x += Math.cos(angle);
y += Math.sin(angle);
}
public Vector2 getMovement() {
double x = Math.cos(angle) + this.x;
double y = Math.sin(angle) + this.y;
return new Vector2(x,y);
}
public void moveForward(float speed, boolean drawVertex) {
x += Math.cos(angle)*speed;
y += Math.sin(angle)*speed;
}
//backward
public void moveBackward() {
x -= Math.cos(angle);
y -= Math.sin(angle);
}
public void setAngle(Point p1)
{
double xDiff = x - p1.x;
double yDiff = y - p1.y;
double _angle = Math.toDegrees(Math.atan2(yDiff, xDiff));
setAngle((int)_angle);
}
public static double getAngle(Point p1, Point p2)
{
double xDiff = p2.x - p1.x;
double yDiff = p2.y - p1.y;
return Math.toDegrees(Math.atan2(yDiff, xDiff));
}
}
I am making Pong in Java right now using Eclipse. I am trying to get the balls to bounce off the padels proportionally to where they hit the padel. If they hit at the top or bottom, I would like them to bounce off at 75 degrees up at the top or 75 degrees down at the bottom. If they hit near the center, then I would like them to bounce off closer to horizontal.
I am calculating the angle in the ball class with this math:
double speed = getSpeed() + ballIncrease;
yPos = Math.abs(yPos);
double angle = multiplier * yPos;
double ratio = Math.tan(angle);
xSpeed = ratio * (speed/(ratio + 1));
ySpeed = Math.sqrt((speed * speed) - (xSpeed * xSpeed));
I think that it should be correct, but the balls don't behave like I expect them to. I was wondering if anyone can help me solve this problem.
package Pong;
/*Place cursor here to start
*
*/
//Import Libraries
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
#SuppressWarnings("serial")
public class Pong extends JPanel implements KeyListener{
//Create random instances
Random r2 =new Random();
public final static int padelStart = 150;
public final static int padelSpace = 10;
final static int BOX_WIDTH = 1200;
public final static int BOX_HEIGHT = 800;
double ballX = BOX_WIDTH/2;
double ballY = BOX_HEIGHT/2;
public static Padel padel1 = new Padel(padelSpace,padelStart,true);
public static Padel padel2 = new Padel(BOX_WIDTH-padelSpace-padel1.getWidth(),padelStart,false);
Ball ball1 = new Ball(ballX,ballY);
Ball ball2 = new Ball(300,300);
public static int padel1y1;
public static int padel1y2;
public static int padel2y1;
public static int padel2y2;
//Constants
public final static int UPDATE_RATE = 200;
//Main game class
public Pong () {
//Set window size
setPreferredSize(new Dimension(BOX_WIDTH,BOX_HEIGHT));
//Start game thread
Thread gameThread = new Thread() {
public void run(){
while(true){
//Draw objects
padel1y1 = padel1.getY();
padel1y2 = padel1.getY() + Padel.padelLength;
padel2y1 = padel2.getY();
padel2y2 = padel2.getY() + Padel.padelLength;
padel1.update();
padel2.update();
ball1.update();
ball2.update();
repaint();
//Wait
try {Thread.sleep(1000 / UPDATE_RATE);}
catch (InterruptedException ex) {}
}
}
};
gameThread.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,BOX_WIDTH,BOX_HEIGHT);
padel1.draw(g);
padel2.draw(g);
ball1.draw(g);
ball2.draw(g);
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP){padel2.setSpeed(-Padel.padelSpeed);}
if(e.getKeyCode() == KeyEvent.VK_DOWN){padel2.setSpeed(Padel.padelSpeed);}
if(e.getKeyCode() == KeyEvent.VK_W){padel1.setSpeed(-Padel.padelSpeed);}
if(e.getKeyCode() == KeyEvent.VK_S){padel1.setSpeed(Padel.padelSpeed);}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){padel2.setSpeed(0);}
if(e.getKeyCode() == KeyEvent.VK_DOWN){padel2.setSpeed(0);}
if(e.getKeyCode() == KeyEvent.VK_W){padel1.setSpeed(0);}
if(e.getKeyCode() == KeyEvent.VK_S){padel1.setSpeed(0);}
}
public void keyTyped(KeyEvent e) {}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Create Frame
JFrame frame = new JFrame("PONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONG");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Pong pong = new Pong();
frame.setContentPane(pong);
frame.setSize(BOX_WIDTH,BOX_HEIGHT);
frame.pack();
frame.addKeyListener(pong);
frame.setVisible(true);
}
});
}
}
Padel Class:
package Pong;
import java.awt.*;
import java.util.Random;
public class Padel {
public int y;
public int x;
public boolean ws;
public int speed = 0;
public final static int padelSpeed = 3;
public final static int padelWidth = 30;
public final static int padelLength = 200;
Random rng = new Random();
int r = rng.nextInt(256);
int g = rng.nextInt(256);
int b = rng.nextInt(256);
Color color = new Color(r,g,b);
public Padel(int xPos, int yPos, boolean wands){
y = yPos;
x = xPos;
ws = wands;
}
public void update(){
if(speed > 0 && y + padelLength < Pong.BOX_HEIGHT){
y = y + speed;
}
if(speed < 0 && y > 0){
y = y + speed;
}
}
public void draw(Graphics g) {
g.setColor(color);
g.fillRoundRect(x, y, padelWidth, padelLength, 25, 25);
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int getWidth(){
return padelWidth;
}
public int getLength(){
return padelLength;
}
public int getSpeed(){
return speed;
}
public void setSpeed(int speed1){
speed = speed1;
}
public int getPadelSpeed(){
return padelSpeed;
}
}
Ball Class:
package Pong;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
public class Ball {
Random rng = new Random();
int r = rng.nextInt(256);
int g = rng.nextInt(256);
int b = rng.nextInt(256);
Color color = new Color(r,g,b);
public final static double ballSpeedMin = -2.0;
public final static double ballSpeedMax = 2.0;
public final static double middleSpeedCutoff = 1.0;
public final static double ballIncrease = .2;
public final int ballRadiusMin = 10;
public final int ballRadiusMax = 40;
double x;
double y;
double xSpeed;
double ySpeed;
int ballRadius;
public Ball(double xPos,double yPos){
x = xPos;
y = yPos;
xSpeed = getRandomSpeed();
ySpeed = getRandomSpeed();
ballRadius = getRandomRadius();
}
public double getRandomSpeed(){
Random r =new Random();
return ballSpeedMin + (ballSpeedMax - ballSpeedMin) * r.nextDouble();
}
public int getRandomRadius(){
Random r = new Random();
return r.nextInt((ballRadiusMax - ballRadiusMin) + 1) + ballRadiusMin;
}
public void update(){
x = x + xSpeed;
y = y + ySpeed;
ySpeed = verticalBounce();
double multiplier = .75;
if(getLowX() < Pong.padelSpace + Padel.padelWidth){
if(y>=Pong.padel1y1 && y<=Pong.padel1y2){
double yPos = y - Pong.padel1y1 - (Padel.padelLength/2);
if(yPos<0){
double speed = getSpeed() + ballIncrease;
yPos = Math.abs(yPos);
double angle = multiplier * yPos;
double ratio = Math.tan(angle);
xSpeed = ratio * (speed/(ratio + 1));
ySpeed = -Math.sqrt((speed * speed) - (xSpeed * xSpeed));
}
else if(yPos>0){
double speed = getSpeed() + ballIncrease;
yPos = Math.abs(yPos);
double angle = multiplier * yPos;
double ratio = Math.tan(angle);
xSpeed = ratio * (speed/(ratio + 1));
ySpeed = Math.sqrt((speed * speed) - (xSpeed * xSpeed));
}
else{
double speed = getSpeed();
xSpeed = speed;
ySpeed = 0;
}
}
else{
System.exit(0);
}
}
if(getHighX() > Pong.BOX_WIDTH - Pong.padelSpace - Padel.padelWidth){
if(y>Pong.padel2y1 && y<Pong.padel2y2){
double yPos = y - Pong.padel2y1 - (Padel.padelLength/2);
if(yPos<0){
double speed = getSpeed() + ballIncrease;
yPos = Math.abs(yPos);
double angle = multiplier * yPos;
double ratio = Math.tan(angle);
xSpeed = - ratio * (speed/(ratio + 1));
ySpeed = -Math.sqrt((speed * speed) - (xSpeed * xSpeed));
}
else if(yPos>0){
double speed = getSpeed() + ballIncrease;
yPos = Math.abs(yPos);
double angle = multiplier * yPos;
double ratio = Math.tan(angle);
xSpeed = - ratio * (speed/(ratio + 1));
ySpeed = Math.sqrt((speed * speed) - (xSpeed * xSpeed));
}
else{
double speed = getSpeed();
xSpeed = -speed;
ySpeed = 0;
}
}
else{
System.exit(0);
}
}
}
public void draw(Graphics g) {
g.setColor(color);
int xPos = (int) Math.round(x) - ballRadius;
int yPos = (int) Math.round(y) - ballRadius;
g.fillOval(xPos,yPos,ballRadius*2,ballRadius*2);
}
public double verticalBounce(){
if(y - ballRadius<0 || y + ballRadius > Pong.BOX_HEIGHT){
return -ySpeed;
}
else{
return ySpeed;
}
}
public double getY(){
return y;
}
public double getX(){
return x;
}
public double getYSpeed(){
return ySpeed;
}
public double getXSpeed(){
return xSpeed;
}
public void setYSpeed(double y){
ySpeed = y;
}
public void setXSpeed(double x){
xSpeed = x;
}
public double getLowX(){
return x - ballRadius;
}
public double getLowY(){
return y - ballRadius;
}
public double getHighX(){
return x + ballRadius;
}
public double getHighY(){
return y + ballRadius;
}
public double getSpeed(){
return Math.sqrt((xSpeed*xSpeed)+(ySpeed*ySpeed));
}
}
double multiplier = .75;
//...
double yPos = y - Pong.padel1y1 - (Padel.padelLength/2);
//...
double angle = multiplier * yPos;
Are you aware that the angles you pass in trigonometric functions are expressed in radians?Assuming your paddle length is 20, with yPos varying between [-10, 10] your angle will vary between [-7.5, 7.5]. Translate this in radians and you'll see your angle rotates around the circle a bit more than 2 times. Is really this what you want?
I created a simple Application which is meant to display, in 2D, dots which are hypothetically on a 3D plane (these points are of type Vector, written below). The class uses the XYZ Coordinates of the Camera and the XYZ Coordinates of the Vector, and uses that information to quickly translate the Vector XYZ Coordinates into XY Coordinates.
The only class needed in this question is the Vector class given below. All other classes used are omitted because they essentially fire mouse movements and redraw the frame.
--My concern is that, as the camera moves, the Vector points jump around as if the formula that I'm using is totally unreliable. Are these formulas (found under Perspective Projection) completely incorrect? The use of those formulas can be found within my set2D method. Am I doing something completely wrong, skipping steps, or perhaps have I translated the formula into code incorrectly?
Thanks!
import java.awt.Color;
import java.awt.Graphics;
public class Vector
{
private int cX, cY, cZ; //Camera Coordinates
private int aX, aY, aZ; //Object Coordinates
private double bX, bY; //3D to 2D Plane Coordinates
public Vector(int aX, int aY, int aZ, int cX, int cY, int cZ)
{
this.aX = aX;
this.aY = aY;
this.aZ = aZ;
this.cX = cX;
this.cY = cY;
this.cY = cZ;
set2D();
}
//SETS
public void setCameraX(int cX)
{
this.cX = cX;
set2D();
}
public void setCameraY(int cY)
{
this.cY = cY;
set2D();
}
public void setCameraZ(int cZ)
{
this.cZ = cZ;
set2D();
}
public void setCameraXYZ(int cX, int cY, int cZ)
{
setCameraX(cX);
setCameraY(cY);
setCameraZ(cZ);
}
public void setObjX(int x)
{
this.aX = x;
}
public void setObjY(int y)
{
this.aY = y;
}
public void setObjZ(int z)
{
this.aZ = z;
}
public void setObjXYZ(int x, int y, int z)
{
this.aX = x;
this.aY = y;
this.aZ = z;
}
public void set2D()
{
//---
//the viewer's position relative to the display surface which goes through point C representing the camera.
double eX = aX - cX;
double eY = aY - cY;
double eZ = aZ - cZ;
//----
double cosX = Math.cos(eX);
double cosY = Math.cos(eY);
double cosZ = Math.cos(eZ);
double sinX = Math.sin(eX);
double sinY = Math.sin(eY);
double sinZ = Math.sin(eZ);
//---
//The position of point A with respect to a coordinate system defined by the camera, with origin in C and rotated by Theta with respect to the initial coordinate system.
double dX = ((cosY*sinZ*eY) + (cosY*cosZ*eX)) - (sinY * eZ);
double dY = ((sinX*cosY*eZ) + (sinX*sinY*sinZ*eY) + (sinX*sinY*cosZ*eX)) + ((cosX*cosZ*eY) - (cosX*sinZ*eX));
double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX));
//---
//---
//The 2D projection coordinates of the 3D object
bX = (int)(((eZ / dZ) * dX) - eX);
bY = (int)(((eZ / dZ) * dY) - eY);
//---
System.out.println(bX + " " + bY);
}
//GETS
public int getCameraX()
{
return cX;
}
public int getCameraY()
{
return cY;
}
public int getCameraZ()
{
return cZ;
}
public int getObjX()
{
return aX;
}
public int getObjY()
{
return aY;
}
public int getObjZ()
{
return aY;
}
public int get2DX()
{
return (int)bX;
}
public int get2DY()
{
return (int)bY;
}
//DRAW
public void draw(Graphics g)
{
g.setColor(Color.red);
g.fillOval((int)bX, (int)bY, 3, 3);
}
//TO STRING
public String toString()
{
return (aX + " " + aY + " " + aZ);
}
}
The following line of your code does not match with the formula you are using:
double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX));
Notice the part - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX))
This should be - ((sinX*cosZ*eY) - (sinX*sinZ*eX))
Since if you take sinX and multiply it, the -ve sign stays outside. If however you multiple -sinX then the sign outside the brackets should become +ve.
I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)
I´m coding a little app that allows the user to draw multiple shapes and then remove or resize them. It´s working perfectly on rectangles and ovals, but I´m having issues with lines.
Here´s a method that I wrote to find if the clicked spot on the screen is part of a specific line:
public boolean containsLocation(int x, int y) {
int m = (getY2() - getY()) / (getX2() - getX());
int b = getY() - (m * getX());
if (y == (m * x) + b) {
return true;
}
return false;
I´m using the famous y = mx + b formula and replacing y and x, wich are the coordinates on the spot clicked, to find if the clicked spot is part of the line.
The original coordinates are determined using the getters getX(), getY() and getX2(), getY2()
The problem is when I click on the screen to remove the line, it only works if I click on the very fist coordinate (x,y) where the line starts.
Nothing happens when I click anywhere else along the line.
Since math is not a strongest suit, can anyone shed a light on what I´m doing wrong?
Here´s my Line full class:
public class Line extends Shape{
private int x2, y2;
public Line (int x, int y, int x2, int y2, Color lineColor) {
super(x, y, lineColor);
this.x2 = x2;
this.y2 = y2;
}
public void draw(Graphics g) {
g.setColor(getLineColor());
g.drawLine(getX(), getY(), getX2(), getY2());
}
#Override
public boolean containsLocation(int x, int y) {
int m = (getY2() - getY()) / (getX2() - getX());
int b = getY() - (m * getX());
if (y == (m * x) + b) {
return true;
}
return false;
}
public int getX2() {
return x2;
}
public void setX2(int x2) {
this.x2 = x2;
}
public int getY2() {
return y2;
}
public void setY2(int y2) {
this.y2 = y2;
}
}
Here´s the Shape class that is being extended by Line:
public abstract class Shape {
private int x, y;
private Color lineColor;
public Shape(int x, int y, Color lineColor) {
this.x = x;
this.y = y;
this.lineColor = lineColor;
}
public abstract void draw(Graphics g);
public abstract boolean containsLocation(int x, int y);
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 Color getLineColor() {
return lineColor;
}
public void setLineColor(Color lineColor) {
this.lineColor = lineColor;
}
}
Here´s the method that calls containsLocation:
public Shape shapeFinder(int x, int y){
for (int i = shapes.size()-1; i >=0; i--){
if (shapes.get(i).containsLocation(x, y)){
return shapes.get(i);
}
}
return null;
}
And here´s the method that should remove the line (it´s working for Ovals and Rectangles):
public void mousePressed(MouseEvent e) {
if (model.getAction() == Model.REMOVE) {
startX = e.getX();
startY = e.getY();
shape = model.shapeFinder(startX, startY);
if (shape != null) {
model.getShape().remove(model.shapeFinder(startX, startY));
}
You're using integer division to calculate your slope. I used my example of (100,100) to (120, 153) and it gave me a slope of 2. It should be a slope of 2.65.
But regardless, you'll never find any integer points in the middle of my line - there are no points along my line where both x and y are integers. If you calculate the slope correctly you'll be able to get the endpoints recognized but you need to find a different way of calculating points in the middle. Maybe introduce some sort of epsilon to your method?
Actually, you need to compute the direction of the line (its angle in radians) using something like Math.atan2. Then, you can apply an inverse rotation to one of the points of the line, considering the other point as the center, and also to the mouse coordinate. Your line is now a horizontal one, so checking if the mouse is over it is straight-forward.
See rotation matrices.
public class LineDemo {
public static void main(String[] args) {
System.out.println(containsLocation(50, 75, 50, 50, 50, 100));
}
public static boolean containsLocation(int x, int y, int x1, int y1, int x2, int y2) {
double dy = y2 - y1;
double dx = x2 - x1;
double dist = Math.sqrt(dx*dx + dy*dy);
double angle = Math.atan2(dy, dx);
double cos = Math.cos(-angle);
double sin = Math.sin(-angle);
double xRot = (x - x1) * cos - (y - y1) * sin;
double yRot = (x - x1) * sin + (y - y1) * cos;
// Actually, I only rotated the mouse point, since
// I can use the first point of the line and its
// euclidian distance to know where the rotated
// second point would end.
if (0 <= xRot && xRot <= dist) {
double tolerance = 3; // distance tolerance in pixels
if (Math.abs(yRot) <= tolerance) {
return true;
}
}
return false;
}
}