简体   繁体   English

如何使用Thread.sleep()?

[英]How can I use Thread.sleep()?

I am creating a Memo Game for a school project and I have a problem with my Thread.sleep. 我正在为一个学校项目创建一个备忘游戏,但我的Thread.sleep存在问题。

When the player returns two cards, the program checks if they are identical. 当玩家返回两张牌时,程序将检查它们是否相同。 If they are not, then they turn face down. 如果不是,则它们会面朝下。 Since the program does it almost instantly, I'd like to pause so that the player has time to see the second card. 由于该程序几乎是立即执行的,因此我想暂停一下,以便玩家有时间看到第二张纸牌。 The problem is that the break is before the card turns 问题是中断是在卡片转动之前

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 !");
    }
}

On my game, Thread.sleep works before majAffichage(carte) and I don't understand why. 在我的游戏中,Thread.sleep在majAffichage(carte)之前起作用,我不明白为什么。 I dont know how to resolve my problem and if you guys can help me I would be very grateful :) 我不知道如何解决我的问题,如果你们能帮助我,我将非常感激:)

Its because of how the UI and drawing works. 这是因为UI和绘图的工作原理。 Inside the android framework on the main thread, there's a giant event loop processing messages. 在主线程上的android框架内部,有一个巨大的事件循环处理消息。 One of those messages is a draw message. 这些消息之一是抽奖消息。 The screen is only drawn when that message is processed. 仅在处理该消息时才绘制屏幕。 Messages can only be processed at the top of the loop. 消息只能在循环的顶部进行处理。 So if the thread sleeps, it never processes new messages during that sleep, and the screen won't update. 因此,如果线程处于休眠状态,则在该休眠期间它永远不会处理新消息,并且屏幕也不会更新。

If you want to do something on a delay like that, there are two options: 如果您希望像这样延迟执行某件事,则有两种选择:

1)Instead of sleeping, post a Runnable to the main looped with postDelayed, so the runnable is run at a time you specify in the future. 1)将Runnable而不是休眠,而是发布到具有postDelayed的主循环中,这样就可以在将来指定的时间运行该Runnable。

2)Use a second Thread and run all your game logic in there, passing messages to it when UI events occur and passing events back to the main thread when it needs to draw. 2)使用第二个线程并在其中运行所有游戏逻辑,在发生UI事件时将消息传递给它,并在需要绘制时将事件传递回主线程。

First, you don't pause the Main Thread but the Background Thread because you don't want the freeze the entire app. 首先,您不暂停主线程,而是暂停后台线程,因为您不希望冻结整个应用程序。

Second, use System.sleep() instead of Thread.sleep() cause the first one doesn't throw an exception. 其次,使用System.sleep()而不是Thread.sleep()会导致第一个不会引发异常。

Thank you for your answer ! 谢谢您的回答 ! I have created a second Thread. 我创建了第二个线程。

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) {}
        } 
    } 

} 

and I call this in my main class : 我在主班上称呼它为:

@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);
    }

My problem is still perduring. 我的问题仍然困扰。 I think I didn't use my GameLoopThread as it must be used. 我认为我没有使用GameLoopThread,因为必须使用它。 Any remarks ? 有什么意见吗?

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

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