How to implement a rectangle control ( graphics2d package, drawRect() ) through the keyboard, and so that it can not only move, but also rotate (wsad and arrows, respectively)? rectangle drawing function:

 public void paint(Graphics g) { Graphics2D gty = (Graphics2D) g; g2d.drawRect(rob_body_x, rob_body_y, rob_body_length, rob_body_width); } 

    1 answer 1

    Here is an example, study, ask questions.

    The idea is that by pressing and lowering the keys, the speed of movement or rotation in a certain direction smoothly changes.

    And during drawing speed is multiplied by the time elapsed from the previous frame to ensure uniform movement between frames, which in fact can be drawn at different times.

    The logic of movement is:

     Action action = actions.get(key); if (action.pressed) action.speed = Math.min(action.speed + dt, 1); else if (action.speed > 0) action.speed = Math.max(action.speed - dt, 0); float dir = key == KeyEvent.VK_W || key == KeyEvent.VK_D ? 1 : -1; if (key == KeyEvent.VK_W || key == KeyEvent.VK_S) { y += Math.sin(r) * action.speed * dir; x += Math.cos(r) * action.speed * dir; } if (key == KeyEvent.VK_A || key == KeyEvent.VK_D) r += action.speed / 30 * dir; 

    But drawing, first we move and rotate the context, and then draw a rectangle:

     Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHints(rh); g2d.clearRect(0,0, 10000, 10000); g2d.translate(x + w/2, y + h/2); g2d.rotate(r); g2d.translate(-w/2, -h/2); g2d.fillRect(0, 0, (int) w, (int) h); 

     import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Map; public class Rect extends JPanel implements KeyListener{ RenderingHints rh = new RenderingHints( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); private class Action { boolean pressed; float speed; } long t = 0; float x = 100; float y = 100; float w = 40; float h = 60; float r = 0; Map<Integer, Action> actions = new HashMap<Integer, Action>(){{ put(KeyEvent.VK_W, new Action()); put(KeyEvent.VK_S, new Action()); put(KeyEvent.VK_A, new Action()); put(KeyEvent.VK_D, new Action()); }}; @Override public void paint(Graphics g) { tick(); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHints(rh); g2d.clearRect(0,0, 10000, 10000); g2d.translate(x +w/2, y+h/2); g2d.rotate(r); g2d.translate(-w/2, -h/2); g2d.fillRect(0, 0, (int)w, (int) h); g2d.dispose(); } private void tick() { long millis = System.currentTimeMillis(); float dt = (millis - t) / 300f; for (Integer key : actions.keySet()) { Action action = actions.get(key); if (action.pressed) action.speed = Math.min(action.speed + dt, 1); else if (action.speed > 0) action.speed = Math.max(action.speed - dt, 0); float dir = key == KeyEvent.VK_W || key == KeyEvent.VK_D ? 1 : -1; if (key == KeyEvent.VK_W || key == KeyEvent.VK_S) { y += Math.sin(r) * action.speed * dir; x += Math.cos(r) * action.speed * dir; } if (key == KeyEvent.VK_A || key == KeyEvent.VK_D) r += action.speed / 30 * dir; } t = millis; } Rect() { t = System.currentTimeMillis(); new Timer(11, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { repaint(); } }).start(); } public static void main(String[] args) { JFrame f = new JFrame(); Rect rect = new Rect(); f.add(rect); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.setSize(500, 500); f.setLocationRelativeTo(null); f.setVisible(true); f.addKeyListener(rect); } @Override public void keyTyped(KeyEvent e) {} @Override public void keyPressed(KeyEvent e) { act(e, true); } @Override public void keyReleased(KeyEvent e) { act(e, false); } void act(KeyEvent e, boolean state){ Action action = actions.get(e.getKeyCode()); if (null != action) action.pressed = state; } } 

    Upd: I made a move forward and backward, in the direction in which the rectangle and turn "look", but now I re-read the question and understood that you wanted it wrong, but easier, turn the arrows ... well, you already, I hope with this Handle, the general meaning will not change.