ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

如何在Java中独立旋转对象/图像?

2019-10-03 03:01:41  阅读:167  来源: 互联网

标签:java animation rotation transform


我试图让一系列矩形围绕它们各自的中心旋转并向右移动,但由于该平面包含所有矩形,所有矩形一致地围绕最新添加的矩形的中心旋转,而不是围绕它们各自的中心独立旋转.以下是代码:

主要方案:

import java.awt.Graphics2D;
import java.util.ArrayList;

public class Rectangles {

    public static final int SCREEN_WIDTH = 400;
    public static final int SCREEN_HEIGHT = 400;

    public static void main(String[] args) throws Exception {
        Rectangles game = new Rectangles();
        game.play();
    }

    public void play() {
        board.setupAndDisplay();
    }

    public Rectangles() {
        board = new Board(SCREEN_WIDTH, SCREEN_HEIGHT, this);
        rectangle_2 = new Rectangle_2();
        rectangles = new ArrayList<Rectangle_2>();
    }

    public void drawRectangles(Graphics2D g, float elapsedTime) {
        ticks++;
        if (ticks % 4000 == 0) {
            Rectangle_2 rectangle = new Rectangle_2();
            rectangles.add(rectangle);
        }
        rotateRectangles(g);
        drawRectangles(g);
        moveRectangles(elapsedTime);

        for (int i = 0; i < rectangles.size(); i++) {
            Rectangle_2 rectangle = rectangles.get(i);
            if (rectangle.getX() < -75) {
                rectangles.remove(i);
                i--;
            }
        }
    }

    public void drawRectangles(Graphics2D g) {
        for (Rectangle_2 rectangle: rectangles) {
            rectangle.drawRectangle(g);
        }
    }

    public void rotateRectangles(Graphics2D g) {
        for (Rectangle_2 rectangle: rectangles) {
            rectangle.rotateRectangle(g);
        }
    }

    public void moveRectangles(float elapsedTime) {
        for (Rectangle_2 rectangle: rectangles) {
            rectangle.move(10 * elapsedTime);
        }
    }

    private Board board;
    private Rectangle_2 rectangle_2;
    private int ticks = 0;
    private ArrayList<Rectangle_2> rectangles;
}

矩形类:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Rectangle_2 {

    public Rectangle_2() {
        x = 0;
        y = 200;
        rectangle = new Rectangle((int) x, (int) y, 25, 25);
    }

    public void drawRectangle(Graphics2D g) {
        g.setColor(Color.red);
        g.draw(rectangle);
    }

    public void rotateRectangle(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        angle += 0.001;
        g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
        g2.setColor(Color.red);
    }

    public void move(float elapsedTime) {
        x = x + elapsedTime;
        rectangle.setLocation((int) x, (int) y);
    }

    public boolean collides(Rectangle r) {
        return r.intersects(rectangle);
    }

    @Override
    public String toString() {
        return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public double getX() {
        return x;
    }

    private double x;
    private double y;
    private double angle = 0;
    private Rectangle rectangle;
}

动画发生的棋盘类:

import java.awt.*;
import javax.swing.*;

public class Board extends JPanel {

    private static final long serialVersionUID = 1L;

    public Board(int width_, int height_, Rectangles simulator_) {
        width = width_;
        height = height_;
        game = simulator_;
        lastTime = -1L;
    }

    public void setupAndDisplay() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JScrollPane(this));
        f.setSize(width, height);
        f.setLocation(200, 200);
        f.setVisible(true);
        this.setFocusable(true);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        boolean first = (lastTime == -1L);
        long elapsedTime = System.nanoTime() - lastTime;
        lastTime = System.nanoTime();
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        g.setColor(Color.white);
        game.drawRectangles((Graphics2D) g, (first ? 0.0f : (float) elapsedTime / 1e9f));
        repaint();
    }

    private int width;
    private int height;
    private long lastTime;
    private Rectangles game;
}

请注意,由于实施了延迟,矩形需要几秒钟才能显示.谢谢 :).

解决方法:

Graphics上下文是一个共享资源,也就是说,在单个绘制周期中,所有组件都获得相同的Graphics上下文.您对Graphics上下文所做的任何更改也会被维护(或者在相同转换的情况下复合).所以这意味着,每次调用Graphics#rotate时,实际上都会复合可能已在其上执行的任何先前旋转.

你需要以两种方式改变你的代码……

>您需要独立的更新周期,与油漆周期无关
>在应用任何转换之前,创建Graphics上下文的本地副本

例如…

enter image description here

矩形成为主要的驱动器/引擎.它负责管理实体并在每个周期更新它们.通常情况下,我会使用某种描述其他情况可能使用的功能的界面,但是你明白了

public class Rectangles {

    public static void main(String[] args) throws Exception {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }
                Rectangles game = new Rectangles();
                game.play();
            }
        });
    }

    public void play() {

        Board board = new Board(this);

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(board);
        f.pack();
        f.setLocation(200, 200);
        f.setVisible(true);
        Timer timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                updateRectangles();
                board.repaint();
                lastTime = System.nanoTime();
            }
        });
        timer.start();
    }

    public Rectangles() {
        rectangle_2 = new Rectangle_2();
        rectangles = new ArrayList<Rectangle_2>();
    }

    protected void updateRectangles() {
        boolean first = (lastTime == -1L);
        double elapsedTime = System.nanoTime() - lastTime;
        elapsedTime = (first ? 0.0f : (float) elapsedTime / 1e9f);

        ticks++;
        if (ticks <= 1 || ticks % 100 == 0) {
            Rectangle_2 rectangle = new Rectangle_2();
            rectangles.add(rectangle);
        }

        rotateRectangles();
        moveRectangles(elapsedTime);


        for (int i = 0; i < rectangles.size(); i++) {
            Rectangle_2 rectangle = rectangles.get(i);
            if (rectangle.getX() < -75) {
                rectangles.remove(i);
                i--;
            }
        }
    }

    public void drawRectangles(Graphics2D g) {
        for (Rectangle_2 rectangle : rectangles) {
            rectangle.drawRectangle(g);
        }
    }

    protected void rotateRectangles() {
        for (Rectangle_2 rectangle : rectangles) {
            rectangle.rotateRectangle();
        }
    }

    protected void moveRectangles(double elapsedTime) {
        for (Rectangle_2 rectangle : rectangles) {
            rectangle.move(10 * elapsedTime);
        }
    }

    private long lastTime = -1L;
    private Rectangle_2 rectangle_2;
    private int ticks = 0;
    private ArrayList<Rectangle_2> rectangles;
}

Board变成了可以渲染实体的表面

public class Board extends JPanel {

    public Board(Rectangles engine) {
        game = engine;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        game.drawRectangles((Graphics2D) g);
    }

    private Rectangles game;
}

而Rectangle_2是一个简单的信息容器,它知道在有机会时如何绘制自己.您将注意到移动和旋转方法只是更新状态,它们什么都不做.

drawRectangle首先创建提供的Graphics2D上下文的副本,然后应用它的更改并呈现矩形,完成后,它调用dispose来处理副本

public class Rectangle_2 {

    public Rectangle_2() {
        x = 0;
        y = 200;
        rectangle = new Rectangle((int) x, (int) y, 25, 25);
    }

    public void drawRectangle(Graphics2D g) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
        g2.setColor(Color.red);
        g2.draw(rectangle);
        g2.dispose();
    }

    public void rotateRectangle() {
        angle += 0.001;
    }

    public void move(double elapsedTime) {
        x = x + elapsedTime;
        rectangle.setLocation((int) x, (int) y);
    }

    public boolean collides(Rectangle r) {
        return r.intersects(rectangle);
    }

    @Override
    public String toString() {
        return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public double getX() {
        return x;
    }

    private double x;
    private double y;
    private double angle = 0;
    private Rectangle rectangle;
}

标签:java,animation,rotation,transform
来源: https://codeday.me/bug/20191003/1846501.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有