JavaFX實戰:從零到一實現一個功能豐富的“高級反應速度測試”游戲

大家好!今天我們不搞簡單的“紅變綠就點”了,來點硬核的!我們要用 JavaFX 從頭開始,構建一個更復雜、更有趣也更考驗能力的“高級反應速度測試”游戲。這個版本將引入選擇反應時 (Choice Reaction Time) 的概念——你需要在多個干擾項中快速找到并點擊指定的目標,這更貼近我們現實生活中的反應場景。

這篇文章將帶你深入了解這個游戲的開發全過程,涉及 JavaFX 布局、事件處理、狀態管理、動畫與計時器、動態 UI 生成等多個方面。無論你是 JavaFX 新手想找個練手項目,還是有經驗的開發者想看看具體應用,相信都能有所收獲。

我們將實現的核心功能:

  • 多目標呈現與選擇: 屏幕隨機位置出現多個圖形(圓形/方形),每次你需要點擊指定的那一種。
  • 干擾項: 除了目標,還有形狀或顏色不同的干擾項。
  • 計時與計分: 精確測量反應時間,并根據表現(命中、誤擊、錯過)進行計分。
  • 多輪測試與統計: 游戲包含固定次數的測試(試次),結束后給出總分和平均反應時間。

設計先行:游戲流程與界面布局

在敲代碼之前,先理清思路很重要。

游戲流程大概是這樣:

  1. 初始狀態: 顯示標題和“開始游戲”按鈕。
  2. 開始游戲: 重置分數和統計,禁用開始按鈕,進入第一個試次。
  3. 準備階段 (GET_READY): 屏幕清空,提示本次要點擊的目標(如“準備… 點擊 圓形!”),并隨機等待 1-2.5 秒。
  4. 刺激呈現 (SHOWING_STIMULUS): 在屏幕隨機位置同時顯示目標和干擾項圖形,并開始計時。提示變為“點擊!”。
  5. 玩家交互:
    • 正確點擊目標: 記錄反應時間,加分,進入下一試次的“準備階段”。
    • 點擊干擾項: 扣分,進入下一試次的“準備階段”。
    • 點擊背景或超時(1.5秒內未點擊): 算作“錯過”,扣少量分,進入下一試次的“準備階段”。
  6. 單次試次結束 (TRIAL_OVER): 短暫顯示本次結果(命中/點錯/錯過),然后自動進入下一試次。
  7. 整輪結束 (ROUND_OVER): 完成所有試次(如10次)后,顯示總得分、平均反應時間、命中/錯誤/錯過統計,并重新啟用“開始游戲”按鈕(文本變為“再玩一輪”)。

界面布局:

我們選用 BorderPane 作為根布局,邏輯清晰:

  • 頂部 (Top): 使用 VBox 垂直排列顯示游戲狀態/指示 (instructionLabel)、試次進度 (trialLabel)、當前得分 (scoreLabel) 和平均反應時間 (avgTimeLabel)。
  • 中部 (Center): 使用 Pane 作為游戲核心區域 (gamePane)。選擇 Pane 是因為它允許我們通過 setLayoutX/Y 精確控制子節點(圖形)的絕對位置,這對于隨機放置目標至關重要。
  • 底部 (Bottom): 使用 HBox 水平放置控制按鈕(目前只有一個“開始游戲”按鈕 startButton)。

在這里插入圖片描述

核心技術點深度解析

1. 狀態管理:GameState 枚舉與狀態機

對于一個交互流程稍復雜的應用,清晰的狀態管理是關鍵。我們定義了一個 GameState 枚舉:

private enum GameState {INITIAL, GET_READY, SHOWING_STIMULUS, TRIAL_OVER, ROUND_OVER
}
private GameState currentState = GameState.INITIAL;

程序在任何時候都處于其中一個狀態。所有的事件處理(如鼠標點擊)和流程控制(如計時器結束)都會首先檢查 currentState,并根據當前狀態執行相應的邏輯,然后可能轉換到下一個狀態。這形成了一個簡單的狀態機,大大降低了邏輯混亂的風險。例如,只有在 SHOWING_STIMULUS 狀態下,點擊圖形才有效;在其他狀態下點擊會被忽略或有不同處理(如 RESULT 狀態點擊是重新開始)。

2. 動態 UI 生成與布局:Pane 的妙用

游戲的核心在于動態生成和放置圖形。

  • 圖形生成 (generateShapes): 每次 showStimulus 時,此方法會:

    • 隨機決定本輪目標是圓是方 (targetShapeDefinition)。
    • 創建一個對應的正確目標節點 (correctTargetNode),設置目標顏色 (TARGET_COLOR)。
    • 循環創建指定數量的干擾項。干擾項與目標的區別是隨機的(要么形狀不同,要么顏色不同,使用預定義的干擾色)。
    • 為每個創建的圖形節點(目標和干擾項)添加點擊事件監聽器 (addClickHandler)。
  • 隨機放置 (placeShapesRandomly):

    • 獲取 gamePane 的實際寬高。
    • 對每個圖形,在 gamePane 內隨機生成 x, y 坐標(注意留出邊緣空間)。
    • 關鍵:使用 Pane 布局,可以直接設置 shape.setLayoutX(x)shape.setLayoutY(y) 來定位。
    • 避重疊(簡化版): 為了防止圖形完全疊在一起,我們做了一個簡單的檢查:新生成的坐標 (x, y) 是否與 gamePane 上已存在的其他圖形的中心點過于接近(距離小于 TARGET_SIZE * 1.5)。如果太近,則重新生成坐標,并限制嘗試次數防止死循環。這個方法可以進一步優化(例如使用更精確的邊界盒碰撞檢測或更智能的布局算法),但對于這個游戲基本夠用。
3. 精確計時與動畫控制:PauseTransitionTimeline

時間控制是反應測試的核心。JavaFX 提供了方便的動畫 API:

  • PauseTransition (waitTimer): 用于實現“準備”階段(GET_READY) 的隨機等待。它非常適合執行一次性的延遲任務。我們設置一個隨機的持續時間,當 onFinished 事件觸發時,調用 showStimulus() 方法。

    // 在 startNextTrial() 中
    double waitSeconds = MIN_WAIT_SECONDS + random.nextDouble() * (MAX_WAIT_SECONDS - MIN_WAIT_SECONDS);
    waitTimer = new PauseTransition(Duration.seconds(waitSeconds));
    waitTimer.setOnFinished(event -> showStimulus()); // 延遲結束時顯示圖形
    waitTimer.play();
    
  • Timeline (stimulusTimer): 用于限制刺激物顯示的最長時間。如果玩家在 STIMULUS_DURATION_SECONDS 內沒有點擊任何東西,Timeline 會觸發它的 KeyFrame 事件。我們在該事件處理器中檢查當前狀態是否仍然是 SHOWING_STIMULUS,如果是,則調用 handleMiss() 處理超時。

    // 在 showStimulus() 中
    stimulusTimer = new Timeline(new KeyFrame(Duration.seconds(STIMULUS_DURATION_SECONDS), event -> {if (currentState == GameState.SHOWING_STIMULUS) {handleMiss(); // 超時算作錯過}
    }));
    stimulusTimer.play();
    
  • 反應時間測量: 我們使用 System.nanoTime() 來獲取納秒級精度的時間戳。在 showStimulus() 時記錄圖形出現的 stimulusAppearTimeNanos,在玩家點擊時 (handleCorrectHit) 再次獲取當前時間,兩者之差除以 1_000_000 就得到毫秒級的反應時間。nanoTime()currentTimeMillis() 更適合測量這種短時間間隔。

4. 事件處理:區分目標、干擾項與背景

用戶交互的核心是鼠標點擊。

  • 圖形點擊 (addClickHandler): 我們為每個生成的圖形(包括目標和干擾項)都添加了 setOnMouseClicked 監聽器。這個監聽器內部:

    • 首先檢查 currentState == GameState.SHOWING_STIMULUS,確保只在該狀態下響應。
    • 調用 stopTimers() 停止所有計時器。
    • 計算反應時間。
    • 根據傳入的 isCorrectTarget 布爾值,調用 handleCorrectHithandleIncorrectHit
    • 調用 event.consume() 非常重要,它阻止鼠標點擊事件繼續向上傳播給父容器 gamePane。否則,點擊圖形也會觸發 gamePane 的背景點擊事件。
  • 背景點擊 (gamePane.setOnMouseClicked): 這個監聽器用于捕捉玩家在刺激物顯示期間點擊了空白區域的情況。如果發生,則調用 handleMiss()

5. 游戲流程控制與反饋
  • 試次循環 (startNextTrial, scheduleNextTrial): startNextTrial 負責準備一次測試的所有工作。當一次測試結束時(handleCorrectHit, handleIncorrectHit, handleMiss),它們都會調用 scheduleNextTrialscheduleNextTrial 內部使用一個短暫的 PauseTransition (例如1秒) 來延遲執行 startNextTrial,目的是讓玩家有時間看到本次試次的結果反饋,然后再進入下一次準備。
  • 結束與重玩 (endRound):currentTrial 達到 NUM_TRIALS 時觸發,負責清場、計算并顯示最終統計數據,并重置開始按鈕狀態允許重玩。
  • UI 更新 (updateUI): 這個輔助方法被頻繁調用,用于將內部狀態(分數、試次、平均時間)實時反映到界面標簽上。注意在 ROUND_OVER 狀態下要避免覆蓋最終的統計顯示。

代碼之外:潛在的優化與擴展方向

這個游戲雖然功能已經比較豐富,但仍有提升空間:

  1. 視覺效果與樣式: 使用 CSS 美化界面,給按鈕、標簽、背景添加樣式;可以給圖形的出現/消失、點擊反饋添加簡單的動畫(如縮放、淡入淡出)。
  2. 聲音反饋: 為點擊正確、錯誤、錯過、游戲結束等事件添加音效,提升沉浸感。
  3. 更優的避重疊算法: 現在的算法比較基礎,可能會在圖形較多時效率降低或效果不佳。可以研究更復雜的布局算法或碰撞檢測。
  4. 動態難度調整: 根據玩家表現(如平均反應時間、正確率)動態調整下一輪的參數(如刺激顯示時間縮短、干擾項增多、目標變小等)。
  5. 配置選項: 允許用戶自定義測試輪數、圖形數量、顏色主題等。
  6. 數據持久化: 保存最高分或玩家的測試記錄。

結語

通過構建這個“高級反應速度測試”游戲,我們不僅復習了 JavaFX 的基礎知識,更深入地實踐了狀態管理、事件處理、計時動畫、動態 UI 構建等進階技巧。它證明了即便是看似簡單的概念(反應速度測試),也可以通過增加復雜度(選擇反應時、多目標、干擾項)來變成一個既有趣又有挑戰性的編程項目。

希望這篇文章的詳細解析能對你學習 JavaFX 或進行類似項目開發有所幫助。最重要的是,動手去實現它,你會在解決問題的過程中學到最多!


附注: 上述代碼片段是說明性的,完整的可運行代碼請參考資源文件中 AdvancedReactionTestFX.java 完整示例。確保你的開發環境已正確配置 JavaFX。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902613.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902613.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902613.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CSS 選擇器介紹

CSS 選擇器介紹 1. 基本概念 CSS(層疊樣式表)是一種用于描述 HTML 或 XML 文檔外觀的語言。通過 CSS,可以控制網頁中元素的布局、顏色、字體等視覺效果。而 CSS 選擇器則是用來指定哪些 HTML 元素應該應用這些樣式的工具。 2. 基本選擇器 …

Vue3父子組件數據同步方法

在 Vue 3 中&#xff0c;當子組件需要修改父組件傳遞的數據副本并同步更新時&#xff0c;可以通過以下步驟實現&#xff1a; 方法 1&#xff1a;使用 v-model 和計算屬性&#xff08;實時同步&#xff09; 父組件&#xff1a; vue <template><ChildComponent v-mo…

el-table中el-input的autofocus無法自動聚焦的解決方案

需求 有一個表格展示了一些進度信息&#xff0c;進度信息可以修改&#xff0c;需要點擊進度信息旁邊的編輯按鈕時&#xff0c;把進度變為輸入框且自動聚焦&#xff0c;當鼠標失去焦點時自動請求更新接口。 注&#xff1a;本例以vue2 element UI為例 分析 這個需求看著挺簡單…

用高斯濺射技術跨越機器人模擬與現實的鴻溝:SplatSim 框架解析

在機器人領域&#xff0c;讓機器人在現實世界中精準執行任務是大家一直追求的目標。可模擬環境和現實世界之間存在著不小的差距&#xff0c;特別是基于 RGB 圖像的操作策略&#xff0c;從模擬轉移到現實時總是狀況百出。 今天咱們就來聊聊 SplatSim 框架&#xff0c;看看它是怎…

【自然語言處理與大模型】如何知道自己部署的模型的最大并行訪問數呢?

當你自己在服務器上部署好一個模型后&#xff0c;使用場景會有兩種。第一種就是你自己去玩&#xff0c;結合自有的數據做RAG等等&#xff0c;這種情況下一般是不會考慮并發的問題。第二種是將部署好的服務給到別人來使用&#xff0c;這時候就必須知道我的服務到底支持多大的訪問…

[FPGA基礎] UART篇

Xilinx FPGA UART 硬件接口使用指南 1. 引言 UART (通用異步收發器) 是一種廣泛使用的串行通信接口&#xff0c;因其簡單、可靠和易于實現而成為 Xilinx FPGA 設計中的常見硬件接口。UART 用于在 FPGA 與外部設備&#xff08;如 PC、微控制器、傳感器等&#xff09;之間進行數…

【Netty4核心原理】【全系列文章目錄】

文章目錄 一、前言二、目錄 一、前言 本系列雖說本意是作為 《Netty4 核心原理》一書的讀書筆記&#xff0c;但在實際閱讀記錄過程中加入了大量個人閱讀的理解和內容&#xff0c;因此對書中內容存在大量刪改。 本系列內容基于 Netty 4.1.73.Final 版本&#xff0c;如下&#xf…

用 PyTorch 和numpy分別實現簡單的 CNN 二分類器

作業用到的知識&#xff1a; 1.Pytorch: 1. nn.Conv2d&#xff08;二維卷積層&#xff09; 作用&#xff1a; 對輸入的多通道二位數據&#xff08;如圖像&#xff09;進行特征提取&#xff0c;通過滑動卷積核計算局部區域的加權和&#xff0c;生成新的特征圖。 關鍵參數&a…

使用n8n構建自動化工作流:從數據庫查詢到郵件通知的使用指南

n8n是一款強大的開源工作流自動化工具&#xff0c;可以幫助你將各種服務和應用程序連接起來&#xff0c;創建復雜的自動化流程。下面我將詳細介紹一個實用的n8n用例&#xff1a;從MySQL數據庫查詢數據并發送郵件通知&#xff0c;包括使用場景、搭建步驟和節點部署方法。 使用場…

Vscode已經打開的python項目,如何使用已經建立的虛擬環境

在 VS Code 中使用已創建的 Conda/Mamba 虛擬環境 pe100&#xff0c;只需以下幾步&#xff1a; 步驟 1&#xff1a;確保虛擬環境已存在 在終端運行以下命令&#xff0c;檢查 pe100 環境是否已正確創建&#xff1a; conda activate pe100 python --version # 應顯示 Python 3…

Volatility工具學習

背景 VMware虛擬機系統hang死&#xff0c;手動重啟無法觸發系統panic&#xff0c;從而不能觸發kdump產生vmcore文件進行原因分析&#xff1b;此種情況下需要手動生成虛擬機內存快照&#xff0c;進而利用Volatility工具分析系統hang死的具體原因。 配置 使用VMware創建虛擬機…

學習筆記(C++篇)--- Day 4

目錄 1.賦值運算符重載 1.1 運算符重載 1.2 賦值運算符重載 1.3 日期類實現 1.賦值運算符重載 1.1 運算符重載 ①當運算符被用于類類型的對象時&#xff0c;C語言允許我們通過通過運算符重載的形式指定新的含義。C規定類類型對象使用運算符時&#xff0c;必須轉換成調用對…

Docker 快速入門教程

1. Docker 基本概念 鏡像(Image): 只讀模板&#xff0c;包含創建容器的指令 容器(Container): 鏡像的運行實例 Dockerfile: 用于構建鏡像的文本文件 倉庫(Repository): 存放鏡像的地方&#xff08;如Docker Hub&#xff09; 2. 安裝Docker 根據你的操作系統選擇安裝方式:…

vue項目中使用tinymce富文本編輯器

vue使用tinymce 文章目錄 vue使用tinymcetinymce富文本編輯器在這里插入圖片描述 一、本文要實現二、使用步驟1.安裝tinymce2.tinymce組件新建3. 在store添加商品詳情的狀態管理4. tinymce組件的引入 tinymce富文本編輯器 提示&#xff1a;以下是本篇文章正文內容&#xff0c;下…

簡單適配torch_npu不支持的ATen算子

簡單適配torch_npu不支持的ATen算子 一、背景說明1.1 PyTorch擴展機制1.2 核心概念二、實現步驟詳解2.1 實現前向、反向傳播算子2.2 編譯生成動態庫2.3 測試驗證程序三、關鍵點解析3.1 設計注意事項3.2 性能優化方向四、驗證結果一、背景說明 1.1 PyTorch擴展機制 PrivateUse1…

同樣的html標記,不同語言的文本,顯示的字體和粗細會不一樣嗎

同樣的 HTML 標記&#xff0c;在不同語言的文本下&#xff0c;顯示出來的字體和粗細確實可能會不一樣&#xff0c;原因如下&#xff1a; &#x1f30d; 不同語言默認字體不同 瀏覽器字體回退機制 CSS 里寫的字體如果當前系統不支持&#xff0c;就會回退到下一個&#xff0c;比如…

基于 Spring Boot 瑞吉外賣系統開發(六)

基于 Spring Boot 瑞吉外賣系統開發&#xff08;六&#xff09; 菜品列表 在系統管理端首頁&#xff0c;單擊左側菜單欄中的“菜品管理”&#xff0c;會在右側打開菜品管理頁面。 請求URL/dish/page&#xff0c;請求方法GET,請求參數page&#xff0c;pageSize。 該菜品列表…

計算機視覺與深度學習 | TensorFlow基本概念與應用場景:MNIST 手寫數字識別(附代碼)

TensorFlow 基本概念 TensorFlow 是一個開源的機器學習框架,由 Google 開發,核心概念包括: 張量(Tensor):多維數組,是數據的基本單位。計算圖(Graph):早期版本中用于描述數據流和計算過程,2.x 默認啟用即時執行(Eager Execution),兼顧靈活性和性能。層(Layers)…

vue+django+LSTM微博輿情分析系統 | 深度學習 | 食品安全分析

文章結尾部分有CSDN官方提供的學長 聯系方式名片 文章結尾部分有CSDN官方提供的學長 聯系方式名片 關注B站&#xff0c;有好處&#xff01; 編號&#xff1a; D031 LSTM 架構&#xff1a;vuedjangoLSTMMySQL 功能&#xff1a; 微博信息爬取、情感分析、基于負面消極內容輿情分析…

RHCE第三次作業 搭建dns的正向解析服務器

server為服務器 client為客戶端 設置主配置文件 在server下&#xff1a; [rootServer ~]#vim /etc/named.conf #進入到配置頁面&#xff0c;并修改 設置區域文件 [rootServer ~]# vim /etc/named.rfc1912.zones 設置域名解析文件 [rootServer named]# cd /var/named…