如何在我的游戏循环中获得预期的动作顺序?
How to obtain the expected order of actions in my game loop?
我不完全了解幕后发生的事情,因此,我可以做些什么来正确编码这个问题。我正在寻找一个可以让我自己弄清楚的解释。这只是一个有趣的家庭项目(我不是学生),我正在编写一个回合制应用程序。但是,战斗场景是随机计算的持续时间,而不是回合制,所以我的愿望如下:
- 在屏幕上显示初始战斗计数 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;
Calculate all skirmishes
您当前的代码这样做是因为 while 循环实际上并没有停止等待。流程将是这样的:
进入 while 循环 -> 调用 displayWarriors() -> 创建 CountDownTimer() 以在 2 秒后执行某些操作 -> return 进入 while 循环 -> 调用 displayBrigands() -> 创建 CountDownTimer() 以执行操作2 秒后的东西 -> return 到 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 中中断代码,然后在适当的时间安排它。
我不完全了解幕后发生的事情,因此,我可以做些什么来正确编码这个问题。我正在寻找一个可以让我自己弄清楚的解释。这只是一个有趣的家庭项目(我不是学生),我正在编写一个回合制应用程序。但是,战斗场景是随机计算的持续时间,而不是回合制,所以我的愿望如下:
- 在屏幕上显示初始战斗计数 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;
Calculate all skirmishes
您当前的代码这样做是因为 while 循环实际上并没有停止等待。流程将是这样的:
进入 while 循环 -> 调用 displayWarriors() -> 创建 CountDownTimer() 以在 2 秒后执行某些操作 -> return 进入 while 循环 -> 调用 displayBrigands() -> 创建 CountDownTimer() 以执行操作2 秒后的东西 -> return 到 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 中中断代码,然后在适当的时间安排它。