Есть ли способ нарисовать границы, которые не являются прямоугольниками в java размах? - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь нарисовать границы для персонажа, которого я перемещаю на JFrame. Я знаю, как рисовать прямоугольники, чтобы установить sh границы, но как я могу это сделать, если область, для которой я хочу нарисовать границы, не является прямоугольником?


Скажем, например, я хочу переместите зеленый круг вокруг квадрата, но синий ромб представляет границы, и круг не может go преодолеть эти границы. Как я мог это сделать?

enter image description here

Ответы [ 3 ]

1 голос
/ 06 апреля 2020

Это то, что я использую для столкновения линий и точек:

http://www.jeffreythompson.org/collision-detection/line-circle.php

это довольно математично, но работает хорошо и не т багги

0 голосов
/ 07 апреля 2020

Я создал простой GUI, чтобы продемонстрировать, как использовать границу многоугольника в Swing GUI. Вот GUI.

Polygon Boundary

Вы не можете видеть на картинке, но вы можете взять зеленый круг (игрока) с помощью мыши и перетащите его в любое место внутри голубого алмаза (границы). Код не позволит вам перетащить игрока за границу.

Вот что я сделал.

  1. Я создал два класса моделей. Один для границы, а другой для игрока. Я использовал эту логическую модель для рисования в представлении и выполнения вычислений в слушателе мыши. Это приложение модель / вид / контроллер .

  2. Я создал простой Swing GUI с панелью для рисования. Я рассчитал, где будет находиться начало овала, чтобы я мог сохранить центральную точку и радиус в модели.

  3. Я создал класс слушателя мыши для прослушивания нажатия и отпускания мыши .

А вот и код. Надеюсь, не так много, чтобы объяснить. Класс Polygon имеет метод, содержащий проверку того, находится ли прямоугольник полностью внутри многоугольника. Я преобразовал круг в прямоугольник в слушателе, чтобы использовать этот метод.

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

public class PolygonBoundary implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new PolygonBoundary());
    }

    private Boundary boundary;

    private Dimension dpSize;

    private Player player;

    public PolygonBoundary() {
        this.dpSize = new Dimension(400, 400);

        Polygon polygon = new Polygon();
        polygon.addPoint(200, 0);
        polygon.addPoint(0, 200);
        polygon.addPoint(200, 400);
        polygon.addPoint(400, 200);
        this.boundary = new Boundary(polygon, Color.BLUE);

        this.player = new Player(200, 200, 24, Color.GREEN);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Polygon Boundary");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DrawingPanel drawingPanel = 
                new DrawingPanel(dpSize, boundary, player);

        frame.add(drawingPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private Boundary boundary;

        private Player player;

        public DrawingPanel(Dimension size, Boundary boundary, 
                Player player) {
            this.boundary = boundary;
            this.player = player;
            this.setPreferredSize(size);
            Border border = BorderFactory.createLineBorder(
                    Color.BLACK, 4);
            this.setBorder(border);
            PlayerMotion playerMotion = 
                    new PlayerMotion(this, boundary, player);
            this.addMouseListener(playerMotion);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(boundary.getColor());
            g2d.setStroke(new BasicStroke(4f));
            g2d.drawPolygon(boundary.getPolygon());

            g2d.setColor(player.getColor());
            Point center = player.getCenter();
            int radius = player.getRadius();
            int diameter = radius + radius;
            g2d.drawOval(center.x - radius, center.y - radius, 
                    diameter, diameter);
        }
    }

    public class PlayerMotion implements MouseListener {

        private Boundary boundary;

        private JPanel panel;

        private Player player;

        private Point originalPoint;

        public PlayerMotion(JPanel panel, Boundary boundary, 
                Player player) {
            this.panel = panel;
            this.boundary = boundary;
            this.player = player;
        }

        @Override
        public void mouseClicked(MouseEvent event) {

        }

        @Override
        public void mousePressed(MouseEvent event) {
            Point center = player.getCenter();
            int radius = player.getRadius();
            Rectangle2D r2d = createRectangle(center, radius);
            if (r2d.contains(event.getPoint())) {
                originalPoint = event.getPoint();
            }
        }

        @Override
        public void mouseReleased(MouseEvent event) {
            if (originalPoint == null) {
                return;
            }

            Point endPoint = event.getPoint();

            Point center = player.getCenter();
            int radius = player.getRadius();
            int newX = center.x - originalPoint.x + endPoint.x;
            int newY = center.y - originalPoint.y + endPoint.y;
            Point newPoint = new Point(newX, newY);
            Rectangle2D r2d = createRectangle(newPoint, radius);

            Polygon polygon = boundary.getPolygon();

            if (polygon.contains(r2d)) {
                player.setCenter(newPoint);
                panel.repaint();
            }

            originalPoint = null;
        }

        private Rectangle2D createRectangle(Point center, int radius) {
            double dx = center.x - radius;
            double dy = center.y - radius;
            double d = radius + radius;
            Rectangle2D r2d = new Rectangle2D.Double(dx, dy, d, d);
            return r2d;
        }

        @Override
        public void mouseEntered(MouseEvent event) {

        }

        @Override
        public void mouseExited(MouseEvent event) {

        }

    }

    public class Boundary {

        private final Color color;

        private final Polygon polygon;

        public Boundary(Polygon polygon, Color color) {
            this.polygon = polygon;
            this.color = color;
        }

        public Polygon getPolygon() {
            return polygon;
        }

        public Color getColor() {
            return color;
        }

    }

    public class Player {

        private final int radius;

        private final Color color;

        private Point center;

        public Player(int x, int y, int radius, Color color) {
            this.center = new Point(x, y);
            this.radius = radius;
            this.color = color;
        }

        public int getRadius() {
            return radius;
        }

        public Point getCenter() {
            return center;
        }

        public void setCenter(Point center) {
            this.center = center;
        }

        public Color getColor() {
            return color;
        }

    }

}
0 голосов
/ 06 апреля 2020

Просто обработайте ваш круг как прямоугольник и подтвердите, если круг находится внутри вашего ромба с методом contains, равным Rectangle ( См. Документы ). Малый урезан:

private Rectangle rect = new Rectangle(25, 25, 450, 450);
private Rectangle circle = new Rectangle(250, 250, 50, 50);

if(rect.contains(tmp)) {
   // True, if the circle does not touch any square-line
}

Полный пример кода:

package circlemoving;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.*;
import javax.swing.*;

public class CircleMoving {

    public static void main(String[] args) {
        MainPanel mp = new MainPanel();
        JFrame jFrame = new JFrame();
        jFrame.add(mp);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
        jFrame.pack();

        jFrame.addKeyListener(new KeyListener() {
            @Override public void keyTyped(KeyEvent e) {}
            @Override public void keyReleased(KeyEvent e) {}

            @Override
            public void keyPressed(KeyEvent e) {
                mp.update(e.getKeyCode());
            }            
        });
    }

    private static class MainPanel extends JPanel {
        private Rectangle rect = new Rectangle(25, 25, 450, 450);
        private Rectangle circle = new Rectangle(250, 250, 50, 50);

        public MainPanel() {
            setPreferredSize(new Dimension(500, 500));
            repaint();
        }

        @Override
        public void paintComponent(Graphics grahpics) {
            super.paintComponent(grahpics);

            Graphics2D g2d = (Graphics2D) grahpics;

            g2d.setStroke(new BasicStroke(1));
            g2d.setColor(Color.BLUE);
            g2d.drawRect(rect.x, rect.y, rect.width, rect.height);

            g2d.setStroke(new BasicStroke(1));
            g2d.setColor(Color.RED);
            g2d.drawOval(circle.x, circle.y, circle.width, circle.width);
        }

        public void update(int keyCode) {
            int tmpX = circle.x;
            int tmpY = circle.y;

            switch (keyCode) {
                case 39:
                    tmpX = circle.x + 3;
                    break;
                case 37:
                    tmpX = circle.x - 3;
                    break;
                case 38:
                    tmpY = circle.y - 3;
                    break;
                case 40:
                    tmpY = circle.y + 3;
                    break;
                default:
                    break;
            }

            Rectangle tmp = new Rectangle(tmpX, tmpY, circle.width, circle.height);

            if(rect.contains(tmp)) {
                circle.x = tmpX;
                circle.y = tmpY;

                repaint();
            }
        }
    }
}

Результат: enter image description here

...