在java中同时旋转和平移单个图像
我正在为我的项目制作一个蛇游戏,我有一个关于同时旋转和转换图像的问题。我的蛇跟随光标向任何方向移动,我想把它的头旋转一个角度,光标执行这个角度。我尝试过很多使用仿射变换的方法,但问题是我们可以同时使用旋转或平移函数,但不能同时使用两者。我已经给出了代码,蛇的身体和它的运动是由绘画组件来处理的,我不知道应该做什么更改才能得到上面提到的所需结果。我查阅了stack overflow上发布的文档和问题,但没有找到解决方案在java中同时旋转和平移单个图像,java,Java,我正在为我的项目制作一个蛇游戏,我有一个关于同时旋转和转换图像的问题。我的蛇跟随光标向任何方向移动,我想把它的头旋转一个角度,光标执行这个角度。我尝试过很多使用仿射变换的方法,但问题是我们可以同时使用旋转或平移函数,但不能同时使用两者。我已经给出了代码,蛇的身体和它的运动是由绘画组件来处理的,我不知道应该做什么更改才能得到上面提到的所需结果。我查阅了stack overflow上发布的文档和问题,但没有找到解决方案 import java.awt.BorderLayout; import ja
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.event.*;
import java.awt.Rectangle;
import java.awt.ComponentOrientation;
import java.awt.Font;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
//class starts
//this class actually contains the game
//the object of this class is created in Snake_Menu class to start the real game
public class Game extends JPanel implements MouseListener, MouseMotionListener {
JFrame jf = new JFrame();// main frame
int x_Cur; // x_position of cursor
int y_Cur; // y_position of cursor
int delta_x, delta_y; // difference between x positions and y positions of
// cursor and snake head
int x_positions[] = new int[3600]; // array for storing x positions of body
// segments
int y_positions[] = new int[3600]; // array for storing y positions of body
// segments
int food_x, food_y; // storing x,y positions of food
double x_inc, y_inc;// the increment added in head positions
int segments;// defines length of snake body
double angle;// calculated btw cursor and snake head
double speed = 5.0;// speed of snake
static int counter = 0;
int rand_loc = 500;
BufferedImage body;// image object for body
BufferedImage head;// image object for head
BufferedImage bgimage;// image object for background
Sound sound = new Sound();// object of "Sound" class
JLabel score = new JLabel("Score:" + sc);
JPanel controlpn = new JPanel();
static int sc;
static int wr = 1;
static int start;
JLabel pause;
int flag = 0;
private JLabel resume = new JLabel("Resume\r\n");
private JLabel Back = new JLabel(" Back");
{
try {
// initializing image objects
body = ImageIO.read(new File("./Images/Body.png"));
bgimage = ImageIO.read(new File("./Images/Back.jpg"));
head = ImageIO.read(new File("./Images/head.png"));
} catch (IOException ex) {
System.out.println("Images not found");
}
}
/******************************************************************************************************************************************/
/* <<<Constructor called by class "Snake_Menu">>> */
/*****************************************************************************************************************************************/
// constructor starts
public Game() {
// sound.music_stop();//slows down background music when playing game
jf.getContentPane().setLayout(new BorderLayout());
JPanel jp = new JPanel();
jp.setBorder(new LineBorder(new Color(0, 0, 0)));
jp.setForeground(new Color(220, 20, 60));
jp.setBackground(new Color(100, 149, 237));
// jp.setBounds(0, 0, 600, 500);
jp.setLayout(new BorderLayout());
pause = new JLabel("Pause");
pause.setFont(new Font("Bradley Hand ITC", Font.BOLD | Font.ITALIC, 20));
pause.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
pause.addMouseListener(new MouseAdapter() {
// actions taken when mouse enters or exits or clicked on the bounds
@Override
public void mouseEntered(MouseEvent e) {
pause.setForeground(Color.red);
}
public void mouseExited(MouseEvent e) {
pause.setForeground(Color.black);
}
public void mouseClicked(MouseEvent e) {
flag = 1;
}
});
resume.setFont(new Font("Bradley Hand ITC", Font.BOLD | Font.ITALIC, 20));
resume.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
resume.addMouseListener(new MouseAdapter() {
// actions taken when mouse enters or exits or clicked on the bounds
@Override
public void mouseEntered(MouseEvent e) {
resume.setForeground(Color.red);
}
public void mouseExited(MouseEvent e) {
resume.setForeground(Color.black);
}
public void mouseClicked(MouseEvent e) {
flag = 0;
}
});
Back.setFont(new Font("Bradley Hand ITC", Font.BOLD | Font.ITALIC, 20));
Back.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
Back.addMouseListener(new MouseAdapter() {
// actions taken when mouse enters or exits or clicked on the bounds
@Override
public void mouseEntered(MouseEvent e) {
Back.setForeground(Color.red);
}
public void mouseExited(MouseEvent e) {
Back.setForeground(Color.black);
}
public void mouseClicked(MouseEvent e) {
sound.music_stop();
Snake_Menu sn=new Snake_Menu();
sn.frame.setVisible(true);
jf.setVisible(false);
}
});
controlpn.add(Back);
controlpn.add(resume);
controlpn.add(pause, BorderLayout.WEST);// add to frame
controlpn.setBackground(new Color(100, 149, 237));
score.setFont(new Font("Bradley Hand ITC", Font.BOLD | Font.ITALIC, 20));
jp.add(score, BorderLayout.WEST);
jp.add(controlpn, BorderLayout.EAST);
jf.getContentPane().add(jp, BorderLayout.NORTH);
// frame properties
jf.getContentPane().add(this, BorderLayout.CENTER);
jf.addMouseMotionListener(this);// adding mouse motion listener to frame
jf.addMouseListener(this);// adding mouse listener to frame
jf.setFocusable(true);
jf.setSize(new Dimension(700, 650));
jf.setResizable(false);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
first_Snake();// this method initializes first snake
sound.music_Bg(); // Sound Class method for playing background music
}// constructor ends
**/******************************************************************************************************************************************/
/* <<<Paint Component>>> */
/*****************************************************************************************************************************************/
// paint starts here
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(bgimage, 0, 0,700,650, this); // drawing background image
g2d.drawImage(body, food_x, food_y, 31, 31, this); // food image
// this for loop paints the body
for (int z = 0; z < segments; z++) {
if (z == 0) {
// do nothing
} else if (z == 1)
g2d.drawImage(body, x_positions[z], y_positions[z], 31, 31,
this);
else
g2d.drawImage(body, x_positions[z], y_positions[z], 31, 31,
this);
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
meet_Food();// checks whether the head has met with food or not
/*********** this block defines the motion of snake ************/
delta_x = x_Cur - x_positions[0];
delta_y = y_Cur - y_positions[0];
angle = Math.atan2(delta_y, delta_x);
double speed = Math.sqrt(delta_x * delta_x + delta_y * delta_y);
speed = Math.min(speed, 3.0);
if (flag != 1) {
x_inc = (speed * Math.cos(angle));
y_inc = (speed * Math.sin(angle));
x_positions[0] += x_inc;
y_positions[0] += y_inc;
}
counter++;// to give a gap between body segments
// when x_positions[0] is incremented 7 times
// then its value is passed to its body segments
// to have a space in segments of body, counter does that job
if (counter % 7 == 0) {
if (!(delta_x == 0 && delta_y == 0)) {
// this for loop transfer the positions of head to its body
for (int z = segments; z > 0; z--) {
x_positions[z] = x_positions[z - 1];
y_positions[z] = y_positions[z - 1];
}
}
counter = 0;
}
/*************************** block ends ***********************/
if (start == 1)
repaint();
}// paint ends**
/******************************************************************************************************************************************/
/* <<<first_Snake method;initializes first snake>>> */
/*****************************************************************************************************************************************/
public void first_Snake() {
segments = 3;
for (int z = 0; z < segments; z++) {
x_positions[z] = 60 - z * 20; // giving space of 20 pixels btw every
// segment
y_positions[z] = 60;
}
}// first_Snake ends
/******************************************************************************************************************************************/
/* <<< locate_Food method; to locate food at random after snake eats it>>> */
/*****************************************************************************************************************************************/
public void locate_Food() {
food_x = (int) (Math.random() * rand_loc);
food_y = (int) (Math.random() * rand_loc);
}// locate_Food ends
/******************************************************************************************************************************************/
/* <<<Checks whether snake has met food or not>>>>> */
/*****************************************************************************************************************************************/
public void meet_Food() {
for (int y = 1; y < 31; y++) {
if ((x_positions[1] >= food_x && x_positions[1] <= food_x + 31)
&& (y_positions[1] + y >= food_y & y_positions[1] + y <= food_y + 31)) {
sound.music_Eat();
sc += 5;
score.setText("Score:" + sc);
segments++;
locate_Food();
}
}
}// meet_Food ends
@Override
public void mouseDragged(MouseEvent me) {
}
/******************************************************************************************************************************************/
/* <<<mouseMoved method to get location of mouse>>> */
/*****************************************************************************************************************************************/
@Override
public void mouseMoved(MouseEvent me) {
x_Cur = me.getX() - 20;
y_Cur = me.getY() - 40;
}// mouseMoved ends
@Override
public void mouseClicked(MouseEvent me) {
start = 1;
repaint();
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mousePressed(MouseEvent arg0) {
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
}// class ends
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Component;
导入java.awt.Cursor;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Image;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionListener;
导入java.awt.geom.AffineTransform;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.FileNotFoundException;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.SwingConstants;
导入java.awt.event.*;
导入java.awt.Rectangle;
导入java.awt.ComponentOrientation;
导入java.awt.Font;
导入javax.swing.border.EtchedBorder;
导入javax.swing.border.LineBorder;
//上课
//这个类实际上包含了这个游戏
//这个类的对象是在Snake_菜单类中创建的,用于开始真正的游戏
公共类游戏扩展JPanel实现MouseListener、MouseMotionListener{
JFrame jf=新JFrame();//主框架
int x_Cur;//光标的x_位置
int y\u Cur;//光标的y\u位置
int delta_x,delta_y;//的x位置和y位置之间的差异
//光标与蛇头
int x_positions[]=new int[3600];//用于存储实体x位置的数组
//分段
int y_positions[]=new int[3600];//用于存储实体y位置的数组
//分段
int food_x,food_y;//存储食物的x,y位置
double x_inc,y_inc;//在头部位置添加的增量
int segments;//定义蛇身的长度
双角度;//计算的btw光标和蛇头
双倍速度=5.0;//蛇的速度
静态整数计数器=0;
int rand_loc=500;
BuffereImage主体;//主体的图像对象
BuffereImage头部;//头部的图像对象
BuffereImage bgimage;//背景的图像对象
Sound Sound=新声音();//Sound类的对象
JLabel分数=新的JLabel(“分数:+sc”);
JPanel controlpn=新的JPanel();
静态int-sc;
静态int wr=1;
静态int启动;
JLabel暂停;
int标志=0;
专用JLabel resume=新JLabel(“resume\r\n”);
专用JLabel Back=新JLabel(“Back”);
{
试一试{
//初始化图像对象
body=ImageIO.read(新文件(“./Images/body.png”);
bgimage=ImageIO.read(新文件(“./Images/Back.jpg”);
head=ImageIO.read(新文件(“./Images/head.png”);
}捕获(IOEX异常){
System.out.println(“未找到图像”);
}
}
/******************************************************************************************************************************************/
/* */
/*****************************************************************************************************************************************/
//构造函数启动
公共游戏(){
//sound.music_stop();//在玩游戏时减慢背景音乐
jf.getContentPane().setLayout(新的BorderLayout());
JPanel jp=新的JPanel();
jp.setboorder(新线条边框(新颜色(0,0,0));
jp.setForeground(新颜色(220,20,60));
jp.setBackground(新颜色(100149237));
//jp.setBounds(0,060500);
jp.setLayout(新的BorderLayout());
暂停=新的JLabel(“暂停”);
pause.setFont(新字体(“Bradley Hand ITC”,Font.BOLD | Font.ITALIC,20));
pause.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_Cursor));
pause.addMouseListener(新的MouseAdapter(){
//鼠标进入或退出或单击边界时采取的操作
@凌驾
公共无效鼠标事件(鼠标事件e){
暂停。设置前景(颜色为红色);
}
公共无效mouseExited(MouseEvent e){
暂停。设置前景(颜色。黑色);
}
公共无效mouseClicked(MouseEvent e){
flag=1;
}
});
resume.setFont(新字体(“Bradley Hand ITC”,Font.BOLD | Font.ITALIC,20));
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_Cursor));
resume.addMouseListener(新的MouseAdapter(){
//鼠标进入或退出或单击边界时采取的操作
@凌驾
公共无效鼠标事件(鼠标事件e){
简历。设置前景(颜色。红色);
}
公共无效mouseExited(MouseEvent e){
简历。设置前景(颜色。黑色);
}
公共无效mouseClicked(MouseEvent e){
flag=0;
}
});
Back.setFont(新字体(“Bradley Hand ITC”,Font.BOLD | Font.ITALIC,20));
Back.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_Cursor));
Back.addMouseListener(新的MouseAdapter(){
//鼠标进入或退出o时采取的操作