diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 000000000..78d51c468 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +misc.xml \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 000000000..6834da5ca --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..aa00ffab7 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 000000000..712ab9d98 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..59ad337eb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 000000000..2b63946d5 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..68a6b6524 --- /dev/null +++ b/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + org.example + Robots + 1.0-SNAPSHOT + + + 18 + 18 + UTF-8 + + + \ No newline at end of file diff --git a/robots/src/gui/GameVisualizer.java b/robots/src/gui/GameVisualizer.java deleted file mode 100644 index f82cfd8f8..000000000 --- a/robots/src/gui/GameVisualizer.java +++ /dev/null @@ -1,210 +0,0 @@ -package gui; - -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.geom.AffineTransform; -import java.util.Timer; -import java.util.TimerTask; - -import javax.swing.JPanel; - -public class GameVisualizer extends JPanel -{ - private final Timer m_timer = initTimer(); - - private static Timer initTimer() - { - Timer timer = new Timer("events generator", true); - return timer; - } - - private volatile double m_robotPositionX = 100; - private volatile double m_robotPositionY = 100; - private volatile double m_robotDirection = 0; - - private volatile int m_targetPositionX = 150; - private volatile int m_targetPositionY = 100; - - private static final double maxVelocity = 0.1; - private static final double maxAngularVelocity = 0.001; - - public GameVisualizer() - { - m_timer.schedule(new TimerTask() - { - @Override - public void run() - { - onRedrawEvent(); - } - }, 0, 50); - m_timer.schedule(new TimerTask() - { - @Override - public void run() - { - onModelUpdateEvent(); - } - }, 0, 10); - addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - setTargetPosition(e.getPoint()); - repaint(); - } - }); - setDoubleBuffered(true); - } - - protected void setTargetPosition(Point p) - { - m_targetPositionX = p.x; - m_targetPositionY = p.y; - } - - protected void onRedrawEvent() - { - EventQueue.invokeLater(this::repaint); - } - - private static double distance(double x1, double y1, double x2, double y2) - { - double diffX = x1 - x2; - double diffY = y1 - y2; - return Math.sqrt(diffX * diffX + diffY * diffY); - } - - private static double angleTo(double fromX, double fromY, double toX, double toY) - { - double diffX = toX - fromX; - double diffY = toY - fromY; - - return asNormalizedRadians(Math.atan2(diffY, diffX)); - } - - protected void onModelUpdateEvent() - { - double distance = distance(m_targetPositionX, m_targetPositionY, - m_robotPositionX, m_robotPositionY); - if (distance < 0.5) - { - return; - } - double velocity = maxVelocity; - double angleToTarget = angleTo(m_robotPositionX, m_robotPositionY, m_targetPositionX, m_targetPositionY); - double angularVelocity = 0; - if (angleToTarget > m_robotDirection) - { - angularVelocity = maxAngularVelocity; - } - if (angleToTarget < m_robotDirection) - { - angularVelocity = -maxAngularVelocity; - } - - moveRobot(velocity, angularVelocity, 10); - } - - private static double applyLimits(double value, double min, double max) - { - if (value < min) - return min; - if (value > max) - return max; - return value; - } - - private void moveRobot(double velocity, double angularVelocity, double duration) - { - velocity = applyLimits(velocity, 0, maxVelocity); - angularVelocity = applyLimits(angularVelocity, -maxAngularVelocity, maxAngularVelocity); - double newX = m_robotPositionX + velocity / angularVelocity * - (Math.sin(m_robotDirection + angularVelocity * duration) - - Math.sin(m_robotDirection)); - if (!Double.isFinite(newX)) - { - newX = m_robotPositionX + velocity * duration * Math.cos(m_robotDirection); - } - double newY = m_robotPositionY - velocity / angularVelocity * - (Math.cos(m_robotDirection + angularVelocity * duration) - - Math.cos(m_robotDirection)); - if (!Double.isFinite(newY)) - { - newY = m_robotPositionY + velocity * duration * Math.sin(m_robotDirection); - } - m_robotPositionX = newX; - m_robotPositionY = newY; - double newDirection = asNormalizedRadians(m_robotDirection + angularVelocity * duration); - m_robotDirection = newDirection; - } - - private static double asNormalizedRadians(double angle) - { - while (angle < 0) - { - angle += 2*Math.PI; - } - while (angle >= 2*Math.PI) - { - angle -= 2*Math.PI; - } - return angle; - } - - private static int round(double value) - { - return (int)(value + 0.5); - } - - @Override - public void paint(Graphics g) - { - super.paint(g); - Graphics2D g2d = (Graphics2D)g; - drawRobot(g2d, round(m_robotPositionX), round(m_robotPositionY), m_robotDirection); - drawTarget(g2d, m_targetPositionX, m_targetPositionY); - } - - private static void fillOval(Graphics g, int centerX, int centerY, int diam1, int diam2) - { - g.fillOval(centerX - diam1 / 2, centerY - diam2 / 2, diam1, diam2); - } - - private static void drawOval(Graphics g, int centerX, int centerY, int diam1, int diam2) - { - g.drawOval(centerX - diam1 / 2, centerY - diam2 / 2, diam1, diam2); - } - - private void drawRobot(Graphics2D g, int x, int y, double direction) - { - int robotCenterX = round(m_robotPositionX); - int robotCenterY = round(m_robotPositionY); - AffineTransform t = AffineTransform.getRotateInstance(direction, robotCenterX, robotCenterY); - g.setTransform(t); - g.setColor(Color.MAGENTA); - fillOval(g, robotCenterX, robotCenterY, 30, 10); - g.setColor(Color.BLACK); - drawOval(g, robotCenterX, robotCenterY, 30, 10); - g.setColor(Color.WHITE); - fillOval(g, robotCenterX + 10, robotCenterY, 5, 5); - g.setColor(Color.BLACK); - drawOval(g, robotCenterX + 10, robotCenterY, 5, 5); - } - - private void drawTarget(Graphics2D g, int x, int y) - { - AffineTransform t = AffineTransform.getRotateInstance(0, 0, 0); - g.setTransform(t); - g.setColor(Color.GREEN); - fillOval(g, x, y, 5, 5); - g.setColor(Color.BLACK); - drawOval(g, x, y, 5, 5); - } -} diff --git a/robots/src/gui/GameWindow.java b/robots/src/gui/GameWindow.java deleted file mode 100644 index ecb63c00f..000000000 --- a/robots/src/gui/GameWindow.java +++ /dev/null @@ -1,20 +0,0 @@ -package gui; - -import java.awt.BorderLayout; - -import javax.swing.JInternalFrame; -import javax.swing.JPanel; - -public class GameWindow extends JInternalFrame -{ - private final GameVisualizer m_visualizer; - public GameWindow() - { - super("Игровое поле", true, true, true, true); - m_visualizer = new GameVisualizer(); - JPanel panel = new JPanel(new BorderLayout()); - panel.add(m_visualizer, BorderLayout.CENTER); - getContentPane().add(panel); - pack(); - } -} diff --git a/robots/src/gui/LogWindow.java b/robots/src/gui/LogWindow.java deleted file mode 100644 index 723d3e2fc..000000000 --- a/robots/src/gui/LogWindow.java +++ /dev/null @@ -1,50 +0,0 @@ -package gui; - -import java.awt.BorderLayout; -import java.awt.EventQueue; -import java.awt.TextArea; - -import javax.swing.JInternalFrame; -import javax.swing.JPanel; - -import log.LogChangeListener; -import log.LogEntry; -import log.LogWindowSource; - -public class LogWindow extends JInternalFrame implements LogChangeListener -{ - private LogWindowSource m_logSource; - private TextArea m_logContent; - - public LogWindow(LogWindowSource logSource) - { - super("Протокол работы", true, true, true, true); - m_logSource = logSource; - m_logSource.registerListener(this); - m_logContent = new TextArea(""); - m_logContent.setSize(200, 500); - - JPanel panel = new JPanel(new BorderLayout()); - panel.add(m_logContent, BorderLayout.CENTER); - getContentPane().add(panel); - pack(); - updateLogContent(); - } - - private void updateLogContent() - { - StringBuilder content = new StringBuilder(); - for (LogEntry entry : m_logSource.all()) - { - content.append(entry.getMessage()).append("\n"); - } - m_logContent.setText(content.toString()); - m_logContent.invalidate(); - } - - @Override - public void onLogChanged() - { - EventQueue.invokeLater(this::updateLogContent); - } -} diff --git a/robots/src/gui/MainApplicationFrame.java b/robots/src/gui/MainApplicationFrame.java deleted file mode 100644 index 62e943ee1..000000000 --- a/robots/src/gui/MainApplicationFrame.java +++ /dev/null @@ -1,156 +0,0 @@ -package gui; - -import java.awt.Dimension; -import java.awt.Toolkit; -import java.awt.event.KeyEvent; - -import javax.swing.JDesktopPane; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import log.Logger; - -/** - * Что требуется сделать: - * 1. Метод создания меню перегружен функционалом и трудно читается. - * Следует разделить его на серию более простых методов (или вообще выделить отдельный класс). - * - */ -public class MainApplicationFrame extends JFrame -{ - private final JDesktopPane desktopPane = new JDesktopPane(); - - public MainApplicationFrame() { - //Make the big window be indented 50 pixels from each edge - //of the screen. - int inset = 50; - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - setBounds(inset, inset, - screenSize.width - inset*2, - screenSize.height - inset*2); - - setContentPane(desktopPane); - - - LogWindow logWindow = createLogWindow(); - addWindow(logWindow); - - GameWindow gameWindow = new GameWindow(); - gameWindow.setSize(400, 400); - addWindow(gameWindow); - - setJMenuBar(generateMenuBar()); - setDefaultCloseOperation(EXIT_ON_CLOSE); - } - - protected LogWindow createLogWindow() - { - LogWindow logWindow = new LogWindow(Logger.getDefaultLogSource()); - logWindow.setLocation(10,10); - logWindow.setSize(300, 800); - setMinimumSize(logWindow.getSize()); - logWindow.pack(); - Logger.debug("Протокол работает"); - return logWindow; - } - - protected void addWindow(JInternalFrame frame) - { - desktopPane.add(frame); - frame.setVisible(true); - } - -// protected JMenuBar createMenuBar() { -// JMenuBar menuBar = new JMenuBar(); -// -// //Set up the lone menu. -// JMenu menu = new JMenu("Document"); -// menu.setMnemonic(KeyEvent.VK_D); -// menuBar.add(menu); -// -// //Set up the first menu item. -// JMenuItem menuItem = new JMenuItem("New"); -// menuItem.setMnemonic(KeyEvent.VK_N); -// menuItem.setAccelerator(KeyStroke.getKeyStroke( -// KeyEvent.VK_N, ActionEvent.ALT_MASK)); -// menuItem.setActionCommand("new"); -//// menuItem.addActionListener(this); -// menu.add(menuItem); -// -// //Set up the second menu item. -// menuItem = new JMenuItem("Quit"); -// menuItem.setMnemonic(KeyEvent.VK_Q); -// menuItem.setAccelerator(KeyStroke.getKeyStroke( -// KeyEvent.VK_Q, ActionEvent.ALT_MASK)); -// menuItem.setActionCommand("quit"); -//// menuItem.addActionListener(this); -// menu.add(menuItem); -// -// return menuBar; -// } - - private JMenuBar generateMenuBar() - { - JMenuBar menuBar = new JMenuBar(); - - JMenu lookAndFeelMenu = new JMenu("Режим отображения"); - lookAndFeelMenu.setMnemonic(KeyEvent.VK_V); - lookAndFeelMenu.getAccessibleContext().setAccessibleDescription( - "Управление режимом отображения приложения"); - - { - JMenuItem systemLookAndFeel = new JMenuItem("Системная схема", KeyEvent.VK_S); - systemLookAndFeel.addActionListener((event) -> { - setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - this.invalidate(); - }); - lookAndFeelMenu.add(systemLookAndFeel); - } - - { - JMenuItem crossplatformLookAndFeel = new JMenuItem("Универсальная схема", KeyEvent.VK_S); - crossplatformLookAndFeel.addActionListener((event) -> { - setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - this.invalidate(); - }); - lookAndFeelMenu.add(crossplatformLookAndFeel); - } - - JMenu testMenu = new JMenu("Тесты"); - testMenu.setMnemonic(KeyEvent.VK_T); - testMenu.getAccessibleContext().setAccessibleDescription( - "Тестовые команды"); - - { - JMenuItem addLogMessageItem = new JMenuItem("Сообщение в лог", KeyEvent.VK_S); - addLogMessageItem.addActionListener((event) -> { - Logger.debug("Новая строка"); - }); - testMenu.add(addLogMessageItem); - } - - menuBar.add(lookAndFeelMenu); - menuBar.add(testMenu); - return menuBar; - } - - private void setLookAndFeel(String className) - { - try - { - UIManager.setLookAndFeel(className); - SwingUtilities.updateComponentTreeUI(this); - } - catch (ClassNotFoundException | InstantiationException - | IllegalAccessException | UnsupportedLookAndFeelException e) - { - // just ignore - } - } -} diff --git a/robots/src/gui/RobotsProgram.java b/robots/src/gui/RobotsProgram.java deleted file mode 100644 index ae0930a8b..000000000 --- a/robots/src/gui/RobotsProgram.java +++ /dev/null @@ -1,25 +0,0 @@ -package gui; - -import java.awt.Frame; - -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -public class RobotsProgram -{ - public static void main(String[] args) { - try { - UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); -// UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); -// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); -// UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } catch (Exception e) { - e.printStackTrace(); - } - SwingUtilities.invokeLater(() -> { - MainApplicationFrame frame = new MainApplicationFrame(); - frame.pack(); - frame.setVisible(true); - frame.setExtendedState(Frame.MAXIMIZED_BOTH); - }); - }} diff --git a/robots/src/log/LogChangeListener.java b/robots/src/log/LogChangeListener.java deleted file mode 100644 index 0b0fb85dd..000000000 --- a/robots/src/log/LogChangeListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package log; - -public interface LogChangeListener -{ - public void onLogChanged(); -} diff --git a/robots/src/log/LogEntry.java b/robots/src/log/LogEntry.java deleted file mode 100644 index 3d9147107..000000000 --- a/robots/src/log/LogEntry.java +++ /dev/null @@ -1,24 +0,0 @@ -package log; - -public class LogEntry -{ - private LogLevel m_logLevel; - private String m_strMessage; - - public LogEntry(LogLevel logLevel, String strMessage) - { - m_strMessage = strMessage; - m_logLevel = logLevel; - } - - public String getMessage() - { - return m_strMessage; - } - - public LogLevel getLevel() - { - return m_logLevel; - } -} - diff --git a/robots/src/log/LogLevel.java b/robots/src/log/LogLevel.java deleted file mode 100644 index 582d010cc..000000000 --- a/robots/src/log/LogLevel.java +++ /dev/null @@ -1,24 +0,0 @@ -package log; - -public enum LogLevel -{ - Trace(0), - Debug(1), - Info(2), - Warning(3), - Error(4), - Fatal(5); - - private int m_iLevel; - - private LogLevel(int iLevel) - { - m_iLevel = iLevel; - } - - public int level() - { - return m_iLevel; - } -} - diff --git a/robots/src/log/LogWindowSource.java b/robots/src/log/LogWindowSource.java deleted file mode 100644 index ca0ce4426..000000000 --- a/robots/src/log/LogWindowSource.java +++ /dev/null @@ -1,89 +0,0 @@ -package log; - -import java.util.ArrayList; -import java.util.Collections; - -/** - * Что починить: - * 1. Этот класс порождает утечку ресурсов (связанные слушатели оказываются - * удерживаемыми в памяти) - * 2. Этот класс хранит активные сообщения лога, но в такой реализации он - * их лишь накапливает. Надо же, чтобы количество сообщений в логе было ограничено - * величиной m_iQueueLength (т.е. реально нужна очередь сообщений - * ограниченного размера) - */ -public class LogWindowSource -{ - private int m_iQueueLength; - - private ArrayList m_messages; - private final ArrayList m_listeners; - private volatile LogChangeListener[] m_activeListeners; - - public LogWindowSource(int iQueueLength) - { - m_iQueueLength = iQueueLength; - m_messages = new ArrayList(iQueueLength); - m_listeners = new ArrayList(); - } - - public void registerListener(LogChangeListener listener) - { - synchronized(m_listeners) - { - m_listeners.add(listener); - m_activeListeners = null; - } - } - - public void unregisterListener(LogChangeListener listener) - { - synchronized(m_listeners) - { - m_listeners.remove(listener); - m_activeListeners = null; - } - } - - public void append(LogLevel logLevel, String strMessage) - { - LogEntry entry = new LogEntry(logLevel, strMessage); - m_messages.add(entry); - LogChangeListener [] activeListeners = m_activeListeners; - if (activeListeners == null) - { - synchronized (m_listeners) - { - if (m_activeListeners == null) - { - activeListeners = m_listeners.toArray(new LogChangeListener [0]); - m_activeListeners = activeListeners; - } - } - } - for (LogChangeListener listener : activeListeners) - { - listener.onLogChanged(); - } - } - - public int size() - { - return m_messages.size(); - } - - public Iterable range(int startFrom, int count) - { - if (startFrom < 0 || startFrom >= m_messages.size()) - { - return Collections.emptyList(); - } - int indexTo = Math.min(startFrom + count, m_messages.size()); - return m_messages.subList(startFrom, indexTo); - } - - public Iterable all() - { - return m_messages; - } -} diff --git a/robots/src/log/Logger.java b/robots/src/log/Logger.java deleted file mode 100644 index b008a5d01..000000000 --- a/robots/src/log/Logger.java +++ /dev/null @@ -1,28 +0,0 @@ -package log; - -public final class Logger -{ - private static final LogWindowSource defaultLogSource; - static { - defaultLogSource = new LogWindowSource(100); - } - - private Logger() - { - } - - public static void debug(String strMessage) - { - defaultLogSource.append(LogLevel.Debug, strMessage); - } - - public static void error(String strMessage) - { - defaultLogSource.append(LogLevel.Error, strMessage); - } - - public static LogWindowSource getDefaultLogSource() - { - return defaultLogSource; - } -} diff --git a/robots/src/main/java/gui/GameWindow.java b/robots/src/main/java/gui/GameWindow.java new file mode 100644 index 000000000..76854c1ec --- /dev/null +++ b/robots/src/main/java/gui/GameWindow.java @@ -0,0 +1,23 @@ +package main.java.gui; + +import java.awt.BorderLayout; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; +import main.java.view.GameView; + +public class GameWindow extends JInternalFrame { + private final GameView gameView; + + public GameWindow(GameView gameView) { + super("Игровое поле", true, true, true, true); + this.gameView = gameView; + JPanel panel = new JPanel(new BorderLayout()); + panel.add(this.gameView, "Center"); + this.getContentPane().add(panel); + this.pack(); + } + + public GameView getGameView() { + return this.gameView; + } +} \ No newline at end of file diff --git a/robots/src/main/java/gui/LogWindow.java b/robots/src/main/java/gui/LogWindow.java new file mode 100644 index 000000000..b3ba182c9 --- /dev/null +++ b/robots/src/main/java/gui/LogWindow.java @@ -0,0 +1,51 @@ +package main.java.gui; + +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.TextArea; +import java.util.Iterator; +import java.util.ResourceBundle; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; +import main.java.log.LogChangeListener; +import main.java.log.LogEntry; +import main.java.log.LogWindowSource; + +public class LogWindow extends JInternalFrame implements LogChangeListener, Translatable { + private LogWindowSource mLogSource; + private TextArea mLogContent; + + public LogWindow(LogWindowSource logSource) { + super("Протокол работы", true, true, true, true); + this.mLogSource = logSource; + this.mLogSource.registerListener(this); + this.mLogContent = new TextArea(""); + this.mLogContent.setSize(200, 500); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(this.mLogContent, "Center"); + this.getContentPane().add(panel); + this.pack(); + this.updateLogContent(); + } + + private void updateLogContent() { + StringBuilder content = new StringBuilder(); + Iterator var2 = this.mLogSource.all().iterator(); + + while(var2.hasNext()) { + LogEntry entry = (LogEntry)var2.next(); + content.append(entry.getMessage()).append("\n"); + } + + this.mLogContent.setText(content.toString()); + this.mLogContent.invalidate(); + } + + public void onLogChanged() { + EventQueue.invokeLater(this::updateLogContent); + } + + public void setTranslate(ResourceBundle bundle) { + this.setTitle(bundle.getString("logWindowHeader")); + } +} diff --git a/robots/src/main/java/gui/MainApplicationFrame.java b/robots/src/main/java/gui/MainApplicationFrame.java new file mode 100644 index 000000000..f5185185d --- /dev/null +++ b/robots/src/main/java/gui/MainApplicationFrame.java @@ -0,0 +1,93 @@ +package main.java.gui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionListener; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import main.java.log.Logger; +import main.java.view.ViewModel; + +public class MainApplicationFrame extends JFrame { + private final JDesktopPane desktopPane = new JDesktopPane(); + + public MainApplicationFrame(ViewModel gameViewModel) { + int inset = 50; + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + this.setBounds(inset, inset, screenSize.width - inset * 2, screenSize.height - inset * 2); + this.setContentPane(this.desktopPane); + LogWindow logWindow = this.createLogWindow(); + this.addWindow(logWindow); + GameWindow gameWindow = gameViewModel.getGameWindow(); + this.addWindow(gameWindow); + this.setJMenuBar(this.generateMenuBar()); + this.setDefaultCloseOperation(3); + } + + protected LogWindow createLogWindow() { + LogWindow logWindow = new LogWindow(Logger.getDefaultLogSource()); + logWindow.setLocation(610, 0); + logWindow.setSize(300, 800); + this.setMinimumSize(logWindow.getSize()); + logWindow.pack(); + Logger.debug("Протокол работает"); + return logWindow; + } + + protected void addWindow(JInternalFrame frame) { + this.desktopPane.add(frame); + frame.setVisible(true); + } + + private JMenu createMenu(String nameOfMenu, String description, int mnemonic) { + JMenu lookAndFeelMenu = new JMenu(nameOfMenu); + lookAndFeelMenu.setMnemonic(86); + lookAndFeelMenu.getAccessibleContext().setAccessibleDescription(description); + return lookAndFeelMenu; + } + + private JMenuItem createMenuItem(String name, ActionListener l) { + JMenuItem systemLookAndFeel = new JMenuItem(name, 83); + systemLookAndFeel.addActionListener(l); + return systemLookAndFeel; + } + + private JMenuBar generateMenuBar() { + JMenuBar menuBar = new JMenuBar(); + JMenu lookAndFeelMenu = this.createMenu("Режим отображения", "Управление режимом отображения приложения", 86); + JMenuItem systemLookAndFeel = this.createMenuItem("Системная схема", (event) -> { + this.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + this.invalidate(); + }); + lookAndFeelMenu.add(systemLookAndFeel); + JMenuItem crossplatformLookAndFeel = this.createMenuItem("Универсальная схема", (event) -> { + this.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + this.invalidate(); + }); + lookAndFeelMenu.add(crossplatformLookAndFeel); + JMenu testMenu = this.createMenu("Тесты", "Тестовые команды", 83); + JMenuItem addLogMessageItem = this.createMenuItem("Сообщение в лог", (event) -> { + Logger.debug("Новая строка"); + }); + testMenu.add(addLogMessageItem); + menuBar.add(lookAndFeelMenu); + menuBar.add(testMenu); + return menuBar; + } + + private void setLookAndFeel(String className) { + try { + UIManager.setLookAndFeel(className); + SwingUtilities.updateComponentTreeUI(this); + } catch (InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException | ClassNotFoundException var3) { + } + + } +} diff --git a/robots/src/main/java/gui/PositionWindow.java b/robots/src/main/java/gui/PositionWindow.java new file mode 100644 index 000000000..efa17c83e --- /dev/null +++ b/robots/src/main/java/gui/PositionWindow.java @@ -0,0 +1,48 @@ +package main.java.gui; + +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.util.Observable; +import java.util.Observer; +import java.util.ResourceBundle; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import main.java.model.Robot; + +public class PositionWindow extends JInternalFrame implements Observer, Translatable { + private final JLabel labelX; + private final JLabel labelY; + private final Robot robot; + + public PositionWindow(Robot robot, int width, int height) { + super("Координаты робота", true, true, true, true); + this.robot = robot; + JPanel panel = new JPanel(new BorderLayout()); + robot.addObserver(this); + this.labelX = new JLabel("X: %f".formatted(robot.getPositionX())); + this.labelY = new JLabel("Y: %f".formatted(robot.getPositionY())); + panel.add(this.labelX, "First"); + panel.add(this.labelY, "Center"); + this.getContentPane().add(panel); + this.pack(); + this.setSize(width, height); + this.setLocation(1600, 50); + } + + public void update(Observable o, Object arg) { + if (arg.equals("The robot's position has changed")) { + EventQueue.invokeLater(this::updateCoords); + } + + } + + public void updateCoords() { + this.labelX.setText("X: %f".formatted(this.robot.getPositionX())); + this.labelY.setText("Y: %f".formatted(this.robot.getPositionY())); + } + + public void setTranslate(ResourceBundle bundle) { + this.setTitle(bundle.getString("positionWindowHeader")); + } +} diff --git a/robots/src/main/java/gui/RobotsProgram.java b/robots/src/main/java/gui/RobotsProgram.java new file mode 100644 index 000000000..1b0bee484 --- /dev/null +++ b/robots/src/main/java/gui/RobotsProgram.java @@ -0,0 +1,35 @@ +package main.java.gui; + +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import main.java.model.GameModel; +import main.java.model.Robot; +import main.java.view.GameView; +import main.java.view.ViewModel; + +public class RobotsProgram { + public RobotsProgram() { + } + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception var7) { + var7.printStackTrace(); + } + + GameModel gameModel = new GameModel(); + GameView gameView = new GameView(gameModel); + GameWindow gameWindow = new GameWindow(gameView); + Robot robot = new Robot(); + PositionWindow positionWindow = new PositionWindow(robot, 800, 600); + positionWindow.updateCoords(); + ViewModel viewModel = new ViewModel(gameModel, gameWindow); + SwingUtilities.invokeLater(() -> { + MainApplicationFrame frame = new MainApplicationFrame(viewModel); + frame.pack(); + frame.setVisible(true); + frame.setExtendedState(6); + }); + } +} diff --git a/robots/src/main/java/gui/Translatable.java b/robots/src/main/java/gui/Translatable.java new file mode 100644 index 000000000..4a6ee20ec --- /dev/null +++ b/robots/src/main/java/gui/Translatable.java @@ -0,0 +1,7 @@ +package main.java.gui; + +import java.util.ResourceBundle; + +public interface Translatable { + void setTranslate(ResourceBundle var1); +} diff --git a/robots/src/main/java/log/LogChangeListener.java b/robots/src/main/java/log/LogChangeListener.java new file mode 100644 index 000000000..d9608308c --- /dev/null +++ b/robots/src/main/java/log/LogChangeListener.java @@ -0,0 +1,5 @@ +package main.java.log; + +public interface LogChangeListener { + void onLogChanged(); +} diff --git a/robots/src/main/java/log/LogEntry.java b/robots/src/main/java/log/LogEntry.java new file mode 100644 index 000000000..8c6a12eb0 --- /dev/null +++ b/robots/src/main/java/log/LogEntry.java @@ -0,0 +1,19 @@ +package main.java.log; + +public class LogEntry { + private LogLevel mLogLevel; + private String mStrMessage; + + public LogEntry(LogLevel logLevel, String strMessage) { + this.mStrMessage = strMessage; + this.mLogLevel = logLevel; + } + + public String getMessage() { + return this.mStrMessage; + } + + public LogLevel getLevel() { + return this.mLogLevel; + } +} \ No newline at end of file diff --git a/robots/src/main/java/log/LogLevel.java b/robots/src/main/java/log/LogLevel.java new file mode 100644 index 000000000..d6ffe0ad2 --- /dev/null +++ b/robots/src/main/java/log/LogLevel.java @@ -0,0 +1,22 @@ +package main.java.log; + +public enum LogLevel { + Trace(0), + Debug(1), + Info(2), + Warning(3), + Error(4), + Fatal(5); + + private int m_iLevel; + + private LogLevel(int iLevel) { + this.m_iLevel = iLevel; + } + + public int level() { + return this.m_iLevel; + } +} + + diff --git a/robots/src/main/java/log/LogWindowSource.java b/robots/src/main/java/log/LogWindowSource.java new file mode 100644 index 000000000..8243b2a2c --- /dev/null +++ b/robots/src/main/java/log/LogWindowSource.java @@ -0,0 +1,70 @@ +package main.java.log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.concurrent.CopyOnWriteArrayList; + +public class LogWindowSource { + private final int mIQueueLength; + private final ArrayList mMessages; + private final CopyOnWriteArrayList mListeners; + private volatile LogChangeListener[] mActivelisteners; + + public LogWindowSource(int iQueueLength) { + this.mIQueueLength = iQueueLength; + this.mMessages = new ArrayList(iQueueLength); + this.mListeners = new CopyOnWriteArrayList(); + } + + public void registerListener(LogChangeListener listener) { + this.mListeners.add(listener); + this.mActivelisteners = null; + } + + public void append(LogLevel logLevel, String strMessage) { + LogEntry entry = new LogEntry(logLevel, strMessage); + if (this.size() >= this.mIQueueLength) { + this.mMessages.remove(0); + } + + synchronized(this) { + this.mMessages.add(entry); + } + + LogChangeListener[] activeListeners = this.mActivelisteners; + if (activeListeners == null) { + synchronized(this.mListeners) { + if (this.mActivelisteners == null) { + activeListeners = (LogChangeListener[])this.mListeners.toArray(new LogChangeListener[0]); + this.mActivelisteners = activeListeners; + } + } + } + + LogChangeListener[] var5 = activeListeners; + int var6 = activeListeners.length; + + for(int var7 = 0; var7 < var6; ++var7) { + LogChangeListener listener = var5[var7]; + listener.onLogChanged(); + } + + } + + public synchronized int size() { + return this.mMessages.size(); + } + + public synchronized Iterable range(int startFrom, int count) { + if (startFrom >= 0 && startFrom < this.size()) { + int indexTo = Math.min(startFrom + count, this.size()); + return this.mMessages.subList(startFrom, indexTo); + } else { + return Collections.emptyList(); + } + } + + public synchronized Iterable all() { + return this.mMessages; + } +} diff --git a/robots/src/main/java/log/Logger.java b/robots/src/main/java/log/Logger.java new file mode 100644 index 000000000..005635194 --- /dev/null +++ b/robots/src/main/java/log/Logger.java @@ -0,0 +1,16 @@ +package main.java.log; + +public final class Logger { + private static final LogWindowSource defaultLogSource = new LogWindowSource(100); + + private Logger() { + } + + public static void debug(String strMessage) { + defaultLogSource.append(LogLevel.Debug, strMessage); + } + + public static LogWindowSource getDefaultLogSource() { + return defaultLogSource; + } +} \ No newline at end of file diff --git a/robots/src/main/java/model/Entity.java b/robots/src/main/java/model/Entity.java new file mode 100644 index 000000000..c1b7d3f7b --- /dev/null +++ b/robots/src/main/java/model/Entity.java @@ -0,0 +1,12 @@ +package main.java.model; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public interface Entity extends PropertyChangeListener { + void update(); + + default void onStart(PropertyChangeSupport var1) { + + } +} diff --git a/robots/src/main/java/model/GameModel.java b/robots/src/main/java/model/GameModel.java new file mode 100644 index 000000000..ad2105cea --- /dev/null +++ b/robots/src/main/java/model/GameModel.java @@ -0,0 +1,81 @@ +package main.java.model; + +import java.awt.Dimension; +import java.awt.Point; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +public class GameModel implements Entity { + public static final String CHANGE_SATIETY_EVENT = "change satiety"; + public static final String SET_DIMENSION_EVENT = "set dimension"; + public static final String NEW_POINT_EVENT = "new point"; + private final List entities = this.initStateOfBacterias(2); + private final PropertyChangeSupport support = new PropertyChangeSupport(this); + + public GameModel() { + Timer timer = initTimer(); + timer.schedule(new TimerTask() { + public void run() { + System.out.println("timer"); + GameModel.this.support.firePropertyChange("change satiety", (Object)null, -10); + } + }, 0L, 1500L); + } + + private static Timer initTimer() { + return new Timer("satiety generator", true); + } + + public void setDimension(Dimension dimension) { + this.support.firePropertyChange("set dimension", (Object)null, dimension); + } + + public Dimension getDimension() { + return ((Robot)this.entities.get(0)).getDimension(); + } + + public void updateModel() { + Iterator var1 = this.entities.iterator(); + + while(var1.hasNext()) { + Entity entity = (Entity)var1.next(); + entity.update(); + } + + } + + public List getEntities() { + return this.entities; + } + + public void setTarget(Point point) { + this.support.firePropertyChange("new point", (Object)null, point); + } + + public List initStateOfBacterias(int amount) { + List entityList = new ArrayList(); + + for(int i = 0; i < amount; ++i) { + Robot robot = new Robot(Math.random() * 400.0, Math.random() * 400.0); + robot.setTarget(new Point((int)(Math.random() * 400.0), (int)(Math.random() * 400.0))); + robot.onStart(this.support); + entityList.add(robot); + } + + return entityList; + } + + public void update() { + } + + public void onStart(PropertyChangeSupport publisher) { + } + + public void propertyChange(PropertyChangeEvent evt) { + } +} diff --git a/robots/src/main/java/model/Robot.java b/robots/src/main/java/model/Robot.java new file mode 100644 index 000000000..3a9f20892 --- /dev/null +++ b/robots/src/main/java/model/Robot.java @@ -0,0 +1,220 @@ +package main.java.model; + +import java.awt.Dimension; +import java.awt.Point; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; +import java.util.Observable; + +public class Robot extends Observable implements Entity { + public static final String ROBOT_POSITION_CHANGED = "The robot's position has changed"; + public static final double MAX_VELOCITY = 0.1; + public static final double MAX_ANGULAR_VELOCITY = 0.01; + public static final int INITIAL_SATIETY = 50; + public static final int MAX_SATIETY = 100; + private double positionX; + private double positionY; + private Target target; + private Dimension dimension; + private volatile double robotDirection; + private int satiety; + private TypeRobot type; + + public Robot() { + this(300.0, 300.0); + } + + public Robot(double x, double y) { + this.positionX = x; + this.positionY = y; + this.target = new Target(); + this.robotDirection = Math.random() * 10.0; + this.dimension = new Dimension(300, 300); + this.satiety = (int)(50.0 + Math.random() * 50.0); + this.type = getType(this.satiety); + } + + public void setType(TypeRobot type) { + this.type = type; + } + + public TypeRobot getType() { + return this.type; + } + + public void changeSatiety(int satiety) { + this.satiety += satiety; + this.type = getType(this.satiety); + } + + public void setDimension(Dimension dimension) { + this.dimension = dimension; + if (!this.target.isPositionCorrect(dimension)) { + this.target = new Target((int)(Math.random() * (double)dimension.width), (int)(Math.random() * (double)dimension.height)); + } + + } + + public Dimension getDimension() { + return this.dimension; + } + + public double getPositionX() { + return this.positionX; + } + + public void setPositionX(double positionX) { + this.positionX = positionX; + } + + public double getPositionY() { + return this.positionY; + } + + public void setPositionY(double positionY) { + this.positionY = positionY; + } + + public double getRobotDirection() { + return this.robotDirection; + } + + public void setRobotDirection(double robotDirection) { + this.robotDirection = robotDirection; + } + + private static double distance(double x1, double y1, double x2, double y2) { + double diffX = x1 - x2; + double diffY = y1 - y2; + return Math.sqrt(diffX * diffX + diffY * diffY); + } + + private static double angleTo(double fromX, double fromY, double toX, double toY) { + double diffX = toX - fromX; + double diffY = toY - fromY; + return asNormalizedRadians(Math.atan2(diffY, diffX)); + } + + private static double asNormalizedRadians(double angle) { + while(angle < 0.0) { + angle += 6.283185307179586; + } + + while(angle >= 6.283185307179586) { + angle -= 6.283185307179586; + } + + return angle; + } + + private double normalizedPositionX(double x) { + if (x < 0.0) { + return 0.0; + } else { + return x > (double)this.dimension.width ? (double)this.dimension.width : x; + } + } + + private double normalizedPositionY(double y) { + if (y < 0.0) { + return 0.0; + } else { + return y > (double)this.dimension.height ? (double)this.dimension.height : y; + } + } + + private static double applyLimits(double value, double min, double max) { + if (value < min) { + return min; + } else { + return value > max ? max : value; + } + } + + public Target getTarget() { + return this.target; + } + + public void setTarget(Point point) { + this.target.setTargetPosition(point); + } + + private void moveRobot(double velocity, double angularVelocity, double duration) { + velocity = applyLimits(velocity, 0.0, 0.1); + angularVelocity = applyLimits(angularVelocity, -0.01, 0.01); + double newX = this.getPositionX() + velocity / angularVelocity * (Math.sin(this.getRobotDirection() + angularVelocity * duration) - Math.sin(this.getRobotDirection())); + if (!Double.isFinite(newX)) { + newX = this.getPositionX() + velocity * duration * Math.cos(this.getRobotDirection()); + } + + double newY = this.getPositionY() - velocity / angularVelocity * (Math.cos(this.getRobotDirection() + angularVelocity * duration) - Math.cos(this.getRobotDirection())); + if (!Double.isFinite(newY)) { + newY = this.getPositionY() + velocity * duration * Math.sin(this.getRobotDirection()); + } + + this.setPositionX(this.normalizedPositionX(newX)); + this.setPositionY(this.normalizedPositionY(newY)); + double newDirection = asNormalizedRadians(this.getRobotDirection() + angularVelocity * duration); + this.setRobotDirection(newDirection); + this.setChanged(); + this.notifyObservers("The robot's position has changed"); + } + + public void update() { + if (this.type != TypeRobot.DEAD) { + if (this.interactionWithEnvironment()) { + this.onTargetAchieved(); + } + + double angleToTarget = angleTo(this.getPositionX(), this.getPositionY(), (double)this.target.getX(), (double)this.target.getY()); + double angularVelocity = 0.0; + if (angleToTarget > this.getRobotDirection()) { + angularVelocity = 0.01; + } + + if (angleToTarget < this.getRobotDirection()) { + angularVelocity = -0.01; + } + + this.moveRobot(0.1, angularVelocity, 10.0); + } + } + + private boolean interactionWithEnvironment() { + double distance = distance((double)this.target.getX(), (double)this.target.getY(), this.getPositionX(), this.getPositionY()); + return distance < 0.5; + } + + public void onStart(PropertyChangeSupport publisher) { + publisher.addPropertyChangeListener(this); + } + + private void onTargetAchieved() { + this.setTarget(new Point((int)(Math.random() * (double)this.dimension.width), (int)(Math.random() * (double)this.dimension.height))); + this.satiety += 25; + this.type = getType(this.satiety); + } + + private static TypeRobot getType(int satiety) { + if (satiety > 50) { + return TypeRobot.CALM; + } else { + return satiety <= 0 ? TypeRobot.DEAD : TypeRobot.HUNGRY; + } + } + + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("new point")) { + this.setTarget((Point)evt.getNewValue()); + } + + if (evt.getPropertyName().equals("change satiety")) { + this.changeSatiety((Integer)evt.getNewValue()); + } + + if (evt.getPropertyName().equals("set dimension")) { + this.setDimension((Dimension)evt.getNewValue()); + } + + } +} \ No newline at end of file diff --git a/robots/src/main/java/model/Target.java b/robots/src/main/java/model/Target.java new file mode 100644 index 000000000..4689da897 --- /dev/null +++ b/robots/src/main/java/model/Target.java @@ -0,0 +1,56 @@ +package main.java.model; + +import java.awt.Dimension; +import java.awt.Point; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; + +public class Target implements Entity { + private volatile int x; + private volatile int y; + + public Target() { + this.x = 100; + this.y = 100; + } + + public Target(int x, int y) { + this.x = x; + this.y = y; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public void setTargetPosition(Point p) { + this.setX(p.x); + this.setY(p.y); + } + + public boolean isPositionCorrect(Dimension dimension) { + return this.x <= dimension.width && this.y <= dimension.height; + } + + public void update() { + } + + public void onStart(PropertyChangeSupport publisher) { + publisher.addPropertyChangeListener(this); + } + + public void propertyChange(PropertyChangeEvent evt) { + } +} diff --git a/robots/src/main/java/model/TypeRobot.java b/robots/src/main/java/model/TypeRobot.java new file mode 100644 index 000000000..5d169b871 --- /dev/null +++ b/robots/src/main/java/model/TypeRobot.java @@ -0,0 +1,27 @@ +package main.java.model; + +import java.awt.Color; +import java.util.List; +import java.util.Random; + +public enum TypeRobot { + CALM(Color.GREEN), + HUNGRY(Color.RED), + DEAD(Color.BLACK); + + private final Color color; + private static final Random RANDOM = new Random(); + private static final List VALUES = List.of(values()); + + public static TypeRobot randomType() { + return (TypeRobot)VALUES.get(RANDOM.nextInt(values().length - 2)); + } + + private TypeRobot(Color color) { + this.color = color; + } + + public Color getColor() { + return this.color; + } +} diff --git a/robots/src/main/java/view/GameDrawer.java b/robots/src/main/java/view/GameDrawer.java new file mode 100644 index 000000000..93c2fc185 --- /dev/null +++ b/robots/src/main/java/view/GameDrawer.java @@ -0,0 +1,20 @@ +package main.java.view; + +import main.java.model.Entity; + +import java.awt.*; + +public abstract class GameDrawer { + protected static void fillOval(Graphics g, int centerX, int centerY, int diam1, int diam2) { + g.fillOval(centerX - diam1 / 2, centerY - diam2 / 2, diam1, diam2); + } + + protected static void drawOval(Graphics g, int centerX, int centerY, int diam1, int diam2) { + g.drawOval(centerX - diam1 / 2, centerY - diam2 / 2, diam1, diam2); + } + + public abstract void draw(Graphics2D g, Entity entity); + + + public abstract Class getDrawingType(); +} diff --git a/robots/src/main/java/view/GameView.java b/robots/src/main/java/view/GameView.java new file mode 100644 index 000000000..bc33ab0b1 --- /dev/null +++ b/robots/src/main/java/view/GameView.java @@ -0,0 +1,58 @@ +package main.java.view; + +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.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import main.java.model.Entity; +import main.java.model.GameModel; +import main.java.model.Robot; +import main.java.model.Target; + +public class GameView extends JPanel { + private final GameModel gameModel; + private final Map, GameDrawer> map; + + public GameView(GameModel gameModel) { + this.gameModel = gameModel; + this.setDoubleBuffered(true); + this.map = new HashMap(); + this.map.put((new RobotDrawer()).getDrawingType(), new RobotDrawer()); + this.map.put((new TargetDrawer()).getDrawingType(), new TargetDrawer()); + this.setPreferredSize(new Dimension(600, 600)); + this.setSize(new Dimension(600, 600)); + this.setBorder(BorderFactory.createLineBorder(Color.RED)); + } + + public void updateView() { + this.onRedrawEvent(); + } + + protected void onRedrawEvent() { + EventQueue.invokeLater(this::repaint); + } + + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D)g; + RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHints(rh); + Iterator var4 = this.gameModel.getEntities().iterator(); + + while(var4.hasNext()) { + Entity entity = (Entity)var4.next(); + ((GameDrawer)this.map.get(entity.getClass())).draw(g2d, entity); + if (entity instanceof Robot) { + ((GameDrawer)this.map.get(Target.class)).draw(g2d, ((Robot)entity).getTarget()); + } + } + + } +} diff --git a/robots/src/main/java/view/RobotDrawer.java b/robots/src/main/java/view/RobotDrawer.java new file mode 100644 index 000000000..e2abec51e --- /dev/null +++ b/robots/src/main/java/view/RobotDrawer.java @@ -0,0 +1,54 @@ +package main.java.view; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import main.java.model.Entity; +import main.java.model.Robot; +import main.java.model.TypeRobot; + +public class RobotDrawer extends GameDrawer { + public RobotDrawer() { + } + + public void draw(Graphics2D g, Entity entity) { + Robot robot = (Robot)entity; + AffineTransform oldTransform = g.getTransform(); + int robotCenterX = (int)Math.round(robot.getPositionX()); + int robotCenterY = (int)Math.round(robot.getPositionY()); + AffineTransform l = new AffineTransform(oldTransform); + AffineTransform t = AffineTransform.getRotateInstance(robot.getRobotDirection(), (double)robotCenterX, (double)robotCenterY); + l.concatenate(t); + g.setTransform(l); + g.setColor(robot.getType().getColor()); + if (robot.getType().equals(TypeRobot.HUNGRY)) { + fillOval(g, robotCenterX, robotCenterY, 20, 10); + g.setColor(Color.BLACK); + drawOval(g, robotCenterX, robotCenterY, 20, 10); + g.setColor(Color.YELLOW); + } + + if (robot.getType().equals(TypeRobot.CALM)) { + fillOval(g, robotCenterX, robotCenterY, 25, 15); + g.setColor(Color.BLACK); + drawOval(g, robotCenterX, robotCenterY, 25, 15); + g.setColor(Color.WHITE); + } + + if (robot.getType().equals(TypeRobot.DEAD)) { + fillOval(g, robotCenterX, robotCenterY, 20, 10); + g.setColor(Color.WHITE); + drawOval(g, robotCenterX, robotCenterY, 20, 10); + g.setColor(Color.BLACK); + } + + fillOval(g, robotCenterX + 7, robotCenterY, 5, 5); + g.setColor(Color.BLACK); + drawOval(g, robotCenterX + 7, robotCenterY, 5, 5); + g.setTransform(oldTransform); + } + + public Class getDrawingType() { + return Robot.class; + } +} diff --git a/robots/src/main/java/view/TargetDrawer.java b/robots/src/main/java/view/TargetDrawer.java new file mode 100644 index 000000000..5cc58da8f --- /dev/null +++ b/robots/src/main/java/view/TargetDrawer.java @@ -0,0 +1,26 @@ +package main.java.view; + +import java.awt.Color; +import java.awt.Graphics2D; +import main.java.model.Entity; +import main.java.model.Target; + +public class TargetDrawer extends GameDrawer { + public TargetDrawer() { + } + + public void draw(Graphics2D g, Entity entity) { + Target target = (Target)entity; + if (target != null) { + g.setColor(Color.GREEN); + fillOval(g, target.getX(), target.getY(), 5, 5); + g.setColor(Color.BLACK); + drawOval(g, target.getX(), target.getY(), 5, 5); + } + + } + + public Class getDrawingType() { + return Target.class; + } +} diff --git a/robots/src/main/java/view/ViewModel.java b/robots/src/main/java/view/ViewModel.java new file mode 100644 index 000000000..9ac8c8250 --- /dev/null +++ b/robots/src/main/java/view/ViewModel.java @@ -0,0 +1,69 @@ +package main.java.view; + +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Timer; +import java.util.TimerTask; +import main.java.gui.GameWindow; +import main.java.model.GameModel; + +public class ViewModel { + private final GameModel gameModel; + private final GameWindow gameWindow; + private final Timer timer = initTimer(); + + private static Timer initTimer() { + return new Timer("events generator", true); + } + + public ViewModel(GameModel gameModel, GameWindow gameWindow) { + this.gameModel = gameModel; + this.gameWindow = gameWindow; + this.initListeners(); + } + + private void initListeners() { + this.timer.schedule(new TimerTask() { + public void run() { + ViewModel.this.gameModel.setDimension(ViewModel.this.gameWindow.getSize()); + ViewModel.this.getGameView().updateView(); + } + }, 0L, 5L); + this.timer.schedule(new TimerTask() { + public void run() { + ViewModel.this.gameModel.updateModel(); + } + }, 0L, 5L); + this.gameWindow.getGameView().addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + ViewModel.this.gameModel.setTarget(e.getPoint()); + ViewModel.this.getGameView().repaint(); + } + }); + this.gameWindow.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + super.componentResized(e); + System.out.println("resize"); + ViewModel.this.gameModel.setDimension(ViewModel.this.gameWindow.getSize()); + System.out.println(ViewModel.this.gameModel.getDimension()); + } + }); + this.gameWindow.getGameView().addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + System.out.println(e.getPoint()); + ViewModel.this.gameModel.setTarget(e.getPoint()); + ViewModel.this.getGameView().repaint(); + } + }); + } + + public GameView getGameView() { + return this.gameWindow.getGameView(); + } + + public GameWindow getGameWindow() { + return this.gameWindow; + } +} diff --git a/target/classes/main/java/gui/GameWindow.class b/target/classes/main/java/gui/GameWindow.class new file mode 100644 index 000000000..335ba1ee7 Binary files /dev/null and b/target/classes/main/java/gui/GameWindow.class differ diff --git a/target/classes/main/java/gui/LogWindow.class b/target/classes/main/java/gui/LogWindow.class new file mode 100644 index 000000000..72799906e Binary files /dev/null and b/target/classes/main/java/gui/LogWindow.class differ diff --git a/target/classes/main/java/gui/MainApplicationFrame.class b/target/classes/main/java/gui/MainApplicationFrame.class new file mode 100644 index 000000000..89647e6c5 Binary files /dev/null and b/target/classes/main/java/gui/MainApplicationFrame.class differ diff --git a/target/classes/main/java/gui/PositionWindow.class b/target/classes/main/java/gui/PositionWindow.class new file mode 100644 index 000000000..68b457143 Binary files /dev/null and b/target/classes/main/java/gui/PositionWindow.class differ diff --git a/target/classes/main/java/gui/RobotsProgram.class b/target/classes/main/java/gui/RobotsProgram.class new file mode 100644 index 000000000..83e760373 Binary files /dev/null and b/target/classes/main/java/gui/RobotsProgram.class differ diff --git a/target/classes/main/java/gui/Translatable.class b/target/classes/main/java/gui/Translatable.class new file mode 100644 index 000000000..04aa1cd4f Binary files /dev/null and b/target/classes/main/java/gui/Translatable.class differ diff --git a/target/classes/main/java/log/LogChangeListener.class b/target/classes/main/java/log/LogChangeListener.class new file mode 100644 index 000000000..490acfe49 Binary files /dev/null and b/target/classes/main/java/log/LogChangeListener.class differ diff --git a/target/classes/main/java/log/LogEntry.class b/target/classes/main/java/log/LogEntry.class new file mode 100644 index 000000000..851ee5c3f Binary files /dev/null and b/target/classes/main/java/log/LogEntry.class differ diff --git a/target/classes/main/java/log/LogLevel.class b/target/classes/main/java/log/LogLevel.class new file mode 100644 index 000000000..88eaf72a4 Binary files /dev/null and b/target/classes/main/java/log/LogLevel.class differ diff --git a/target/classes/main/java/log/LogWindowSource.class b/target/classes/main/java/log/LogWindowSource.class new file mode 100644 index 000000000..358e3cb6f Binary files /dev/null and b/target/classes/main/java/log/LogWindowSource.class differ diff --git a/target/classes/main/java/log/Logger.class b/target/classes/main/java/log/Logger.class new file mode 100644 index 000000000..bb1a92cfd Binary files /dev/null and b/target/classes/main/java/log/Logger.class differ diff --git a/target/classes/main/java/model/Entity.class b/target/classes/main/java/model/Entity.class new file mode 100644 index 000000000..254baba41 Binary files /dev/null and b/target/classes/main/java/model/Entity.class differ diff --git a/target/classes/main/java/model/GameModel$1.class b/target/classes/main/java/model/GameModel$1.class new file mode 100644 index 000000000..8d07e96cf Binary files /dev/null and b/target/classes/main/java/model/GameModel$1.class differ diff --git a/target/classes/main/java/model/GameModel.class b/target/classes/main/java/model/GameModel.class new file mode 100644 index 000000000..5b1a82277 Binary files /dev/null and b/target/classes/main/java/model/GameModel.class differ diff --git a/target/classes/main/java/model/Robot.class b/target/classes/main/java/model/Robot.class new file mode 100644 index 000000000..37c96380a Binary files /dev/null and b/target/classes/main/java/model/Robot.class differ diff --git a/target/classes/main/java/model/Target.class b/target/classes/main/java/model/Target.class new file mode 100644 index 000000000..0d6518bbc Binary files /dev/null and b/target/classes/main/java/model/Target.class differ diff --git a/target/classes/main/java/model/TypeRobot.class b/target/classes/main/java/model/TypeRobot.class new file mode 100644 index 000000000..3d97ff4e2 Binary files /dev/null and b/target/classes/main/java/model/TypeRobot.class differ diff --git a/target/classes/main/java/view/GameDrawer.class b/target/classes/main/java/view/GameDrawer.class new file mode 100644 index 000000000..141239f18 Binary files /dev/null and b/target/classes/main/java/view/GameDrawer.class differ diff --git a/target/classes/main/java/view/GameView.class b/target/classes/main/java/view/GameView.class new file mode 100644 index 000000000..8912b410b Binary files /dev/null and b/target/classes/main/java/view/GameView.class differ diff --git a/target/classes/main/java/view/RobotDrawer.class b/target/classes/main/java/view/RobotDrawer.class new file mode 100644 index 000000000..00c3e89e4 Binary files /dev/null and b/target/classes/main/java/view/RobotDrawer.class differ diff --git a/target/classes/main/java/view/TargetDrawer.class b/target/classes/main/java/view/TargetDrawer.class new file mode 100644 index 000000000..0e428003e Binary files /dev/null and b/target/classes/main/java/view/TargetDrawer.class differ diff --git a/target/classes/main/java/view/ViewModel$1.class b/target/classes/main/java/view/ViewModel$1.class new file mode 100644 index 000000000..452ca5abf Binary files /dev/null and b/target/classes/main/java/view/ViewModel$1.class differ diff --git a/target/classes/main/java/view/ViewModel$2.class b/target/classes/main/java/view/ViewModel$2.class new file mode 100644 index 000000000..3227a5e49 Binary files /dev/null and b/target/classes/main/java/view/ViewModel$2.class differ diff --git a/target/classes/main/java/view/ViewModel$3.class b/target/classes/main/java/view/ViewModel$3.class new file mode 100644 index 000000000..4896743d4 Binary files /dev/null and b/target/classes/main/java/view/ViewModel$3.class differ diff --git a/target/classes/main/java/view/ViewModel$4.class b/target/classes/main/java/view/ViewModel$4.class new file mode 100644 index 000000000..660924a0e Binary files /dev/null and b/target/classes/main/java/view/ViewModel$4.class differ diff --git a/target/classes/main/java/view/ViewModel$5.class b/target/classes/main/java/view/ViewModel$5.class new file mode 100644 index 000000000..e674289d2 Binary files /dev/null and b/target/classes/main/java/view/ViewModel$5.class differ diff --git a/target/classes/main/java/view/ViewModel.class b/target/classes/main/java/view/ViewModel.class new file mode 100644 index 000000000..d26139efb Binary files /dev/null and b/target/classes/main/java/view/ViewModel.class differ