I am a self taught programmer and I am coding Screen Snake for fun. I am using not using integers to store the position of the snake or apples, I am using doubles. I am having an issue when the snake goes through the apple. When the collide, the code does not register that it collided. I am assuming that this is because their X and Y values might be like .1 off. I have been trying to fix this for 2 weeks but have not been able to. Sorry if my code is a bit messy. I don't know exactly what you guys need from the code so I posted all of it. Also I really appreciate the help! Thanks!!
Main class:
Random random = new Random();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double ScreenW = screenSize.getWidth();
double ScreenH = screenSize.getHeight();
int ScreenX = (int)Math.round(ScreenW);
int ScreenY = (int)Math.round(ScreenH);
JFrame frame = new JFrame();
double x = 1, y = 1;
int size = 5;
int ticks;
private int columnCount = 25;
private int rowCount = 15;
double a = (ScreenW / columnCount) - 1;
double b = (ScreenH / rowCount) - 1;
private Key key;
private List<Rectangle2D> cells;
private Point selectedCell;
boolean up = false;
boolean down = false;
boolean right = true;
boolean left = false;
boolean running = true;
private Thread thread;
private BodyP p;
private ArrayList<BodyP> snake;
private Apple apple;
private ArrayList<Apple> apples;
double width = screenSize.width;
double height = screenSize.height;
double cellWidth = width / columnCount;
double cellHeight = height / rowCount;
double xOffset = (width - (columnCount * cellWidth)) / 2;
double yOffset = (height - (rowCount * cellHeight)) / 2;
public Max_SnakeGame() throws IOException {
System.out.println(screenSize);
System.out.println(a + "," + b);
System.out.println(ScreenH + b);
System.out.println(ScreenW + a);
frame.getContentPane().add(new Screen());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setLocationRelativeTo(null);
frame.setMaximumSize(screenSize);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
Image img = Toolkit
.getDefaultToolkit()
.getImage(
"C:/Users/Max/My Documents/High School/Sophomore year/Graphic Disign/People art/The Mods Who Tell Pointless Stories.jpg");
frame.setIconImage(img);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new Max_SnakeGame();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public class Screen extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
public Screen() {
key = new Key();
addKeyListener(key);
setMaximumSize(screenSize);
setOpaque(false);
setBackground(new Color(0, 0, 0, 0));
setFocusable(true);
snake = new ArrayList<BodyP>();
apples = new ArrayList<>();
start();
}
public void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public void run() {
while (running) {
MoveUpdate();
repaint();
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
repaint();
Graphics2D g2d = (Graphics2D) g.create();
cells = new ArrayList<>(columnCount * rowCount);
if (cells.isEmpty()) {
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
Rectangle2D cell = new Rectangle2D.Double(xOffset
+ (col * cellWidth), yOffset
+ (row * cellHeight), cellWidth, cellHeight);
cells.add(cell);
}
}
}
g2d.setColor(Color.GRAY);
for (Rectangle2D cell : cells) {
g2d.draw(cell);
}
for (int i = 0; i < snake.size(); i++) {
snake.get(i).draw(g);
}
for (int i = 0; i < apples.size(); i++) {
apples.get(i).draw(g);
}
}
}
private class Key implements KeyListener {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_RIGHT && !left) {
up = false;
down = false;
right = true;
}
if (keyCode == KeyEvent.VK_LEFT && !right) {
up = false;
down = false;
left = true;
}
if (keyCode == KeyEvent.VK_UP && !down) {
left = false;
right = false;
up = true;
}
if (keyCode == KeyEvent.VK_DOWN && !up) {
left = false;
right = false;
down = true;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public void MoveUpdate() {
if (snake.size() == 0) {
p = new BodyP(x, y, a, b);
snake.add(p);
}
if (apples.size() == 0){
double x1 = random.nextInt(25);
double Ax = ((x1*a+x1+1)*10)/10;
double y1 = random.nextInt(15);
double Ay = ((y1*b+y1+1)*10)/10;
double Afx = Math.round(Ax);
double Afy = Math.round(Ay);
System.out.println("Ax:"+Afx);
System.out.println("Ay:"+Afy);
apple = new Apple(Ax, Ay, a, b);
apples.add(apple);
}
for(int i = 0; i < apples.size(); i++) {
if(Math.round(x)-1 == apples.get(i).getx() || Math.round(x) == apples.get(i).getx() && Math.round(y)== apples.get(i).gety() || Math.round(y)-1 == apples.get(i).gety()) {
size++;
apples.remove(i);
i--;
}
}
ticks++;
if (ticks > 2500000) {
if (up == true) {
if (y <= 2) {
y = ScreenH - b;
System.out.println("Y:" + y);
} else {
y -= b + 1;
System.out.println("Y:" + y);
}
}
// down loop
else if (down == true) {
if (y >= ScreenH - b) {
y = 1;
System.out.println("Y:" + y);
}
else {
y += b + 1;
System.out.println("Y:" + y);
}
}
// left loop
else if (left == true) {
if (x <= 1) {
x = ScreenW - a;
System.out.println("X:" + x);
}
else {
x -= a + 1;
System.out.println("X:" + x);
}
}
// right loop
else if (right == true) {
if (x >= ScreenW - a) {
x = 1;
System.out.println("X:" + x);
}
else {
x += a + 1;
System.out.println("X:" + x);
}
}
ticks = 0;
p = new BodyP(x, y, a, b);
snake.add(p);
// rect.setFrame(x, y, a, b);
if (snake.size() > size) {
snake.remove(0);
}
}
}
}
Snake class:
public class BodyP {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double ScreenW = screenSize.getWidth();
double ScreenH = screen`enter code here`Size.getHeight();
double x = 1, y = 1;
private int columnCount = 25;
private int rowCount = 15;
double a = (ScreenW / columnCount) - 1;
double b = (ScreenH / rowCount) - 1;
public BodyP(double x, double y, double a, double b) {
this.x = x;
this.y = y;
this.a = a;
this.b = b;
}
public void MoveUpdate(){
}
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double(x, y, a, b);
g.setColor(Color.BLACK);
g2.fill(rect);
}
public double getx() {
return x;
}
public void setx(double x) {
this.x = x;
}
public double gety() {
return y;
}
public void sety(double y) {
this.y = y;
}
}
Apple class:
public class Apple {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double ScreenW = screenSize.getWidth();
double ScreenH = screenSize.getHeight();
double x = 1, y = 1;
private int columnCount = 25;
private int rowCount = 15;
double a = (ScreenW / columnCount) - 1;
double b = (ScreenH / rowCount) - 1;
public Apple(double x, double y, double a, double b) {
this.x = x;
this.y = y;
this.a = a;
this.b = b;
}
public void MoveUpdate(){
}
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double(x, y, a, b);
g.setColor(Color.RED);
g2.fill(rect);
}
public double getx() {
return x;
}
public void setx(double x) {
this.x = x;
}
public double gety() {
return y;
}
public void sety(double y) {
this.y = y;
}
}
If you think this is due rounding errors, use Euclidean distance and compare with the desired tolerance:
final double tolerance = 1.0; // or whatsoever
double dx = snake.x - apple.x;
double dy = snake.y - apple.y;
if ( dx*dx + dy*dy < tolearance * tolerance ) ...
I suggest to implement something like Point.distanceTo(Point) method to make this convenient.
Related
I have been working from the following example provided by the user Andrew Thompson -> Collision detection with complex shapes
I have attempted to implement this in my program (code below) in the method 'draw' but for some reason the statement to change the colour of the square to "Red" will never evaluate as true and I can't fathom why; I have tried almost everything at this point but lacking further help from Andrew I don't seem to be able to progress in correctly implementing this code so that when the flock of triangles come into contact with the square, the square changes colour to Red.
Any and all help is greatly appreciated (code below):
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.geom.*;
import static java.lang.Math.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
import javax.swing.Timer;
public class Boids extends JPanel {
Flock flock;
Flock flock2;
final int w, h;
public Boids() {
w = 1200;
h = 600;
setPreferredSize(new Dimension(w, h));
setBackground(Color.black);
spawnFlock();
new Timer(17, (ActionEvent e) -> {
if (flock.hasLeftTheBuilding(w))
spawnFlock();
repaint();
}).start();
}
public void spawnFlock() {
Random rand = new Random();
int n = rand.nextInt(599) + 1;
flock = Flock.spawn(100, h - n, 20);
}
#Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
flock.run(g, w, h);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Simulator v0.6");
f.setResizable(false);
f.add(new Boids(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class Boid {
static final Random r = new Random();
static final Vec migrate = new Vec(0.02, 0);
static final int size = 3;
final double maxForce, maxSpeed;
Vec location, velocity, acceleration;
private boolean included = true;
Boid(double x, double y) {
acceleration = new Vec();
velocity = new Vec(r.nextInt(3) + 1, r.nextInt(3) - 1);
location = new Vec(x, y);
maxSpeed = 3.0;
maxForce = 0.05;
}
void update() {
velocity.add(acceleration);
velocity.limit(maxSpeed);
location.add(velocity);
acceleration.mult(0);
}
void applyForce(Vec force) {
acceleration.add(force);
}
Vec seek(Vec target) {
Vec steer = Vec.sub(target, location);
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
return steer;
}
void flock(Graphics2D g, List<Boid> boids) {
view(g, boids);
Vec rule1 = separation(boids);
Vec rule2 = alignment(boids);
Vec rule3 = cohesion(boids);
rule1.mult(2.5);
rule2.mult(1.5);
rule3.mult(1.3);
applyForce(rule1);
applyForce(rule2);
applyForce(rule3);
applyForce(migrate);
}
public boolean doAreasCollide(Area area1, Area area2) {
boolean collide = false;
Area collide1 = new Area(area1);
collide1.subtract(area2);
if (!collide1.equals(area1)) {
collide = true;
}
Area collide2 = new Area(area2);
collide2.subtract(area1);
if (!collide2.equals(area2)) {
collide = true;
}
return collide;
}
void view(Graphics2D g, List<Boid> boids) {
double sightDistance = 100;
double peripheryAngle = PI * 0.85;
for (Boid b : boids) {
b.included = false;
if (b == this)
continue;
double d = Vec.dist(location, b.location);
if (d <= 0 || d > sightDistance)
continue;
Vec lineOfSight = Vec.sub(b.location, location);
double angle = Vec.angleBetween(lineOfSight, velocity);
if (angle < peripheryAngle)
b.included = true;
}
}
Vec separation(List<Boid> boids) {
double desiredSeparation = 25;
Vec steer = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < desiredSeparation)) {
Vec diff = Vec.sub(location, b.location);
diff.normalize();
diff.div(d); // weight by distance
steer.add(diff);
count++;
}
}
if (count > 0) {
steer.div(count);
}
if (steer.mag() > 0) {
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
return steer;
}
return new Vec(0, 0);
}
Vec alignment(List<Boid> boids) {
double preferredDist = 50;
Vec steer = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < preferredDist)) {
steer.add(b.velocity);
count++;
}
}
if (count > 0) {
steer.div(count);
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
}
return steer;
}
Vec cohesion(List<Boid> boids) {
double preferredDist = 50;
Vec target = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < preferredDist)) {
target.add(b.location);
count++;
}
}
if (count > 0) {
target.div(count);
return seek(target);
}
return target;
}
void draw(Graphics2D g) {
AffineTransform save = g.getTransform();
int[] xTriangle = {33,36,34};
int[] yTriangle = {30,30,20};
Area triangle = new Area(new Polygon(xTriangle, yTriangle, 3));
g.translate(location.x, location.y);
g.rotate(velocity.heading() + PI / 2);
g.setColor(Color.green);
// g.fill(shape);
g.setColor(Color.green);
g.draw(triangle);
g.fill(triangle);
g.setTransform(save);
Area square = new Area(new Rectangle(600,250,200,200));
g.draw(square);
if (doAreasCollide(square, triangle)) {
g.setColor(Color.RED);
System.out.println("Collision");
} else {
g.setColor(Color.GREEN);
System.out.println("noCollision");
}
g.fill(square);
}
public void run(Graphics2D g, List<Boid> boids, int w, int h) {
flock(g, boids);
update();
draw(g);
}
}
class Flock {
List<Boid> boids;
Flock() {
boids = new ArrayList<>();
}
void run(Graphics2D g, int w, int h) {
for (Boid b : boids) {
b.run(g, boids, w, h);
}
}
boolean hasLeftTheBuilding(int w) {
int count = 0;
for (Boid b : boids) {
if (b.location.x + Boid.size > w)
count++;
}
return boids.size() == count;
}
void addBoid(Boid b) {
boids.add(b);
}
static Flock spawn(double w, double h, int numBoids) {
Flock flock = new Flock();
for (int i = 0; i < numBoids; i++)
flock.addBoid(new Boid(w, h));
return flock;
}
}
class Vec {
double x, y;
Vec() {
}
Vec(double x, double y) {
this.x = x;
this.y = y;
}
void add(Vec v) {
x += v.x;
y += v.y;
}
void sub(Vec v) {
x -= v.x;
y -= v.y;
}
void div(double val) {
x /= val;
y /= val;
}
void mult(double val) {
x *= val;
y *= val;
}
double mag() {
return sqrt(pow(x, 2) + pow(y, 2));
}
double dot(Vec v) {
return x * v.x + y * v.y;
}
void normalize() {
double mag = mag();
if (mag != 0) {
x /= mag;
y /= mag;
}
}
void limit(double lim) {
double mag = mag();
if (mag != 0 && mag > lim) {
x *= lim / mag;
y *= lim / mag;
}
}
double heading() {
return atan2(y, x);
}
static Vec sub(Vec v, Vec v2) {
return new Vec(v.x - v2.x, v.y - v2.y);
}
static double dist(Vec v, Vec v2) {
return sqrt(pow(v.x - v2.x, 2) + pow(v.y - v2.y, 2));
}
static double angleBetween(Vec v, Vec v2) {
return acos(v.dot(v2) / (v.mag() * v2.mag()));
}
}
The program spawns a flock of triangles that 'fly' through an environment. In this environment, there is a rectangle and sometimes the flock will fly through the rectangle. The flock itself is comprised of 20 triangles - what I want to know is how many of these triangles pass through the rectangle each time the flock flys through the environment (once the flock disappears outside of the environment it respawns).
At the moment, my attempt at implementing this is the "hasFoundFood" method where I attempt to detect whether, for each of the boids, they have come into contact with the bounds of the rectangle but the value for noSuccessful is always 20.
Is there a way to detect whether any or all of the triangles have come into contact with the boundaries of rectangle and then count how many times this has occurred?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.*;
import static java.lang.Math.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
import javax.swing.Timer;
import java.util.Random;
import javax.swing.JButton;
public class Boids extends JPanel {
Flock flock;
Flock flock2;
final int w, h;
int noSuccessful;
public Area food = new Area(new Rectangle(600,250,200,200));
int[] xTriangle = {33,36,34};
int[] yTriangle = {30,30,20};
public Area triangle = new Area(new Polygon(xTriangle, yTriangle, 3));
public Boids() {
w = 1200;
h = 600;
setPreferredSize(new Dimension(w, h));
setBackground(Color.black);
spawnFlock();
flock.hasFoundFood(noSuccessful);
new Timer(17, (ActionEvent e) -> {
if (flock.hasLeftTheBuilding(w))
spawnFlock();
repaint();
}).start();
}
public void spawnFlock() {
Random rand = new Random();
int n = rand.nextInt(599) + 1;
flock = Flock.spawn(100, h - n, 20);
flock2 = Flock.spawn(100, h - n, 1);
}
#Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
flock.run(g, w, h);
g.draw(food);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Simulator v0.6");
f.setResizable(false);
f.add(new Boids(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class Boid {
static final Random r = new Random();
static final Vec migrate = new Vec(0.02, 0);
static final int size = 3;
/* static final Path2D shape = new Path2D.Double();
static {
shape.moveTo(0, -size * 2);
shape.lineTo(-size, size * 2);
shape.lineTo(size, size * 2);
shape.closePath();
}
*/
final double maxForce, maxSpeed;
Vec location, velocity, acceleration;
private boolean included = true;
Boid(double x, double y) {
acceleration = new Vec();
velocity = new Vec(r.nextInt(3) + 1, r.nextInt(3) - 1);
location = new Vec(x, y);
maxSpeed = 3.0;
maxForce = 0.05;
}
void update() {
velocity.add(acceleration);
velocity.limit(maxSpeed);
location.add(velocity);
acceleration.mult(0);
}
void applyForce(Vec force) {
acceleration.add(force);
}
Vec seek(Vec target) {
Vec steer = Vec.sub(target, location);
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
return steer;
}
void flock(Graphics2D g, List<Boid> boids) {
view(g, boids);
Vec rule1 = separation(boids);
Vec rule2 = alignment(boids);
Vec rule3 = cohesion(boids);
rule1.mult(2.5);
rule2.mult(1.5);
rule3.mult(1.3);
applyForce(rule1);
applyForce(rule2);
applyForce(rule3);
applyForce(migrate);
}
public boolean doAreasCollide(Area area1, Area area2) {
boolean collide = false;
Area collide1 = new Area(area1);
collide1.subtract(area2);
if (!collide1.equals(area1)) {
collide = true;
}
Area collide2 = new Area(area2);
collide2.subtract(area1);
if (!collide2.equals(area2)) {
collide = true;
}
return collide;
}
void view(Graphics2D g, List<Boid> boids) {
double sightDistance = 100;
double peripheryAngle = PI * 0.85;
for (Boid b : boids) {
b.included = false;
if (b == this)
continue;
double d = Vec.dist(location, b.location);
if (d <= 0 || d > sightDistance)
continue;
Vec lineOfSight = Vec.sub(b.location, location);
double angle = Vec.angleBetween(lineOfSight, velocity);
if (angle < peripheryAngle)
b.included = true;
}
}
Vec separation(List<Boid> boids) {
double desiredSeparation = 25;
Vec steer = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < desiredSeparation)) {
Vec diff = Vec.sub(location, b.location);
diff.normalize();
diff.div(d); // weight by distance
steer.add(diff);
count++;
}
}
if (count > 0) {
steer.div(count);
}
if (steer.mag() > 0) {
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
return steer;
}
return new Vec(0, 0);
}
Vec alignment(List<Boid> boids) {
double preferredDist = 50;
Vec steer = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < preferredDist)) {
steer.add(b.velocity);
count++;
}
}
if (count > 0) {
steer.div(count);
steer.normalize();
steer.mult(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
}
return steer;
}
Vec cohesion(List<Boid> boids) {
double preferredDist = 50;
Vec target = new Vec(0, 0);
int count = 0;
for (Boid b : boids) {
if (!b.included)
continue;
double d = Vec.dist(location, b.location);
if ((d > 0) && (d < preferredDist)) {
target.add(b.location);
count++;
}
}
if (count > 0) {
target.div(count);
return seek(target);
}
return target;
}
void draw(Graphics2D g) {
AffineTransform save = g.getTransform();
int[] xTriangle = {33,36,34};
int[] yTriangle = {30,30,20};
Area triangle = new Area(new Polygon(xTriangle, yTriangle, 3));
g.translate(location.x, location.y);
g.rotate(velocity.heading() + PI / 2);
g.setColor(Color.green);
// g.fill(shape);
g.setColor(Color.green);
g.draw(triangle);
g.fill(triangle);
g.setTransform(save);
}
public void run(Graphics2D g, List<Boid> boids, int w, int h) { //similair method to run leader
flock(g, boids);
update();
draw(g);
}
}
class Flock {
List<Boid> boids;
Flock() {
boids = new ArrayList<>();
}
void run(Graphics2D g, int w, int h) {
for (Boid b : boids) {
b.run(g, boids, w, h);
}
}
boolean hasLeftTheBuilding(int w) {
int count = 0;
for (Boid b : boids) {
if (b.location.x + Boid.size > w) //will also be used to calculate votes based on whether boids is near food
count++;
}
return boids.size() == count;
}
void addBoid(Boid b) {
boids.add(b);
}
static Flock spawn(double w, double h, int numBoids) {
Flock flock = new Flock();
for (int i = 0; i < numBoids; i++)
flock.addBoid(new Boid(w, h));
return flock;
}
int hasFoundFood(int noSuccessful) {
Area food = new Area(new Rectangle(600,250,200,200));
int[] xTriangle = {33,36,34};
int[] yTriangle = {30,30,20};
Area triangle = new Area(new Polygon(xTriangle, yTriangle, 3));
noSuccessful = 0;
for (Boid b : boids) {
if(b.doAreasCollide(food, triangle)); {
noSuccessful++;
}
}
System.out.println(noSuccessful);
return noSuccessful;
}
}
class Vec {
double x, y;
Vec() {
}
Vec(double x, double y) {
this.x = x;
this.y = y;
}
void add(Vec v) {
x += v.x;
y += v.y;
}
void sub(Vec v) {
x -= v.x;
y -= v.y;
}
void div(double val) {
x /= val;
y /= val;
}
void mult(double val) {
x *= val;
y *= val;
}
double mag() {
return sqrt(pow(x, 2) + pow(y, 2));
}
double dot(Vec v) {
return x * v.x + y * v.y;
}
void normalize() {
double mag = mag();
if (mag != 0) {
x /= mag;
y /= mag;
}
}
void limit(double lim) {
double mag = mag();
if (mag != 0 && mag > lim) {
x *= lim / mag;
y *= lim / mag;
}
}
double heading() {
return atan2(y, x);
}
static Vec sub(Vec v, Vec v2) {
return new Vec(v.x - v2.x, v.y - v2.y);
}
static double dist(Vec v, Vec v2) {
return sqrt(pow(v.x - v2.x, 2) + pow(v.y - v2.y, 2));
}
static double angleBetween(Vec v, Vec v2) {
return acos(v.dot(v2) / (v.mag() * v2.mag()));
}
}
Update:
I have altered the code in line with Andrews code about collisions detection using Area's and it still wont work?! when I call hasFoundFood it still produces the value 20 which is incorrect as, at this point, it should be 0. I am pulling my hair out at this point and cannot for the life of me figure out what is wrong here?!
Currently i'm using LWJGL to make a 2D game. But I've run into an issue. I am trying to make an "infinite world" but an issue comes up because if I create a lot of objects the frames drop and I believe it has to do with the amount of textures being loaded to objects.
Currently I'm creating my world in a grid fashion like this
for(int x = -WORLDWIDTH; x < WORLDWIDTH; x+= BW)
{
for(int y = -WORLDHEIGHT; y < WORLDHEIGHT; y += BH)
{
Tile newTile = new Tile(x,y,BW,BH,TileType.Grass);
tiles.add(newTile);
}
}
Where BW and BH are the block width and height. I try to keep texture loading to only objects on screen using this if statement
if(x >= 0-BW && x + width < WIDTH+BW && y >= 0-BH && y+ height < HEIGHT+BH)
{
DrawQuadTexRotate(getTexture(), getX(), getY(), getWidth(),getHeight(),angle);
}
To load textures I do this
public static void DrawQuadTexRotate(Texture tex, float x, float y, float width, float height, float angle)
{
tex.bind();
glTranslatef(x + width / 2, y + height / 2, 0);
glRotatef(angle, 0 ,0 , 1);
glTranslatef(- width / 2, - height / 2, 0);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(0,0);
glTexCoord2f(1,0);
glVertex2f(width,0);
glTexCoord2f(1,1);
glVertex2f(width,height);
glTexCoord2f(0,1);
glVertex2f(0,height);
glEnd();
glLoadIdentity();
}
public static Texture LoadTexture(String path, String fileType)
{
Texture tex = null;
InputStream in = ResourceLoader.getResourceAsStream(path);
try {
tex = TextureLoader.getTexture(fileType, in);
} catch (IOException e) {
e.printStackTrace();
}
return tex;
}
The Tile class basically has methods to do certain things based on what type it is. It holds the width, height, x, y and texture which my DrawQuadTex method uses
Here is the tile class
public class Tile {
public float x, y, width, height, angle;
private Texture texture;
private TileType type;
public long timeStart = 0;
public int filled = 1;
public int power = 0;
public int transmitPower = 0;
int connected = 0;
public boolean moveRight,moveLeft,moveUp,moveDown,moveAngle;
public Tile(float x, float y, float width, float height,TileType type)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.type = type;
this.texture = QuickLoad(type.textureName);
timeStart = Timer.getTime();
updateType();
updateFill();
}
public void draw()
{
if(x >= 0-BW && x + width < WIDTH+BW && y >= 0-BH && y+ height < HEIGHT+BH)
{
DrawQuadTexRotate(getTexture(), getX(), getY(), getWidth(),getHeight(),angle);
}
}
public void addFood()
{
if(this.type == TileType.Farm && filled == 1)
{
long timing = Timer.getTime();
if(timing >= (timeStart + 10000))
{
Values.food += (1+Artist.riverAmount);
timeStart = timing;
}
}
}
public void mineOre()
{
if(this.type == TileType.Mine && filled == 1)
{
long timing = Timer.getTime();
if(timing >= (timeStart + 20000))
{
for(int i = 0; i < tiles.size();i++)
{
if(tiles.get(i).getType() == TileType.Ore)
{
tiles.get(i).setType(TileType.LandTile);
Values.oreAmount += 1;
timeStart = timing;
break;
}
}
}
}
}
public void move()
{
if(moveRight == true)
{
x -= 10;
}
if(moveLeft == true)
{
x += 10;
}
if(moveUp == true)
{
y += 10;
}
if(moveDown == true)
{
y -= 10;
}
}
public void testPower()
{
for(int i = 0; i < tiles.size(); i++)
{
if(tiles.get(i).x >= x - BW && tiles.get(i).x <= x + BW && tiles.get(i).y >= y - BH && tiles.get(i).y <= y + BH && tiles.get(i).getType() == TileType.Wire && tiles.get(i).transmitPower == 1 && type == TileType.HomeBasic)
{
power = 1;
break;
}
else
{
power = 0;
}
if(tiles.get(i).x >= x - BW && tiles.get(i).x <= x + BW && tiles.get(i).y >= y - BH && tiles.get(i).y <= y + BH && (tiles.get(i).transmitPower == 1 || tiles.get(i).type == TileType.PowerPlant) && type == TileType.Wire)
{
transmitPower = 1;
break;
}
else if(tiles.get(i).type == TileType.Wire && tiles.get(i).transmitPower == 0)
{
transmitPower = 0;
}
else
{
transmitPower = 0;
}
}
}
public void updateFill()
{
if(type == TileType.HomeBasic || type == TileType.Farm || type == TileType.Mine)
{
filled = 0;
}
}
public void stats()
{
if(type == TileType.HomeBasic)
{
//wt.drawString((int)x, (int)(y-25), Integer.toString(filled), Color.white);
}
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public TileType getType() {
return type;
}
public void setType(TileType type) {
this.type = type;
updateType();
}
public void updateType()
{
this.texture = QuickLoad(type.textureName);
timeStart = Timer.getTime();
updateFill();
}
}
public static Texture QuickLoad(String name)
{
Texture tex = null;
tex = LoadTexture("res/" + name + ".png", "PNG");
return tex;
}
So how would I go about trying to fix this?
I am trying to use Jpanel and Jform to load a pic and perform some actions on it,so far the picture loads, but when I click to perform the action, it doesnt do anything. in fact it goes through the click event, but what I guess about the problem is, that the repaint() maybe doesnt work properly there.
here is the code:
public class SeamCarving
{
static SeamCarving frame=new SeamCarving();
public SeamCarving() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage input;
BufferedImage[] toPaint;
public TestPane() {
try {
input = ImageIO.read(new File("C:\\Users\\SONY\\Desktop\\my-pic\\Fatima.jpg"));
toPaint = new BufferedImage[]{input};
toPaint = new BufferedImage[1];
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
out = input;
toPaint[0] = out;
repaint();
System.out.println("Do Something Clicked");
}
});
add(loadButton);
JButton startButton = new JButton("Start");
add(startButton);
startButton.addActionListener(new ActionListener() {
BufferedImage out = input;
#Override
public void actionPerformed(ActionEvent ae) {
out = deleteVerticalSeam(out);
System.out.println("Do Something Clicked");
toPaint[0]=out;
repaint();
}
});
}
what i want is this line: out = deleteVerticalSeam(out);
but it doesnt effect the photo at all.
EDIT
If doing like below, it will work. but I want it with button and Panel
public class SeamCarving
{
public static void main(String[] args) throws IOException {
final BufferedImage input = ImageIO.read(new File(args[0]));
final BufferedImage[] toPaint = new BufferedImage[]{input};
final Frame frame = new Frame("Seams") {
#Override
public void update(Graphics g) {
final BufferedImage im = toPaint[0];
if (im != null) {
g.clearRect(0,0,getWidth(), getHeight());
g.drawImage(im,0,0,this);
}
}
};
frame.setSize(input.getWidth(), input.getHeight());
frame.setVisible(true);
BufferedImage out = input;
for(int i = 0; i < 200; i++) {
out = deleteVerticalSeam(out);
toPaint[0]=out;
frame.repaint();
}
}
and the deleteVerticalSeam
private static BufferedImage deleteVerticalSeam(BufferedImage input) {
return deleteVerticalSeam(input, findVerticalSeam(input));
}
private static BufferedImage deleteVerticalSeam(final BufferedImage input, final int[] seam) {
int w = input.getWidth(), h = input.getHeight();
final BufferedImage out = new BufferedImage(w-1,h, BufferedImage.TYPE_INT_ARGB);
for(int y = 0; y < h; y++) {
for(int x = 0; x < seam[y]; x++) {
out.setRGB(x,y,input.getRGB(x, y));
}
for(int x = seam[y]+1; x < w; x++) {
out.setRGB(x-1,y,input.getRGB(x, y));
}
}
return out;
}
private static int[] findVerticalSeam(BufferedImage input) {
final int w = input.getWidth(), h = input.getHeight();
final FloatImage intensities = FloatImage.fromBufferedImage(input);
final FloatImage energy = computeEnergy(intensities);
final FloatImage minima = FloatImage.createSameSize(energy);
//First row is equal to the energy
for(int x = 0; x < w; x++) {
minima.set(x,0, energy.get(x,0));
}
//I assume that the rightmost pixel column in the energy image is garbage
for(int y = 1; y < h; y++) {
minima.set(0,y, energy.get(0,y) + min(minima.get(0, y - 1),
minima.get(1, y - 1)));
for(int x = 1; x < w-2; x++) {
final float sum = energy.get(x,y) + min(min(minima.get(x - 1, y - 1),
minima.get(x, y - 1)),minima.get(x + 1, y - 1));
minima.set(x,y, sum);
}
minima.set(w-2,y, energy.get(w-2,y) + min(minima.get(w-2, y - 1),minima.get(w-3, y - 1)));
}
//We find the minimum seam
float minSum = Float.MAX_VALUE;
int seamTip = -1;
for(int x = 1; x < w-1; x++) {
final float v = minima.get(x, h-1);
if(v < minSum) {
minSum=v;
seamTip=x;
}
}
//Backtrace the seam
final int[] seam = new int[h];
seam[h-1]=seamTip;
for(int x = seamTip, y = h-1; y > 0; y--) {
float left = x>0?minima.get(x-1, y-1):Float.MAX_VALUE;
float up = minima.get(x, y-1);
float right = x+1<w?minima.get(x+1, y-1):Float.MAX_VALUE;
if(left < up && left < right) x=x-1;
else if(right < up && right < left) x= x+1;
seam[y-1]=x;
}
return seam;
}
floatimage
public final class FloatImage extends JFrame{
private final int width;
private final int height;
private final float[] data;
public FloatImage(int width, int height) {
this.width = width;
this.height = height;
this.data = new float[width*height];
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public float get(final int x, final int y) {
if(x < 0 || x >= width) throw new IllegalArgumentException("x: " + x);
if(y < 0 || y >= height) throw new IllegalArgumentException("y: " + y);
return data[x+y*width];
}
public void set(final int x, final int y, float value) {
if(x < 0 || x >= width) throw new IllegalArgumentException("x: " + x);
if(y < 0 || y >= height) throw new IllegalArgumentException("y: " + y);
data[x+y*width] = value;
}
public static FloatImage createSameSize(final BufferedImage sample) {
return new FloatImage(sample.getWidth(), sample.getHeight());
}
public static FloatImage createSameSize(final FloatImage sample) {
return new FloatImage(sample.getWidth(), sample.getHeight());
}
public static FloatImage fromBufferedImage(final BufferedImage src) {
final int width = src.getWidth();
final int height = src.getHeight();
final FloatImage result = new FloatImage(width, height);
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
final int argb = src.getRGB(x, y);
int r = (argb >>> 16) & 0xFF;
int g = (argb >>> 8) & 0xFF;
int b = argb & 0xFF;
result.set(x,y, (r*0.3f+g*0.59f+b*0.11f)/255);
}
}
return result;
}
public BufferedImage toBufferedImage(float scale) {
final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
final int intensity = ((int) (get(x, y) * scale)) & 0xFF;
result.setRGB(x,y,0xFF000000 | intensity | intensity << 8 | intensity << 16);
}
}
return result;
}
}
I "think" your basic problem starts here...
startButton.addActionListener(new ActionListener() {
BufferedImage out = input;
#Override
public void actionPerformed(ActionEvent ae) {
out = deleteVerticalSeam(out);
System.out.println("Do Something Clicked");
toPaint[0]=out;
repaint();
}
});
Try removing the instance variable out...
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage out = deleteVerticalSeam(input);
System.out.println("Do Something Clicked");
toPaint[0]=out;
repaint();
}
});
Updated
I've updated the ActionListener to work more like...
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage out = deleteVerticalSeam(toPaint[0]);
System.out.println("Do Something Clicked");
toPaint[0] = out;
repaint();
}
});
Which feeds the last result of the operation back into itself, which gradually decreases the number of vertical pixels in the image...
Updated with working example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static java.lang.Math.abs;
import static java.lang.Math.min;
public class SeamCarving {
public static void main(String[] args) {
new SeamCarving();
}
public SeamCarving() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage input;
BufferedImage[] toPaint;
public TestPane() {
try {
input = ImageIO.read(new File("..."));
toPaint = new BufferedImage[]{input};
toPaint = new BufferedImage[1];
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
toPaint[0] = input;
repaint();
System.out.println("Do Something Clicked");
}
});
add(loadButton);
JButton startButton = new JButton("Start");
add(startButton);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage out = deleteVerticalSeam(toPaint[0]);
System.out.println("Do Something Clicked");
toPaint[0] = out;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return input == null ? super.getPreferredSize() : new Dimension(input.getWidth(), input.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(toPaint[0], 0, 0, this);
g2d.dispose();
}
}
private static BufferedImage deleteVerticalSeam(BufferedImage input) {
return deleteVerticalSeam(input, findVerticalSeam(input));
}
private static BufferedImage deleteVerticalSeam(final BufferedImage input, final int[] seam) {
int w = input.getWidth(), h = input.getHeight();
final BufferedImage out = new BufferedImage(w - 1, h, BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < h; y++) {
for (int x = 0; x < seam[y]; x++) {
out.setRGB(x, y, input.getRGB(x, y));
}
for (int x = seam[y] + 1; x < w; x++) {
out.setRGB(x - 1, y, input.getRGB(x, y));
}
}
return out;
}
private static int[] findVerticalSeam(BufferedImage input) {
final int w = input.getWidth(), h = input.getHeight();
final FloatImage intensities = FloatImage.fromBufferedImage(input);
final FloatImage energy = computeEnergy(intensities);
final FloatImage minima = FloatImage.createSameSize(energy);
//First row is equal to the energy
for (int x = 0; x < w; x++) {
minima.set(x, 0, energy.get(x, 0));
}
//I assume that the rightmost pixel column in the energy image is garbage
for (int y = 1; y < h; y++) {
minima.set(0, y, energy.get(0, y) + min(minima.get(0, y - 1),
minima.get(1, y - 1)));
for (int x = 1; x < w - 2; x++) {
final float sum = energy.get(x, y) + min(min(minima.get(x - 1, y - 1),
minima.get(x, y - 1)), minima.get(x + 1, y - 1));
minima.set(x, y, sum);
}
minima.set(w - 2, y, energy.get(w - 2, y) + min(minima.get(w - 2, y - 1), minima.get(w - 3, y - 1)));
}
//We find the minimum seam
float minSum = Float.MAX_VALUE;
int seamTip = -1;
for (int x = 1; x < w - 1; x++) {
final float v = minima.get(x, h - 1);
if (v < minSum) {
minSum = v;
seamTip = x;
}
}
//Backtrace the seam
final int[] seam = new int[h];
seam[h - 1] = seamTip;
for (int x = seamTip, y = h - 1; y > 0; y--) {
float left = x > 0 ? minima.get(x - 1, y - 1) : Float.MAX_VALUE;
float up = minima.get(x, y - 1);
float right = x + 1 < w ? minima.get(x + 1, y - 1) : Float.MAX_VALUE;
if (left < up && left < right) {
x = x - 1;
} else if (right < up && right < left) {
x = x + 1;
}
seam[y - 1] = x;
}
return seam;
}
private static FloatImage computeEnergy(FloatImage intensities) {
int w = intensities.getWidth(), h = intensities.getHeight();
final FloatImage energy = FloatImage.createSameSize(intensities);
for (int x = 0; x < w - 1; x++) {
for (int y = 0; y < h - 1; y++) {
//I'm aproximating the derivatives by subtraction
float e = abs(intensities.get(x, y) - intensities.get(x + 1, y))
+ abs(intensities.get(x, y) - intensities.get(x, y + 1));
energy.set(x, y, e);
}
}
return energy;
}
public static final class FloatImage {
private final int width;
private final int height;
private final float[] data;
public FloatImage(int width, int height) {
this.width = width;
this.height = height;
this.data = new float[width * height];
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public float get(final int x, final int y) {
if (x < 0 || x >= width) {
throw new IllegalArgumentException("x: " + x);
}
if (y < 0 || y >= height) {
throw new IllegalArgumentException("y: " + y);
}
return data[x + y * width];
}
public void set(final int x, final int y, float value) {
if (x < 0 || x >= width) {
throw new IllegalArgumentException("x: " + x);
}
if (y < 0 || y >= height) {
throw new IllegalArgumentException("y: " + y);
}
data[x + y * width] = value;
}
public static FloatImage createSameSize(final BufferedImage sample) {
return new FloatImage(sample.getWidth(), sample.getHeight());
}
public static FloatImage createSameSize(final FloatImage sample) {
return new FloatImage(sample.getWidth(), sample.getHeight());
}
public static FloatImage fromBufferedImage(final BufferedImage src) {
final int width = src.getWidth();
final int height = src.getHeight();
final FloatImage result = new FloatImage(width, height);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int argb = src.getRGB(x, y);
int r = (argb >>> 16) & 0xFF;
int g = (argb >>> 8) & 0xFF;
int b = argb & 0xFF;
result.set(x, y, (r * 0.3f + g * 0.59f + b * 0.11f) / 255);
}
}
return result;
}
public BufferedImage toBufferedImage(float scale) {
final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int intensity = ((int) (get(x, y) * scale)) & 0xFF;
result.setRGB(x, y, 0xFF000000 | intensity | intensity << 8 | intensity << 16);
}
}
return result;
}
}
}
I am trying to get the x and y value of a point after increasing the distance r. Perhaps there is a better way of calculate the angle phi too, so that I don't need to check in which quadrant the point is. The 0-point is at the half of the width and height of the window. Here is my attempt:
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public final class Laser extends java.applet.Applet implements Runnable{
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point point = new Point(405,100);
Point point1 = new Point(405,100);
public void calc(){
int x = getWidth()/2;
int y = getHeight()/2;
int px = point.x;
int py = point.y;
int px1 = point1.x;
int py1 = point1.y;
double r = 0;
double phi = 0;
// Point is in:
// Quadrant 1
if(px > x && py < y){
r = Math.hypot(px1-x, y-py1);
phi = Math.acos((px1-x)/r)*(180/Math.PI);
}/*
// Quadrant 2
else if(px < x && py < y){
r = Math.hypot(x-px, y-py);
phi = Math.acos((px-x)/r)*(180/Math.PI);
}
// Quadrant 3
else if(px < x && py > y){
r = Math.hypot(x-px, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}
// Quadrant 4
else if(px > x && py > y){
r = Math.hypot(px-x, py-y);
phi = Math.acos((px-x)/r)*(180/Math.PI)+180;
}*/
r += 1;
point1.x = (int) (r*Math.cos(phi));
point1.y = (int) (r*Math.sin(phi));
System.out.println(r+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine(point.x, point.y, point1.x, point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h/2, w, h/2);
g.drawLine(w/2, 0, w/2, h);
}
/*
public void initPoints(){
for(int i = 0; i < pointsStart.length; i++){
int x = (int)(Math.random()*getWidth());
int y = (int)(Math.random()*getHeight());
pointsStart[i] = pointsEnd[i] = new Point(x,y);
}
}
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
//initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try { Thread.sleep(700); }
catch (InterruptedException e) { }
}
}
public void update(Graphics g) {
paint(g);
}
}
You are changing (x,y) to be r from some other point, when it had previously been some distance r' from that point, correct? So why not avoid the trigonometry, and just scale each of the components from that point by r/r'?
Edit: ok, iterate over the pixels along whichever component (x or y) is longer (let's assume it's y); for each xi in (0..x), yi = xi*(y/x), and you plot (xi,yi).
Keep it simple! And use double variables for such computations, I changed it for you.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
public final class Laser extends java.applet.Applet implements Runnable {
private static final long serialVersionUID = -7566644836595581327L;
Thread runner;
int width = 800;
int height = 600;
Point2D.Double point = new Point2D.Double(400, 100);
Point2D.Double point1 = new Point2D.Double(405, 102);
public void calc() {
double px = point.x;
double py = point.y;
double px1 = point1.x;
double py1 = point1.y;
double dx = px1 - px;
double dy = py1 - py;
double len = Math.hypot(dx, dy);
double newlen = len+2;
double coeff = Math.abs((newlen-len)/len);
point1.x += dx * coeff;
point1.y += dy * coeff;
System.out.println(len+";"+point1.x+";"+point1.y);
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
calc();
g.drawLine((int)point.x, (int)point.y, (int)point1.x, (int)point1.y);
int h = getHeight();
int w = getWidth();
g.setColor(Color.GREEN);
g.drawLine(0, h / 2, w, h / 2);
g.drawLine(w / 2, 0, w / 2, h);
}
/*
* public void initPoints(){
*
* for(double i = 0; i < pointsStart.length; i++){ double x =
* (double)(Math.random()*getWidth()); double y =
* (double)(Math.random()*getHeight()); pointsStart[i] = pointsEnd[i] = new
* Point(x,y); }
*
* }
*/
public void start() {
if (runner == null) {
runner = new Thread(this);
setBackground(Color.black);
setSize(width, height);
// initPoints();
runner.start();
}
}
#SuppressWarnings("deprecation")
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(700);
}
catch (InterruptedException e) {
}
}
}
public void update(Graphics g) {
paint(g);
}
}