android - 如何在我的游戏循环中获得预期的动作顺序?
问题描述
我不完全了解幕后发生的事情,因此,我可以做些什么来正确编码这个问题。我正在寻找一个可以让我自己弄清楚的解释。这只是一个有趣的家庭项目(我不是学生),我正在编写一个基于回合的应用程序。但是,战斗场景是随机计算的持续时间,而不是基于回合的,所以我的愿望如下:
- 在屏幕上显示初始战斗计数 2 秒
- 计算第一次小冲突
- 在屏幕上显示更新的战斗计数 2 秒
- 计算第二次小冲突
- ...
- ...
- 在屏幕上显示胜利或失败
我遇到的问题是该应用程序当前执行如下:
- 在屏幕上显示初始战斗计数
- 计算所有小冲突
- 页面显示该数字为空,因为它显然已经返回?
代码如下所示:
void fightBattle(){
setContentView(R.layout.brigands);
boolean winnerDetermined = false;
while(!winnerDetermined) {
boolean brigandsWon = brigandsWon(player, brigandCount);
if(brigandsWon) {
player.removeWarriors(2);
}
displayWarriors(player);
if(brigandsWon){
if(player.getWarriors() < 2){
winnerDetermined = true;
}
}
if(!brigandsWon) {
brigandCount = brigandCount / 2;
}
displayBrigands();
if(brigandCount == 0){
winnerDetermined = true;
}
}
}
private void displayWarriors(Player player){
final Player currentPlayer = player;
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
}.start();
}
private void displayBrigands(Player player){
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.brigands);
TextView brigand_count_tv = findViewById(R.id.brigand_count_tv);
brigand_count_tv.setText(Integer.toString(brigandCount));
}
}.start();
}
最终,我想看到的是类似于下面的 sudo 代码:
displayPage1For2Seconds;
while(somethingIsTrue){
calculateNumber;
displayPage2For2Seconds;
displayPage3for2Seconds;
}
displayPage4For2Seconds;
解决方案
计算所有小冲突
您当前的代码这样做是因为 while 循环实际上并没有停止等待。流程将是这样的:
进入while循环->调用displayWarriors()->创建CountDownTimer()2秒后做某事->返回while循环->调用displayBrigands()->创建CountDownTimer()2秒后做某事->返回while循环 -> 做同样的事情直到你退出 while
使用此代码,您最终会得到一堆 CountDownTimer,它们是在相同(几乎)时间创建和执行的,所以两秒钟后,它们都尝试将视图设置为某个值(您提到的不确定行为会发生) .
有几种方法可以做你想做的事。例如,您可以使用线程:
void fightBattle(){
setContentView(R.layout.brigands);
new Thread(new Runnable() {
public void run() {
// I assume R.layout.brigands is the initial screen that you want to show for 2 seconds?!? In this case wait 2 seconds
TimeUnit.Seconds.sleep(2);
boolean winnerDetermined = false;
while(!winnerDetermined) {
// ...
// from your code it seems you want to show this for 2 seconds?
displayWarriors(player);
TimeUnit.Seconds.sleep(2);
//...
displayBrigands();
// also show this for 2 seconds
TimeUnit.Seconds.sleep(2);
// ...
}
}
}).start();
}
然后你的显示方法将是这样的:
private void displayWarriors(Player player){
// you need to wrap this code in a runOnUiThread() method(from the activity)
// because we are on a background thread and we are changing views!
final Player currentPlayer = player;
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
另一种方法是使用 Handler 并在 Runnables 中破坏您的代码,然后在适当的时间安排这些代码。
推荐阅读
- ruby-on-rails - 捆绑更新轨道上的不兼容依赖项
- javascript - javascript 无法从 Python 烧瓶转换为对象 JSON 只能将其视为字符串
- scipy - Scipy最小化函数约束声明问题
- html - PSD to bootstrap - 请建议保持 HTML 与大 PSD 相同
- javascript - JSON 文件中的 HTML 标记显示为纯文本而不是真正的 HTML 标记
- multithreading - 在并行迭代器中执行计算,然后将其提供给单线程迭代器?
- google-apps-script - 在谷歌表格中取消选择或保存当前单元格
- spring-boot - 卡夫卡保留.字节| 手动确认
- html - Tailwind CSS 不必要的空格
- javascript - 我需要获取创建的频道的ID,但我不知道该怎么做?(discord.js)