翻转旋转和图像

2024-05-06

我正在用 Java 编写一个平台游戏,并且正在手动编码玩家动画。我分别为每个肢体设置动画,改变位置和旋转。当玩家面向右时,这工作得很好,但是当玩家面向左时,我不知道如何处理旋转,以使它们在玩家向左转时看起来相同。每个身体部位的位置都是相对于玩家的 x 和 y 值存储的,因此我确实需要一种水平翻转旋转的方法。我知道我解释得不是很好,但如果有人理解我想说的并且可以提供帮助,我将非常感激。先感谢您。 :)


所以基本的想法是简单地翻转/镜像Graphics通过将轴之一缩放负值(-1).

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

graphics.scale(-1, 1);

您需要翻译Graphics通过可视区域的宽度以及使用Graphics#translate将图像重新定位在可视区域内。

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

这是一个(相当可悲的动画明智的)示例......基本上,当您按向左或向右箭头时,标志会翻转并重新绘制场景。根据标志的不同,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);

        }
    }

}

魔法发生在几个地方......

The 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在上下文中,每个副本都将继承其父级的当前状态,这使得这是一项非常有用的技术......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

翻转旋转和图像 的相关文章

  • 如何在 JFace 的 TableViewer 中创建复选框?

    我创建了一个包含两列的 tableViewer 我想将其中一列设为复选框 为此 我创建了一个 CheckBoxCellEditor 但我不知道为什么它不起作用 名为 tableName 的列显示其值正常 色谱柱规格如下 String COL
  • 在Windows上安装Java 11 OpenJDK(系统路径问题)

    Java 11 最近发布了 众所周知 这个版本没有安装文件 当然 要在没有安装程序的情况下安装 Java 我将系统设置 PATH 和 JAVA HOME 设置为解压缩 Java 11 的文件夹的地址 根据对类似问题的已接受回复建议 唯一的事
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • 解决错误:日志已在具有多个实例的atomikos中使用

    我仅在使用atomikos的实时服务器上遇到问题 在我的本地服务器上它工作得很好 我在服务器上面临的问题是 init 中出错 日志已在使用中 完整的异常堆栈跟踪 java lang RuntimeException Log already
  • Java8无符号算术

    据广泛报道 Java 8 具有对无符号整数的库支持 然而 似乎没有文章解释如何使用它以及有多少可能 有些函数 例如 Integer CompareUnsigned 很容易找到 并且似乎可以实现人们所期望的功能 但是 我什至无法编写一个简单的
  • IntelliJ IDEA 创建的 JAR 文件无法运行

    我在 IntelliJ 中编写了一个跨越几个类的程序 当我在 IDE 中测试它时它运行良好 但是 每当我按照教程将项目制作成 jar 可执行文件时 它就不会运行 双击 out 文件夹中的文件时 该文件不会运行 并显示 无法启动 Java J
  • CXF Swagger2功能添加安全定义

    我想使用 org apache cxf jaxrs swagger Swagger2Feature 将安全定义添加到我的其余服务中 但是我看不到任何相关方法或任何有关如何执行此操作的资源 下面是我想使用 swagger2feature 生成
  • 使用替换字符串中多个单词的最有效方法[重复]

    这个问题在这里已经有答案了 此刻我正在做 Example line replaceAll replaceAll cat dog replaceAll football rugby 我觉得那很丑 不确定有更好的方法吗 也许循环遍历哈希图 ED
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • Clip 在 Java 中播放 WAV 文件时出现严重延迟

    我编写了一段代码来读取 WAV 文件 大小约为 80 mb 并播放该文件 问题是声音播放效果很差 极度滞后 你能告诉我有什么问题吗 这是我的代码 我称之为doPlayJframe 构造函数内的函数 private void doPlay f
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • org.jdesktop.application 包不存在

    几天以来我一直在构建一个 Java 桌面应用程序 一切都很顺利 但是今天 当我打开Netbeans并编译文件时 出现以下编译错误 Compiling 9 source files to C Documents and Settings Ad
  • Java中未绑定通配符泛型的用途和要点是什么?

    我不明白未绑定通配符泛型有什么用 具有上限的绑定通配符泛型 stuff for Object item stuff System out println item Since PrintStream println 可以处理所有引用类型 通
  • Tomcat 6找不到mysql驱动

    这里有一个类似的问题 但关于类路径 ClassNotFoundException com mysql jdbc Driver https stackoverflow com questions 1585811 classnotfoundex
  • Windows 上的 Nifi 命令

    在我当前的项目中 我一直在Windows操作系统上使用apache nifi 我已经提取了nifi 0 7 0 bin zip文件输入C 现在 当我跑步时 bin run nifi bat as 管理员我在命令行上看到以下消息 但无法运行
  • 如何测试 spring-security-oauth2 资源服务器安全性?

    随着 Spring Security 4 的发布改进了对测试的支持 http docs spring io spring security site docs 4 0 x reference htmlsingle test我想更新我当前的
  • 休眠以持久保存日期

    有没有办法告诉 Hibernate java util Date 应该持久保存 我需要这个来解决 MySQL 中缺少的毫秒分辨率问题 您能想到这种方法有什么缺点吗 您可以自己创建字段long 或者使用自定义的UserType 实施后User
  • 如何修复“sessionFactory”或“hibernateTemplate”是必需的问题

    我正在使用 Spring Boot JPA WEB 和 MYSQL 创建我的 Web 应用程序 它总是说 sessionFactory or hibernateTemplate是必需的 我该如何修复它 我已经尝试过的东西 删除了本地 Mav
  • KeyPressed 和 KeyTyped 混淆[重复]

    这个问题在这里已经有答案了 我搜索过之间的区别KeyPressedand KeyTyped事件 但我仍然不清楚 我发现的一件事是 Keypressed 比 KeyTyped 首先被触发 请澄清一下这些事件何时被准确触发 哪个适合用于哪个目的
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是

随机推荐

  • 如何从字典构造defaultdict?

    如果我有d dict zip range 1 10 range 50 61 我怎样才能建立一个collections defaultdict出于dict 唯一的论点defaultdict似乎采取的是工厂功能 我必须初始化然后再经历原来的d并
  • 当用户的角色没有足够的权限时,将用户从 web.config 重定向到另一个页面

    我正在使用 ASP NET 我希望能够将用户从 Web 配置重定向到另一个页面 我有很多限制 例如
  • 如何使用xampp连接sql服务器和php?

    我正在尝试使用 Xampp 将我的 SQL 服务器与 PHP 连接 我已经在ext文件夹中上传了dll文件 但无法连接它 我的PHP版本是7 2 6 上传的dll文件是 php pdo sqlsrv 72 ts dll php sqlsrv
  • CSV 数据中的逗号

    我有一个 CSV 文件 我将其直接导入到 SQL Server 表中 在 CSV 文件中 每一列都用逗号分隔 但我的问题是我有一个 地址 列 并且该列中的数据包含逗号 所以发生的情况是 地址列的一些数据将转到其他列 并将导入到 SQL Se
  • .class:hover 在 Firefox 中不起作用?

    所以我有一些html a class clicktext read more a 我想给它一个 hover 动画 如下所示 clicktext clicktext hover text decoration underline clickt
  • 注释扩展函数的惰性求值

    我编写了一个函数来扩展组内的注释 function data group col expand col data gt dplyr group by rlang ensym group col gt dplyr mutate rlang e
  • 在 Cocoa 应用程序中验证用户输入的 URL 的最佳方法是什么?

    我正在尝试构建一个自制的网络浏览器 以更加熟练地使用 Cocoa 我需要一种好方法来验证用户是否输入了有效的 URL 我尝试过一些正则表达式 但 NSString 有一些有趣的怪癖 并且不喜欢我见过的大多数正则表达式使用的一些反引号 你可以
  • Python数据框将列表列分解为多行[重复]

    这个问题在这里已经有答案了 我有一个像这样的数据框 desc id info a b c 2 type u v w 18 tail 三列 desc id info desc 是一个列表 我想要这个 des id info a 2 type
  • JAVA GENERICS错误:具有相同的擦除,但两者都没有覆盖另一个[重复]

    这个问题在这里已经有答案了 为了好玩 我正在创建一个排序框架 以更好地理解各种排序算法 而且 我试图使其足够通用 以便它可以对实现扩展可比较接口的接口的任何内容进行排序 然而 java 编译器对我不满意 这是我的界面 public inte
  • 如何覆盖!重要?

    我创建了一个自定义样式表 它覆盖了我的 WordPress 模板的原始 CSS 但是 在我的日历页面上 原始 CSS 将每个表格单元格的高度设置为 important宣言 td height 100px important 有什么方法可以覆
  • 尝试从 npm 安装 Angular 2 Material - 源文本中无法识别的标记

    我从 PowerShell 尝试以下命令 以管理员身份 npm install angular2 material 并得到错误 Unrecognized token in source text At line 1 char 13 npm
  • 是否可以更改 Android L TimePickerDialog 的样式?

    我正在 Android L 模拟器上测试我的应用程序 我注意到 TimePickerDialog 已显着更改为 这与我的应用程序的主题不符 我想知道在 Android L 上运行时是否可以获得旧的 TimePickerDialog 样式 A
  • jekyll 变量,if 函数

    为什么这样的东西不起作用 我尝试过滤今年的所有帖子 div class tiles for post in site categories articles capture pubyear post date date Y endcaptu
  • 通过访问硬盘序列号来保护软件[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想获得VB NET或VB代码来在启
  • 静态方法而不是原型方法Javascript

    当在类中调用实例函数时 对象的每个实例都会获得自己的函数副本 但在原型方法和静态方法中不会创建副本 它们属于类 所以如果它们都没有创建其函数的副本 那么为什么如果我们不想复制 可以简单地使用原型方法 那么我们是否有静态函数 我有点困惑 如果
  • 使用 SimpleXML 从 XML 获取多个项目

    我正在尝试使用下面的代码循环 XML 中的多个项目 xml get data the url data simplexml load string xml foreach data gt item AS item foreach item
  • 在 iOS 8 上本地化用户

    你好 我开始将我的应用程序移植到 iOS 8 但很快我就遇到了 CLLocationManager 的问题 基本上 该应用程序不再将地图集中在用户位置上 而是提出错误 尝试启动 MapKit 位置更新而不提示位置授权 必须首先调用 CLLo
  • Jasmine的spyOn()是否允许执行spies on函数?

    茉莉花有吗spyOn 方法允许执行监视函数 或者确实是这样 当 即将 调用监视方法时拦截调用 并返回true PS 谁能给我解释一下spyOn 的内部运作 Spy 间谍可以伪装成一个函数或一个对象 您可以在编写单元测试代码时使用它们来检查函
  • 'NSDate' 没有可见的 @interface 声明选择器 'initWithString:' [重复]

    这个问题在这里已经有答案了 可能的重复 NSDate initWithString https stackoverflow com questions 7770257 nsdate initwithstring 我写了下面一行代码 NSDa
  • 翻转旋转和图像

    我正在用 Java 编写一个平台游戏 并且正在手动编码玩家动画 我分别为每个肢体设置动画 改变位置和旋转 当玩家面向右时 这工作得很好 但是当玩家面向左时 我不知道如何处理旋转 以使它们在玩家向左转时看起来相同 每个身体部位的位置都是相对于