11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/com/example/bouncingballgamejavafx/hello-view.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Son Nguyen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.example
8 | BouncingBallGameJavaFX
9 | 1.0-SNAPSHOT
10 | Bouncing Ball Game JavaFX
11 |
12 |
13 | UTF-8
14 | 5.9.1
15 |
16 |
17 |
18 |
19 | org.openjfx
20 | javafx-controls
21 | 17.0.2
22 |
23 |
24 | org.openjfx
25 | javafx-fxml
26 | 17.0.2
27 |
28 |
29 |
30 | org.junit.jupiter
31 | junit-jupiter-api
32 | ${junit.version}
33 | test
34 |
35 |
36 | org.junit.jupiter
37 | junit-jupiter-engine
38 | ${junit.version}
39 | test
40 |
41 |
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-compiler-plugin
48 | 3.10.1
49 |
50 | 17
51 | 17
52 |
53 |
54 |
55 | org.openjfx
56 | javafx-maven-plugin
57 | 0.0.8
58 |
59 |
60 |
61 | default-cli
62 |
63 |
64 | com.example.bouncingballgamejavafx/com.example.bouncingballgamejavafx.BouncingBall
65 |
66 | app
67 | app
68 | app
69 | true
70 | true
71 | true
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bouncing Ball Game with JavaFX
2 |
3 | ## Table of Contents
4 |
5 | - [Overview](#overview)
6 | - [How to Play](#how-to-play)
7 | - [User Interface](#user-interface)
8 | - [Demo GIF](#demo-gif)
9 | - [Welcome Screen](#welcome-screen)
10 | - [Game Interface](#game-interface)
11 | - [Win Screen](#win-screen)
12 | - [Lose Screen](#lose-screen)
13 | - [Features](#features)
14 | - [Prerequisites](#prerequisites)
15 | - [Setup and Installation](#setup-and-installation)
16 | - [Configuration](#configuration)
17 | - [Running the Application](#running-the-application)
18 | - [Contributing](#contributing)
19 | - [License](#license)
20 | - [Author](#author)
21 |
22 | ## Overview
23 |
24 | The Bouncing Ball game is a simple, interactive JavaFX application where a ball bounces around the screen. Users can control the speed of the ball using the up and down arrow keys. The game demonstrates the use of JavaFX animation and event handling capabilities.
25 |
26 | ## How to Play
27 |
28 | 1. **Start the Game**: Run the application to start the game. The ball will start bouncing around the screen.
29 | 2. **Objective**: Reach the number of bounces required to win the game without the ball going too fast.
30 | 3. **Control the Ball Speed**: Use the UP and DOWN arrow keys to increase or decrease the ball speed, respectively.
31 | 4. **Win or Lose**: If the ball reaches the required number of bounces without exceeding the maximum speed, you win. Otherwise, you lose.
32 | 5. **Play Again**: After winning or losing, you can play the game again by clicking the "Play Again" button.
33 |
34 | ## User Interface
35 |
36 | ### Demo GIF
37 |
38 |
39 |
40 |
41 |
42 | > Our apologies for the low quality of the GIF. The actual game interface is much smoother and visually appealing. Please try running the game on your machine for a better experience!
43 |
44 | ### Welcome Screen
45 |
46 |
47 |
48 |
49 |
50 | ### Game Interface
51 |
52 |
53 |
54 |
55 |
56 | ### Win Screen
57 |
58 |
59 |
60 |
61 |
62 | ### Lose Screen
63 |
64 |
65 |
66 |
67 |
68 | ## Features
69 |
70 | - Ball speed control with keyboard inputs (UP to increase speed, DOWN to decrease speed).
71 | - Dynamic color change of the ball upon collision with the screen boundaries.
72 | - Display of current ball speed on the screen.
73 | - Game over screen with a win or lose message based on the ball speed.
74 | - Different background colors for the game interface and game over screens.
75 | - Customizable ball size, speed, and screen dimensions.
76 | - And more!
77 |
78 | ## Prerequisites
79 |
80 | - JDK 11 or above.
81 | - Maven (for building the project).
82 | - JavaFX SDK (compatible with your JDK version).
83 | - A Java IDE (e.g. IntelliJ IDEA or Eclipse) is highly recommended.
84 |
85 | ## Setup and Installation
86 |
87 | 1. **Download JavaFX SDK**: Download the JavaFX SDK from the [OpenJFX](https://openjfx.io/) website and extract it to a known location on your machine.
88 | 2. **Clone the Repository**: Clone this repository to your local machine using `git clone https://github.com/hoangsonww/Space-Invader-Game-JavaFX.git`.
89 | 3. **Open the Project**: Open the project in your Java IDE (e.g., IntelliJ IDEA).
90 | 4. **Configure JavaFX SDK**: Configure the JavaFX SDK in your IDE by adding it as a library to the project.
91 | 5. **Run the Application**: Run the application using the IDE or Maven commands.
92 |
93 | ## Configuration
94 |
95 | Before running the application, ensure that JavaFX is properly configured in your IDE (e.g., IntelliJ IDEA, Eclipse):
96 | - **IntelliJ IDEA**:
97 | 1. Go to `File` > `Project Structure` > `Libraries` and add the JavaFX SDK as a library to the project.
98 | 2. In the `Run` configurations, add the VM options to include the JavaFX modules:
99 | ```
100 | --module-path "path/to/javafx-sdk/lib" --add-modules javafx.controls,javafx.fxml
101 | ```
102 | Replace `"path/to/javafx-sdk/lib"` with the actual path to the JavaFX SDK lib directory on your machine.
103 |
104 | - **Eclipse**:
105 | 1. Right-click on the project > `Properties` > `Java Build Path` > `Libraries` and add the JavaFX SDK as an external JAR.
106 | 2. In the run configurations, add the VM arguments similar to the IntelliJ setup.
107 |
108 | ## Running the Application
109 |
110 | To run the application, navigate to the `src/com/example/bouncingballgamejavafx` directory and compile the `BouncingBall.java` file. Then, execute the main method within the `BouncingBall` class.
111 |
112 | Ensure that the JavaFX SDK is properly configured in your IDE before running the application.
113 |
114 | Alternatively, you can run the application using the following Maven command:
115 | ```
116 | mvn clean javafx:run
117 | ```
118 |
119 | ## Contributing
120 |
121 | Contributions to the Bouncing Ball game are welcome. Please feel free to fork the repository, make your changes, and submit a pull request.
122 |
123 | ## License
124 |
125 | This project is licensed under the MIT license. See [LICENSE](LICENSE) for more details.
126 |
127 | ## Author
128 |
129 | - **Son Nguyen** - [hoangsonww](https://github.com/hoangsonww)
130 |
131 | ---
132 |
133 | Created with ❤️ by [Son Nguyen](https://github.com/hoangsonww) in 2024.
134 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/src/main/java/com/example/bouncingballgamejavafx/BouncingBall.java:
--------------------------------------------------------------------------------
1 | package com.example.bouncingballgamejavafx;
2 |
3 | import javafx.animation.AnimationTimer;
4 | import javafx.application.Application;
5 | import javafx.geometry.Pos;
6 | import javafx.scene.Scene;
7 | import javafx.scene.canvas.Canvas;
8 | import javafx.scene.canvas.GraphicsContext;
9 | import javafx.scene.control.Button;
10 | import javafx.scene.control.Label;
11 | import javafx.scene.image.Image;
12 | import javafx.scene.input.KeyCode;
13 | import javafx.scene.input.KeyEvent;
14 | import javafx.scene.layout.*;
15 | import javafx.scene.paint.Color;
16 | import javafx.scene.text.Font;
17 | import javafx.scene.text.FontWeight;
18 | import javafx.stage.Stage;
19 |
20 | import java.util.Objects;
21 | import java.util.Random;
22 |
23 | /** BouncingBall class to represent the bouncing ball game */
24 | public class BouncingBall extends Application {
25 |
26 | /** Store the width of the game window */
27 | private static final int WIDTH = 800;
28 |
29 | /** Store the height of the game window */
30 | private static final int HEIGHT = 600;
31 |
32 | /** Store the radius of the ball */
33 | private static final double BALL_RADIUS = 20;
34 |
35 | /** Store the speed increment */
36 | private static final double SPEED_INCREMENT = 0.2;
37 |
38 | /** Store the ball speed in the x direction */
39 | private double ballSpeedX = 3;
40 |
41 | /** Store the ball speed in the y direction */
42 | private double ballSpeedY = 3;
43 |
44 | /** Store the ball x position */
45 | private double ballX = WIDTH / 2;
46 |
47 | /** Store the ball y position */
48 | private double ballY = HEIGHT / 2;
49 |
50 | /** Store the random object */
51 | private final Random random = new Random();
52 |
53 | /** Store the ball color */
54 | private Color ballColor = Color.RED;
55 |
56 | /** Store the score */
57 | private int score = 0;
58 |
59 | /** Store the paused state */
60 | private boolean paused = false;
61 |
62 | /** Store the target score */
63 | private int targetScore = 20 + random.nextInt(31); // Random target score between 20 and 50
64 |
65 | /** Store the max speed */
66 | private double maxSpeed = 10 + random.nextInt(6); // Random max speed between 10 and 15
67 |
68 | /** Store the speed label */
69 | private final Label speedLabel = new Label();
70 |
71 | /** Store the score label */
72 | private final Label scoreLabel = new Label();
73 |
74 | /** Store the max speed label */
75 | private final Label maxSpeedLabel = new Label();
76 |
77 | /** Store the welcome scene */
78 | private Scene welcomeScene;
79 |
80 | /** Store the game scene */
81 | private Scene gameScene;
82 |
83 | /** Store the end scene */
84 | private Scene endScene;
85 |
86 | /** Store the game loop */
87 | private AnimationTimer gameLoop;
88 |
89 | /** Store the ball image */
90 | private Image ballImage;
91 |
92 | /**
93 | * Main method to launch the application
94 | *
95 | * @param args String[] representing the command line arguments
96 | */
97 | public static void main(String[] args) {
98 | launch(args);
99 | }
100 |
101 | /**
102 | * Start method to initialize the application
103 | *
104 | * @param primaryStage Stage object representing the primary stage
105 | */
106 | @Override
107 | public void start(Stage primaryStage) {
108 | // Load the ball image
109 | ballImage = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/ball.png")));
110 |
111 | // Set the application icon
112 | primaryStage.getIcons().add(ballImage);
113 |
114 | // Create the scenes
115 | welcomeScene = createWelcomeScene(primaryStage);
116 | gameScene = createGameScene(primaryStage);
117 |
118 | // Set the welcome scene initially
119 | primaryStage.setScene(welcomeScene);
120 | primaryStage.setTitle("Bouncing Ball Game");
121 | primaryStage.setResizable(false);
122 | primaryStage.show();
123 | }
124 |
125 | /**
126 | * Create the welcome scene
127 | *
128 | * @param stage Stage object representing the stage
129 | * @return Scene object representing the welcome scene
130 | */
131 | private Scene createWelcomeScene(Stage stage) {
132 | VBox layout = new VBox();
133 | layout.setAlignment(Pos.CENTER);
134 | layout.setSpacing(30);
135 | layout.setStyle("-fx-background-color: #2b2b2b; -fx-padding: 50px;");
136 |
137 | Label title = new Label("Welcome to the Bouncing Ball Game");
138 | title.setFont(Font.font("Arial", FontWeight.BOLD, 32));
139 | title.setTextFill(Color.WHITE);
140 |
141 | Label instructions =
142 | new Label(
143 | String.format(
144 | "Win by reaching a score of %d!\nDon't exceed the max speed of %.2f.",
145 | targetScore, maxSpeed));
146 | instructions.setFont(Font.font("Arial", FontWeight.NORMAL, 18));
147 | instructions.setTextFill(Color.LIGHTGRAY);
148 | instructions.setWrapText(true);
149 | instructions.setAlignment(Pos.CENTER);
150 |
151 | Button startButton = new Button("Start Game");
152 | startButton.setStyle(
153 | "-fx-background-color: #0078d7; -fx-text-fill: white; -fx-font-size: 18px; -fx-padding: 10px 20px;");
154 | startButton.setOnAction(event -> stage.setScene(gameScene));
155 |
156 | Button exitButton = new Button("Exit Game");
157 | exitButton.setStyle(
158 | "-fx-background-color: #d9534f; -fx-text-fill: white; -fx-font-size: 18px; -fx-padding: 10px 20px;");
159 | exitButton.setOnAction(event -> System.exit(0));
160 |
161 | layout.getChildren().addAll(title, instructions, startButton, exitButton);
162 |
163 | return new Scene(layout, WIDTH, HEIGHT);
164 | }
165 |
166 | /**
167 | * Create the game scene
168 | *
169 | * @param stage Stage object representing the stage
170 | * @return Scene object representing the game scene
171 | */
172 | private Scene createGameScene(Stage stage) {
173 | Pane root = new Pane();
174 | Canvas canvas = new Canvas(WIDTH, HEIGHT);
175 | root.getChildren().add(canvas);
176 |
177 | GraphicsContext gc = canvas.getGraphicsContext2D();
178 |
179 | Scene scene = new Scene(root, WIDTH, HEIGHT, Color.BLACK);
180 |
181 | // Speed Label
182 | speedLabel.setTranslateX(10);
183 | speedLabel.setTranslateY(10);
184 | speedLabel.setTextFill(Color.RED);
185 | speedLabel.setFont(Font.font("Arial", FontWeight.BOLD, 18));
186 |
187 | // Score Label
188 | scoreLabel.setTranslateX(10);
189 | scoreLabel.setTranslateY(40);
190 | scoreLabel.setTextFill(Color.GREEN);
191 | scoreLabel.setFont(Font.font("Arial", FontWeight.BOLD, 18));
192 |
193 | // Max Speed Label
194 | maxSpeedLabel.setTranslateX(10);
195 | maxSpeedLabel.setTranslateY(70);
196 | maxSpeedLabel.setTextFill(Color.ORANGE);
197 | maxSpeedLabel.setFont(Font.font("Arial", FontWeight.BOLD, 18));
198 | maxSpeedLabel.setText(String.format("Max Speed: %.2f", maxSpeed));
199 |
200 | root.getChildren().addAll(speedLabel, scoreLabel, maxSpeedLabel);
201 | updateSpeedLabel();
202 | updateScoreLabel();
203 |
204 | // Game Loop
205 | gameLoop =
206 | new AnimationTimer() {
207 | @Override
208 | public void handle(long now) {
209 | if (!paused) {
210 | gc.clearRect(0, 0, WIDTH, HEIGHT);
211 |
212 | // Draw the ball image tinted with the current ball color
213 | gc.setFill(ballColor);
214 | gc.fillOval(
215 | ballX - BALL_RADIUS, ballY - BALL_RADIUS, BALL_RADIUS * 2, BALL_RADIUS * 2);
216 | gc.setGlobalAlpha(0.8); // Tint effect
217 | gc.drawImage(
218 | ballImage,
219 | ballX - BALL_RADIUS,
220 | ballY - BALL_RADIUS,
221 | BALL_RADIUS * 2,
222 | BALL_RADIUS * 2);
223 | gc.setGlobalAlpha(1.0); // Reset alpha
224 |
225 | // Update ball position
226 | ballX += ballSpeedX;
227 | ballY += ballSpeedY;
228 |
229 | // Bounce logic
230 | if (ballX - BALL_RADIUS < 0 || ballX + BALL_RADIUS > WIDTH) {
231 | ballSpeedX = -ballSpeedX;
232 | ballColor = randomColor();
233 | score++;
234 | updateScoreLabel();
235 | }
236 | if (ballY - BALL_RADIUS < 0 || ballY + BALL_RADIUS > HEIGHT) {
237 | ballSpeedY = -ballSpeedY;
238 | ballColor = randomColor();
239 | score++;
240 | updateScoreLabel();
241 | }
242 |
243 | // Check win condition
244 | if (score >= targetScore) {
245 | gameLoop.stop();
246 | stage.setScene(createEndScene(stage, true));
247 | }
248 |
249 | // Check game-over condition
250 | double speed = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY);
251 | if (speed > maxSpeed) {
252 | gameLoop.stop();
253 | stage.setScene(createEndScene(stage, false));
254 | }
255 | }
256 | }
257 | };
258 |
259 | gameLoop.start();
260 |
261 | // Key Events
262 | scene.addEventHandler(
263 | KeyEvent.KEY_PRESSED,
264 | event -> {
265 | if (event.getCode() == KeyCode.UP) {
266 | ballSpeedX *= (1 + SPEED_INCREMENT);
267 | ballSpeedY *= (1 + SPEED_INCREMENT);
268 | updateSpeedLabel();
269 | } else if (event.getCode() == KeyCode.DOWN) {
270 | ballSpeedX *= (1 - SPEED_INCREMENT);
271 | ballSpeedY *= (1 - SPEED_INCREMENT);
272 | updateSpeedLabel();
273 | } else if (event.getCode() == KeyCode.SPACE) {
274 | paused = !paused;
275 | }
276 | });
277 |
278 | return scene;
279 | }
280 |
281 | /**
282 | * Create the end scene
283 | *
284 | * @param stage Stage object representing the stage
285 | * @param win boolean representing if the player won
286 | * @return Scene object representing the end scene
287 | */
288 | private Scene createEndScene(Stage stage, boolean win) {
289 | VBox layout = new VBox();
290 | layout.setAlignment(Pos.CENTER);
291 | layout.setSpacing(30);
292 | layout.setStyle("-fx-background-color: #2b2b2b; -fx-padding: 50px;");
293 |
294 | Label message = new Label(win ? "You Win!" : "Game Over!");
295 | message.setFont(Font.font("Arial", FontWeight.BOLD, 32));
296 | message.setTextFill(win ? Color.GREEN : Color.RED);
297 |
298 | Label finalScoreLabel = new Label(String.format("Final Score: %d / %d", score, targetScore));
299 | finalScoreLabel.setFont(Font.font("Arial", FontWeight.BOLD, 24));
300 | finalScoreLabel.setTextFill(Color.WHITE);
301 |
302 | Button restartButton = new Button("Restart Game");
303 | restartButton.setStyle(
304 | "-fx-background-color: #0078d7; -fx-text-fill: white; -fx-font-size: 18px; -fx-padding: 10px 20px;");
305 | restartButton.setOnAction(
306 | event -> {
307 | resetGame();
308 | stage.setScene(gameScene);
309 | });
310 |
311 | Button exitButton = new Button("Exit Game");
312 | exitButton.setStyle(
313 | "-fx-background-color: #d9534f; -fx-text-fill: white; -fx-font-size: 18px; -fx-padding: 10px 20px;");
314 | exitButton.setOnAction(event -> System.exit(0));
315 |
316 | layout.getChildren().addAll(message, finalScoreLabel, restartButton, exitButton);
317 |
318 | return new Scene(layout, WIDTH, HEIGHT);
319 | }
320 |
321 | /** Reset the game */
322 | private void resetGame() {
323 | score = 0;
324 | ballSpeedX = 3;
325 | ballSpeedY = 3;
326 | ballX = WIDTH / 2;
327 | ballY = HEIGHT / 2;
328 | paused = false;
329 | targetScore = 20 + random.nextInt(31); // New random target score
330 | maxSpeed = 10 + random.nextInt(6); // New random max speed
331 | maxSpeedLabel.setText(String.format("Max Speed: %.2f", maxSpeed));
332 | updateSpeedLabel();
333 | updateScoreLabel();
334 | gameLoop.start();
335 | }
336 |
337 | /**
338 | * Generate a random color
339 | *
340 | * @return Color object representing the random color
341 | */
342 | private Color randomColor() {
343 | return Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256));
344 | }
345 |
346 | /** Update the speed label */
347 | private void updateSpeedLabel() {
348 | double speed = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY);
349 | speedLabel.setText(String.format("Speed: %.2f", speed));
350 | }
351 |
352 | /** Update the score label */
353 | private void updateScoreLabel() {
354 | scoreLabel.setText(String.format("Score: %d / %d", score, targetScore));
355 | }
356 | }
357 |
--------------------------------------------------------------------------------