我正在尝试在屏幕(JFrame)的边缘制作无法穿过的墙壁。因此,当我将图像向左移动并碰到框架的左侧时,将迫使图像不移动。我尝试了各种方法,但似乎似乎找不到合适的代码,因此我想知道如何根据我的代码进行操作。

import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.net.URL;

public class MovingImages extends JPanel implements KeyListener, ActionListener
{
  Timer t = new Timer(5, this);
  int x = 0, y = 0; //coordinates for the image
  int imageScaleX = 100, imageScaleY = 100; //scale the size of the image
  int velX = 0, velY = 0;
//--------------------------------------------------------------------------------------- DISPLAYING IMAGE

  public MovingImages()
  {
    t.start();
    addKeyListener(this); //enables the KeyListener so keys can be pressed
    setFocusable(true);
  }

  /** This code is only used for importing the image and runs the program even when there is no image
    * @param path is a String that is used to represent the the name or where your file is
    * @return is the tempImage which is the image that the program found
    */
  public Image getImage(String path)
  {
    Image tempImage = null;
    try
    {
      URL imageURL = MovingImages.class.getResource(path); //finds where the image is
      tempImage = Toolkit.getDefaultToolkit().getImage(imageURL); //loads image from file
    }
    catch (Exception e)
    {
    }
    return tempImage;
  }

  /** This code is used to display the image in specified coordinates
    * @param g is a variable that uses the Graphics method
    */
  public void paint(Graphics g)
  {
    Image image = getImage("sprite.png"); //choose the file for your image
    super.paintComponent(g); //everytime the image moves, it clears the previous image
    Graphics2D g2 = (Graphics2D) g; //converts graphics into 2D
    g2.drawImage(image, x, y, imageScaleX, imageScaleY, this); //draws image in specific coordinates
  }
//--------------------------------------------------------------------------------------- KEYBOARD FUNCTIONS

  public void actionPerformed(ActionEvent e)
  {
    x += velX;
    y += velY;
    repaint();
  }

  public void up()
  {
    velY = -2;
  }

  public void down()
  {
    velY = 2;
  }

  public void left()
  {
    velX = -2;
  }

  public void right()
  {
    velX = 2;
  }

  public void keyPressed(KeyEvent e)
  {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_UP)
    {
      up();
    }
    if (keyCode == KeyEvent.VK_DOWN)
    {
      down();
    }
    if (keyCode == KeyEvent.VK_LEFT)
    {
      left();
    }
    if (keyCode == KeyEvent.VK_RIGHT)
    {
      right();
    }
  }

  public void keyTyped(KeyEvent e)
  {
  }

  public void keyReleased(KeyEvent e)
  {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_UP)
    {
      velY = 0;
    }
    if (keyCode == KeyEvent.VK_DOWN)
    {
      velY = 0;
    }
    if (keyCode == KeyEvent.VK_LEFT)
    {
      velX = 0;
    }
    if (keyCode == KeyEvent.VK_RIGHT)
    {
      velX = 0;
    }
  }
//--------------------------------------------------------------------------------------- MAIN

  public static void main(String args[])
  {
    MovingImages s = new MovingImages();
    JFrame f = new JFrame();
    f.add(s);
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(1280, 720);
  }
}

最佳答案

以下答案说明了强制对象停留在其容器内的一般原理。在程序的事件循环中,您将直接响应键盘输入或在基于保存速度的计时器循环中更新对象的x和y坐标。在这两种情况下,基本原理都相同:


  检测对象的边缘何时碰撞到容器的边界,并且不对将其移动的对象坐标进行任何更改,以使其部分或完全位于容器外部。


以下伪代码描述了每次更新对象位置时必须执行的操作。我只显示水平运动的代码,而垂直运动则作为练习。我假设对象的“位置”是其边界框左下角的坐标。

    int left_edge  = pos_x;
    int right_edge = pox_x + width;
    if (velocity_x < 0)
        pos_x += left_edge > 0 ? velocity_x : 0;
    else if (velocity_x > 0)
        pos_x += right_edge < container_width ? velocity_x : 0;


我尚未解决的一些问题留给练习:


垂直运动
当物体撞击墙壁时,速度会发生什么变化。 (a)物体是否继续“尝试”移动,或者(b)沿该方向的速度是否降至零?例如,如果容器中间存在某种障碍,则第一个选项(a)可能适用。物体可能会碰到它并停止水平运动,同时仍然保持垂直运动,并最终最终垂直清除障碍物,然后继续水平运动。
如果为velocity > 1,则上述代码可能会导致部分结束于容器外部(即,您以x==1velocity==-2开始)。您需要增强针对这种情况的代码,同时牢记您对以上第2项的回答。

09-18 08:12