如何将图像设置为以给定速度移动?

时间:2011-10-12 14:31:56

标签: java swing awt

我有一个在x轴上移动的人的图像。现在我想以5米/秒的相应速度移动该人,其中delta时间以纳秒为单位,这是我的问题。你能告诉我怎么做的吗?

非常感谢任何帮助......

以下是代码:

public class Board extends Canvas

{
 public double meter;//PIXEL

private final java.util.List<Sprite> sprites = new ArrayList<Sprite>();

private final java.util.List<Sprite> z_sorted_sprites = new ArrayList<Sprite>();

private BufferStrategy strategy;

int x0_pixel;
int y0_pixel;

int x1_pixel;
int y1_pixel;

double x1_world;
double y1_world;


public Board(double meter)
{
    this.setIgnoreRepaint(true);

    this.meter = meter;

    init();

    addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentResized(ComponentEvent e)
        {
            render();
        }
    });
}
public void init()
{
    HumanBeing humanBeing = new HumanBeing(this, 2, 2, 0);

           sprites.add(humanBeing);


    z_sorted_sprites.add(humanBeing);
       }

@Override
public void paint(Graphics g)
{
}

public void render()
{
    setupStrategy();

    x0_pixel = 0;
    y0_pixel = 0;

    x1_pixel = getWidth();
    y1_pixel = getHeight();

    x1_world = x1_pixel / meter;
    y1_world = y1_pixel / meter;


    Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();

    g2d.setBackground(Color.lightGray);
    g2d.clearRect(0, 0, x1_pixel, y1_pixel);

    g2d.setColor(Color.BLACK);

    for (double x = 0; x < x1_world; x++)
    {
        for (double y = 0; y < y1_world; y++)
        {
            int xx = convertToPixelX(x);
            int yy = convertToPixelY(y);

            g2d.drawOval(xx, yy, 2, 2);
        }
    }

    for (Sprite z_sorted_sprite : z_sorted_sprites)
    {
        z_sorted_sprite.render(g2d);
    }

    g2d.dispose();
    strategy.show();

    Toolkit.getDefaultToolkit().sync();
}

public int convertToPixelX(double distance)
{
    return (int) (distance * meter);
}

public int convertToPixelY(double y_world)
{
    return (int) (y1_pixel - (y_world * meter));
}

public void onZoomUpdated(int value)
{
    meter = value;
    render();
}

private void setupStrategy()
{
    if (strategy == null)
    {
        this.createBufferStrategy(2);
        strategy = this.getBufferStrategy();
    }
}

public void start() throws InterruptedException
{
    long previousTime = System.nanoTime();

    while (true)
    {
        long now = System.nanoTime();
        long dt = now - previousTime;

        for (Sprite sprite : sprites)
        {
            sprite.move(0);
        }
        render();

        Thread.sleep(1);
        previousTime = now;

    }
 }
}

for Human Class

public class HumanBeing extends Sprite  implements ImageObserver
{
private java.awt.Image humanImage;
private final Board board;
private double x;

private double y;

private int speed;

private java.util.List<Sprite> objects = new ArrayList<Sprite>();
private int cImage;

public HumanBeing(Board board, int x, int y, int speed)
{
    this.board = board;

    this.x = x;
    this.y = y;
    this.speed = speed;

    URL iU = this.getClass().getResource("human.jpg");
    ImageIcon icon = new ImageIcon(iU);
    humanImage = icon.getImage();

    objects.add(this);

}
public Image getImage()
{
    return humanImage;
}

@Override
public void move(long ns)
{  
    x += 0.001;

}

@Override
public void render(Graphics2D g2d)
{
    AffineTransform t = g2d.getTransform();

    final double humanHeight = 1.6;// meter
    final double humanWidth = 1.8;  //meter

    final double foot_position_x = humanHeight / 2;
    final double foot_position_y = humanWidth;

    int xx = board.convertToPixelX(x - foot_position_x); // to find the upper-left corner
    int yy = board.convertToPixelY(y + foot_position_y); // to find the upper-left corner

    g2d.translate(xx, yy);

    // ratio for actual Image size

    double x_expected_pixels = humanHeight * board.meter;
    double y_expected_pixels = humanWidth * board.meter;

    double w = ((ToolkitImage) humanImage).getWidth();
    double h = ((ToolkitImage) humanImage).getHeight();

    double x_s = x_expected_pixels / w;
    double y_s = y_expected_pixels / h;

    g2d.scale(x_s, y_s);

    g2d.drawImage(getImage(), 0, 0, this); // upper left corner

    g2d.setColor(Color.BLACK);

    g2d.setTransform(t);
}
@Override
public void moveAt(double distance_x, double distance_y)
{
    this.x = distance_x;
    this.y = distance_y;
}

@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
    return false;
}
}

1 个答案:

答案 0 :(得分:1)

这是构建解决方案的想法。我假设你已经知道图像每秒移动多少像素就是你想要的速度。让我们说,对于您的游戏或模拟,这意味着每秒10像素。您有一个起始位置和一个结束位置。所以你知道什么时候需要移动图像。使用类ScheduledThreadPoolExecutor及其方法scheduleWithFixedRate设置图像位置的定期更新,每秒在更新的位置发出一次调用图像。请记住,当Swing线程为其他GUI请求提供服务时,您对图像的定位调用可能会被短暂延迟。但是您的预定线程不受影响。假设计划的线程告诉Swing将您的图像放在位置x和时间1.0秒。实际上,Swing稍后会在1.1秒时触及它。但你不希望这个三角洲搞砸你的时间。这不是因为scheduleWithFixedRate将在2.0秒的正确时间发出下一个Swing调用,而不是2.1秒。第二次图像更新恰好位于正确的时间点(或者足够接近,具体取决于GUI线程的繁忙程度)。