Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import javax.swing.JPanel;
- import javax.swing.JFrame;
- import java.awt.Graphics;
- import java.awt.Dimension;
- import java.util.List;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.awt.Color;
- import java.awt.event.MouseAdapter;
- import java.awt.event.MouseEvent;
- class Vector {
- private final double x,y;
- Vector(double x, double y) {
- this.x = x;
- this.y = y;
- }
- public double getX() {
- return x;
- }
- public double getY() {
- return y;
- }
- public Vector addX(double dx) {
- return new Vector(x+dx, y);
- }
- public Vector addY(double dy) {
- return new Vector(x, y+dy);
- }
- public Vector add(Vector v) {
- return new Vector(x+v.x, y+v.y);
- }
- public Vector sub(Vector v) {
- return new Vector(x-v.x, y-v.y);
- }
- public Vector mul(double d) {
- return new Vector(x*d, y*d);
- }
- public Vector div(double d) {
- return new Vector(x/d, y/d);
- }
- public Vector neg() {
- return new Vector(-x, -y);
- }
- public Vector negX() {
- return new Vector(-x, y);
- }
- public Vector negY() {
- return new Vector(x, -y);
- }
- public double angle() {
- return Math.atan2(y, x);
- }
- public double length() {
- return Math.sqrt(x*x+y*y);
- }
- public double distance(Vector v) {
- return sub(v).length();
- }
- public Vector normalize() {
- double length = length();
- if(length == 1) return this;
- else if(length == 0) return new Vector(1,0);
- else return new Vector(x/length, y/length);
- }
- public Vector rotate90() {
- return new Vector(-y, x);
- }
- public Vector rotate(double angle) {
- double sin = Math.sin(angle);
- double cos = Math.cos(angle);
- return new Vector(x*cos - y*sin,
- x*sin + y*cos);
- }
- public Vector rotate(Vector v) {
- v = v.normalize();
- return new Vector(x*v.x - y*v.y,
- x*v.y + y*v.x);
- }
- public Vector oppositeRotVector() {
- return new Vector(x, -y).normalize();
- }
- @Override
- public String toString() {
- return "Vector("+x+", "+y+")";
- }
- }
- abstract class Shape {
- private Vector pos;
- private Vector velocity;
- Shape(Vector pos) {
- this.pos = pos;
- this.velocity = new Vector(0,0);
- }
- abstract public double getArea();
- abstract public boolean collides(Circle c);
- abstract public boolean contains(Vector v);
- public Vector getPos() {
- return pos;
- }
- public Vector getVelocity() {
- return velocity;
- }
- public void setVelocity(Vector v) {
- this.velocity = v;
- }
- public void move(Vector v) {
- pos = pos.add(v);
- }
- public void accelerate(Vector v) {
- velocity = velocity.add(v);
- }
- public void update(double time) {
- pos = pos.add(velocity.mul(time));
- }
- abstract public void paint(Graphics g);
- }
- class Circle extends Shape {
- private double radius;
- private boolean moveable = true;
- Circle(Vector pos, double radius) {
- super(pos);
- this.radius = radius;
- }
- public void setMoveable(boolean moveable) {
- this.moveable = moveable;
- }
- public boolean isMoveable() {
- return moveable;
- }
- public double getRadius() {
- return radius;
- }
- public double getArea() {
- return Math.PI*radius*radius;
- }
- public boolean collides(Circle c) {
- return getPos().sub(c.getPos()).length() <= radius+c.radius;
- }
- public boolean contains(Vector v) {
- return v.sub(getPos()).length() <= radius;
- }
- public void collisionCheck(List<Shape> shapes, double time) {
- boolean movedBack = false;
- for(int i = 0; i < shapes.size(); i++) {
- Shape shape = shapes.get(i);
- if(shape != this && shape.collides(this)) {
- if(!movedBack) {
- move(getVelocity().mul(time).neg());
- movedBack = true;
- }
- if(shape instanceof Circle) reflect((Circle)shape);
- else if(shape instanceof Rectangle) reflect((Rectangle)shape);
- else setVelocity(getVelocity().neg());
- }
- }
- }
- public void reflect(Rectangle r) {
- if(getPos().getX() >= r.getPos().getX() && getPos().getX() < r.getPos().getX()+r.getWidth()) {
- setVelocity(getVelocity().negY());
- } else if(getPos().getY() >= r.getPos().getY() && getPos().getY() < r.getPos().getY()+r.getHeight()) {
- setVelocity(getVelocity().negX());
- } else {
- Vector corner = null;
- for(Vector c: r.getCorners()) {
- if(corner == null) corner = c;
- else if(getPos().distance(c) < getPos().distance(corner)) {
- corner = c;
- }
- }
- Circle c = new Circle(corner, 1);
- c.setMoveable(false);
- reflect(c);
- }
- }
- public void reflect(Circle c) {
- Vector tangent = c.getPos().sub(getPos()).rotate90().normalize();
- Vector rotVector = tangent.oppositeRotVector();
- Vector vel1 = getVelocity().rotate(rotVector);
- Vector vel2 = c.getVelocity().rotate(rotVector);
- double v1 = vel1.getY();
- double v2 = vel2.getY();
- double m1 = getArea();
- double m2 = c.getArea();
- double speedm = 2*(m1*v1+m2*v2)/(m2+m1);
- double newV1 = speedm-v1;
- double newV2 = speedm-v2;
- if(!isMoveable()) {
- newV1 = v1;
- newV2 = -v2;
- } else if(!c.isMoveable()) {
- newV1 = -v1;
- newV2 = v2;
- }
- vel1 = new Vector(vel1.getX(), newV1).rotate(tangent);
- vel2 = new Vector(vel2.getX(), newV2).rotate(tangent);
- setVelocity(vel1);
- c.setVelocity(vel2);
- }
- public void paint(Graphics g) {
- g.fillOval((int)(getPos().getX()-radius),
- (int)(getPos().getY()-radius),
- (int)(radius*2), (int)(radius*2));
- }
- }
- class Rectangle extends Shape {
- private double width, height;
- Rectangle(Vector pos, double width, double height) {
- super(pos);
- this.width = width;
- this.height = height;
- }
- public double getWidth() {
- return width;
- }
- public double getHeight() {
- return height;
- }
- public double getArea() {
- return width*height;
- }
- public List<Vector> getCorners() {
- return Arrays.asList(getPos(), getPos().addX(width),
- getPos().addX(width).addY(height), getPos().addY(height));
- }
- public boolean contains(Vector v) {
- return !(v.getX() < getPos().getX() || v.getX() >= getPos().getX()+width ||
- v.getY() < getPos().getY() || v.getY() >= getPos().getY()+height);
- }
- public boolean collides(Circle c) {
- for(Vector corner: getCorners()) {
- if(c.contains(corner)) {
- return true;
- }
- }
- Vector cPos = c.getPos();
- return (cPos.getX() >= getPos().getX() &&
- cPos.getX() < getPos().getX()+width &&
- cPos.getY()+c.getRadius() >= getPos().getY() &&
- cPos.getY()-c.getRadius() < getPos().getY()+height) ||
- (cPos.getX()+c.getRadius() >= getPos().getX() &&
- cPos.getX()-c.getRadius() < getPos().getX()+width &&
- cPos.getY() >= getPos().getY() &&
- cPos.getY() < getPos().getY()+height);
- }
- public void paint(Graphics g) {
- g.fillRect((int)getPos().getX(),
- (int)getPos().getY(),
- (int)width, (int)height);
- }
- }
- public class Collision extends JPanel {
- ArrayList<Shape> shapes = new ArrayList<Shape>();
- Vector mousePressedPos = null;
- Vector mousePos = null;
- private MouseAdapter mouseAdapter = new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- mousePressedPos = new Vector(e.getX(), e.getY());
- mousePos = null;
- }
- public void mouseReleased(MouseEvent e) {
- if(mousePos != null) {
- Circle ball = new Circle(mousePressedPos, 20);
- for(Shape shape: shapes) {
- if(shape.collides(ball)) {
- return;
- }
- }
- ball.setVelocity(mousePos.sub(mousePressedPos));
- addShapes(ball);
- }
- }
- public void mouseDragged(MouseEvent e) {
- mousePos = new Vector(e.getX(), e.getY());
- }
- };
- public Collision() {
- addMouseListener(mouseAdapter);
- addMouseMotionListener(mouseAdapter);
- }
- public void addShapes(Shape ... shapes) {
- for(Shape s: shapes) this.shapes.add(s);
- repaint();
- }
- public void start() throws Exception {
- long lastTime = System.nanoTime();
- while(true) {
- long currentTime = System.nanoTime();
- double time = (currentTime - lastTime)/1e9;
- lastTime = currentTime;
- for(int i=0; i<shapes.size(); i++) {
- Shape s = shapes.get(i);
- s.update(time);
- if(s instanceof Circle) {
- ((Circle)s).collisionCheck(shapes, time);
- }
- }
- repaint();
- Thread.sleep(1);
- }
- }
- public static void main(String[] args) throws Exception {
- JFrame frame = new JFrame();
- Collision panel = new Collision();
- Rectangle r1 = new Rectangle(new Vector(100,100), 200, 300);
- Circle c1 = new Circle(new Vector(400,200), 50);
- c1.setMoveable(false);
- panel.addShapes(r1,c1);
- panel.setPreferredSize(new Dimension(800,600));
- frame.add(panel);
- frame.pack();
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setVisible(true);
- panel.start();
- }
- @Override
- public void paint(Graphics g) {
- g.setColor(Color.WHITE);
- g.fillRect(0,0,getWidth(),getHeight());
- g.setColor(Color.BLACK);
- for(int i=0; i < shapes.size(); i++) {
- shapes.get(i).paint(g);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement