2016-04-09 13 views
1

Ich bin ziemlich neu in Java Swing und arbeite an einem Leitern und Snaked-Projekt für meinen College-Kurs. Der Ausbilder hat uns angewiesen, ein Spiel zu implementieren, in dem der Spieler genau auswählen kann, wie viele Schlangen auf dem Spielbrett sind und wo die Schlangen sind. So ist es für die Leitern! Ich kann also kein oder mehrere fixe Bilder in meinem Spiel verwenden, so dass der Spieler sie nicht mehr ändern kann.Wie zeichne Schlangen in Swing?

Ich brauche eine Möglichkeit, solche Schlangen und Leitern in meinem Spiel zu zeichnen. Die Frage ist, was ist die beste Option, dies in Java zu tun? Mit welchen Mitteln kann ich vom Benutzer gewünschte Schlangen auf mein Spielbrett zeichnen?

+0

Zeichne auf ein 'BufferedImage' und zeichne es auf ein' JLabel'. Entweder konvertieren Sie es in eine 'ImageIcon' oder überschreiben Sie' paintComponent'. Zumindest mache ich das normalerweise so. http://stackoverflow.com/a/2710035/4434762 hat ein Beispiel. – Sarvadi

+0

Danke für deine Hilfe, lieber Sarvadi, aber ich weiß nicht, wie man die Geometrie einer Schlange zeichnet. Eine Schlange hat mehrere Bogensegmente, und ich habe keine Ahnung, wie ich sie zeichnen soll. – Narges

+0

Ich denke, die beste Option für einfache 2D-Spiele ist die Verwendung von JavaFX Canvas mit dem GraphicsContext. Es ist schneller und vollständiger als Swing's Graphics2D. – Nasso

Antwort

3

Eine Sache, die Sie tun können, ist das Bild um einen bestimmten Winkel drehen, auf diese Weise können Sie Standbilder verwenden und die Fähigkeit, liefern ihre Start- und Endpunkte ändern

Rotate Image

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       try { 
        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(new TestPane()); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException exp) { 
        exp.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private BufferedImage ladder; 
     private double angle; 

     public TestPane() throws IOException { 
      ladder = ImageIO.read(getClass().getResource("Ladder.png")); 
      JSlider slider = new JSlider(0, 100, 0); 
      slider.addChangeListener(new ChangeListener() { 
       @Override 
       public void stateChanged(ChangeEvent e) { 
        angle = (360d * (slider.getValue()/100d)); 
        repaint(); 
       } 
      }); 
      setLayout(new BorderLayout()); 
      add(slider, BorderLayout.SOUTH); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(400, 400); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      applyQualityRenderingHints(g2d); 
      int x = getWidth()/2; 
      int y = getHeight()/2; 
      g2d.setColor(Color.RED); 
      g2d.rotate(Math.toRadians(angle), x, y); 
      g2d.drawImage(ladder, x - (ladder.getWidth()/2), y - ladder.getHeight(), this); 
      g2d.fillOval(x - 3, y - 3, 6, 6); 
      g2d.dispose(); 
     } 

     protected void applyQualityRenderingHints(Graphics2D g2d) { 
      g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
     } 

    } 

} 

Nun, weil Sie den tatsächlichen Graphics Kontext drehen, kann dies sehr schnell sehr kompliziert werden, besonders wenn Sie versuchen, den Standort zu ändern und eine Reihe von Objekten zu drehen

Eine andere Möglichkeit könnte sein, r Otate das Bild als Ganzes, zum Beispiel ...

Rotated Image

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       try { 
        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(new TestPane()); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException exp) { 
        exp.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private BufferedImage ladder; 
     private double angle; 

     public TestPane() throws IOException { 
      ladder = ImageIO.read(getClass().getResource("Ladder.png")); 
      JSlider slider = new JSlider(0, 100, 0); 
      slider.addChangeListener(new ChangeListener() { 
       @Override 
       public void stateChanged(ChangeEvent e) { 
        angle = (360d * (slider.getValue()/100d)); 
        repaint(); 
       } 
      }); 
      setLayout(new BorderLayout()); 
      add(slider, BorderLayout.SOUTH); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(400, 400); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      applyQualityRenderingHints(g2d); 
      int x = getWidth()/2; 
      int y = getHeight()/2; 
      g2d.setColor(Color.RED); 
      BufferedImage rotated = rotate(ladder, angle); 
      g2d.drawImage(rotated, x - (rotated.getWidth()/2), y - (rotated.getHeight()/2), this); 
      g2d.dispose(); 
     } 

     public BufferedImage rotate(BufferedImage image, double byAngle) { 

      double rads = Math.toRadians(byAngle); 
      double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads)); 
      int w = image.getWidth(); 
      int h = image.getHeight(); 
      int newWidth = (int) Math.floor(w * cos + h * sin); 
      int newHeight = (int) Math.floor(h * cos + w * sin); 

      BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); 
      Graphics2D g2d = rotated.createGraphics(); 
      applyQualityRenderingHints(g2d); 
      AffineTransform at = new AffineTransform(); 
      at.translate((newWidth - w)/2, (newHeight - h)/2); 

      int x = w/2; 
      int y = h/2; 

      at.rotate(Math.toRadians(byAngle), x, y); 
      g2d.setTransform(at); 
      g2d.drawImage(image, 0, 0, this); 
      g2d.dispose(); 

      return rotated; 
     } 

     protected void applyQualityRenderingHints(Graphics2D g2d) { 
      g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
     } 

    } 

} 

So oder so, haben Sie einige ernsthafte Management und Mathematik vor dir.

Sie mögen vielleicht einen genaueren Blick auf Painting in AWT and Swing und Performing Custom Painting und 2D Graphics für weitere Details sind

1

Es nehmen viele (viele, viele) diese Frage Freiheitsgrade für die Beantwortung. In der Tat könnte man es als "zu breit" betrachten, da es nicht viel spezifischer ist als "wie kann ich etwas in Swing malen?" (mit "etwas" ist hier eine Schlange oder eine Leiter). Es gibt einen Grund, warum ein bedeutender Teil der Spieleentwicklung nicht nur einfache Programmierung ist, sondern auch das Grafikdesign usw.

Es ist nicht klar, wie sehr die Aufgabe Ihres Kurses genau auf diesen Punkt konzentriert ist. Wenn es sich um einen allgemeinen Informatikkurs handelt, dann ist es wahrscheinlich nicht nötig, dutzende Stunden damit zu verbringen, das Spiel "hübscheste" zu machen. Stattdessen könnte es ausreichend sein, zwischen den Feldern, die die Schlangen/Leitern verbinden sollten, Zeilen zu zeichnen. Grüne Linien für Schlangen, braune Linien für Leitern. Vielleicht sind die Prioritäten jedoch unterschiedlich.


In Bezug auf diese Frage insbesondere, gibt es, grob gesagt, zwei Möglichkeiten:

  • Malen Sie die Schlangen als Bilder
  • Malen Sie die Schlangen als graphische Objekte

MadProgrammer zeigte in his answer den Ansatz der Verwendung von Bildern. Sie können beliebig rotiert und gezeichnet und skaliert werden. Wenn Sie beispielsweise ein Bild mit der Größe 100x1000 haben, können Sie zwei beliebige Punkte aufspannen.Wenn Sie also die Punkte (200,400) und (700,1100) auf dem Bildschirm haben, können Sie eine Ausrichtung und Skalierung für das Bild berechnen, sodass der obere Mittelpunkt Ihres Bildes bei (200,400) und der unteren Mitte liegt Punkt ist bei (700,1100) - was wahrscheinlich eine Anforderung ist, die erscheinen kann, wenn Sie "eine Leiter zeichnen wollen, die an einem Feld beginnt und an einem anderen endet".

Das Problem, das ich in Bezug auf die Schlangen sah, war, dass der "Inhalt" des Bildes vom Anfangs- und Endpunkt abhängen müsste. Nämlich, eine Schlange, die zwischen zwei Feldern, die nahe miteinander bemalt sind, könnte eine völlig andere Form als eine, die zwischen zwei entfernten Feldern gemalt hat.

(In ähnlicher Weise eine Leiter: Die Anzahl der Schritte, die die Leiter haben sollte, würde sicherlich auf den Abstand zwischen den Feldern abhängen, die es verbindet).


Also, ich habe ein paar "Freizeit-Programmierung" hier gemacht, und schuf eine Schlange Malerei Klasse. Der Unterschied, verglichen mit Bildern, ist, dass die Schlangen grafische Objekte sind - insbesondere bestehen sie aus Shape Objekten. Der schwierige Teil ist der Körper der Schlange: Es sollte einige Wellen und eine bestimmte Dicke haben, und die Dicke sollte entlang des Körpers weitgehend konstant sein, mit Ausnahme des Schwanzteils ....

Nochmals: Es gibt viele Freiheitsgrade, und natürlich ist dies nur ein Schnipsel, schnell niedergeschrieben, um (vor allem für mich selbst) zu sehen, wie man dieses Problem des "Zeichnens eines Schlangenkörpers" angehen könnte.

Das Ergebnis ist eine Schlange, wo man um den Kopf und Schwanz zwischen beliebigen Punkten ziehen:

SmallSnake

Einige der Freiheitsgrade, die ich erwähnt werden als (kompilieren Zeit) Variablen zusammengefasst in die Snake Klasse. Man könnte zum Beispiel, stellen Sie die Anzahl der „Wellen“, basierend auf dem Abstand zwischen dem Kopf und dem Schwanz Punkt:

LongSnake

Aber das sind Dinge, die ich zu den echten Künstlern verlassen werden; -)

Der Code ist ein bisschen grob und weitgehend unkommentiert, aber vielleicht jemand findet es hilfreich dennoch:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Path2D; 
import java.awt.geom.Point2D; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class SnakeDrawing 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(() -> createAndShowGUI()); 
    } 

    private static void createAndShowGUI() 
    { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     f.getContentPane().add(new SnakeDrawingPanel()); 

     f.setSize(800, 800); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 

class Snake 
{ 
    private Point2D point0 = new Point2D.Double(100,500); 
    private Point2D point1 = new Point2D.Double(700,500); 

    double bodyWidth = 10; 
    int waves = 4; 
    double waveHeight = 0.05; 
    double tailStart = 0.8; 
    double headLength = 20; 
    double headWidth = 16; 
    double eyeRadius = 6; 
    double irisRadius = 3; 

    private Shape body; 
    private Shape head; 
    private Shape eyeR; 
    private Shape eyeL; 
    private Shape irisR; 
    private Shape irisL; 

    void setPoints(Point2D point0, Point2D point1) 
    { 
     this.point0.setLocation(point0); 
     this.point1.setLocation(point1); 

     AffineTransform at = AffineTransform.getRotateInstance(
      currentAngleRad(), point0.getX(), point0.getY()); 
     at.translate(point0.getX(), point0.getY()); 

     createBody(at); 
     createHead(at); 
    } 

    void draw(Graphics2D g) 
    { 
     g.setColor(new Color(0,128,0)); 
     g.fill(body); 
     g.fill(head); 
     g.setColor(Color.WHITE); 
     g.fill(eyeR); 
     g.fill(eyeL); 
     g.setColor(Color.BLACK); 
     g.fill(irisR); 
     g.fill(irisL); 
    } 

    private void createBody(AffineTransform at) 
    { 
     double distance = point1.distance(point0); 
     int steps = 100; 
     Path2D body = new Path2D.Double(); 
     Point2D previousPoint = null; 
     for (int i=0; i<steps; i++) 
     { 
      double alpha = (double)i/(steps-1); 
      Point2D point = computeCenterPoint(alpha, distance); 
      if (previousPoint != null) 
      { 
       Point2D bodyPoint = 
        computeBodyPoint(alpha, point, previousPoint); 
       if (i==1) 
       { 
        body.moveTo(bodyPoint.getX(), bodyPoint.getY()); 
       } 
       else 
       { 
        body.lineTo(bodyPoint.getX(), bodyPoint.getY()); 
       } 
      } 
      previousPoint = point; 
     } 
     previousPoint = null; 
     for (int i=steps-1; i>=0; i--) 
     { 
      double alpha = (double)i/(steps-1); 
      Point2D point = computeCenterPoint(alpha, distance); 
      if (previousPoint != null) 
      { 
       Point2D bodyPoint = 
        computeBodyPoint(alpha, point, previousPoint); 
       body.lineTo(bodyPoint.getX(), bodyPoint.getY()); 
      } 
      previousPoint = point; 
     } 
     this.body = at.createTransformedShape(body); 
    } 

    private Point2D computeBodyPoint(
     double alpha, Point2D point, Point2D previousPoint) 
    { 
     double dx = point.getX() - previousPoint.getX(); 
     double dy = point.getY() - previousPoint.getY(); 
     double rdx = -dy; 
     double rdy = dx; 
     double d = Math.hypot(dx, dy); 
     double localBodyWidth = bodyWidth; 
     if (alpha > tailStart) 
     { 
      localBodyWidth *= (1 - (alpha - tailStart)/(1.0 - tailStart)); 
     } 
     double px = point.getX() + rdx * (1.0/d) * localBodyWidth; 
     double py = point.getY() + rdy * (1.0/d) * localBodyWidth; 
     return new Point2D.Double(px, py); 
    } 

    private Point2D computeCenterPoint(
     double alpha, double distance) 
    { 
     double r = alpha * Math.PI * 2 * waves; 
     double verticalScaling = 1 - (alpha * 2 - 1) * (alpha * 2 - 1); 
     double y = Math.sin(r) * distance * waveHeight * verticalScaling; 
     double x = alpha * distance; 
     return new Point2D.Double(x,y); 
    } 

    private void createHead(AffineTransform at) 
    { 
     Shape head = new Ellipse2D.Double(
      -headLength, -headWidth, 
      headLength + headLength, 
      headWidth + headWidth); 
     this.head = at.createTransformedShape(head); 

     Shape eyeR = new Ellipse2D.Double(
      -headLength * 0.5 - eyeRadius, 
      -headWidth * 0.6 - eyeRadius, 
      eyeRadius + eyeRadius, 
      eyeRadius + eyeRadius); 
     Shape eyeL = new Ellipse2D.Double(
      -headLength * 0.5 - eyeRadius, 
      headWidth * 0.6 - eyeRadius, 
      eyeRadius + eyeRadius, 
      eyeRadius + eyeRadius); 
     this.eyeR = at.createTransformedShape(eyeR); 
     this.eyeL = at.createTransformedShape(eyeL); 

     Shape irisR = new Ellipse2D.Double(
      -headLength * 0.4 - eyeRadius, 
      -headWidth * 0.6 - irisRadius, 
      irisRadius + irisRadius, 
      irisRadius + irisRadius); 
     Shape irisL = new Ellipse2D.Double(
      -headLength * 0.4 - eyeRadius, 
      headWidth * 0.6 - irisRadius, 
      irisRadius + irisRadius, 
      irisRadius + irisRadius); 
     this.irisR = at.createTransformedShape(irisR); 
     this.irisL = at.createTransformedShape(irisL); 
    } 

    private double currentAngleRad() 
    { 
     double dx = point1.getX() - point0.getX(); 
     double dy = point1.getY() - point0.getY(); 
     double angleRad = Math.atan2(dy, dx); 
     return angleRad; 
    } 
} 

class SnakeDrawingPanel extends JPanel 
    implements MouseListener, MouseMotionListener 
{ 
    private Point2D point0 = new Point2D.Double(100,500); 
    private Point2D point1 = new Point2D.Double(700,500); 
    private Point2D draggedPoint = null; 
    private Snake snake = new Snake(); 

    SnakeDrawingPanel() 
    { 
     addMouseListener(this); 
     addMouseMotionListener(this); 
    } 

    @Override 
    protected void paintComponent(Graphics gr) 
    { 
     super.paintComponent(gr); 
     Graphics2D g = (Graphics2D)gr; 
     g.setRenderingHint(
      RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 

     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     snake.setPoints(point0, point1); 
     snake.draw(g); 
    } 


    @Override 
    public void mouseDragged(MouseEvent e) 
    { 
     if (draggedPoint != null) 
     { 
      draggedPoint.setLocation(e.getPoint()); 
      repaint(); 
     } 
    } 

    @Override 
    public void mouseMoved(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mousePressed(MouseEvent e) 
    { 
     draggedPoint = null; 
     double thresholdSquared = 10*10; 

     if (e.getPoint().distanceSq(point0) < thresholdSquared) 
     { 
      draggedPoint = point0; 
     } 
     if (e.getPoint().distanceSq(point1) < thresholdSquared) 
     { 
      draggedPoint = point1; 
     } 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) 
    { 
     draggedPoint = null; 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseExited(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

} 

EDIT:

Als Beispiel/Verlängerung der Antwort von MadProgrammer, hier ist ein Programm, das eine Methode, die Ihnen ein Bild zwischen zwei vorgegebenen Punkten zeichnen kann.Also, für eine Leiter Bild gegeben, können Sie im Grunde ziehen um die oberen und unteren Mittelpunkt des Bildes:

LadderImage

Zufälligerweise die entsprechende Methode drawImageBetweenPoints aufgerufen:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Point2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class LadderDrawing 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(() -> createAndShowGUI()); 
    } 

    private static void createAndShowGUI() 
    { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     f.getContentPane().add(new LadderDrawingPanel()); 

     f.setSize(800, 800); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 


class LadderDrawingPanel extends JPanel 
    implements MouseListener, MouseMotionListener 
{ 
    private Point2D point0 = new Point2D.Double(300,300); 
    private Point2D point1 = new Point2D.Double(500,700); 
    private Point2D draggedPoint = null; 

    private BufferedImage ladderImage; 

    LadderDrawingPanel() 
    { 
     addMouseListener(this); 
     addMouseMotionListener(this); 

     try 
     { 
      ladderImage = ImageIO.read(new File("ladder.png")); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    protected void paintComponent(Graphics gr) 
    { 
     super.paintComponent(gr); 
     Graphics2D g = (Graphics2D)gr; 
     g.setRenderingHint(
      RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 

     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     g.setColor(Color.RED); 
     paintDot(g, point0, 8); 
     paintDot(g, point1, 8); 

     drawImageBetweenPoints(g, ladderImage, point0, point1); 
    } 

    private static void paintDot(Graphics2D g, Point2D p, double radius) 
    { 
     g.fill(new Ellipse2D.Double(
      p.getX() - radius, p.getY() - radius, 
      radius + radius, radius + radius)); 
    } 

    private static void drawImageBetweenPoints(
     Graphics2D g, BufferedImage image, Point2D p0, Point2D p1) 
    { 
     AffineTransform at = new AffineTransform(); 
     at.concatenate(AffineTransform.getTranslateInstance(
      p0.getX(), p0.getY())); 

     double dx = p1.getX() - p0.getX(); 
     double dy = p1.getY() - p0.getY(); 
     double angleRad = Math.atan2(dy, dx) - Math.PI * 0.5; 
     at.concatenate(AffineTransform.getRotateInstance(angleRad)); 

     double distance = p1.distance(p0); 
     double scalingY = distance/image.getHeight(); 

     // Default: Uniform scaling 
     double scalingX = scalingY; 

     // For keeping the width of the image 
     //scalingX = 1.0; 

     // For scaling to a fixed width: 
     //double desiredWidth = 50; 
     //scalingX = desiredWidth/image.getWidth(); 

     at.concatenate(AffineTransform.getScaleInstance(scalingX, scalingY)); 

     at.concatenate(AffineTransform.getTranslateInstance(
      -image.getWidth() * 0.5, 0)); 

     AffineTransform oldAT = g.getTransform(); 
     g.transform(at); 
     g.drawImage(image, 0, 0, null); 
     g.setTransform(oldAT); 
    } 


    @Override 
    public void mouseDragged(MouseEvent e) 
    { 
     if (draggedPoint != null) 
     { 
      draggedPoint.setLocation(e.getPoint()); 
      repaint(); 
     } 
    } 

    @Override 
    public void mouseMoved(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mousePressed(MouseEvent e) 
    { 
     draggedPoint = null; 
     double thresholdSquared = 10*10; 

     if (e.getPoint().distanceSq(point0) < thresholdSquared) 
     { 
      draggedPoint = point0; 
     } 
     if (e.getPoint().distanceSq(point1) < thresholdSquared) 
     { 
      draggedPoint = point1; 
     } 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) 
    { 
     draggedPoint = null; 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseExited(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

} 

Wieder Ich denke, dass eine manuelle Zeichnung flexibler sein kann (und vor allem für die Leiter, nicht viel schwieriger), weil Sie die Anzahl der Schritte der Leiter dynamisch basierend auf der Entfernung der Punkte anpassen können. Zum Beispiel:

LadderManual01

LadderManual02

Es läuft darauf hinaus, ein wenig Mathematik Festlegung der Positionen der Stäbe und Schritte zur Berechnung und ein wenig mit Strichen und Formen spielen:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.Stroke; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.awt.geom.Point2D; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class LadderDrawingManual 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(() -> createAndShowGUI()); 
    } 

    private static void createAndShowGUI() 
    { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     f.getContentPane().add(new LadderDrawingManualPanel()); 

     f.setSize(800, 800); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 


class LadderDrawingManualPanel extends JPanel 
    implements MouseListener, MouseMotionListener 
{ 
    private Point2D point0 = new Point2D.Double(300,300); 
    private Point2D point1 = new Point2D.Double(500,700); 
    private Point2D draggedPoint = null; 

    LadderDrawingManualPanel() 
    { 
     addMouseListener(this); 
     addMouseMotionListener(this); 
    } 

    @Override 
    protected void paintComponent(Graphics gr) 
    { 
     super.paintComponent(gr); 
     Graphics2D g = (Graphics2D)gr; 
     g.setRenderingHint(
      RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 

     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     g.setColor(Color.RED); 
     paintDot(g, point0, 8); 
     paintDot(g, point1, 8); 

     drawLadderBetweenPoints(g, point0, point1); 
    } 

    private static void paintDot(Graphics2D g, Point2D p, double radius) 
    { 
     g.fill(new Ellipse2D.Double(
      p.getX() - radius, p.getY() - radius, 
      radius + radius, radius + radius)); 
    } 

    private static void drawLadderBetweenPoints(
     Graphics2D g, Point2D p0, Point2D p1) 
    { 
     final double ladderWidth = 40; 
     final double distanceBetweenSteps = 30; 
     final double barWidth = 5; 

     double dx = p1.getX() - p0.getX(); 
     double dy = p1.getY() - p0.getY(); 
     double distance = p1.distance(p0); 

     double dirX = dx/distance; 
     double dirY = dy/distance; 

     double offsetX = dirY * ladderWidth * 0.5; 
     double offsetY = -dirX * ladderWidth * 0.5; 

     Line2D lineR = new Line2D.Double(
      p0.getX() + offsetX, 
      p0.getY() + offsetY, 
      p1.getX() + offsetX, 
      p1.getY() + offsetY); 

     Line2D lineL = new Line2D.Double(
      p0.getX() - offsetX, 
      p0.getY() - offsetY, 
      p1.getX() - offsetX, 
      p1.getY() - offsetY); 

     drawBar(g, lineL, barWidth); 
     drawBar(g, lineR, barWidth); 

     int numSteps = (int)(distance/distanceBetweenSteps); 
     for (int i=0; i<numSteps; i++) 
     { 
      double stepOffsetX = (i+1) * distanceBetweenSteps; 
      double stepOffsetY = (i+1) * distanceBetweenSteps; 

      Line2D step = new Line2D.Double(
       p0.getX() + stepOffsetX * dirX - offsetX, 
       p0.getY() + stepOffsetY * dirY - offsetY, 
       p0.getX() + stepOffsetX * dirX + offsetX, 
       p0.getY() + stepOffsetY * dirY + offsetY); 
      drawBar(g, step, barWidth); 
     } 
    } 

    private static void drawBar(Graphics2D g, Line2D line, double barWidth) 
    { 
     Stroke stroke = new BasicStroke(
      (float)barWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 
     Shape bar = stroke.createStrokedShape(line); 
     g.setColor(new Color(200,100,0)); 
     g.fill(bar); 
     g.setColor(Color.BLACK); 
     g.draw(bar); 
    } 


    @Override 
    public void mouseDragged(MouseEvent e) 
    { 
     if (draggedPoint != null) 
     { 
      draggedPoint.setLocation(e.getPoint()); 
      repaint(); 
     } 
    } 

    @Override 
    public void mouseMoved(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mousePressed(MouseEvent e) 
    { 
     draggedPoint = null; 
     double thresholdSquared = 10*10; 

     if (e.getPoint().distanceSq(point0) < thresholdSquared) 
     { 
      draggedPoint = point0; 
     } 
     if (e.getPoint().distanceSq(point1) < thresholdSquared) 
     { 
      draggedPoint = point1; 
     } 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) 
    { 
     draggedPoint = null; 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

    @Override 
    public void mouseExited(MouseEvent e) 
    { 
     // Nothing to do here 
    } 

}