翻转旋转和图像

我正在编写一个Java平台游戏,我正在手动编写播放器动画。 我分别为每个肢体制作动画,改变位置和旋转。 当玩家面向右侧时,此function正常,但当玩家面向左侧时,我不知道如何处理旋转以使玩家向左转时看起来相同。 每个身体部位的位置都是相对于玩家的x和y值存储的,所以我真的需要一种方法来水平翻转旋转。 我知道我并没有很好地解释这一点,但如果有人理解我想说的并且可以提供帮助,我会非常感激。 先谢谢你。 🙂

因此,基本思想是通过将一个轴缩放一个负值( -1 )来简单地翻转/镜像Graphics上下文。

这可以通过简单地使用Graphics#scale来实现,例如,水平翻转图形,您只需使用

 graphics.scale(-1, 1); 

您需要使用可视区域的宽度来翻译Graphics ,并使用Graphics#translate在可视区域内重新定位图像。

在此之后绘制的所有内容都将受到更改的影响。 因此,您应该在每次重大更改之前拍摄Graphics上下文的快照,只需确保在完成disposedispose

这是一个(相当可悲的动画明智)示例……基本上,当您按下左箭头或右箭头时,会翻转一个标志并重新绘制场景。 根据标志, Graphics上下文被翻转/镜像…

小马跑

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class AnimateCharacter { public static void main(String[] args) { new AnimateCharacter(); } public AnimateCharacter() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private BufferedImage body; private BufferedImage[] legs; private double[] angels; private double[] deltas; private Point[] pivots = new Point[]{ // Foreground... new Point(100, 227), // Foreleg new Point(155, 201), // Hindleg // Background... new Point(93, 218), // Foreleg new Point(143, 195), // Hindleg }; private Point[] locations = new Point[]{ // Foreground... new Point(67, 221), // Foreleg new Point(124, 172), // Hindleg // Background... new Point(60, 219), // Foreleg new Point(112, 166), // Hindleg }; private int direction = 1; public TestPane() { legs = new BufferedImage[4]; angels = new double[]{ 45, 40, -5, 0 }; deltas = new double[]{ -4, -4, 4, 4 }; try { body = ImageIO.read(getClass().getResource("/Body.png")); // Foreground... legs[0] = ImageIO.read(getClass().getResource("/ForeLeg.png")); legs[1] = ImageIO.read(getClass().getResource("/HindLeg.png")); // Background... legs[2] = ImageIO.read(getClass().getResource("/ForeLeg.png")); legs[3] = ImageIO.read(getClass().getResource("/HindLeg.png")); } catch (IOException exp) { exp.printStackTrace(); } Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (int index = 0; index < angels.length; index++) { angels[index] += deltas[index]; if (angels[index] < -45) { angels[index] = -45; deltas[index] *= -1; } else if (angels[index] > 45) { angels[index] = 45; deltas[index] *= -1; } } repaint(); } }); timer.start(); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right"); am.put("left", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { direction = 1; repaint(); } }); am.put("right", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { direction = -1; repaint(); } }); } @Override public Dimension getPreferredSize() { return body == null ? new Dimension(200, 200) : new Dimension(body.getWidth() + 50, body.getHeight() + 50); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); applyQualityRenderingHints(g2d); int x = (getWidth() - body.getWidth()) / 2; int y = (getHeight() - body.getHeight()) / 2; if (direction < 0) { g2d.scale(-1, 1); g2d.translate(-getWidth(), 0); } // Background legs... drawLegs(g2d, x, y, 2); g2d.drawImage(body, x, y, this); // Foreground legs... drawLegs(g2d, x, y, 0); g2d.dispose(); } protected void drawLegs(Graphics2D g2d, int x, int y, int offset) { for (int index = 0; index < 2; index++) { Graphics2D copy = (Graphics2D) g2d.create(); copy.translate(x, y); int leg = index + offset; int pivotX = pivots[leg].x; int pivotY = pivots[leg].y; copy.rotate(Math.toRadians(angels[leg]), pivotX, pivotY); copy.drawImage( legs[leg], locations[leg].x, locations[leg].y, this); copy.dispose(); } } public void applyQualityRenderingHints(Graphics2D g2d) { g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); // g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } } } 

魔术发生在一些地方......

首先复制Graphics上下文,然后使用scale翻转(如果需要)...

 protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); //... if (direction < 0) { g2d.scale(-1, 1); g2d.translate(-getWidth(), 0); } 

在画腿时我也使用相同的技术......

 protected void drawLegs(Graphics2D g2d, int x, int y, int offset) { for (int index = 0; index < 2; index++) { Graphics2D copy = (Graphics2D) g2d.create(); copy.translate(x, y); //... copy.rotate(Math.toRadians(angels[leg]), pivotX, pivotY); copy.drawImage( legs[leg], locations[leg].x, locations[leg].y, this); copy.dispose(); } 

这将更改隔离到Graphics上下文的副本,每个副本将inheritance它的父级的当前状态,使这成为一个非常有用的技术...