화면 중심을 기준으로 마우스를 따라 회전하는 BufferedImage 의 예
화면 중앙에서 마우스 위치를 향하여 회전하며 마우스를 클릭하면 마우스 방향으로 포탄이 발사되는 예제
GameWindow.java, GamePanel.java
package rotation; import java.awt.*; import java.awt.event.*; import java.awt.geom.AffineTransform; import java.awt.image.*; import java.util.*; import javax.swing.*; public class GameWindow extends JFrame { public GameWindow(){ setTitle("회전 테스트"); getContentPane().setLayout(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100,50,540,560); GamePanel gp = new GamePanel(); add(gp); setVisible(true); } public static void main(String[] args) { new GameWindow(); } } class GamePanel extends JPanel { BufferedImage circle; BufferedImage barrel; java.util.List<Cannonball> ballList = new ArrayList<>(); int centerX, centerY; double cannonballX, cannonballY; double rad; // 마우스 현재 위치 각도 public GamePanel() { setLayout(null); setBounds(10,10,500,500); //정사각형일 경우 오브젝트의 회전효과에 유리하다 setBackground(Color.WHITE); setDoubleBuffered(true); centerX = getWidth()/2; centerY = getWidth()/2; createBarrel(); createCircle(); addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { Cannonball cb = null; for(int i=0;i<ballList.size();i++){ if(!ballList.get(i).isRunning()){ cb = ballList.get(i); break; } } if(cb==null) { cb = new Cannonball(); ballList.add(cb); //System.out.println("포탄 새로 생성됨"); } cb.setFireAngle(rad); //발사각도로부터 각 방향속도를 구한다 cb.setxSpeed(Math.cos(rad)); cb.setySpeed(Math.sin(rad)); //발사방향의 포구에 포탄을 위치시킨다 cb.setX(cb.getxSpeed()*100 + centerX-20); cb.setY(cb.getySpeed()*100 + centerY-20); cb.setRunning(true); //System.out.println("포탄갯수:"+ballList.size()); } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseClicked(MouseEvent e) { } }); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { int mouseX = e.getX(); int mouseY = e.getY(); rad = Math.atan2(mouseY-centerY, mouseX-centerX);//중앙에서 마우스를 향한 각도 } @Override public void mouseDragged(MouseEvent e) { } }); gameLoop(); } //End of constructor private void createBarrel() { barrel = new BufferedImage(100, 40, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = (Graphics2D)barrel.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(Color.GRAY); g2d.fillRect(0,0,100,40); } private void createCircle() { circle = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = (Graphics2D)circle.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(Color.ORANGE); g2d.fillOval(0,0,100,100); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; Cannonball cb = null; for(int i=0;i<ballList.size();i++){ cb = ballList.get(i); if(!cb.isRunning()) continue; g2d.drawImage(cb, (int)cb.getX(), (int)cb.getY(), null); } AffineTransform old = g2d.getTransform(); g2d.rotate(rad, centerX, centerY); g2d.drawImage(barrel, getWidth()/2, getHeight()/2-20, null); g2d.setTransform(old); g2d.drawImage(circle, getWidth()/2-50, getHeight()/2-50, null); } private void gameLoop() { new Thread() { @Override public void run() { while(true){ for(int i=0;i<ballList.size();i++){ Cannonball cb = null; cb = ballList.get(i); if(!cb.isRunning()) continue; cb.setX(cb.getX()+cb.getxSpeed()*3); cb.setY(cb.getY()+cb.getySpeed()*3); if(cb.getX() < 0 || cb.getX() > getWidth()-40) cb.setRunning(false); if(cb.getY() < 0 || cb.getY() > getHeight()-40) cb.setRunning(false); } repaint(); try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } }// end of while }// end of run() }.start(); } }
Cannonball.java
package rotation; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; public class Cannonball extends BufferedImage { private double fireAngle; //발사각도(라디안) private double x, y; private double xSpeed, ySpeed; private boolean isRunning; public Cannonball(){ super(40,40,BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = (Graphics2D) this.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(Color.RED); g2d.fillOval(0,0,40,40); } public double getFireAngle() { return fireAngle; } public void setFireAngle(double fireAngle) { this.fireAngle = fireAngle; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } public double getxSpeed() { return xSpeed; } public void setxSpeed(double xSpeed) { this.xSpeed = xSpeed; } public double getySpeed() { return ySpeed; } public void setySpeed(double ySpeed) { this.ySpeed = ySpeed; } public boolean isRunning() { return isRunning; } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } }