今日目標,倒數計時。
既然要讀秒,那我們先嘗試使用 Timer,不過這個方法是不可行的,待會會說明,然後這邊為了方便,我們寫測試程式來 Demo。
package com.example.game;
import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo {
private int time = 0;
public void run() {
// 建立 Timer
Timer timer = new Timer();
// 要執行的工作
TimerTask task = new TimerTask () {
public void run() {
doSomething(time++);
}
};
// 開始執行,第一次執行延遲 0 秒,每次執行間隔 1 秒(1000毫秒)
timer.schedule (task, 0, 1000);
}
public void doSomething(int n) {
System.out.println(n);
}
}
run()
點右鍵,選擇 generate
package com.example.game;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class TimerDemoTest {
@Test
public void testRun() throws InterruptedException {
TimerDemo timer = new TimerDemo();
timer.run();
// 設定要等多久,不然他會直接停掉
Thread.sleep(1000 * 5);
}
}
我們剛才這樣做乍看好像沒什麼問題,把 time 改成我們要的秒數,比如 20,讓他往回扣就好,然後減到 0 就停止這個 timer,但最大的問題在於,當玩家打出手牌時,應該要直接停止這個 timer 並且輪到下一次的倒數,雖然我們可以做到停止,但沒辦法知道它哪時候停止。
因此,我們要改用別的方式來實現。
我們一樣示範一下程式用法。
package com.example.game;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TimerDemo {
private int time = 0;
public void run() {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(()-> {
doSomething(time++);
}, 0, 1, TimeUnit.SECONDS);
}
public void doSomething(int n) {
System.out.println(n);
}
}
package com.example.game;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TimerDemo {
private int time = 0;
public void run(int task) {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
// 要執行什麼
// 也定義延遲 0 秒開始執行,每次間隔 1 秒,最方便的是,可以透過 TimeUnit.SECONDS 來自定義單位,不必自己換算
timer.scheduleAtFixedRate(()-> {
doSomething(task, time++);
}, 0, 1, TimeUnit.SECONDS);
}
public void doSomething(int task, int n) {
System.out.println(task + ": " + n);
}
}
package com.example.game;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class TimerDemoTest {
@Test
public void testRun() throws InterruptedException {
TimerDemo timer1 = new TimerDemo();
timer1.run(1);
TimerDemo timer2 = new TimerDemo();
timer2.run(2);
Thread.sleep(1000 * 5);
}
}
package com.example.game;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TimerDemo {
private int time = 0;
public void run(int task) throws InterruptedException {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(()-> {
doSomething(task, time++);
// 設定一下中斷點,執行 5 秒就結束
if (time > 5) {
timer.shutdown();
}
}, 0, 1, TimeUnit.SECONDS);
// 等 timer 執行 7 秒
timer.awaitTermination(7, TimeUnit.SECONDS);
}
public void doSomething(int task, int n) {
System.out.println(task + ": " + n);
}
}
awaitTermination()
等待前一個結束後,讓下一個 timer 執行既然搞懂 Timer 怎麼弄,那我們就來定義自己的 Timer 吧,並生出對應方法,之後也比較好調用。
package com.example.game;
import com.example.call.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class GameTimer {
private ScheduledExecutorService timer;
private Integer time = 1;
// 初始化
public void init(int time) {
this.timer = Executors.newSingleThreadScheduledExecutor();
this.time = time;
}
// 倒數 (參數 printer 我們還沒定義)
public void countDown(Callable printer) {
try {
Thread.sleep(1000);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
this.timer.scheduleAtFixedRate(()-> {
printer.call(time.toString());
time--;
if (time <= 0) {
stop();
}
}, 1, 1, TimeUnit.SECONDS);
}
// 等待的最大秒數
public void await(int timeoutWithSeconds) {
try{
this.timer.awaitTermination(timeoutWithSeconds, TimeUnit.SECONDS);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
// 停止 Timer
public void stop() {
this.timer.shutdown();
}
}
package com.example.call;
public interface Callable {
public void call(String param);
}
package com.example.game;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class GameTimerTest {
@Test
public void testGameTimer() throws InterruptedException {
GameTimer timer = new GameTimer();
timer.init(5);
timer.countDown(System.out::println);
timer.await(3);
timer.stop();
}
}
今天先講解如何實現倒數計時,之後會將這個套用到遊戲進行的時候~~