如何在精确的着陆位置坐标处停止精灵
How to stop a sprite at exact touchdown position coordinates
我想从屏幕的任意位置移动一个精灵(恰好是一个矩形),并让它恰好停在屏幕被触摸的位置。现在,我已经可以停止我的精灵了,但不能停在确切的触摸位置。在不牺牲准确性或冒着精灵根本不停止的风险的情况下,我找不到一个好的方法来做到这一点。
自然地 - 出现问题是因为当前位置是 Float
,因此 Vector 永远不会(或极少)具有与触摸点(int
)完全相同的坐标.
在下面的代码中,我通过简单地检查当前位置和目标位置(即触摸位置 Vector3)之间的距离来停止我的精灵,就像这样 if (touch.dst(currentPsition.x, currentPosition.y, 0) < 4)
。
例如,如果精灵在位置 (5,5),我在 (100,100) 处触摸屏幕,它会停在 (98.5352,96.8283) 处。
我的问题是,如何将精灵停在准确的触摸位置,而不必近似?
void updateMotion() {
if (moveT) {
movement.set(velocity).scl(Gdx.graphics.getDeltaTime());
this.setPosition(currentPosition.add(movement));
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
}
}
public void setMoveToTouchPosition(boolean moveT) {
this.moveT = moveT;
this.touch = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
GameScreen.getCamera().unproject(touch);
currentPosition = new Vector2(this.x, this.y);
direction.set(new Vector2(touch.x, touch.y)).sub(currentPosition).nor();
velocity = new Vector2(direction).scl(speed);
}
当然,由于很多原因,sprite 不能平滑地移动到触摸位置然后停在完全相同的位置。只需更改此
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
到这个
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 2) {
currentPosition.x = touch.x;
currentPosition.y = touch.y;
moveT = false;
}
一个快速但可接受的解决方案可能是使用 Rectangle
class。考虑到您在移动实体周围制作了一个 Rectangle
并根据其当前位置不断更新其边界,它的纹理 width
和纹理 height
。你可以在 overlaps
和 "target position" 时停止它。如果你这样做,你可以保证它会准确地停在那个位置。例如:
Texture entityTexture = new Texture("assets/image.png");
Rectangle entityBounds = new Rectangle();
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture .getWidth(), entityTexture .getHeight()));
Rectangle targetBounds = new Rectangle();
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1)); // make width and height 1 by 1 for max accuracy
public void update(){
// update bounds based on new position
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture.getWidth(), entityTexture.getHeight()));
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1));
if(entityBounds.overlaps(targetBounds)){
// do something
}
}
我想从屏幕的任意位置移动一个精灵(恰好是一个矩形),并让它恰好停在屏幕被触摸的位置。现在,我已经可以停止我的精灵了,但不能停在确切的触摸位置。在不牺牲准确性或冒着精灵根本不停止的风险的情况下,我找不到一个好的方法来做到这一点。
自然地 - 出现问题是因为当前位置是 Float
,因此 Vector 永远不会(或极少)具有与触摸点(int
)完全相同的坐标.
在下面的代码中,我通过简单地检查当前位置和目标位置(即触摸位置 Vector3)之间的距离来停止我的精灵,就像这样 if (touch.dst(currentPsition.x, currentPosition.y, 0) < 4)
。
例如,如果精灵在位置 (5,5),我在 (100,100) 处触摸屏幕,它会停在 (98.5352,96.8283) 处。
我的问题是,如何将精灵停在准确的触摸位置,而不必近似?
void updateMotion() {
if (moveT) {
movement.set(velocity).scl(Gdx.graphics.getDeltaTime());
this.setPosition(currentPosition.add(movement));
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
}
}
public void setMoveToTouchPosition(boolean moveT) {
this.moveT = moveT;
this.touch = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
GameScreen.getCamera().unproject(touch);
currentPosition = new Vector2(this.x, this.y);
direction.set(new Vector2(touch.x, touch.y)).sub(currentPosition).nor();
velocity = new Vector2(direction).scl(speed);
}
当然,由于很多原因,sprite 不能平滑地移动到触摸位置然后停在完全相同的位置。只需更改此
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
到这个
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 2) {
currentPosition.x = touch.x;
currentPosition.y = touch.y;
moveT = false;
}
一个快速但可接受的解决方案可能是使用 Rectangle
class。考虑到您在移动实体周围制作了一个 Rectangle
并根据其当前位置不断更新其边界,它的纹理 width
和纹理 height
。你可以在 overlaps
和 "target position" 时停止它。如果你这样做,你可以保证它会准确地停在那个位置。例如:
Texture entityTexture = new Texture("assets/image.png");
Rectangle entityBounds = new Rectangle();
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture .getWidth(), entityTexture .getHeight()));
Rectangle targetBounds = new Rectangle();
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1)); // make width and height 1 by 1 for max accuracy
public void update(){
// update bounds based on new position
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture.getWidth(), entityTexture.getHeight()));
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1));
if(entityBounds.overlaps(targetBounds)){
// do something
}
}