我正在为学校项目创建一个备忘录游戏,我的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)之前工作,我不明白为什么。我不知道如何解决我的问题,如果你们能帮助我,我会非常感激:)
这是因为UI和绘图的工作原理。在主线程的android框架内,有一个巨大的事件循环处理消息。其中一条消息是绘制消息。仅在处理该消息时绘制屏幕。消息只能在循环的顶部处理。因此,如果线程休眠,它在该睡眠期间永远不会处理新消息,并且屏幕将不会更新。
如果你想在这样的延迟上做点什么,有两种选择:
1)而不是睡觉,使用postDelayed将Runnable发布到主循环,因此runnable将在您将来指定的时间运行。
2)使用第二个Thread并在那里运行所有游戏逻辑,在UI事件发生时将消息传递给它,并在需要绘制时将事件传递回主线程。
首先,您不要暂停主线程而是暂停后台线程,因为您不希望冻结整个应用程序。
其次,使用System.sleep()而不是Thread.sleep()导致第一个不抛出异常。
谢谢您的回答 !我创建了第二个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) {}
}
}
}
我在我的主要课堂上称之为:
@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,因为必须使用它。有何评论?