我正在为我的项目制作一个蛇游戏,我有一个关于同时旋转和翻译图像的问题。我的蛇沿任何方向跟随光标,我想将它的头部旋转一个光标所执行的角度。我已经尝试了很多使用仿射变换,但问题是我们可以一次使用旋转或平移功能,但不能同时使用两者。我已经给出了代码,蛇体和它的运动是由油漆组件处理的,我混淆了我应该做什么改变以获得所需的结果,如上所述。我已经通过堆栈溢出发布的文档和问题,但我没有解决方案
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