如何使用 Thread.sleep()?
How can I use Thread.sleep()?
我正在为一个学校项目创建一个备忘录游戏,但我的 Thread.sleep 有问题。
当玩家 returns 两张牌时,程序会检查它们是否相同。如果不是,则他们脸朝下。由于程序几乎是立即完成的,我想暂停一下,以便玩家有时间看到第二张牌。问题是break是在翻牌前
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) 之前工作,我不明白为什么。
我不知道如何解决我的问题,如果你们能帮助我,我将不胜感激:)
首先,您不会暂停主线程,而是暂停后台线程,因为您不想冻结整个应用程序。
其次,使用 System.sleep() 而不是 Thread.sleep() 因为第一个不会抛出异常。
这是因为 UI 和绘图的工作原理。在主线程的 android 框架中,有一个巨大的事件循环处理消息。其中一条消息是绘制消息。只有在处理该消息时才会绘制屏幕。消息只能在循环的顶部处理。因此,如果线程休眠,它在休眠期间永远不会处理新消息,屏幕也不会更新。
如果你想像这样延迟做某事,有两个选择:
1) post 主循环的 Runnable 与 postDelayed 不同,而不是休眠,因此 运行nable 在您指定的时间为 运行未来。
2) 使用第二个线程和 运行 那里的所有游戏逻辑,当 UI 事件发生时将消息传递给它,并在需要绘制时将事件传递回主线程。
谢谢您的回答!
我创建了第二个线程。
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) {}
}
}
}
我在主 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);
}
我的问题仍然存在。我想我没有使用我的 GameLoopThread,因为它必须被使用。有什么意见吗?
我正在为一个学校项目创建一个备忘录游戏,但我的 Thread.sleep 有问题。
当玩家 returns 两张牌时,程序会检查它们是否相同。如果不是,则他们脸朝下。由于程序几乎是立即完成的,我想暂停一下,以便玩家有时间看到第二张牌。问题是break是在翻牌前
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) 之前工作,我不明白为什么。 我不知道如何解决我的问题,如果你们能帮助我,我将不胜感激:)
首先,您不会暂停主线程,而是暂停后台线程,因为您不想冻结整个应用程序。
其次,使用 System.sleep() 而不是 Thread.sleep() 因为第一个不会抛出异常。
这是因为 UI 和绘图的工作原理。在主线程的 android 框架中,有一个巨大的事件循环处理消息。其中一条消息是绘制消息。只有在处理该消息时才会绘制屏幕。消息只能在循环的顶部处理。因此,如果线程休眠,它在休眠期间永远不会处理新消息,屏幕也不会更新。
如果你想像这样延迟做某事,有两个选择:
1) post 主循环的 Runnable 与 postDelayed 不同,而不是休眠,因此 运行nable 在您指定的时间为 运行未来。
2) 使用第二个线程和 运行 那里的所有游戏逻辑,当 UI 事件发生时将消息传递给它,并在需要绘制时将事件传递回主线程。
谢谢您的回答! 我创建了第二个线程。
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) {}
}
}
}
我在主 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);
}
我的问题仍然存在。我想我没有使用我的 GameLoopThread,因为它必须被使用。有什么意见吗?