我有一个工作代码,您可以使用箭头键盘控制金鱼的移动。当你按下向上键时,金鱼会游起来。按下向下键时,金鱼会向下游泳。按左键时,金鱼向左游动。当你按下右键时,金鱼游向右边。我这样做是为了让金鱼的像素每次朝新的方向移动时增加或减少1个像素,但是当你这样做的时候,金鱼游得非常慢。我知道如果你将像素增加1以上,金鱼似乎游得更快,但那样它就不会画出每个像素,金鱼游泳看起来也不会那么光滑。所以我的问题是,有没有办法重新绘制金鱼以加快速度而不增加它所绘制的像素?这是我的代码:
public class Fishy extends Panel implements KeyListener, MouseMotionListener {
static int x1;// first x location of the shape.
static int x2;// second x location of the shape
static int y1;// first y location of the shape
static int y2;// second y location of the shape
static int shapeWidth;// width of the shape
static int shapeHeight;// height of the shape
static final int left = 37;
static final int right = 39;
static final int down = 40;
static final int up = 38;
static boolean leftPress;
static boolean rightPress;
static boolean upPress;
static boolean downPress;
static int speed = 1;
static int x;
static int y;
static int size = 50;
static String facingDirection = "RIGHT";
int enemyX1;
int enemyY1;
int enemyX2;
int enemyY2;
int enemySpeed;
int enemySize;
static Image LimageFishy = new ImageIcon("F://Picture//Lfish.png").getImage();
static Image RimageFishy = new ImageIcon("F://Picture//Rfish.png").getImage();
static BufferedImage bufferedImageFishy;
Fishy enemyFish[] = new Fishy[20];
static JFrame frame = new JFrame("Fishy");
// TREE method of extending classes[]
static Fishy fishy = new Fishy(1000, 500, 9);
Fishy(int width, int length, int minusBy) {
super(width, length, minusBy);
}
/* Graphics goes here */
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 1000, 500);
// size++;
if (facingDirection.equals("RIGHT")) {
g.drawImage(RimageFishy, x1, y1, size, size, null);
}
if (facingDirection.equals("LEFT")) {
g.drawImage(LimageFishy, x1, y1, size, size, null);
}
g.drawString(DraggingShapes.mousePointerLocation, 50, 50);
}
public static void main(String args[]) throws IOException, InterruptedException {
frame.addKeyListener(fishy);
fishy.addMouseMotionListener(fishy);
frame.add(fishy);
Frame.showFrame(frame, false);
/*while (true) {
Thread.sleep(1);
if (x1 < 1000) {
x1++;
} else {
x1 = 0;
}
frame.repaint();
}*/
}
@Override
public void keyPressed(KeyEvent e) {
if (up == e.getKeyCode()) {
upPress = true;
}
if (down == e.getKeyCode()) {
downPress = true;
}
if (left == e.getKeyCode()) {
leftPress = true;
facingDirection = "LEFT";
}
if (right == e.getKeyCode()) {
rightPress = true;
facingDirection = "RIGHT";
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if (upPress == true && leftPress == false && rightPress == false) {
fishy.y1 -= speed;
}
if (downPress == true && leftPress == false && rightPress == false) {
fishy.y1 += speed;
}
if (leftPress == true && upPress == false && downPress == false) {
fishy.x1 -= speed;
}
if (rightPress == true && upPress == false && downPress == false) {
fishy.x1 += speed;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if (leftPress == true && upPress == true) {
fishy.x1 -= speed;
fishy.y1 -= speed;
}
if (leftPress == true && downPress == true) {
fishy.x1 -= speed;
fishy.y1 += speed;
}
if (rightPress == true && upPress == true) {
fishy.x1 += speed;
fishy.y1 -= speed;
}
if (rightPress == true && downPress == true) {
fishy.x1 += speed;
fishy.y1 += speed;
}
System.out.println("PRESSING (Left:" + leftPress + ") (Right:" + rightPress + ") (Up:" + upPress + ") (Down:" + downPress + ")");
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
if (up == e.getKeyCode()) {
upPress = false;
}
if (down == e.getKeyCode()) {
downPress = false;
}
if (left == e.getKeyCode()) {
leftPress = false;
}
if (right == e.getKeyCode()) {
rightPress = false;
}
}
@Override
public void mouseMoved(MouseEvent e) {
DraggingShapes.showPointerLocation(e.getX(), e.getY());
repaint();
}
/*** METHODS THAT WE'RE NOT GOING TO USE ***/
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
}
另外,我注意到当你用键盘输入控制图像时,只是告诉它使用Thread.sleep(毫秒)进行重绘,当你将它告诉Thread.sleep时(1)毫秒),图像重新绘制得非常快,即使你只增加了1个像素,我也想知道它为什么与键盘输入不一样。
答案 0 :(得分:0)
如果保持密钥,KeyListener将每隔n毫秒触发一次(这可能取决于操作系统,但在我的Windows系统上为n~33ms)。因此重绘将每隔~n毫秒调用一次。相对于Thread.sleep(1)方法,这慢了约n倍(注意这是近似的,因为重绘是对EDT绘制的请求,实际工作的速度可能取决于重绘队列和绘画本身)。因此,在33毫秒时,您的物体仅行进约30像素/秒。
我没有必要建议尝试提高重新绘制的速度来加快速度,而不是通过提高它的移动速度来加快速度(例如速度变量)。沿着这些相同的行,您可以使用Swing计时器来提供动画循环。
javax.swing.Timer timer = new javax.swing.Timer(60, new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
repaint();
}
});
timer.start();
这使您可以更好地控制动画发生的速度。您可以使用UI侦听器元素(或其他方式)更改模型,并依赖此计时器进行动画处理。下降经验法则可能是计时器每隔60ms发射一次。请注意,这不会加快速度 - 只需让您更好地控制动画过程。
答案 1 :(得分:-1)
我不确定这是否正是您所寻找的,但这可能是您使用sleep(1)与使用键盘移动鱼之间存在一些差异的原因。我通过添加HashMap重构了您的代码,因为它允许更容易更新并使用它来更新方向变量。
public class Fishy extends Panel implements KeyListener, MouseMotionListener {
// here is the map declaration for the data structure
// that will map the key, which was an integer, to
// (up,down,right,left)press, which was a boolean.
static Map<Integer, Boolean> map = new HashMap<>();
static int x1;// first x location of the shape.
static int x2;// second x location of the shape
static int y1;// first y location of the shape
static int y2;// second y location of the shape
static int shapeWidth;// width of the shape
static int shapeHeight;// height of the shape
static final int left = 37;
static final int right = 39;
static final int down = 40;
static final int up = 38;
static boolean leftPress;
static boolean rightPress;
static boolean upPress;
static boolean downPress;
static int speed = 1;
static int x;
static int y;
static int size = 50;
static String facingDirection = "RIGHT";
int enemyX1;
int enemyY1;
int enemyX2;
int enemyY2;
int enemySpeed;
int enemySize;
static Image LimageFishy = new ImageIcon("F://Picture//Lfish.png").getImage();
static Image RimageFishy = new ImageIcon("F://Picture//Rfish.png").getImage();
static BufferedImage bufferedImageFishy;
Fishy enemyFish[] = new Fishy[20];
static JFrame frame = new JFrame("Fishy");
// TREE method of extending classes[]
static Fishy fishy = new Fishy(1000, 500, 9);
Fishy(int width, int length, int minusBy) {
super(width, length, minusBy);
}
/* Graphics goes here */
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 1000, 500);
// size++;
if (facingDirection.equals("RIGHT")) {
g.drawImage(RimageFishy, x1, y1, size, size, null);
}
if (facingDirection.equals("LEFT")) {
g.drawImage(LimageFishy, x1, y1, size, size, null);
}
g.drawString(DraggingShapes.mousePointerLocation, 50, 50);
}
static void buildMap() {
map.put(up, false);
map.put(down, false);
map.put(left, false);
map.put(right, false);
}
public static void main(String args[]) throws IOException, InterruptedException {
buildMap();
frame.addKeyListener(fishy);
fishy.addMouseMotionListener(fishy);
frame.add(fishy);
Frame.showFrame(frame, false);
/*while (true) {
Thread.sleep(1);
if (x1 < 1000) {
x1++;
} else {
x1 = 0;
}
frame.repaint();
}*/
}
@Override
public void keyPressed(KeyEvent e) {
// using the hashmap, we can refactor away the if statements
map.put(e.getKeyCode(), true);
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// It is possible to refactor away the following if statements
// but that requires further surgery on the code.
for (Map.Entry<Integer, Boolean> entry: map.entrySet()) {
if (entry.getValue()) {
if (entry.getKey() == up) {
fishy.y1 -= speed;
}
else if (entry.getKey() == down) {
fishy.y1 += speed;
}
else if (entry.getKey() == right) {
fishy.x1 += speed;
}
else if (entry.getKey() == left) {
fishy.x1 -= speed;
}
}
}
System.out.println("PRESSING (Left:" + leftPress + ") (Right:" + rightPress + ") (Up:" + upPress + ") (Down:" + downPress + ")");
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
// got rid of the unnecessary if statements
// and directly accessed the hashmap to update the value
map.put(e.getKeyCode(), false);
}
@Override
public void mouseMoved(MouseEvent e) {
DraggingShapes.showPointerLocation(e.getX(), e.getY());
repaint();
}
/*** METHODS THAT WE'RE NOT GOING TO USE ***/
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
}