diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/Catamarans.iml b/.idea/Catamarans.iml
new file mode 100644
index 0000000..b107a2d
--- /dev/null
+++ b/.idea/Catamarans.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..07115cd
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..f9b8061
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/30px_arrow_down.png b/Resources/30px_arrow_down.png
new file mode 100644
index 0000000..7aa3255
Binary files /dev/null and b/Resources/30px_arrow_down.png differ
diff --git a/Resources/30px_arrow_left.png b/Resources/30px_arrow_left.png
new file mode 100644
index 0000000..9a3dfa2
Binary files /dev/null and b/Resources/30px_arrow_left.png differ
diff --git a/Resources/30px_arrow_right.png b/Resources/30px_arrow_right.png
new file mode 100644
index 0000000..0f06fd0
Binary files /dev/null and b/Resources/30px_arrow_right.png differ
diff --git a/Resources/30px_arrow_up.png b/Resources/30px_arrow_up.png
new file mode 100644
index 0000000..67ae4bc
Binary files /dev/null and b/Resources/30px_arrow_up.png differ
diff --git a/src/DrawingBoat.java b/src/DrawingBoat.java
new file mode 100644
index 0000000..447fd76
--- /dev/null
+++ b/src/DrawingBoat.java
@@ -0,0 +1,199 @@
+package src;
+
+import java.awt.*;
+import java.util.Random;
+
+public class DrawingBoat {
+ // Объект-сущность лодки
+ public EntityBoat entityBoat;
+ // Объект отрисовки весел лодки
+ private DrawingBoatPaddle __drawingBoatPaddle;
+ // Координата X верхнего левого угла лодки
+ private float __startPosX;
+ // Координата Y верхнего левого угла лодки
+ private float __startPosY;
+ // Ширина отрисовки лодки
+ private final int __boatWidth = 100;
+ // Высота отрисовки лодки
+ private final int __boatHeight = 60;
+ // Ширина области отрисовки
+ private Integer __pictureWidth = null;
+ // Высота области отрисовки
+ private Integer __pictureHeight = null;
+
+
+ // Инициализатор класса
+ public void Init(int speed, float weight, Color bodyColor) {
+ entityBoat = new EntityBoat();
+ entityBoat.Init(speed, weight, bodyColor);
+ __drawingBoatPaddle = new DrawingBoatPaddle();
+ SetPaddlesCount();
+ }
+
+ // Метод для установки количества весел лодки
+ public void SetPaddlesCount() {
+ Random rnd = new Random();
+ int paddlesCount = rnd.nextInt(1, 4);
+ __drawingBoatPaddle.SetEnumNumber(paddlesCount);
+ }
+
+ // Метод установки позиции и размеров объекта
+ public void SetPosition(int x, int y, int width, int height) {
+ if (x > 0 && x < width - __boatWidth && y > 0 && y < height - __boatHeight) {
+ __startPosX = x;
+ __startPosY = y;
+ __pictureWidth = width;
+ __pictureHeight = height;
+ }
+ }
+
+ // Метод перемешения обхекта
+ public void MoveTransport(EnumDirection enumDirection) {
+ // Если не установлен объект-сущность - выходим
+ if (entityBoat == null) {
+ return;
+ }
+
+ // Если не назначены границы области отрисовки - выходим
+ if (__pictureWidth == null || __pictureHeight == null) {
+ return;
+ }
+
+ // Проверяем возможность перемещения и перемещаем обхект по заданному направлению
+ switch (enumDirection) {
+ case Right:
+ if (__startPosX + __boatWidth + entityBoat.Step() < __pictureWidth) {
+ __startPosX += entityBoat.Step();
+ }
+ break;
+ case Left:
+ if (__startPosX - entityBoat.Step() > 0) {
+ __startPosX -= entityBoat.Step();
+ }
+ break;
+ case Up:
+ if (__startPosY - entityBoat.Step() > 0) {
+ __startPosY -= entityBoat.Step();
+ }
+ break;
+ case Down:
+ if (__startPosY + __boatHeight + entityBoat.Step() < __pictureHeight) {
+ __startPosY += entityBoat.Step();
+ }
+ break;
+ }
+ }
+
+ // Метод отрисовки объекта
+ public void DrawTransport(Graphics g) {
+ // Если не установлен объект-сущность - выходим
+ if (entityBoat == null) {
+ return;
+ }
+
+ // Если координаты не валидны или размер области отрисовки не установлен - выходим
+ if (__startPosX < 0 || __startPosY < 0
+ || __pictureHeight == null || __pictureWidth == null) {
+ return;
+ }
+
+ Graphics2D g2d = (Graphics2D) g;
+
+ int height = __boatHeight - 30;
+
+ // Промежуточные переменные, чтобы не писать каждый раз (int)
+ int startX = (int) __startPosX;
+ int startY = (int) __startPosY + 15;
+
+ // Рисуем корпус лодки
+ // Задаем цвет корпуса
+ g2d.setColor(entityBoat.BodyColor);
+
+ // Массив координат X для полигона корпуса лодки
+ int[] xPoints = new int[]{
+ startX,
+ startX + __boatWidth - __boatWidth / 4,
+ startX + __boatWidth,
+ startX + __boatWidth - __boatWidth / 4,
+ startX
+ };
+
+ // Массив координат Y для полигона корпуса лодки
+ int[] yPoints = new int[]{
+ startY,
+ startY,
+ startY + height / 2,
+ startY + height,
+ startY + height
+ };
+
+ // Заполняем полигон
+ g2d.fillPolygon(xPoints, yPoints, 5);
+
+ // Рисуем окантовку
+ g2d.setColor(Color.BLACK);
+ g2d.drawPolygon(xPoints, yPoints, 5);
+
+ // Рисуем палубу
+ // Левая дуга
+ g2d.drawArc(
+ startX + __boatWidth / 10,
+ startY + height / 5,
+ height - height / 5 - height / 5,
+ height - height / 5 - height / 5,
+ 90, 180
+ );
+
+ // Правая дуга
+ g2d.drawArc(
+ startX + __boatWidth - __boatWidth / 4 - __boatWidth / 10 - height / 5,
+ startY + height / 5,
+ height - height / 5 - height / 5,
+ height - height / 5 - height / 5,
+ -90, 180
+ );
+
+ // Верхняя линия
+ g2d.drawLine(
+ startX + __boatWidth / 10 + (height - height / 2) / 2,
+ startY + height / 5,
+ startX + __boatWidth - __boatWidth / 4 - __boatWidth / 10 - height / 5 + (height - height / 2) / 2,
+ startY + height / 5
+ );
+
+ // Нижняя линия
+ g2d.drawLine(
+ startX + __boatWidth / 10 + (height - height / 2) / 2,
+ startY + height - height / 5,
+ startX + __boatWidth - __boatWidth / 4 - __boatWidth / 10 - height / 5 + (height - height / 2) / 2,
+ startY + height - height / 5
+ );
+
+ // Отрисовка весел лодки
+ __drawingBoatPaddle.DrawBoatPaddles(g, entityBoat.BodyColor, __startPosX, startY, __boatWidth, height);
+ }
+
+ // Метод изменения границ области отрисовки
+ public void ChangeBorders(int width, int height) {
+ __pictureWidth = width;
+ __pictureHeight = height;
+
+ // Если новые размеры области отрисовки меньше, чем размеры отрисовки лодки,
+ // то обнуляем размеры области отрисовки - рисовать не можем
+ if (__pictureWidth <= __boatWidth || __pictureHeight <= __boatHeight) {
+ __pictureWidth = null;
+ __pictureHeight = null;
+ return;
+ }
+
+ // Если выходим за правую границу, то сдвигаемся влево
+ if (__startPosX + __boatWidth > __pictureWidth) {
+ __startPosX = __pictureWidth - __boatWidth;
+ }
+
+ // Если выходим за нижнюю границу, то сдвигаемся вверх
+ if (__startPosY + __boatHeight > __pictureHeight) {
+ __startPosY = __pictureHeight - __boatHeight;
+ }
+ }
+}
diff --git a/src/DrawingBoatPaddle.java b/src/DrawingBoatPaddle.java
new file mode 100644
index 0000000..a5f2fe8
--- /dev/null
+++ b/src/DrawingBoatPaddle.java
@@ -0,0 +1,49 @@
+package src;
+
+import java.awt.*;
+
+public class DrawingBoatPaddle {
+ private EnumPaddlesCount __enumPaddlesCount;
+ private final BasicStroke __paddleStroke = new BasicStroke(3);
+
+ public void SetEnumNumber(int paddlesCount) {
+ for (EnumPaddlesCount val : __enumPaddlesCount.values()) {
+ if (val.enumNumber == paddlesCount) {
+ __enumPaddlesCount = val;
+ return;
+ }
+ }
+ }
+
+ public void DrawBoatPaddles(Graphics g, Color color,
+ float startPosX, float startPosY, int boatWidth, int boatHeight) {
+ int startX = (int) startPosX;
+ int startY = (int) startPosY;
+
+ Graphics2D g2d = (Graphics2D) g;
+ // Задаем цвет как у лодки
+ g2d.setColor(color);
+ // Задаем толщину линии побольше
+ g2d.setStroke(__paddleStroke);
+
+ // Промежуточная переменная, чтобы уменьшить расчеты
+ float t = boatWidth - (float) boatWidth / 4 - (float) boatWidth / 15;
+
+ for (int i = 0; i < __enumPaddlesCount.enumNumber; i++) {
+ // Рисуем верхнее весло
+ g2d.drawLine(
+ (int) (startX + t - t / 3 * i),
+ startY,
+ (int) (startX + t - t / 3 * (i + 1)),
+ startY - 15
+ );
+ // Рисуем нижнее весло
+ g2d.drawLine(
+ (int) (startX + t - t / 3 * i),
+ startY + boatHeight,
+ (int) (startX + t - t / 3 * (i + 1)),
+ startY + boatHeight + 15
+ );
+ }
+ }
+}
diff --git a/src/EntityBoat.java b/src/EntityBoat.java
new file mode 100644
index 0000000..77152e8
--- /dev/null
+++ b/src/EntityBoat.java
@@ -0,0 +1,25 @@
+package src;
+
+import java.awt.*;
+import java.util.Random;
+
+public class EntityBoat {
+ // Скорость лодки
+ public int Speed;
+ // Вес лодки
+ public float Weight;
+ // Цвет корпуса
+ public Color BodyColor;
+
+ // Шаг перемещения
+ public float Step() {
+ return Speed * 100 / Weight;
+ }
+
+ public void Init(int speed, float weight, Color bodyColor) {
+ Random rnd = new Random();
+ Speed = speed <= 0 ? rnd.nextInt(50, 150) : speed;
+ Weight = weight <= 0 ? rnd.nextInt(40, 70) : weight;
+ BodyColor = bodyColor;
+ }
+}
diff --git a/src/EnumDirection.java b/src/EnumDirection.java
new file mode 100644
index 0000000..45e77ea
--- /dev/null
+++ b/src/EnumDirection.java
@@ -0,0 +1,9 @@
+package src;
+
+// Перечисление для направлений движения лодки
+public enum EnumDirection {
+ Up,
+ Down,
+ Left,
+ Right
+}
diff --git a/src/EnumPaddlesCount.java b/src/EnumPaddlesCount.java
new file mode 100644
index 0000000..a5da9e6
--- /dev/null
+++ b/src/EnumPaddlesCount.java
@@ -0,0 +1,14 @@
+package src;
+
+// Дополнительное перечисление количества весел
+public enum EnumPaddlesCount {
+ One(1),
+ Two(2),
+ Three(3);
+
+ public final int enumNumber;
+
+ EnumPaddlesCount(int i) {
+ this.enumNumber = i;
+ }
+}
diff --git a/src/FormBoat.form b/src/FormBoat.form
new file mode 100644
index 0000000..ef5a2d4
--- /dev/null
+++ b/src/FormBoat.form
@@ -0,0 +1,134 @@
+
+
diff --git a/src/FormBoat.java b/src/FormBoat.java
new file mode 100644
index 0000000..1ee812e
--- /dev/null
+++ b/src/FormBoat.java
@@ -0,0 +1,153 @@
+package src;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class FormBoat {
+ protected DrawingBoat _drawingBoat = new DrawingBoat();
+
+ JPanel PanelWrapper;
+ private JPanel PictureBox;
+ private JToolBar StatusStrip;
+ private JLabel StatusStripLabelSpeed;
+ private JLabel StatusStripLabelWeight;
+ private JLabel StatusStripLabelColor;
+ private JButton ButtonCreate;
+ private JButton ButtonDown;
+ private JButton ButtonUp;
+ private JButton ButtonLeft;
+ private JButton ButtonRight;
+
+ private List __controls;
+
+ // Конструктор формы
+ public FormBoat() {
+ // Инициализируем список элементов управления для их перерисовки
+ InitializeControlsRepaintList();
+
+ ButtonUp.setName("ButtonUp");
+ ButtonDown.setName("ButtonDown");
+ ButtonLeft.setName("ButtonLeft");
+ ButtonRight.setName("ButtonRight");
+
+ // Обработчик нажатия кнопки "Создать"
+ ButtonCreate.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Создаем новый объект отрисовки лодки
+ _drawingBoat = new DrawingBoat();
+ Random random = new Random();
+
+ // Инициализируем обхект отрисовки
+ _drawingBoat.Init(random.nextInt(100, 300), random.nextInt(1000, 2000),
+ new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
+
+ // Устанавливаем позицию и размеры объекта отрисовки
+ _drawingBoat.SetPosition(random.nextInt(10, 100), random.nextInt(10, 100),
+ PictureBox.getWidth(), PictureBox.getHeight());
+
+ // Обновляем информацию в статусбаре
+ StatusStripLabelSpeed.setText("Скорость: " + _drawingBoat.entityBoat.Speed + " ");
+ StatusStripLabelWeight.setText("Вес: " + _drawingBoat.entityBoat.Weight + " ");
+ Color color = _drawingBoat.entityBoat.BodyColor;
+ StatusStripLabelColor.setText("Цвет: (" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")");
+
+ // Перерисовываем содержимое
+ Draw();
+ }
+ });
+
+ // Обработчик изменения размеров формы
+ PanelWrapper.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ super.componentResized(e);
+
+ // Изменяем граници области отрисовки для объекта отрисовки
+ _drawingBoat.ChangeBorders(PictureBox.getWidth(), PictureBox.getHeight());
+
+ // Перерисовываем содержимое
+ Draw();
+ }
+ });
+
+ ActionListener buttonMoveClickedListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Получаем имя кнопки перемещения
+ String buttonName = ((JButton) e.getSource()).getName();
+
+ // В зависимости от нажатой кнопки перемещаяем объект
+ switch (buttonName) {
+ case ("ButtonUp"): {
+ _drawingBoat.MoveTransport(EnumDirection.Up);
+ }
+ break;
+ case ("ButtonDown"): {
+ _drawingBoat.MoveTransport(EnumDirection.Down);
+ }
+ break;
+ case ("ButtonLeft"): {
+ _drawingBoat.MoveTransport(EnumDirection.Left);
+ }
+ break;
+ case ("ButtonRight"): {
+ _drawingBoat.MoveTransport(EnumDirection.Right);
+ }
+ break;
+ }
+
+ // Перерисовываем содержимое
+ Draw();
+ }
+ };
+
+ ButtonUp.addActionListener(buttonMoveClickedListener);
+ ButtonDown.addActionListener(buttonMoveClickedListener);
+ ButtonLeft.addActionListener(buttonMoveClickedListener);
+ ButtonRight.addActionListener(buttonMoveClickedListener);
+ }
+
+ // Метод отрисовки
+ public void Draw() {
+ // Если сущности внутри объекта отрисовки нет - выходим
+ if (_drawingBoat.entityBoat == null) {
+ return;
+ }
+
+ // Закрашиваем PictureBox цветом окна (очищаем его)
+ Graphics g = PictureBox.getGraphics();
+ g.setColor(PictureBox.getBackground());
+ g.fillRect(0, 0, PictureBox.getWidth(), PictureBox.getHeight());
+
+ // Рисуем объект
+ _drawingBoat.DrawTransport(g);
+
+ // Перерисовываем элементы управления (PictureBox закрашивает их)
+ RepaintControls();
+ }
+
+ // Метод перерисовки элементов управления
+ private void RepaintControls() {
+ for (JComponent control : __controls) {
+ control.repaint();
+ }
+ }
+
+ // Метод инициализации списка элементов управления для их перерисовки
+ private void InitializeControlsRepaintList() {
+ __controls = new LinkedList<>();
+ __controls.add(ButtonCreate);
+ __controls.add(ButtonUp);
+ __controls.add(ButtonDown);
+ __controls.add(ButtonLeft);
+ __controls.add(ButtonRight);
+ }
+}
diff --git a/src/Program.java b/src/Program.java
new file mode 100644
index 0000000..d8d19a6
--- /dev/null
+++ b/src/Program.java
@@ -0,0 +1,16 @@
+package src;
+
+import javax.swing.*;
+
+public class Program {
+ public static void main(String[] args) {
+ JFrame.setDefaultLookAndFeelDecorated(false);
+ JFrame frame = new JFrame("Катамаран");
+ frame.setContentPane(new FormBoat().PanelWrapper);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setLocation(500, 200);
+ frame.pack();
+ frame.setSize(1000, 500);
+ frame.setVisible(true);
+ }
+}