libgdx 生成后的临时精灵移动
libgdx Temporary sprite movement after being spawned
public class Player {
private Sprite enemy;
public Rectangle bounds;
private SpriteBatch batch;
private float deltaTime;
private float timer;
private ArrayList<Sprite> enemies;
private Iterator<Sprite> enemyIterator;
private ArrayList<Vector2> posCoordinate;
Sprite newEnemy;
public void create(){
batch=new SpriteBatch();
timer=0;
enemy=new Sprite(new Texture(Gdx.files.internal("spr_player.png")));
bounds=new Rectangle(200,700,82,80);
enemies=new ArrayList<Sprite>();
posCoordinate=new ArrayList<Vector2>();
newEnemy=Pools.obtain(Sprite.class);
}
public void update(){
deltaTime=Gdx.graphics.getDeltaTime();
enemyIterator=enemies.iterator();
timer+=1*deltaTime;
if(timer>=1f){
newEnemy(); //method called every second
timer-=1;
}
}
public void newEnemy(){
Vector2 position=Pools.obtain(Vector2.class); //vector2 is created for each enemy every second.
position.set(200,700);
posCoordinate.add(position);
newEnemy=Pools.obtain(Sprite.class); //enemy created every second
newEnemy.set(enemy);
enemies.add(newEnemy);
}
public void draw(SpriteBatch batch){
//this is where the enemy position is set and movement
for(Sprite enemy:enemies){
enemy.draw(batch);
}for(Vector2 position:posCoordinate){
newEnemy.setPosition(position.x,position.y);
position.y-=2;
}
}
}
newEnemy()
方法每秒都会被调用,这就是为什么每秒都会渲染一个新的精灵。
基本上我想要做的是当一个新的敌人产生时,它必须向下移动直到它超出 screen.But 发生的事情是敌人只会移动一秒钟。
我认为您通过引入成员变量 newEnemy
混淆了事情。你有一个方法可以创建一个新的敌人并将其添加到你的敌人列表中,之后,不应该有理由从列表中单独引用它,所以你应该只允许 newEnemy
引用被丢弃.
因此,您应该从 class 中删除 Sprite newEnemy
行,并在 newEnemy()
方法中声明它。
此外,不需要 Vector2 的位置列表,因为 Sprite class 已经存储了一个位置。您只需要移动单个精灵。因此,也删除与 posCoordinate
相关的所有内容。您的 newEnemy()
方法应该如下所示:
private void newEnemy(){
Sprite newEnemy = Pools.obtain(Sprite.class);
newEnemy.set(enemy); //I recommend renaming your `enemy` variable to something like `prototypeEnemy` for clarity
newEnemy.setPosition(200, 700); //need to start it at correct location.
enemies.add(newEnemy);
}
最后,在您的 draw
方法(这是错误的更新位置)中,您试图仅移动最近创建的敌人,而不是移动所有敌人。请注意,循环的每次迭代都会影响同一个实例:newEnemy
,这只是您创建的最后一个敌人。
以下是我将如何修改您的 class。
1) 移动速度应该是一个常数,以每秒世界单位为单位,所以在你的 class:
顶部声明这样的东西
private static final float ENEMY_SPEED = -120f;
2) 在你的 update()
方法的底部,你可以添加这个来让你所有的敌人移动:
for (Sprite sprite : enemies){
sprite.translateY(deltaTime * ENEMY_SPEED);
}
3) 在此之下,您可以添加检查它们何时离开屏幕,以便您可以将它们移除。必须使用迭代器实例来避免 ConcurrentModificationException。
Iterator<Sprite> enemyIterator = enemies.iterator();
while (enemyIterator.hasNext()){
Sprite sprite = enemyIterator.next();
if (sprite.getY() + sprite.getHeight() < screenBottom) //screenBottom is something you can calculate from your camera like camera.getPosition().y - camera.getHeight()/2
removeEnemy(sprite);
}
4) 并删除它们,因为你正在使用池化,所以你应该在用完它们后将它们放回池中
private void removeEnemy(Sprite sprite){
enemies.remove(sprite);
Pools.free(sprite);
}
5) 在您的 draw
方法中,删除第二个 for 循环,现在我们正在 update
方法中处理位置更新。
public class Player {
private Sprite enemy;
public Rectangle bounds;
private SpriteBatch batch;
private float deltaTime;
private float timer;
private ArrayList<Sprite> enemies;
private Iterator<Sprite> enemyIterator;
private ArrayList<Vector2> posCoordinate;
Sprite newEnemy;
public void create(){
batch=new SpriteBatch();
timer=0;
enemy=new Sprite(new Texture(Gdx.files.internal("spr_player.png")));
bounds=new Rectangle(200,700,82,80);
enemies=new ArrayList<Sprite>();
posCoordinate=new ArrayList<Vector2>();
newEnemy=Pools.obtain(Sprite.class);
}
public void update(){
deltaTime=Gdx.graphics.getDeltaTime();
enemyIterator=enemies.iterator();
timer+=1*deltaTime;
if(timer>=1f){
newEnemy(); //method called every second
timer-=1;
}
}
public void newEnemy(){
Vector2 position=Pools.obtain(Vector2.class); //vector2 is created for each enemy every second.
position.set(200,700);
posCoordinate.add(position);
newEnemy=Pools.obtain(Sprite.class); //enemy created every second
newEnemy.set(enemy);
enemies.add(newEnemy);
}
public void draw(SpriteBatch batch){
//this is where the enemy position is set and movement
for(Sprite enemy:enemies){
enemy.draw(batch);
}for(Vector2 position:posCoordinate){
newEnemy.setPosition(position.x,position.y);
position.y-=2;
}
}
}
newEnemy()
方法每秒都会被调用,这就是为什么每秒都会渲染一个新的精灵。
基本上我想要做的是当一个新的敌人产生时,它必须向下移动直到它超出 screen.But 发生的事情是敌人只会移动一秒钟。
我认为您通过引入成员变量 newEnemy
混淆了事情。你有一个方法可以创建一个新的敌人并将其添加到你的敌人列表中,之后,不应该有理由从列表中单独引用它,所以你应该只允许 newEnemy
引用被丢弃.
因此,您应该从 class 中删除 Sprite newEnemy
行,并在 newEnemy()
方法中声明它。
此外,不需要 Vector2 的位置列表,因为 Sprite class 已经存储了一个位置。您只需要移动单个精灵。因此,也删除与 posCoordinate
相关的所有内容。您的 newEnemy()
方法应该如下所示:
private void newEnemy(){
Sprite newEnemy = Pools.obtain(Sprite.class);
newEnemy.set(enemy); //I recommend renaming your `enemy` variable to something like `prototypeEnemy` for clarity
newEnemy.setPosition(200, 700); //need to start it at correct location.
enemies.add(newEnemy);
}
最后,在您的 draw
方法(这是错误的更新位置)中,您试图仅移动最近创建的敌人,而不是移动所有敌人。请注意,循环的每次迭代都会影响同一个实例:newEnemy
,这只是您创建的最后一个敌人。
以下是我将如何修改您的 class。
1) 移动速度应该是一个常数,以每秒世界单位为单位,所以在你的 class:
顶部声明这样的东西private static final float ENEMY_SPEED = -120f;
2) 在你的 update()
方法的底部,你可以添加这个来让你所有的敌人移动:
for (Sprite sprite : enemies){
sprite.translateY(deltaTime * ENEMY_SPEED);
}
3) 在此之下,您可以添加检查它们何时离开屏幕,以便您可以将它们移除。必须使用迭代器实例来避免 ConcurrentModificationException。
Iterator<Sprite> enemyIterator = enemies.iterator();
while (enemyIterator.hasNext()){
Sprite sprite = enemyIterator.next();
if (sprite.getY() + sprite.getHeight() < screenBottom) //screenBottom is something you can calculate from your camera like camera.getPosition().y - camera.getHeight()/2
removeEnemy(sprite);
}
4) 并删除它们,因为你正在使用池化,所以你应该在用完它们后将它们放回池中
private void removeEnemy(Sprite sprite){
enemies.remove(sprite);
Pools.free(sprite);
}
5) 在您的 draw
方法中,删除第二个 for 循环,现在我们正在 update
方法中处理位置更新。