我正在为一个学校项目创建一个备忘游戏,但是我的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)之前起作用,我不明白为什么。 我不知道如何解决我的问题,如果你们能帮助我,我将非常感激:)
答案 0 :(得分:2)
这是因为UI和绘图的工作方式。在主线程上的android框架内部,有一个巨大的事件循环处理消息。这些消息之一是抽奖消息。仅在处理该消息时才绘制屏幕。消息只能在循环的顶部进行处理。因此,如果线程处于休眠状态,则在该休眠期间它永远不会处理新消息,并且屏幕也不会更新。
如果您想像这样延迟地做某事,有两种选择:
1)不是将其睡眠,而是将一个Runnable发布到具有postDelayed的主循环中,因此该Runnable会在您将来指定的时间运行。
2)使用第二个线程并在其中运行所有游戏逻辑,在发生UI事件时将消息传递给它,并在需要绘制时将事件传递回主线程。
答案 1 :(得分:0)
首先,您不暂停主线程,而是暂停后台线程,因为您不希望冻结整个应用程序。
第二,使用System.sleep()而不是Thread.sleep(),因为第一个不会引发异常。
答案 2 :(得分:0)
谢谢您的回答! 我创建了第二个线程。
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,因为必须使用它。有任何评论吗?