【问题标题】:libgdx Temporary sprite movement after being spawnedlibgdx 生成后的临时精灵移动
【发布时间】:2015-07-16 22:02:13
【问题描述】:
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() 方法每秒被调用一次,这就是为什么每秒都会渲染一个新的精灵。

基本上我想要做的是,当一个新的敌人产生时,它必须向下移动直到它离开屏幕。但是发生的是敌人只会移动一秒钟。

【问题讨论】:

    标签: java libgdx spawning


    【解决方案1】:

    我认为您通过引入成员变量newEnemy 混淆了一些事情。您有一个方法可以创建一个新敌人并将其添加到您的敌人列表中,之后,不应有理由将其与列表分开引用,因此您应该只允许丢弃 newEnemy 引用。

    因此,您应该从类中删除 Sprite newEnemy 行,并在 newEnemy() 方法中声明它。

    此外,不需要 Vector2 的位置列表,因为 Sprite 类已经存储了一个位置。您只需要移动各个精灵。所以删除与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,这只是您创建的最后一个敌人。

    这就是我将如何修改你的课程。

    1) 移动速度应该是一个常数,以每秒世界单位为单位测量,因此请在类的顶部声明如下内容:

    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 方法中的位置更新。

    【讨论】:

    • 我是池化新手,当我移除 Sprite 并将它们放回池中时,如何再次使用池内的 sprite?这是做什么的 // Sprite newEnemy = Pools.obtain(Sprite.class);
    • Pools.obtain(Sprite.class);从池中拉出一个精灵供您使用。如果池是空的,它会自动实例化一个新的 Sprite 并给你。你不知道你得到的精灵是新的还是回收的,所以一定要立即设置它的纹理区域和位置。
    • 所以你不需要写额外的代码,它会自动回收精灵?感谢您的回答,非常有帮助。
    • 这就是 Pools 类的美妙之处。它会在幕后自动生成所需的一切。但它仅适用于具有无参数构造函数的类。对于其他课程,您需要编写更多内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2018-09-03
    • 1970-01-01
    • 2014-09-18
    相关资源
    最近更新 更多