I am writing a pentomino game, but there was a problem with moving the pieces. The shapes move, but the coordinates of the polygon borders with each move do not actually correspond to the polygon borders, and moving the shapes becomes impossible.
That's what I did:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
public class MyPanel extends JFrame implements MouseListener, MouseMotionListener {
Boolean isPressed = false;
JPanel mainPane;
Container contentPane;
Point offset;
ArrayList<Polygon> polygons = new ArrayList<Polygon>();
Polygon fig1 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig2 = new Polygon(new int[]{170, 250, 250, 210, 210, 170, 170, 130, 130, 170}, new int[]{80, 80, 120, 120, 200, 200, 160, 160, 120, 120}, 10);
Polygon fig3 = new Polygon(new int[]{370, 410, 410, 330, 330, 370}, new int[]{90, 90, 200, 200, 160, 160}, 6);
/*Polygon fig4 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig5 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig6 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig7 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig8 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig9 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig10 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig11 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);
Polygon fig12 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4);*/
int x, y;
MyPanel(){
polygons.add(fig1);
polygons.add(fig2);
polygons.add(fig3);
mainPane = new JPanel(){
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(Shape fig: polygons){
g2.setColor(Color.BLUE);
g2.fill(fig);
}
}
};
contentPane = this.getContentPane();
contentPane.add(mainPane);
mainPane.setLayout(null);
setVisible(true);
setSize(1000, 600);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
mainPane.addMouseListener(this);
mainPane.addMouseMotionListener(this);
}
public void mousePressed(MouseEvent e) {
for(Polygon polygon: polygons) {
if (polygon.getBounds().contains(e.getPoint())) {
//offset = new Point(e.getPoint().x - polygon.getBounds().x, e.getPoint().y - polygon.getBounds().y);
x = e.getX();
y = e.getY();
}
}
}
public void mouseClicked(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseDragged(MouseEvent e) {
if(e.getSource() == mainPane) {
for(Polygon polygon: polygons) {
if (polygon.getBounds().contains(x, y)) {
int dx = e.getX() - x;
int dy = e.getY() - y;
for (int i = 0; i < polygon.npoints; i ) {
polygon.xpoints[i] = dx;
polygon.ypoints[i] = dy;
repaint();
}
x = dx;
y = dy;
}
}
}
}
public void mouseMoved(MouseEvent e){}
}
I understand that the problem lies somewhere here:
public void mouseDragged(MouseEvent e) {
if(e.getSource() == mainPane) {
for(Polygon polygon: polygons) {
if (polygon.getBounds().contains(x, y)) {
int dx = e.getX() - x;
int dy = e.getY() - y;
for (int i = 0; i < polygon.npoints; i ) {
polygon.xpoints[i] = dx;
polygon.ypoints[i] = dy;
repaint();
}
x = dx;
y = dy;
}
}
}
}
But I do not understand how to solve it, please tell me what is the problem.
CodePudding user response:
The problem
The Polygon
class stores the calculated bounding box (instance of Rectangle
), so it must not be re-calculated every time it is needed. The cached bounding box is not re-calculated if the coordinates of the Polygon are changed directly (xpoints
and ypoints
).
Solutions:
use the
translate()
method of Polygon to translate its points - it will clear the cached bounding box, forcing it to be re-calculated; oruse the
invalidate()
method ofPolygon
, after changing all points, to delete the cached bounding box and force its re-calculation.
IMO the first point should be preferred: no loop needed, better describes the intention.
Notes:
- there is no need to call
repaint()
for every changed coordinate point inside the loop - it would suffice to call it once after all points whee moved - usingtranslate
, there is no need for the loop at all, butrepaint()
must still be called once; - I would also create a field to store the Polygon being clicked at in the
mousePressed
method, and only move that Polygon when the mouse is dragged; - IMHO it is an error to have the coordinates and
npoints
declaredpublic
!