简体   繁体   English

试图避免子弹离开屏幕后强制关闭

[英]Trying to avoid a Force close after a bullet goes off screen

So I'm just messing around learning to create a Space invaders type game. 因此,我只是在学习创建“太空侵略者”类型游戏。 I can get the bad guys to move, Great!!. 我可以让坏家伙动弹,太好了! Hero moves, Great!! 英雄动作,太好了!! Bullets move, Great!! 子弹移动,太好了! However I try to remove my bullets once they leave the screen as to not eat up all resources and it force closes on me once it gets rid of the bullet. 但是,我尝试将子弹离开屏幕后将其删除,以免耗尽所有资源,并且一旦摆脱子弹,它就会强制关闭。 It goes off the screen. 它从屏幕上消失。 Hits the int of -2 and then we use the remove() and boom. 达到-2的整数,然后我们使用remove()和繁荣。 Force Close. 强制关闭。

Here is my code. 这是我的代码。 I'm wondering if they access the size() at the same time and just cause a force close because of it. 我想知道他们是否同时访问size()并因此而导致强制关闭。

//I removed everything that doesn't pertane to the bullets.
public class GameScreen{ 
    Bullet bullet = world.bullet;

    public GameScreen(Game game) {
        super(game);
        world = new World();
    }


    //Draws our bullets. 
    int bulletLength = bullet.bullets.size();
    for(int i = 0; i < bulletLength; i++) {
        Placement part = bullet.bullets.get(i);
        x = part.x * 32 + 11;
        y = part.y * 32;
        g.drawPixmap(Assets.bullet, x, y);
    }

Class that holds my bullets. 装有我子弹的班级。

public class Bullet {
    public List<Placement> bullets = new ArrayList<Placement>();

    public Bullet() {

    }

    public void shoot(int x, int y){
        bullets.add(new Placement(x,y));
    }


    public void advance(){
    int len = bullets.size(); // gets all bullets.
    for(int i = 0; i < len; i++) {
        bullets.get(i).y --;

        if (bullets.get(i).y <= -2){//removes them once they are off the screen.
            bullets.remove(i);
        }
    }
}

This is what I use to keep track of placement. 这就是我用来跟踪位置的方法。

package com.learning.planecomander;

public class Placement {
public int x, y;

public Placement(int x, int y) {
    this.x = x;
    this.y = y;
}
}

When going through your list to remove bullets, you can remove bullets from a list but that affects the list immediately instead of after your loop is done. 浏览列表以删除项目符号时,可以从列表中删除项目符号,但这会立即影响列表,而不是在循环完成之后。 Since you are traversing to the length of the list at the start, you are going off the end of the list since you've removed elements. 由于您要从列表的开头开始遍历列表的长度,因此,由于已删除元素,因此要离开列表的末尾。 An example is probably more helpful than that description. 一个例子可能比描述更有用。

Let's say you have a list with three bullets (which I'll call a, b, c to make the example easier). 假设您有一个包含三个项目符号的列表(为了简化示例,我将其称为a,b,c)。 On a pass through the list, a and c are fine but b needs to be removed. 在通过列表时,a和c可以,但是b需要删除。

i = 0; i = 0; bullets[0] = a; bullets [0] = a; bullets[1] = b; 项目符号[1] = b; bullets[2] = c; bullets [2] = c;

First loop goes fine, second loop starts like this 第一循环正常,第二循环这样开始

i = 1; i = 1; bullets[0] = a; bullets [0] = a; bullets[1] = b; 项目符号[1] = b; bullets[2] = c; bullets [2] = c;

We remove b, but the loop keeps going 我们删除了b,但是循环继续进行

i = 2; 我= 2; bullets[0] = a; bullets [0] = a; bullets[1] = c; 项目符号[1] = c;

OH CRAP ARRAYINDEXOUTOFBOUNDS! 哦,收割了ARRAYINDEXOUTOFBOUNDS! PROGRAM CRASHES! 程序崩溃!

The way to solve this is to use a temp list to store the bullets that need to be removed, and then once your update loop is finished, make a call to bullets.removeAll(temp) 解决此问题的方法是使用临时列表存储需要删除的项目符号,然后在完成更新循环后,调用bullets.removeAll(temp)

Doing two passes is a good answer. 做两遍是一个很好的答案。 It makes the loops simpler and easy to understand. 它使循环更简单易懂。 If you'd like to do it in one pass though, iterate through the list in reverse order, and when you remove a bullet you can go to the next one and not worry about blasting past the end of the ArrayList. 但是,如果您想一次通过,请以相反的顺序遍历列表,当您删除项目符号时,可以转到下一个项目,而不必担心炸破ArrayList的末尾。

Alternatively, you can keep your bullets in a linked list, and run through the list with an Iterator, which you can also use to remove items from the list with. 或者,您可以将项目符号保存在链接列表中,并使用迭代器遍历该列表,还可以使用该迭代器从列表中删除项目。 Removing from the beginning middle or end of an linked list is always a constant time operation. 从链表的开头中间或结尾删除始终是恒定时间的操作。 Whereas removing from the beginning of an ArrayList can be more expensive. 而从ArrayList的开头删除可能会更昂贵。 If you need random access to the elements in the list, then they can be inefficient. 如果您需要随机访问列表中的元素,则它们可能效率很低。 Keep in mind though, if you're only dealing with a handful of objects, then it doesn't really matter. 但是请记住,如果您只处理少数几个对象,那么这并不重要。

For bonus points, you might want to put all of your objects in a list, and then have your central loop process them all and have your game objects respond polymorphically to calls like dead?, think, move, draw or whatever you think is appropriate. 为了获得加分,您可能希望将所有对象放入列表中,然后让您的中央循环处理所有对象,并使游戏对象对死角之类的呼叫进行多态响应,然后思考,移动,绘制或您认为合适的任何东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM