简短摘要
我有一个活动游戏。用户将点击图片:
用户有5秒钟的时间点击并选择正确的一个。 5秒后,正确的图像视图将以不同方式显示以引起注意,并在5秒后再次显示,用户将看到下一级别。
用户无需等待5秒即可点击,因此点击后应立即进入下一级别。
我正在动态创建视图和图像视图。图像视图从本地数据库sqlite作为字节进行编译。
我的方法是在oncreate方法中创建。我使用for或while循环。每次迭代都是一个游戏级别。每个级别都有不同的图像视图和不同的图像视图数。
为了延迟5 + 5秒,我不得不使用处理程序,线程,倒数计时器。每一个都造成了问题。
在使用处理程序时,当用户在5秒之前点击时,我无法终止当前会话。
我不知道这是否正确。
您可以在下面看到我的代码:
长期解释和代码
定时器:
nCreate() {
for (int i = 0; i < 2; i++) {
handler.postDelayed(new Runnable() {
public void run() {
imageAnswer.setImageBitmap(bmp);
imageAnswer.setId(R.id.imgAnswer);
//adding image to screen
finalRLayout.removeAllViews();
finalRLayout.addView(imageAnswer, rLayParams);
//starting timer, if no answer in 5 seconds, run again timer
startTimer();
//clicklisterner
imageAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//if clicks true, cancel timer and go to next iteration of for loop
if (view == findViewById(R.id.imgAnswer)) {
Log.d(TAG, "clicked");
//PUT IN CODE HERE TO GET NEXT IMAGE
cancelTimer();
} else { //if not true, run again timer for last chance
Log.d(TAG, "nonclick");
cancelTimer();
startTimer();
}
}
});
}
}, 2000 * i);
} //for end
} //oncreate end
//start timer function
void startTimer() {
cTimer = new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d(TAG, "ontick");
}
public void onFinish() {
Log.d(TAG, "timer onfinish");
}
};
cTimer.start();
}
//cancel timer
void cancelTimer() {
Log.d(TAG, "canceltimer");
if (cTimer != null)
cTimer.cancel();
}
3个不同的线程操作但没有工作。其中一个屏幕进入黑屏。其他两个并没有阻止循环。
runnable version
for ( int i = 0; i< 20 ; i++) {
Log.d(TAG, "for i2="+ i);
final int finalI = i;
final RelativeLayout finalRLayout = rLayout;
final Runnable r=new Runnable() {
@Override
public void run() {
Log.d(TAG, "for finali2="+ finalI);
TrainingObject trainingObject = new TrainingObject();
trainingObject = trainingObjectList.get(finalI);
objectCount = 2;
//test icin
Log.d(TAG,"testicin trainingobjectid: "+trainingObject.getTrainingobjectID());
object = dbHandler.getObjectObject(trainingObject.getTrainingobjectAnswer());
RelativeLayout.LayoutParams rLayParams = new RelativeLayout.LayoutParams(140,140);
rLayParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
rLayParams.addRule(RelativeLayout.CENTER_IN_PARENT);
imgBytes = object.getObjectImageBlob();
bmp = BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length);
imageAnswer.setImageBitmap(bmp);
imageAnswer.setTag(trainingObject.getTrainingobjectAnswer());
imageAnswer.setId(R.id.imgAnswer);
finalRLayout.removeAllViews();
finalRLayout.addView(imageAnswer,rLayParams);
}
};
Log.d(TAG, "3000i2 sonrasi");
handler.postDelayed(r, 6000 * i);
imageAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view == findViewById(R.id.imgAnswer)) {
Log.d(TAG, "clicked");handler.removeCallbacks(r); handler.postDelayed(r, 0);
//PUT IN CODE HERE TO GET NEXT IMAGE
}
else{
Log.d(TAG, "nonclick");
handler.removeCallbacks(r); handler.postDelayed(r, 6000);
}
}
});
}//for end
答案 0 :(得分:3)
你可以简单地使用handler来实现你的目的,你应该做的是创建一个runnable并在处理程序之外声明它然后在postDelayed
处理程序中使用它的名字,如果用户点击了,只需删除所有处理程序回调:
// first create runnable
Runnable r = new Runnable{
public void run(){
//do what you need to do after 5 seconds
}
}
// then create handler
Handler mHandler = new Handler();
// then in your onCreate method
nCreate() {
for (int i = 0; i < 2; i++) {
handler.postDelayed(new Runnable() {
public void run() {
imageAnswer.setImageBitmap(bmp);
imageAnswer.setId(R.id.imgAnswer);
//adding image to screen
finalRLayout.removeAllViews();
finalRLayout.addView(imageAnswer, rLayParams);
//starting handler, if no answer in 5 seconds, run again timer
mHandler.postDelayed(r, 5000);
//clicklisterner
imageAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//if clicks true, cancel timer and go to next iteration of for loop
if (view == findViewById(R.id.imgAnswer)) {
Log.d(TAG, "clicked");
//PUT IN CODE HERE TO GET NEXT IMAGE
myHandler.removeCallbacks(r);
} else { //if not true, run again timer for last chance
Log.d(TAG, "nonclick");
// stop the handler
myHandler.removeCallbacks(r);
// run a new one
mHandler.postDelayed(r, 5000);
}
}
});
}
}, 2000 * i);
} //for end
} //oncreate end
答案 1 :(得分:2)
对于游戏开发,您应该使用更专业的东西来实现您的游戏,我建议您阅读本书Beginning Android Games 2nd Edition它具有2D和3D游戏的基础知识,您可以从中学习各种选项。 现在为您的代码我建议您在外部线程上跟踪时间,并使其回调到您在主游戏活动中实现的界面 示例:
<强> TimeThread.java 强>
import android.util.Log;
public class TimeThread implements Runnable {
Thread thread = null;
TimeTickListener listener;
volatile boolean running = false;
public TimeThread(TimeTickListener listener) {
this.listener = listener;
}
public void resume() {
thread = new Thread(this);
running = true;
if (thread != null)
thread.start();
}
@Override
public void run() {
while (running) {
// sending callbacks to the mainActivity
listener.onTimeTick();
}
}
public void pause() {
running = false;
while (true) {
try {
thread.join();
Log.v("my", "joined ");
break;
} catch (InterruptedException e) {
Log.v("my", "not joined cause : " + e.getMessage());
}
}
}
}
我们使用的界面:
public interface TimeTickListener {
public void onTimeTick();
}
以下是mainActivity的示例:
<强> MainActivity.java 强>
public class MainActivity extends Activity implements TimeTickListener {
long startTime = System.nanoTime();
// the interface method that we implemented
@Override
public void onTimeTick() {
// keep trace of the time untill it sums up to 1 sec then do an action
// in your situation you can make it to count 5 sec
// and make your action here
if ((System.nanoTime() - startTime) / 1000000000 >= 1) {
totalTime += 1;
// this handler is because you should change the textView from its
// original thread
// and it is not allowed to be edited from another thread
// in your case you should change the imageViews like this in the main thread
mainHandler.post(new Runnable() {
@Override
public void run() {
text.setText(totalTime + " seconds passed ");
}
});
startTime = System.nanoTime();
// and this is how to terminate the thread manually (optional)
if (totalTime >= 10) {
timeThread.pause();
}
}
}
Handler mainHandler;
TextView text;
float totalTime = 0;
TimeThread timeThread;
TimeTickListener listener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
text = new TextView(this);
text.setText("wait...");
setContentView(text);
// initializing the handler with the main activity looper
mainHandler = new Handler(getMainLooper());
//getting our implemented listener to pass it to the timeThread for the callbacks
listener = (TimeTickListener) this;
timeThread = new TimeThread(listener);
// resume method will launch the thread and make it start calling the interface method (onTimeTick)
timeThread.resume();
}
@Override
protected void onPause() {
// don't forget to pause the thread here
timeThread.pause();
super.onPause();
}
}
此代码已经过测试并取得了巨大成功,时间准确且同步得很好。
然而,它有点复杂,占用资源,因为第二个线程中的while循环有很多优点,可以让你正确控制你的应用程序。
这个答案是为了获得准确的时间,如何处理时间跟踪线程以及在何处进行操作但是如果您遇到游戏逻辑问题或者很难隐藏并在这种情况下向用户显示图像不是你想要的答案所以告诉我,我会尽力帮助你。