Skip to content
Open
138 changes: 15 additions & 123 deletions robots/src/gui/GameVisualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,27 @@
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;
import javax.swing.*;

import static gui.RobotModel.round;

public class GameVisualizer extends JPanel
{
public RobotModel robotModel = new RobotModel();
public RobotCoordinatesWindow robotCoordinatesWindow = new RobotCoordinatesWindow(robotModel);
private final Timer m_timer = initTimer();

private static 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()
public GameVisualizer()
{
m_timer.schedule(new TimerTask()
{
Expand All @@ -48,128 +39,31 @@ public void run()
@Override
public void run()
{
onModelUpdateEvent();
robotModel.onModelUpdateEvent();
}
}, 0, 10);
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
setTargetPosition(e.getPoint());
robotModel.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);
Graphics2D g2d = (Graphics2D)g;
drawRobot(g2d, round(robotModel.m_robotPositionX), round(robotModel.m_robotPositionY), robotModel.m_robotDirection);
drawTarget(g2d, robotModel.m_targetPositionX, robotModel.m_targetPositionY);
}

private static void fillOval(Graphics g, int centerX, int centerY, int diam1, int diam2)
Expand All @@ -181,12 +75,11 @@ private static void drawOval(Graphics g, int centerX, int centerY, int diam1, in
{
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);
int robotCenterX = round(robotModel.m_robotPositionX);
int robotCenterY = round(robotModel.m_robotPositionY);
AffineTransform t = AffineTransform.getRotateInstance(robotModel.m_robotDirection, robotCenterX, robotCenterY);
g.setTransform(t);
g.setColor(Color.MAGENTA);
fillOval(g, robotCenterX, robotCenterY, 30, 10);
Expand All @@ -197,7 +90,6 @@ private void drawRobot(Graphics2D g, int x, int y, double direction)
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);
Expand Down
18 changes: 11 additions & 7 deletions robots/src/gui/GameWindow.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package gui;

import java.awt.BorderLayout;
import java.util.ResourceBundle;

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();
public class GameWindow extends JInternalFrame {
public final GameVisualizer m_visualizer = new GameVisualizer();
//private ResourceBundle messages;

public GameWindow() {
super(MainApplicationFrame.messages.getString("game.window.title"), true, true, true, true);
JPanel panel = new JPanel(new BorderLayout());
panel.add(m_visualizer, BorderLayout.CENTER);
getContentPane().add(panel);
pack();
}

public void updateTitle() {
setTitle(MainApplicationFrame.messages.getString("game.window.title"));
}
}
7 changes: 6 additions & 1 deletion robots/src/gui/LogWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class LogWindow extends JInternalFrame implements LogChangeListener

public LogWindow(LogWindowSource logSource)
{
super("Протокол работы", true, true, true, true);
super(MainApplicationFrame.messages.getString("protocol.window.title"), true, true, true, true);
m_logSource = logSource;
m_logSource.registerListener(this);
m_logContent = new TextArea("");
Expand All @@ -29,6 +29,7 @@ public LogWindow(LogWindowSource logSource)
getContentPane().add(panel);
pack();
updateLogContent();
updateTitleP();
}

private void updateLogContent()
Expand All @@ -40,6 +41,10 @@ private void updateLogContent()
}
m_logContent.setText(content.toString());
m_logContent.invalidate();
updateTitleP();
}
public void updateTitleP() {
setTitle(MainApplicationFrame.messages.getString("protocol.window.title"));
}

@Override
Expand Down
Loading