Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions robots/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions robots/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions robots/.idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions robots/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions robots/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

173 changes: 47 additions & 126 deletions robots/src/gui/GameVisualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,37 @@
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JPanel;

public class GameVisualizer extends JPanel
public class GameVisualizer extends JPanel implements Observer
{
private final Timer m_timer = initTimer();

private static Timer initTimer()
private final Timer timer = initTimer();
private final RobotModel model;

private static Timer initTimer()
{
Timer timer = new Timer("events generator", true);
return timer;
return new Timer("events generator", true);
}

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(RobotModel model)
{
m_timer.schedule(new TimerTask()
this.model = model;
this.model.addObserver(this);

timer.schedule(new TimerTask()
{
@Override
public void run()
{
onRedrawEvent();
}
}, 0, 50);
m_timer.schedule(new TimerTask()
timer.schedule(new TimerTask()
{
@Override
public void run()
Expand All @@ -57,154 +52,80 @@ public void run()
public void mouseClicked(MouseEvent e)
{
setTargetPosition(e.getPoint());
repaint();
}
});
setDoubleBuffered(true);
}

protected void setTargetPosition(Point p)
protected void setTargetPosition(Point point)
{
m_targetPositionX = p.x;
m_targetPositionY = p.y;
model.setTargetPosition(point);
}

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;
model.update();
}

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);
return (int) (value + 0.5);
}

@Override
public void paint(Graphics g)
public void paint(Graphics graphics)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
drawRobot(g2d, round(m_robotPositionX), round(m_robotPositionY), m_robotDirection);
drawTarget(g2d, m_targetPositionX, m_targetPositionY);
super.paint(graphics);
Graphics2D g2d = (Graphics2D) graphics;
drawRobot(g2d, round(model.getRobotPositionX()), round(model.getRobotPositionY()), model.getRobotDirection());
drawTarget(g2d, model.getTargetPositionX(), model.getTargetPositionY());
}

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);
AffineTransform oldTransform = g.getTransform();
AffineTransform rotateTransform = AffineTransform.getRotateInstance(direction, x, y);
g.setTransform(rotateTransform);
g.setColor(Color.MAGENTA);
fillOval(g, robotCenterX, robotCenterY, 30, 10);
fillOval(g, x, y, 30, 10);
g.setColor(Color.BLACK);
drawOval(g, robotCenterX, robotCenterY, 30, 10);
drawOval(g, x, y, 30, 10);
g.setColor(Color.WHITE);
fillOval(g, robotCenterX + 10, robotCenterY, 5, 5);
fillOval(g, x + 10, y, 5, 5);
g.setColor(Color.BLACK);
drawOval(g, robotCenterX + 10, robotCenterY, 5, 5);
drawOval(g, x + 10, y, 5, 5);
g.setTransform(oldTransform);
}

private void drawTarget(Graphics2D g, int x, int y)
{
AffineTransform t = AffineTransform.getRotateInstance(0, 0, 0);
g.setTransform(t);
AffineTransform oldTransform = g.getTransform();
g.setTransform(AffineTransform.getRotateInstance(0, 0, 0));
g.setColor(Color.GREEN);
fillOval(g, x, y, 5, 5);
g.setColor(Color.BLACK);
drawOval(g, x, y, 5, 5);
g.setTransform(oldTransform);
}

@Override
public void update(Observable observable, Object arg)
{
onRedrawEvent();
}
}
9 changes: 5 additions & 4 deletions robots/src/gui/GameWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

public class GameWindow extends JInternalFrame
{
private final GameVisualizer m_visualizer;
public GameWindow()
private final GameVisualizer visualizer;

public GameWindow(RobotModel model)
{
super("Игровое поле", true, true, true, true);
m_visualizer = new GameVisualizer();
visualizer = new GameVisualizer(model);
JPanel panel = new JPanel(new BorderLayout());
panel.add(m_visualizer, BorderLayout.CENTER);
panel.add(visualizer, BorderLayout.CENTER);
getContentPane().add(panel);
pack();
}
Expand Down
Loading