Определенные действия приводят к нежелательным результатам - PullRequest
1 голос
/ 14 марта 2020

Итак, я начну с некоторого объяснения.

Я делаю игру, используя Android studio, и она похожа на Space shooter и такие игры (хорошо, если эти игры вам неизвестны) , но дело в том, что я пытаюсь делать патроны с регулярным интервалом.

Это код, который я использую для этого (и при необходимости он дает удовлетворительный результат): -

( Короче говоря, этот фрагмент кода добавляет объектную пулю в очередь со свойствами, такими как ее расположение сверху и слева, которые можно использовать при рисовании пуль на холсте с интервалами REGULAR)

public void buildBullets()
{
 bulletBuildingThread = new Thread("Bullets Building Thread") {
        @Override
        public void run() {
            super.run();
            double shipWidthHalf = (currentShipImage.getScaledWidth(currentShipImage.getDensity()) * 0.5);
            double shipHeightHalf = (currentShipImage.getScaledHeight(currentShipImage.getDensity()) * 0.5);
            double bulletWidthHalf = (currentShip.getBulletWidth()) * 0.5;
            double bulletHeightHalf = (currentShip.getBulletHeight()) * 0.5;

            while (shouldBuildBullets) {
                do {
                    previousBulletStartTime = System.nanoTime() / 1000000;
                    bullet = new Bullet(currentShip.getLoopBulletFrame(), currentShip.getBulletUpSpeed(), currentShip.getBulletDownSpeed(),
                            currentShip.getBulletRightSpeed(), currentShip.getBulletLeftSpeed(), currentShip.getMillisBeforeNextBullet());

                    bullet.setLocationLeft((int) (ship_left + shipWidthHalf - bulletWidthHalf));
                    bullet.setLocationTop((int) (ship_top + shipHeightHalf - bulletHeightHalf));
                    bulletQueue.Enqueue(bullet);
                    previousBulletTimeSpan = (System.nanoTime() / 1000000) - previousBulletStartTime;
                    try {
                        Thread.sleep(bullet.getMillisBeforeNextBullet() - previousBulletTimeSpan);
                    } catch (InterruptedException e) {
                        Log.e(TAG, "run: ", e);
                    }
                }
                while (shouldBuildBullets && !GamePlay_Activity.shouldPauseTheView());
                bulletQueue.DequeueAll();
            }
        }
    };
    bulletBuildingThread.start();
}

Мой основной класс - это SurfaceView, который реализует Runnalbe. Соответствующий метод запуска: -

@Override
public void run()
{
    try
    {
        while (drawingActive)
        {

            frameStartTime = System.nanoTime();
            Canvas canvas = holder.lockCanvas();
            if (canvas != null)
            {
                try
                {
                    // Your drawing here
                    // First is Background
                    canvas.drawBitmap(currentBackgroundImage, 0, 0, null);
                    numberOfBullets = bulletQueue.getSize();
                    for(int i = 0; i < numberOfBullets; i++)
                    {
                        bullet = bulletQueue.get(i);
                        tempBulletLeft = bullet.getLocationLeft() + bullet.getRightSpeed() - bullet.getLeftSpeed();
                        tempBulletTop = (bullet.getLocationTop()) - bullet.getUpSpeed() + bullet.getDownSpeed();
                        if(tempBulletTop <= 0 || tempBulletTop >= canvas_bottom || tempBulletLeft <= 0 || tempBulletLeft >= canvas_right)
                        {
                            bulletQueue.Dequeue(i);
                            numberOfBullets -= 1;
                            i -= 1;
                        }
                        else
                        {
                            bulletQueue.setLocationTop(i, tempBulletTop); //changes the location properties of bullet at index i in the queue.
                            bulletQueue.setLocationLeft(i, tempBulletLeft);
                        }
                    }
                    numberOfBulletsToDraw = bulletQueue.getSize();
                    for(int i = 0; i < numberOfBulletsToDraw; i++)
                    {
                        drawBullet = bulletQueue.get(i);
                        canvas.drawBitmap(drawBullet.getBulletImage(), drawBullet.getLocationLeft(), drawBullet.getLocationTop(), null);
                    }
                    canvas.drawBitmap(currentShipImage, ship_left, ship_top, null);

                }
                finally
                {

                    holder.unlockCanvasAndPost(canvas);
                }
            }

            // calculate the time required to draw the frame in ms
            frameTime = (System.nanoTime() - frameStartTime) / 1000000;

            if (frameTime < MAX_FRAME_TIME) // faster than the max fps - limit the FPS
            {
                try
                {
                    Thread.sleep(MAX_FRAME_TIME - frameTime);
                } catch (InterruptedException e)
                {
                    // ignore
                }
            }
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

Я удалил не относящуюся к делу часть кода и попытался дать минимальный код. Если потребуется что-то дополнительное, я также предоставлю это.

Изначально все это прекрасно работает. Но когда я помещаю свое приложение в последнее время и открываю его несколько раз, создаются дополнительные пули. Это видео более информативно в отношении того, что происходит: -

Видео, показывающее проблему

Я пробовал несколько вещей, таких как спящий основной поток, когда onDestroyed или onPause вызывается в действии с использованием этого представления, но ничего не работает.

Может кто-нибудь сказать мне, как это исправить. Я хочу иметь постоянную скорость и разрыв между пулями, чего не происходит, если я несколько раз открываю и закрываю приложение из последних.

...