Как я могу использовать Thread.sleep ()? - PullRequest
1 голос
/ 23 апреля 2019

Я создаю памятную игру для школьного проекта, и у меня возникла проблема с моим Thread.sleep.

Когда игрок возвращает две карты, программа проверяет, идентичны ли они.Если нет, то они поворачиваются лицом вниз.Поскольку программа делает это практически мгновенно, я бы хотел сделать паузу, чтобы у игрока было время увидеть вторую карту.Проблема в том, что перерыв происходит до того, как карта поворачивается

if (deck1.contains(carte)) {
    if (carte.getEtat() == 0) {
        carte.setEtat(1);
        cartesRetournees1.add(carte);
        majAffichage(carte);

        try {
            Thread.sleep(500);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
    if (cartesRetournees1.size() == 2) {
        int nouveauEtat = 0;
        if (cartesRetournees1.get(0).getMotif() == cartesRetournees1.get(1).getMotif()) {
            nouveauEtat = -1;
            this.nbPairsTrouvees++;
        }

        cartesRetournees1.get(0).setEtat(nouveauEtat);
        cartesRetournees1.get(1).setEtat(nouveauEtat);

        majAffichage(cartesRetournees1.get(0));
        majAffichage(cartesRetournees1.get(1));
        cartesRetournees1.remove(1);
        cartesRetournees1.remove(0);

        if (nbPairsTrouvees == this.plateau.size()) System.out.println("GAGNE !");
    }
}

В моей игре Thread.sleep работает до majAffichage (carte), и я не понимаю, почему.Я не знаю, как решить мою проблему, и если вы, ребята, можете мне помочь, я был бы очень благодарен:)

Ответы [ 3 ]

2 голосов
/ 23 апреля 2019

Это из-за того, как работает интерфейс и рисование.Внутри платформы Android в главном потоке есть гигантский цикл обработки сообщений.Одним из таких сообщений является сообщение ничья.Экран отображается только при обработке этого сообщения.Сообщения могут быть обработаны только в верхней части цикла.Поэтому, если поток спит, он никогда не обрабатывает новые сообщения во время этого сна, и экран не обновляется.

Если вы хотите что-то сделать с такой задержкой, есть два варианта:

1) Вместо того, чтобы спать, разместите Runnable на главном цикле с помощью postDelayed, чтобы он запускался в то время, которое вы укажете в будущем.

2) Используйте второй поток и запустите всю свою игровую логикутам, передавая ему сообщения, когда происходят события пользовательского интерфейса, и передавая события обратно в основной поток, когда ему нужно рисовать.

0 голосов
/ 24 апреля 2019

Спасибо за ваш ответ!Я создал вторую тему.

package com.example.jeudumemo;

import android.graphics.Canvas;

public class GameLoopThread extends Thread
{
    private final static int FRAMES_PER_SECOND = 30;

    private final static int SKIP_TICKS = 1000 / FRAMES_PER_SECOND;

    private final Game view; 
    private boolean running = false; 

    public GameLoopThread(Game view) {
        this.view = view;
    }

    public void setRunning(boolean run) {
        running = run;
    }

    @Override
    public void run()
    {
        long startTime;
        long sleepTime;

        while (running)
        {
            startTime = System.currentTimeMillis();

            synchronized (view.getHolder()) {view.update();}

            Canvas c = null;
            try {
                c = view.getHolder().lockCanvas();
                synchronized (view.getHolder()) {view.draw(c);}
            }
            finally
            {
                try {
                    if (c != null) {
                        view.getHolder().unlockCanvasAndPost(c);
                    }
                } catch(IllegalArgumentException iae) { iae.printStackTrace(); }
            }
            sleepTime = SKIP_TICKS-(System.currentTimeMillis() - startTime);
            try {
                if (sleepTime >= 0) {sleep(sleepTime);}
            }
            catch (Exception e) {}
        } 
    } 

} 

, и я называю это в моем основном классе:

@Override
    public void surfaceCreated(SurfaceHolder holder) {
        if(gameLoopThread.getState()==Thread.State.TERMINATED) {
            gameLoopThread=new GameLoopThread(this);
        }
        gameLoopThread.setRunning(true);
        gameLoopThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        gameLoopThread.setRunning(false);
        while (retry) {
            try {
                gameLoopThread.join();
                retry = false;
            }
            catch (InterruptedException e) {}
        }
    }

public void controleJeu(Carte carte) {
        if(deck1.contains(carte)) {
            if (carte.getEtat() == 0) {
                carte.setEtat(1);
                cartesRetournees1.add(carte);
                majAffichage(carte);

            }
            if (cartesRetournees1.size() == 2) {
                try {
                    gameLoopThread.sleep(500);
                }catch(InterruptedException ie) { ie.printStackTrace(); }
                int nouveauEtat = 0;
                if (cartesRetournees1.get(0).getMotif() == cartesRetournees1.get(1).getMotif()) {
                    nouveauEtat = -1;
                    this.nbPairsTrouvees++;
                }

                cartesRetournees1.get(0).setEtat(nouveauEtat);
                cartesRetournees1.get(1).setEtat(nouveauEtat);

                majAffichage(cartesRetournees1.get(0));
                majAffichage(cartesRetournees1.get(1));
                cartesRetournees1.remove(1);
                cartesRetournees1.remove(0);
            }
        }
        else if(deck2.contains(carte)) {
            if (carte.getEtat() == 0) {
                carte.setEtat(1);
                cartesRetournees2.add(carte);
                majAffichage(carte);
            }
            if (cartesRetournees2.size() == 2) {
                try {
                    gameLoopThread.sleep(500);
                }catch(InterruptedException ie) { ie.printStackTrace(); }
                int nouveauEtat = 0;
                if (cartesRetournees2.get(0).getMotif() == cartesRetournees2.get(1).getMotif()) {
                    nouveauEtat = -1;
                    this.nbPairsTrouvees++;
                }

                cartesRetournees2.get(0).setEtat(nouveauEtat);
                cartesRetournees2.get(1).setEtat(nouveauEtat);

                majAffichage(cartesRetournees2.get(0));
                majAffichage(cartesRetournees2.get(1));
                cartesRetournees2.remove(1);
                cartesRetournees2.remove(0);
            }
        }
        if (nbPairsTrouvees == nbDeck*6) { showPopupVictoire(this); this.victory = true; }
        System.out.println(nbDeck);
    }

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

0 голосов
/ 23 апреля 2019

Во-первых, вы не приостанавливаете основной поток, а фоновый, потому что не хотите останавливать все приложение.

Во-вторых, используйте System.sleep () вместо Thread.sleep (), так как первый не вызывает исключение.

...