diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..30aa607
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,163 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/intellij
+# Edit at https://www.toptal.com/developers/gitignore?templates=intellij
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+# End of https://www.toptal.com/developers/gitignore/api/intellij
+
+
+# Created by https://www.toptal.com/developers/gitignore/api/java
+# Edit at https://www.toptal.com/developers/gitignore?templates=java
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# End of https://www.toptal.com/developers/gitignore/api/java
+
+
+# Created by https://www.toptal.com/developers/gitignore/api/gradle
+# Edit at https://www.toptal.com/developers/gitignore?templates=gradle
+
+### Gradle ###
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
+# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
+# gradle/wrapper/gradle-wrapper.properties
+
+### Gradle Patch ###
+**/build/
+
+# End of https://www.toptal.com/developers/gitignore/api/gradle
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..717cc5c
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+AlienDefence
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..919ce1f
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..ac216bc
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..8c8418f
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1b578d5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/VL_AlienDefence.iml b/.idea/modules/VL_AlienDefence.iml
new file mode 100644
index 0000000..f491540
--- /dev/null
+++ b/.idea/modules/VL_AlienDefence.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 216bf88..c5e10c4 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,13 @@
-# VL_AlienDefence
-Projekt Alien Defence von Schick&Kannix eingekauft
+# Lernsituation "Alien Defence"
+Fast wäre die Firma Schick&Kannix insolvent gegangen, wenn Ihre Firma die Gamepool GmbH sie nicht aufgekauft hätte. Im Projektportfolio der Schick&Kannix finden Sie ein altes Pflichtenheft für die Entwicklung eines Shoot-’em-up-Computerspiels, das zu einem Software-Erstellungsvertrag für die Future Technologie Consulting GmbH gehört. Diese wollen keine schnarchnasigen Mitarbeiter mehr einstellen und wollen als Einstellungstest die Bewerber mit diesem Spiel auf Reaktion und Geschicklichkeit mit der Maus testen. Als Fertigstellungstermin ist offensichtlich der 1.4. diesen Jahres vereinbart worden. Während Ihre kaufmännische Abteilung fieberhaft nach dem Vertrag sucht, müssen Sie sich um die noch nicht umgesetzten Punkte des Pflichtenheftes kümmern und die Programmierung des Spiels fertigstellen.
+
+Ihnen liegen eine funktionierende Angriffswelt, verschiedene Menüs und ein spielbares Testlevel vor. Allerdings fehlen Ihnen noch diverse UserStories und die Software sieht noch sehr unfertig aus. Zentraler Bestandteil des Pflichtenheftes ist, dass nach jedem Level die erreichten Punkte für den*die Spieler*in in eine Highscore-Liste eingetragen werden sollen. Das Score-System errechnet sich aus dem Prozentsatz der abgeschossenen Objekte sowie der gesamten Reaktionszeit. Alle Daten müssen in einer zugrundeliegenden Datenbank persistent gehalten werden, die Ihnen die Mitarbeiter*innen der Schick&Kannix halbfertig noch hinterlassen haben.
+
+**Auftrag: Sichten Sie anhand der Entwurfsdokumente und des Scrumboards den Arbeitsstand und die Softwarearchitektur des Spiels Alien Defence und stellen Sie in einem Team die Software termingerecht fertig.**
+
+In den Räumlichkeiten der Schick&Kannix gibt es einiges, was Ihnen bei der Entwicklung helfen kann. Zum einen finden Sie hier den Quellcode des Spiels.
+
+Auch wurde ein Scrumboard zurückgelassen, das noch die aktuellen ToDos bei dem Projekt zeigt.
+Außerdem gibt es eine kleine Fachbibliothek mit Literatur, die für die Fertigstellung der Software wichtig ist, und die Sie in jedem Abschnitt in Moodle finden.
+
+Also auf gehts ans Werk!
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..864e019
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,37 @@
+plugins {
+ id 'java'
+}
+
+group 'de.oszimt.ls'
+version '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+/**
+ * 1st approach: Setting encoding during compilation in Java and Test classes
+ */
+compileJava.options.encoding = "UTF-8"
+compileTestJava.options.encoding = "UTF-8"
+
+/**
+ * 2nd approach: Setting encoding during compilation in Java and Test classes
+ */
+tasks.withType(JavaCompile) {
+ options.encoding = "UTF-8"
+}
+
+tasks.withType(Test) {
+ systemProperty "file.encoding", "UTF-8"
+}
+
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1e81d89
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.warning.mode=none
+org.gradle.jvmargs=-Dfile.encoding=UTF8
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..be52383
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e9a8d3f
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'AlienDefence'
+
diff --git a/sql/alien_defence.sql b/sql/alien_defence.sql
new file mode 100644
index 0000000..0a6a2dc
--- /dev/null
+++ b/sql/alien_defence.sql
@@ -0,0 +1,188 @@
+-- phpMyAdmin SQL Dump
+-- version 4.0.9
+-- http://www.phpmyadmin.net
+--
+-- Host: 127.0.0.1
+-- Erstellungszeit: 11. Feb 2021 um 09:23
+-- Server Version: 5.6.14
+-- PHP-Version: 5.5.6
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+
+--
+-- Datenbank: `alien_defence`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `levels`
+--
+
+CREATE TABLE IF NOT EXISTS `levels` (
+ `P_level_id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `background` varchar(100) NOT NULL,
+ `duration` int(11) NOT NULL,
+ PRIMARY KEY (`P_level_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=4 ;
+
+--
+-- Daten für Tabelle `levels`
+--
+
+INSERT INTO `levels` (`P_level_id`, `name`, `background`, `duration`) VALUES
+(1, 'Level 1', 'background_1.jpg', 10000),
+(2, 'Level 2', 'background_2.jpg', 5000),
+(3, 'Level 3', 'background_10.jpg', 10000);
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `targets`
+--
+
+CREATE TABLE IF NOT EXISTS `targets` (
+ `P_target_id` int(11) NOT NULL AUTO_INCREMENT,
+ `F_level_id` int(11) NOT NULL,
+ `x_position` int(11) NOT NULL,
+ `y_position` int(11) NOT NULL,
+ `width` int(11) NOT NULL,
+ `height` int(11) NOT NULL,
+ `time` int(11) NOT NULL,
+ `duration` int(11) NOT NULL,
+ `image_address` varchar(100) NOT NULL,
+ PRIMARY KEY (`P_target_id`),
+ KEY `FK LEVELS ID` (`F_level_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=60 ;
+
+--
+-- Daten für Tabelle `targets`
+--
+
+INSERT INTO `targets` (`P_target_id`, `F_level_id`, `x_position`, `y_position`, `width`, `height`, `time`, `duration`, `image_address`) VALUES
+(40, 1, 100, 100, 150, 50, 1000, 2000, 'ufo_1.png'),
+(41, 1, 500, 100, 150, 50, 2000, 2000, 'ufo_2.png'),
+(44, 1, 800, 800, 150, 50, 3000, 2000, 'ufo_3.png'),
+(51, 1, 600, 400, 150, 50, 4000, 1000, 'ufo_4.png'),
+(52, 1, 200, 400, 150, 50, 5000, 1500, 'ufo_5.png'),
+(53, 1, 1000, 800, 150, 50, 6000, 1000, 'ufo_3.png'),
+(54, 1, 500, 500, 150, 50, 7000, 1000, 'ufo_1.png'),
+(55, 2, 600, 400, 150, 50, 1000, 2000, 'ufo_3.png'),
+(56, 2, 400, 600, 150, 50, 2000, 2000, 'ufo_2.png'),
+(57, 3, 600, 400, 150, 50, 1000, 1000, 'ufo_3.png'),
+(58, 3, 600, 400, 150, 50, 6000, 1000, 'ufo_3.png'),
+(59, 3, 100, 300, 400, 150, 4000, 1000, 'ufo_3.png');
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `attempts`
+--
+
+CREATE TABLE IF NOT EXISTS `attempts` (
+ `P_attempt_id` int(11) NOT NULL AUTO_INCREMENT,
+ `F_user_id` int(11) NOT NULL,
+ `F_level_id` int(11) NOT NULL,
+ `shots` int(11) NOT NULL,
+ `hits` int(11) NOT NULL,
+ `reaction_time` int(11) NOT NULL,
+ `date` date NOT NULL,
+ `time` time NOT NULL,
+ PRIMARY KEY (`P_attempt_id`),
+ KEY `FK PARTICIPANTS ID` (`F_user_id`),
+ KEY `FK LEVELS2 ID` (`F_level_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=333 ;
+
+--
+-- Daten für Tabelle `attempt`
+--
+
+INSERT INTO `attempts` (`P_attempt_id`, `F_user_id`, `F_level_id`, `shots`, `hits`, `reaction_time`, `date`, `time`) VALUES
+(278, 1, 3, 3, 2, 2214, '2020-08-15', '09:23:32'),
+(279, 1, 3, 3, 3, -942, '2020-08-15', '09:24:04'),
+(299, 1, 3, 3, 2, 3533, '2020-08-15', '10:16:46'),
+(300, 1, 3, 5, 2, 2451, '2020-08-15', '10:17:21'),
+(303, 1, 3, 5, 3, -979, '2020-08-15', '10:32:21'),
+(304, 1, 3, 9, 2, 878, '2020-08-15', '10:32:49'),
+(313, 1, 2, 2, 1, 571, '2020-08-15', '13:56:01'),
+(314, 1, 2, 4, 2, 1101, '2020-08-15', '14:21:01'),
+(315, 1, 1, 10, 4, 514, '2020-08-15', '14:21:30'),
+(316, 1, 2, 3, 2, 724, '2020-08-15', '14:23:59'),
+(317, 1, 2, 0, 0, 0, '2020-08-15', '16:03:36'),
+(318, 1, 2, 4, 2, 651, '2020-08-15', '16:23:43'),
+(319, 1, 2, 6, 2, 1262, '2020-08-15', '17:09:40'),
+(320, 1, 2, 6, 2, 784, '2020-08-15', '17:11:35'),
+(321, 1, 2, 3, 1, 1857, '2020-08-15', '17:11:51'),
+(322, 1, 1, 7, 6, 1021, '2021-02-09', '10:15:41'),
+(323, 1, 1, 6, 6, 664, '2021-02-09', '10:16:19'),
+(324, 1, 1, 5, 5, 1000, '2021-02-09', '15:14:03'),
+(325, 1, 1, 20, 7, 300, '2021-02-09', '15:14:45'),
+(326, 1, 1, 5, 5, 703, '2021-02-09', '15:57:42'),
+(327, 1, 1, 0, 0, 0, '2021-02-09', '16:20:42'),
+(328, 1, 1, 7, 7, 622, '2021-02-09', '17:37:38'),
+(329, 1, 3, 2, 2, -1772, '2021-02-09', '17:37:57'),
+(330, 1, 1, 27, 6, 935, '2021-02-10', '15:34:13'),
+(331, 1, 1, 7, 7, 660, '2021-02-10', '15:44:01'),
+(332, 1, 1, 3, 3, 1013, '2021-02-11', '08:39:39');
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `users`
+--
+
+CREATE TABLE IF NOT EXISTS `users` (
+ `P_user_id` int(11) NOT NULL AUTO_INCREMENT,
+ `first_name` varchar(100) NOT NULL,
+ `sur_name` varchar(100) NOT NULL,
+ `birthday` date NOT NULL,
+ `street` varchar(100) NOT NULL,
+ `house_number` varchar(6) NOT NULL,
+ `postal_code` char(5) NOT NULL,
+ `city` varchar(100) NOT NULL,
+ `login_name` varchar(100) NOT NULL,
+ `password` varchar(100) NOT NULL,
+ `salary_expectations` int(100) NOT NULL,
+ `marital_status` varchar(100) NOT NULL,
+ `final_grade` decimal(3,2) NOT NULL,
+ PRIMARY KEY (`P_user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=6 ;
+
+--
+-- Daten für Tabelle `users`
+--
+
+INSERT INTO `users` (`P_user_id`, `first_name`, `sur_name`, `birthday`, `street`, `house_number`, `postal_code`, `city`, `login_name`, `password`, `salary_expectations`, `marital_status`, `final_grade`) VALUES
+(1, 'Mike', 'Leveltester', '2000-10-25', 'Testweg', '1', '10245', 'Berlin', 'test', 'pass', 36000, 'Roboter', '1.00'),
+(2, 'MC', 'A', '1998-02-03', 'Brooklynstreet', '2', '10113', 'NYC', 'user', 'pass', 100000, 'ledig', '2.40'),
+(3, 'Susanne', 'König', '2001-12-25', 'Hasenweg', '4', '08900', 'Bretnig-Hauswalde', 'susi', 'pass', 20000, 'verheirate', '2.90'),
+(4, 'Jan', 'Jonas', '2004-02-29', 'Galihag', '111C', '10317', 'Berlin', 'jan', 'pass', 44444, 'ledig', '1.00'),
+(5, 'Felix', 'DelSande', '1985-04-01', 'Lerchenweg', '23', '10245', 'Berlin', 'felix', 'pass', 36000, 'ledig', '3.70');
+
+--
+-- Constraints der exportierten Tabellen
+--
+
+--
+-- Constraints der Tabelle `targets`
+--
+ALTER TABLE `targets`
+ ADD CONSTRAINT `FK LEVELS ID` FOREIGN KEY (`F_level_id`) REFERENCES `levels` (`P_level_id`);
+
+ALTER TABLE `attempts`
+ ADD CONSTRAINT `FK LEVEL ID` FOREIGN KEY (`F_level_id`) REFERENCES `levels` (`P_level_id`);
+
+ALTER TABLE `attempts`
+ ADD CONSTRAINT `FK USER ID` FOREIGN KEY (`F_user_id`) REFERENCES `users` (`P_user_id`);
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/src/main/java/controller/AlienDefenceController.java b/src/main/java/controller/AlienDefenceController.java
new file mode 100644
index 0000000..24ae958
--- /dev/null
+++ b/src/main/java/controller/AlienDefenceController.java
@@ -0,0 +1,49 @@
+package controller;
+
+import model.Level;
+import model.persistence.IPersistance;
+import toDo.User;
+
+public class AlienDefenceController {
+
+ //Teilcontroller
+ private GameController gameController;
+ private LevelController levelController;
+ private TargetController targetController;
+ private AttemptController attemptController;
+ //TODO UserController implementieren
+
+ //Persistenz
+ private IPersistance alienDefenceModel;
+
+ public AlienDefenceController(IPersistance alienDefenceModel) {
+ super();
+ this.alienDefenceModel = alienDefenceModel;
+ this.attemptController = new AttemptController(alienDefenceModel);
+ this.levelController = new LevelController(alienDefenceModel);
+ this.targetController = new TargetController(alienDefenceModel);
+ }
+
+ public IPersistance getAlienDefenceModel() {
+ return alienDefenceModel;
+ }
+
+ public AttemptController getAttemptController() {
+ return attemptController;
+ }
+
+ public LevelController getLevelController() {
+ return levelController;
+ }
+
+ public TargetController getTargetController() {
+ return targetController;
+ }
+
+ public GameController startGame(Level selectedLevel, User user) {
+ this.gameController = new GameController(selectedLevel, user, this);
+ return this.gameController;
+ }
+
+
+}
diff --git a/src/main/java/controller/AttemptController.java b/src/main/java/controller/AttemptController.java
new file mode 100644
index 0000000..6a476d0
--- /dev/null
+++ b/src/main/java/controller/AttemptController.java
@@ -0,0 +1,46 @@
+package controller;
+
+import java.util.Vector;
+
+import model.Level;
+import model.persistence.IAttemptPersistance;
+import model.persistence.IPersistance;
+
+public class AttemptController {
+
+ private IAttemptPersistance attemptPersistance;
+
+ /**
+ * erstellt ein neues Objekt eines AttemptController welches Attemptobjekte in
+ * der übergebenen Datenhaltung persisiert
+ *
+ * @param alienDefenceModel.getAttemptDB()
+ * Persistenzklasse der Attemptobjekte
+ */
+ public AttemptController(IPersistance alienDefenceModel) {
+ this.attemptPersistance = alienDefenceModel.getAttemptPersistance();
+ }
+
+ public Vector> getAllAttemptsPerLevel(Level level, int game_id) {
+ return attemptPersistance.getAllAttemptsPerLevel(level, game_id);
+ }
+
+ public int getPlayerPosition() {
+ return attemptPersistance.getPlayerPosition();
+ }
+
+ public void deleteHighscore(int level_id) {
+ attemptPersistance.deleteHighscore(level_id);
+ }
+
+ /**
+ * calculates points from attempt for highscore TODO create formula here
+ *
+ * @param level Levelobjekt
+ * @param hitcounter Controllerobjekt das die Treffer und Reaktionszeiten misst
+ * @return points
+ */
+ public int calculatePoints(Level level, HitCounter hitcounter) {
+ return -1;
+ }
+}
diff --git a/src/main/java/controller/GameController.java b/src/main/java/controller/GameController.java
new file mode 100644
index 0000000..69fdccc
--- /dev/null
+++ b/src/main/java/controller/GameController.java
@@ -0,0 +1,152 @@
+package controller;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import model.Level;
+import model.Point;
+import model.Target;
+import toDo.User;
+import view.menue.Highscore;
+
+public class GameController {
+
+ private AlienDefenceController alienDefenceController;
+ private Level currentLevel;
+ private User currentUser;
+ private boolean hasWon;
+ private HitCounter hitCounter;
+ private boolean setHighscore = true;
+ private long timer = 0L, starttimer = 0L, endtimer = 0L;
+ private List targets;
+
+ public GameController(Level selectedLevel, User user, AlienDefenceController alienDefenceController) {
+
+ this.currentLevel = selectedLevel;
+ this.currentUser = user;
+ this.hitCounter = new HitCounter(currentLevel.getTargets().size());
+ this.targets = currentLevel.getTargets();
+ this.hasWon = false;
+ this.alienDefenceController = alienDefenceController;
+ }
+
+ public void doLogik(long delta) {
+ timer += delta;
+
+ // time for next logic step
+
+ // section to run once a second
+ if (timer >= 1000) {
+ timer -= 100;
+
+ if (this.isAllTargetDestroyed()) {
+ this.hasWon = true;
+ }
+
+ if ((this.timeleft() <= 0 || this.isHasWon()) && this.setHighscore) {
+
+ setHighscore = false; //damit keine doppelten Eintrüge erzeugt werden
+
+ // TODO Highscoreeintrag erzeugen Highscore >> F_user_id, F_level_id, shots,
+ // hits, reaction_time
+ System.out.println("Highscoreeintrag für " + currentLevel.getName() + ": " + currentUser.getFirst_name()
+ + " hat " + this.getShotsFired() + " mal auf " + this.getTargets().size()
+ + " Ziele gefeuert und " + this.getHits() + " mal getroffen.");
+ System.out.println("Highscorepunkte: " + alienDefenceController.getAttemptController().calculatePoints(this.currentLevel, this.hitCounter));
+ int insert_id = 0;
+ // AttemptDB attemptDB =
+ // this.alienDefenceController.getAlienDefenceModel().getAttemptPersistance();
+ // int insert_id = attemptDB.createHighscoreEntry(currentUser.getP_user_id(),
+ // currentLevel.getLevel_id(),
+ // this.getShotsFired(), this.getHits(), relReactionDiffernce);
+
+ new Highscore(this.alienDefenceController.getAttemptController(), currentLevel,
+ insert_id);
+
+ }
+ }
+ // steps that use only delta
+ }
+
+ // fire
+ public void fireShot(int x, int y) {
+ boolean isHit = false;
+
+ // iterates through all targets and checks if a target is hit
+ for (Target t : targets) {
+ if (t.getHitbox().contains(new Point(x, y)) && !t.isHit()) {
+
+ long differnce = time() - t.getTime();
+ this.hitCounter.addReactionTime(differnce);
+
+ if (differnce > 0 && (t.getTime() + t.getDuration()) > time()) {
+ isHit = true;
+ t.setHit(true);
+ }
+ }
+ }
+
+ // hit
+ if (isHit) {
+ this.hitCounter.hit();
+ } else
+ this.hitCounter.miss();
+
+ }
+
+ public double getAccuracy() {
+ return hitCounter.getAccuracy();
+ }
+
+ public Level getCurrLevel() {
+ return currentLevel;
+ }
+
+ public int getHits() {
+ return this.hitCounter.getHit();
+ }
+
+ public int getShotsFired() {
+ return this.hitCounter.getShots();
+ }
+
+ public List getTargets() {
+ return (this.targets != null) ? this.targets : (new LinkedList());
+ }
+
+ private boolean isAllTargetDestroyed() {
+ for (Target t : this.targets) {
+ if (!t.isHit())
+
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isHasWon() {
+ return this.hasWon;
+ }
+
+ public void setCurrLevel(Level currLevel) {
+ this.currentLevel = currLevel;
+ }
+
+ public void setHasWon(boolean hasWon) {
+ this.hasWon = hasWon;
+ }
+
+ public void startLevel() {
+ this.starttimer = System.currentTimeMillis();
+ this.endtimer = this.starttimer + currentLevel.getDuration();
+ }
+
+ public long time() {
+ return System.currentTimeMillis() - this.starttimer;
+ }
+
+ public long timeleft() {
+ return (starttimer == 0) ? this.currentLevel.getDuration()
+ : (this.endtimer - System.currentTimeMillis()) / 1000;
+ }
+
+}
diff --git a/src/main/java/controller/HitCounter.java b/src/main/java/controller/HitCounter.java
new file mode 100644
index 0000000..af3a5da
--- /dev/null
+++ b/src/main/java/controller/HitCounter.java
@@ -0,0 +1,99 @@
+package controller;
+
+public class HitCounter {
+
+ private int shots, hit, targets;
+ private long sumReactionDiffernce;
+
+ /**
+ * erstellt einen neuen Hitcounter
+ *
+ * @param target
+ * Anzahl der zu zühlenden Ziele, übergeben Sie die maximale Anzahl
+ * der Ziele des Levels
+ */
+ public HitCounter(int target) {
+ this.reset(target);
+ }
+
+ /**
+ * gibt die Anzahl der abgegebenen Schüsse zurück
+ * @return Anzahl der abgegebenen Schüsse
+ */
+ public int getShots() {
+ return shots;
+ }
+
+ /**
+ * gibt die Anzahl der Treffer zurück
+ * @return Anzahl der Treffer
+ */
+ public int getHit() {
+ return hit;
+ }
+
+ /**
+ * gibt die Anzahl der noch nicht getroffenen Targets zurück
+ * @return Anzahl der noch nicht getroffenen Targets
+ */
+ public int getTargets() {
+ return targets;
+ }
+
+ /**
+ * setzt den Wert der Target auf dem im Parameter übergebenen Wert
+ * @param targets neue Targetanzahl nicht getroffener Ziele
+ */
+ public void setTargets(int targets) {
+ this.targets = targets;
+ }
+
+ public long getReactionTime() {
+ if(this.getHit() == 0)
+ return 0;
+ else
+ return this.sumReactionDiffernce / this.getHit();
+ }
+
+ public long getSumReactionDiffernce() {
+ return sumReactionDiffernce;
+ }
+
+ public void addReactionTime(long time) {
+ this.sumReactionDiffernce += time;
+ }
+
+ /**
+ * registriert einen Treffer
+ */
+ public void hit() {
+ this.hit++;
+ this.shots++;
+ }
+
+ /**
+ * registriert einen Fehlschuss
+ */
+ public void miss() {
+ this.shots++;
+ }
+
+ /**
+ * berechnet die Treffergenauigkeit
+ * @return Wert zwischen 0-100% der Treffergenauigkeit auf 2 Nachkommastellen gerundet
+ */
+ public double getAccuracy() {
+ return Math.round((100.0 / this.shots * this.hit) * 100.0) / 100.0;
+ }
+
+ /**
+ * setzt den HitCounter zurück
+ * @param target
+ */
+ public void reset(int target) {
+ this.targets = target;
+ this.shots = 0;
+ this.hit = 0;
+ this.sumReactionDiffernce = 0L;
+ }
+}
diff --git a/src/main/java/controller/LevelController.java b/src/main/java/controller/LevelController.java
new file mode 100644
index 0000000..f8d903f
--- /dev/null
+++ b/src/main/java/controller/LevelController.java
@@ -0,0 +1,81 @@
+package controller;
+
+import java.util.List;
+
+import model.Level;
+import model.persistence.ILevelPersistance;
+import model.persistence.IPersistance;
+
+public class LevelController {
+
+ private ILevelPersistance levelPersistance;
+ public final String DEFAULT_LEVELNAME = "unnamed";
+ public final String DEFAULT_BACKGROUND_PICTURE_URL = "background_1.jpg";
+ public final long DEFAULT_DURATION = 90000L;
+
+ /**
+ * erstellt ein neues Objekt eines LevelControllers, welche Levelobjekte der
+ * übergebenen Datenhaltung persistiert
+ *
+ * @param alienDefenceModel
+ * Persistenzklasse des gesamten Model
+ */
+ public LevelController(IPersistance alienDefenceModel) {
+ this.levelPersistance = alienDefenceModel.getLevelPersistance();
+ }
+
+ /**
+ * legt ein neues Level mit den Standardwerten an
+ *
+ * @return Levelobjekt
+ */
+ public Level createLevel() {
+ int level_id = levelPersistance.createLevel(DEFAULT_LEVELNAME, DEFAULT_BACKGROUND_PICTURE_URL, DEFAULT_DURATION);
+ return new Level(level_id);
+ }
+
+ /**
+ * gibt das konkrete Level zurück
+ *
+ * @param level_id
+ * @return Levelobjekt oder null bei nicht vorhandener Level_id
+ */
+ public Level readLevel(int level_id) {
+ List levels = levelPersistance.readAllLevel();
+ for (int i = 0; i < levels.size(); i++) {
+ if (level_id == levels.get(i).getLevel_id()) {
+ return levels.get(i);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * liest alle Level aus der DB
+ *
+ * @return Levelliste
+ */
+ public List readAllLevels() {
+ return this.levelPersistance.readAllLevel();
+ }
+
+ /**
+ * validiert die ünderungen und speichert das Level ab
+ *
+ * @param lvl
+ */
+ public void updateLevel(Level lvl) {
+ // TODO write Code to validate Level-Data
+ levelPersistance.updateLevel(lvl);
+ }
+
+ /**
+ * lüscht ein Level aus der Datenhaltung
+ *
+ * @param level_id
+ */
+ public void deleteLevel(int level_id) {
+ this.levelPersistance.deleteLevel(level_id);
+ }
+
+}
diff --git a/src/main/java/controller/TargetController.java b/src/main/java/controller/TargetController.java
new file mode 100644
index 0000000..9c0a8d6
--- /dev/null
+++ b/src/main/java/controller/TargetController.java
@@ -0,0 +1,113 @@
+package controller;
+
+import java.util.List;
+import java.util.ListIterator;
+
+import model.Level;
+import model.Target;
+import model.persistence.IPersistance;
+import model.persistence.ITargetPersistance;
+
+public class TargetController {
+
+ private ITargetPersistance targetPersistance;
+
+ /**
+ * erstellt ein neues Objekt eines TargetControllers welches Targetobjekte in
+ * der übergebenen Datenhaltung persisiert
+ *
+ * @param alienDefenceModel
+ * Persistenzklasse der Targetobjekte
+ */
+ public TargetController(IPersistance alienDefenceModel) {
+ this.targetPersistance = alienDefenceModel.getTargetPersistance();
+ }
+
+ /**
+ * fügt dem gewühlten Level ein neues Target hinzu
+ *
+ * @param target
+ * neues Ziel
+ * @param lvl
+ * ausgewühltes Level
+ * @return -1 wenn die Operation nicht geklappt hat, sonst die Target_id des
+ * neuen Ziels
+ */
+ public Target createTarget(Level lvl) {
+ Target target = new Target(600, 400, 150, 50, 1000, 1000, "ufo_3.png");
+ int image_id = 1;
+ int target_id = targetPersistance.createTarget(target, lvl.getLevel_id(), image_id);
+ target.setTarget_id(target_id);
+ lvl.getTargets().add(target);
+
+ return target;
+ }
+
+ /**
+ * gibt alle Targets zu einem Level aus der Datenhaltung aus
+ *
+ * @param level_id
+ * eindeutige Nummer des Levels
+ * @return Liste mit Zielen des Levels
+ */
+ public List readTargets(int level_id) {
+ return this.targetPersistance.readAllTargetsPerLevel(level_id);
+ }
+
+ /**
+ * tauscht ein Target im Levelobjekt aus und persistiert die ünderungen
+ *
+ * @param lvl
+ * zu welchem Level das Target gehürt
+ * @param target
+ * das zu ündernde Target
+ * @return true wenn das angegebene Target in der Liste gefunden wurde, false
+ * wenn nicht
+ */
+ public boolean updateTarget(Level lvl, Target target) {
+ boolean success = false;
+ // Target im Level austauschen
+ ListIterator iterator = lvl.getTargets().listIterator();
+ while (iterator.hasNext()) {
+ if (iterator.next().getTarget_id() == target.getTarget_id()) {
+ iterator.set(target);
+ success = true;
+ }
+ }
+ // Target in der Persistenz ündern
+ if (success) {
+ this.targetPersistance.updateTarget(target);
+ }
+ return success;
+ }
+
+ /**
+ * lüscht ein Target aus dem Levelobjekt und persistiert die ünderungen
+ *
+ * @param lvl
+ * zu welchem Level das Target gehürt
+ * @param target
+ * das zu lüschende Target
+ * @return true wenn das angegebene Target in der Liste gefunden wurde, false
+ * wenn nicht
+ */
+ public boolean deleteTarget(Level lvl, int target_id) {
+ boolean success = false;
+
+ ListIterator iterator = lvl.getTargets().listIterator();
+ while (iterator.hasNext()) {
+ if (iterator.next().getTarget_id() == target_id) {
+ iterator.remove();
+ success = true;
+ }
+ }
+
+ // Target in Persistenz lüschen
+ if (success) {
+ this.targetPersistance.deleteTarget(target_id);
+ }
+
+ return success;
+ }
+
+}
diff --git a/src/main/java/model/Attempt.java b/src/main/java/model/Attempt.java
new file mode 100644
index 0000000..3e5a01e
--- /dev/null
+++ b/src/main/java/model/Attempt.java
@@ -0,0 +1,51 @@
+package model;
+
+import java.time.LocalDateTime;
+import java.util.Vector;
+
+import toDo.User;
+
+public class Attempt {
+
+ // Attribute
+ private User user;
+ private Level level;
+ private int placement;
+ private double hitsShots;
+ private double hitsTargets;
+ private double reactionDuration;
+ private double highscorePoints;
+ private LocalDateTime datetime;
+
+ // Konstruktor
+ public Attempt(int place, Level level, double hitsShots, double hitsTargets, double reactionDuration,
+ double highscoreFormula, User user, LocalDateTime datetime) {
+ super();
+ this.placement = place;
+ this.level = level;
+ this.reactionDuration = reactionDuration;
+ this.highscorePoints = highscoreFormula;
+ this.user = user;
+ this.hitsShots = hitsShots;
+ this.hitsTargets = hitsTargets;
+ this.datetime = datetime;
+ }
+
+ public Vector getRowVector() {
+ Vector v = new Vector(8);
+ v.addElement(String.valueOf(this.placement));
+ v.addElement(this.user.getFirst_name() + " " + this.user.getSur_name());
+ v.addElement(this.datetime.getDayOfMonth() +"."+this.datetime.getMonthValue() + "." + this.datetime.getYear());;
+ v.addElement(this.datetime.getHour() + ":" + this.datetime.getMinute());
+ v.addElement(String.valueOf((int) this.hitsTargets));
+ v.addElement(String.valueOf((int) this.hitsShots));
+ v.addElement(String.valueOf((int) this.reactionDuration));
+ v.addElement(String.valueOf((int) this.highscorePoints));
+ return v;
+ }
+
+ public Level getLevel() {
+ return this.level;
+ }
+
+}
diff --git a/src/main/java/model/Hitbox.java b/src/main/java/model/Hitbox.java
new file mode 100644
index 0000000..c8ea5d1
--- /dev/null
+++ b/src/main/java/model/Hitbox.java
@@ -0,0 +1,86 @@
+package model;
+
+import java.util.Random;
+
+public class Hitbox {
+ private Point point;
+ private int width;
+ private int height;
+ public static final int MAXWIDTH = 1200;
+ public static final int MAXHEIGHT = 1000;
+ private static Random rand = new Random();
+
+ public Hitbox() {
+ this.point = new Point();
+ this.width = 0;
+ this.height = 0;
+ }
+
+ public Hitbox(int x, int y, int breite, int hoehe) {
+ super();
+ this.point = new Point(x, y);
+ this.setWidth(breite);
+ this.setHeight(hoehe);
+ }
+
+ public int getX() {
+ return this.point.getX();
+ }
+
+ public void setX(int x) {
+ this.point.setX(x);
+ }
+
+ public int getY() {
+ return this.point.getY();
+ }
+
+ public void setY(int y) {
+ this.point.setY(y);
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setWidth(int width) {
+ this.width = Math.abs(width);
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setHeight(int height) {
+ this.height = Math.abs(height);
+ }
+
+ public boolean contains(Point p) {
+ return contains(p.getX(), p.getY());
+ }
+
+ public boolean contains(int x, int y) {
+ return this.point.getX() <= x && x <= this.point.getX() + this.width && this.point.getY() <= y
+ && y <= this.point.getY() + this.height;
+ }
+
+ public boolean contains(Hitbox hitbox) {
+ Point upperleft = new Point(hitbox.getX(), hitbox.getY());
+ Point lowerright = new Point(hitbox.getX() + hitbox.getWidth(), hitbox.getY() + hitbox.getHeight());
+ return contains(upperleft) && contains(lowerright);
+ }
+
+ public static Hitbox generateRandomHitbox() {
+ int x = rand.nextInt(MAXWIDTH + 1);
+ int y = rand.nextInt(MAXHEIGHT + 1);
+ int width = rand.nextInt(MAXWIDTH - x + 1);
+ int height = rand.nextInt(MAXHEIGHT - y + 1);
+ return new Hitbox(x, y, width, height);
+ }
+
+ @Override
+ public String toString() {
+ return "Hitbox [x=" + this.point.getX() + ", y=" + this.point.getY() + ", width=" + width + ", height=" + height
+ + "]";
+ }
+}
diff --git a/src/main/java/model/Level.java b/src/main/java/model/Level.java
new file mode 100644
index 0000000..bf68385
--- /dev/null
+++ b/src/main/java/model/Level.java
@@ -0,0 +1,149 @@
+package model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Level {
+
+ /** unique value */
+ private int level_id;
+ /** name of that level */
+ private String name;
+ /** List of Targets */
+ private List targets;
+ /** duration a level lasts im ms */
+ private long duration;
+ /** default duration for a level is 90s */
+ public final long DEFAULT_DURATION = 90000L;
+ /** path to background image */
+ private String backgroundImage;
+
+ public Level() {
+ this.targets = new ArrayList(100);
+ this.name = "unnamed";
+ this.duration = DEFAULT_DURATION;
+ this.backgroundImage = "background_1.jpg";
+ }
+
+ public Level(int level_id) {
+ this();
+ this.level_id = level_id;
+ }
+
+ public int getLevel_id() {
+ return this.level_id;
+ }
+
+ public void setLevel_id(int level_id) {
+ this.level_id = level_id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getTargets() {
+ return this.targets;
+ }
+
+ public void setTargets(List targets) {
+ this.targets = targets;
+ }
+
+ public long getDuration() {
+ return this.duration;
+ }
+
+ public void setDuration(long duration) {
+ this.duration = duration;
+ }
+
+ public String getBackgroundImage() {
+ return backgroundImage;
+ };
+
+ public void setBackgroundImage(String backgroundImage) {
+ this.backgroundImage = backgroundImage;
+ }
+
+ public String[][] getTargetsAsTableModel() {
+ String[][] result = new String[this.targets.size()][];
+ int i = 0;
+ for (Target t : this.targets) {
+ result[i++] = t.getData();
+ }
+ return result;
+ }
+
+ public String[] getData() {
+ return new String[] { "" + this.level_id, this.name, this.backgroundImage, "" + this.targets.size(),
+ "" + this.duration };
+ }
+
+ public String toString() {
+ return "Level [level_id=" + level_id + ", name=" + name + ", duration=" + duration + ", backgroundImage="
+ + backgroundImage + ", targets=" + targets + "]";
+ }
+
+ /** use this Level only for test porposes */
+ public static Level getDefaultLevel() {
+ Level level = new Level();
+ // Objekte des Levels hier eintragen
+ level.targets.add(new Target(100, 100, 75, 150, 0, 500000, "lemon.png"));
+ level.targets.add(new Target(200, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(300, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(400, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(500, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(600, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(700, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(800, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(900, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1000, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1100, 100, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(100, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(200, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(300, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(400, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(500, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(600, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(700, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(800, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(900, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1000, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1100, 300, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(100, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(200, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(300, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(400, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(500, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(600, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(700, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(800, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(900, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1000, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1100, 500, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(100, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(200, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(300, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(400, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(500, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(600, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(700, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(800, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(900, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1000, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.targets.add(new Target(1100, 700, 75, 150, 0, 500000, "ballon.png"));
+ level.duration = 25000L;
+ level.name = "DefaultTestLevel 001";
+ level.level_id = 1;
+ return level;
+ }
+
+ public static String[] getLevelDescriptions() {
+ return new String[] { "Nr.", "Name", "Hintergrund", "Targets", "Dauer" };
+ }
+}
diff --git a/src/main/java/model/Point.java b/src/main/java/model/Point.java
new file mode 100644
index 0000000..9093ba3
--- /dev/null
+++ b/src/main/java/model/Point.java
@@ -0,0 +1,43 @@
+package model;
+
+public class Point {
+ private int x;
+ private int y;
+
+ public Point() {
+ this.x = 0;
+ this.y = 0;
+ }
+
+ public Point(int x, int y) {
+ super();
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ public boolean equals(Point p) {
+ return this.x == p.getX() && this.y == p.getY();
+ }
+
+ @Override
+ public String toString() {
+ return "Punkt [x=" + x + ", y=" + y + "]";
+ }
+
+}
diff --git a/src/main/java/model/Target.java b/src/main/java/model/Target.java
new file mode 100644
index 0000000..c3cd136
--- /dev/null
+++ b/src/main/java/model/Target.java
@@ -0,0 +1,118 @@
+package model;
+
+import java.util.Random;
+
+public class Target {
+
+ private int target_id;
+ /** the area of a target */
+ private Hitbox hitbox;
+ /** time a target appears after game begins */
+ private long time;
+ /** time a target is able to hit */
+ private long duration;
+ private boolean hit;
+ private String imageAddress;
+
+ /** image of target */
+
+ public Target() {
+ super();
+ this.target_id = 0;
+ this.hitbox = new Hitbox(100, 100, 150, 50);
+ this.time = 1000;
+ this.duration = Long.MAX_VALUE;
+ this.setHit(false);
+ this.setImageAddress("ufo_1.png");
+ }
+
+ public Target(int x, int y, int width, int height, long time, long duration, String image) {
+ super();
+ this.target_id = 0;
+ this.hitbox = new Hitbox(x, y, width, height);
+ this.time = time;
+ this.duration = duration;
+ this.setHit(false);
+ this.setImageAddress(image);
+ }
+
+ public Target(Hitbox hitbox, long time, long duration) {
+ super();
+ this.target_id = 0;
+ this.hitbox = hitbox;
+ this.time = time;
+ this.duration = duration;
+ this.setHit(false);
+ }
+
+ public int getTarget_id() {
+ return target_id;
+ }
+
+ public void setTarget_id(int target_id) {
+ this.target_id = target_id;
+ }
+
+ public Hitbox getHitbox() {
+ return hitbox;
+ }
+
+ public void setHitbox(Hitbox hitbox) {
+ this.hitbox = hitbox;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public void setTime(long time) {
+ this.time = time;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public void setDuration(long duration) {
+ this.duration = duration;
+ }
+
+ public boolean isHit() {
+ return hit;
+ }
+
+ public void setHit(boolean hit) {
+ this.hit = hit;
+ }
+
+ public String getImageAddress() {
+ return imageAddress;
+ }
+
+ public void setImageAddress(String imageAdress) {
+ this.imageAddress = imageAdress;
+ }
+
+ public static Target getRandomTarget(int screenResolution_X, int screenResolution_Y) {
+ Random rand = new Random();
+ return new Target(rand.nextInt(screenResolution_X - 50), rand.nextInt(screenResolution_Y - 50), 350, 129, 0,
+ 90000, "ufo_4.png");
+ }
+
+ public String[] getData() {
+ return new String[] { this.target_id + "", this.hitbox.getX() + "", this.hitbox.getY() + "",
+ this.hitbox.getWidth() + "", this.hitbox.getHeight() + "", this.getImageAddress(), this.getTime() + "",
+ this.getDuration() + "" };
+ }
+
+ public static String[] getTableDescriptions() {
+ return new String[] { "Nr.", "X", "Y", "Breite", "Hühe", "Bild", "Startzeit", "Dauer" };
+ }
+
+ @Override
+ public String toString() {
+ return "Target [target_id=" + target_id + ", hitbox=" + hitbox + ", time=" + time + ", duration=" + duration
+ + ", hit=" + hit + ", imageAddress=" + imageAddress + "]";
+ }
+
+}
diff --git a/src/main/java/model/persistence/IAttemptPersistance.java b/src/main/java/model/persistence/IAttemptPersistance.java
new file mode 100644
index 0000000..015c364
--- /dev/null
+++ b/src/main/java/model/persistence/IAttemptPersistance.java
@@ -0,0 +1,14 @@
+package model.persistence;
+
+import java.util.Vector;
+
+import model.Level;
+
+public interface IAttemptPersistance {
+
+ int createHighscoreEntry(int F_user_id, int F_level_id, int shots, int hits, long reaction_time);
+ int getPlayerPosition();
+ Vector> getAllAttemptsPerLevel(Level level, int game_id);
+ //no update needed
+ void deleteHighscore(int level_id);
+}
diff --git a/src/main/java/model/persistence/ILevelPersistance.java b/src/main/java/model/persistence/ILevelPersistance.java
new file mode 100644
index 0000000..fa26c11
--- /dev/null
+++ b/src/main/java/model/persistence/ILevelPersistance.java
@@ -0,0 +1,38 @@
+package model.persistence;
+
+import java.util.List;
+
+import model.Level;
+
+public interface ILevelPersistance {
+
+ /**
+ * legt in der Datenbank ein neues Level an
+ *
+ * @return level_id für das neue Level
+ */
+ int createLevel(String levelname, String backgroundUrl, long duration);
+
+ /**
+ * gibt alle Level aus der Datenbank als Liste zurück
+ *
+ * @return Liste aller Level
+ */
+ List readAllLevel();
+
+ /**
+ * aktualisiert die Daten eines Levels
+ *
+ * @param lvl
+ * ein Levelobjekt
+ */
+ void updateLevel(Level lvl);
+
+ /**
+ * lüscht ein Level aus der Datenbank
+ *
+ * @param P_level_id
+ */
+ void deleteLevel(int level_id);
+
+}
\ No newline at end of file
diff --git a/src/main/java/model/persistence/IPersistance.java b/src/main/java/model/persistence/IPersistance.java
new file mode 100644
index 0000000..aee96a0
--- /dev/null
+++ b/src/main/java/model/persistence/IPersistance.java
@@ -0,0 +1,10 @@
+package model.persistence;
+
+public interface IPersistance {
+
+ IAttemptPersistance getAttemptPersistance();
+ ILevelPersistance getLevelPersistance();
+ ITargetPersistance getTargetPersistance();
+ IUserPersistance getUserPersistance();
+
+}
diff --git a/src/main/java/model/persistence/ITargetPersistance.java b/src/main/java/model/persistence/ITargetPersistance.java
new file mode 100644
index 0000000..3aca497
--- /dev/null
+++ b/src/main/java/model/persistence/ITargetPersistance.java
@@ -0,0 +1,17 @@
+package model.persistence;
+
+import java.util.List;
+
+import model.Target;
+
+public interface ITargetPersistance {
+
+ int createTarget(Target target, int level_id, int image_id);
+
+ List readAllTargetsPerLevel(int level_id);
+
+ void updateTarget(Target target);
+
+ void deleteTarget(int target_id);
+
+}
\ No newline at end of file
diff --git a/src/main/java/model/persistence/IUserPersistance.java b/src/main/java/model/persistence/IUserPersistance.java
new file mode 100644
index 0000000..87cf03b
--- /dev/null
+++ b/src/main/java/model/persistence/IUserPersistance.java
@@ -0,0 +1,9 @@
+package model.persistence;
+
+import toDo.User;
+
+public interface IUserPersistance {
+
+ User readUser(String username);
+
+}
\ No newline at end of file
diff --git a/src/main/java/model/persistenceDB/AccessDB.java b/src/main/java/model/persistenceDB/AccessDB.java
new file mode 100644
index 0000000..001fa32
--- /dev/null
+++ b/src/main/java/model/persistenceDB/AccessDB.java
@@ -0,0 +1,55 @@
+package model.persistenceDB;
+
+public class AccessDB {
+
+ // Attribute
+ private String dbName;
+ private String user;
+ private String password;
+ private String url;
+
+ // Konstruktor
+ public AccessDB() {
+ this.url = "jdbc:mysql://localhost:3306/";
+ this.dbName = "alien_defence";
+ this.user = "root";
+ this.password = "";
+ }
+
+ // Getter und Setter
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getFullURL() {
+ return this.url + this.dbName;
+ }
+}
diff --git a/src/main/java/model/persistenceDB/AttemptDB.java b/src/main/java/model/persistenceDB/AttemptDB.java
new file mode 100644
index 0000000..b2b7a08
--- /dev/null
+++ b/src/main/java/model/persistenceDB/AttemptDB.java
@@ -0,0 +1,148 @@
+package model.persistenceDB;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Vector;
+
+import model.Attempt;
+import model.Level;
+import model.persistence.IAttemptPersistance;
+import toDo.User;
+
+public class AttemptDB implements IAttemptPersistance {
+
+ // Attribute
+ private AccessDB dbAccess;
+ private int playerPosition = -100000;
+
+ // Konstuktor
+ public AttemptDB(AccessDB dbAccess) {
+ this.dbAccess = dbAccess;
+ }
+
+ // Eintrag des Spiels in die Highscore wird vorgenommen - Aufgerufen wird von
+ // der Klasse GameController
+ public int createHighscoreEntry(int F_user_id, int F_level_id, int shots, int hits, long reaction_time) {
+ String sql = "INSERT INTO attempts (F_user_id, F_level_id, shots, hits, reaction_time, date, time)"
+ + " values (?, ?, ?, ?, ?, ?, ?)";
+ int last_inserted_id = 0;
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword());
+ PreparedStatement statement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);) {
+
+ // Aktuelle Datum und Uhrzeit holen und in Strings speichern
+ LocalDate datum = LocalDate.now(); // Erstellt Datum-Objekt heute
+ LocalTime time = LocalTime.now();
+ String now = time.getHour() + ":" + time.getMinute() + ":" + time.getSecond();
+
+ statement.setInt(1, F_user_id);
+ statement.setInt(2, F_level_id);
+ statement.setInt(3, shots);
+ statement.setInt(4, hits);
+ statement.setLong(5, reaction_time);
+ statement.setString(6, datum.toString());
+ statement.setString(7, now);
+
+ statement.execute();
+
+ ResultSet rs = statement.getGeneratedKeys(); // Letzte eingtragene ID
+ if (rs.next()) {
+ last_inserted_id = rs.getInt(1);
+ }
+
+ } catch (SQLException ex) {
+ System.err.println(ex.getMessage());
+ }
+ return last_inserted_id;
+ }
+
+ public Vector> getAllAttemptsPerLevel(Level level, int game_id) {
+ Vector> vecTests = null;
+ String url = dbAccess.getUrl() + dbAccess.getDbName();
+
+ String highscoreFormula = "(hits / targets * 1000)*0.4 + (hits / shots * 1000)*0.2 + (1000 - (reaction_time / sum_duration * 1000))*0.4";
+
+ String query = "SELECT P_attempt_id, targets, shots, hits, reaction_time, first_name, sur_name, date, time, (hits / targets * 1000) AS hitsTargets, (hits / shots * 1000) AS hitsShots, (1000 - (reaction_time / sum_duration * 1000)) AS reactionDuration,"
+ + highscoreFormula + "AS highscoreFormula FROM "
+ + "(SELECT F_level_id, COUNT(P_target_id) AS targets, SUM(duration ) AS sum_duration FROM `targets` WHERE F_level_id = "
+ + level.getLevel_id() + ") AS count_targets INNER JOIN "
+ + "attempts ON attempts.F_level_id = count_targets.F_level_id INNER JOIN "
+ + "users ON P_user_id = F_user_id ORDER BY highscoreFormula DESC, reactionDuration DESC";
+
+ try {
+ Connection con = DriverManager.getConnection(url, dbAccess.getUser(), dbAccess.getPassword());
+ Statement stmt = con.createStatement();
+ ResultSet results = stmt.executeQuery(query);
+ vecTests = getVecTest(level, game_id, results);
+
+ } catch (SQLException ex) {
+ System.err.println(ex.getMessage());
+ }
+ return vecTests;
+ }
+
+ public int getPlayerPosition() {
+ return this.playerPosition;
+ }
+
+ // 2 Diese Methode wird vom Konstruktor aufgerufen.
+ // Daten aus der Datenbank werden in einem zweidimensionalen Vector gespeichert.
+ private Vector> getVecTest(Level level, int gameId, ResultSet results) {
+
+ Vector> vecTests = new Vector>();
+ try {
+ int nummerierung = 0;
+ while (results.next()) {
+
+ nummerierung++;
+
+ //Markierung des Spielers für Highscoreansicht
+ //TODO Verstoü gegen 3 Schichtenarchitektur beheben
+ if (results.getInt("P_attempt_id") == gameId)
+ this.playerPosition = nummerierung - 1;
+
+ LocalDate date = results.getDate("date").toLocalDate();
+ User user = new User();
+ user.setFirst_name(results.getString("first_name"));
+ user.setSur_name(results.getString("sur_name"));
+ LocalDateTime dateTime = date.atTime(results.getTime("time").toLocalTime());
+ Attempt tmp = new Attempt(nummerierung, level, results.getDouble("hitsShots"),
+ results.getDouble("hitsTargets"), results.getInt("reactionDuration"),
+ results.getInt("highscoreFormula"), user, dateTime);
+
+ Vector v = tmp.getRowVector();
+ vecTests.add(v);
+ }
+ } catch (SQLException ex) {
+ System.err.println(ex.getMessage());
+ }
+ return vecTests;
+ }
+
+ // lüscht alle Eintrüge
+ public void deleteHighscore(int level_id) {
+
+ String url = dbAccess.getFullURL();
+ try {
+
+ Connection con = DriverManager.getConnection(url, dbAccess.getUser(), dbAccess.getPassword());
+
+ String query = "DELETE FROM attempts WHERE F_level_id = ?";
+
+ PreparedStatement preparedStmt = con.prepareStatement(query);
+ preparedStmt.setInt(1, level_id);
+
+ preparedStmt.execute();
+
+ } catch (SQLException ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/model/persistenceDB/LevelDB.java b/src/main/java/model/persistenceDB/LevelDB.java
new file mode 100644
index 0000000..9f433ad
--- /dev/null
+++ b/src/main/java/model/persistenceDB/LevelDB.java
@@ -0,0 +1,112 @@
+package model.persistenceDB;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Vector;
+
+import model.Level;
+import model.persistence.ILevelPersistance;
+import model.persistence.ITargetPersistance;
+
+public class LevelDB implements ILevelPersistance {
+
+ private AccessDB dbAccess;
+
+ public LevelDB(AccessDB dbAccess) {
+ this.dbAccess = dbAccess;
+ }
+
+ public int createLevel(String levelname, String backgroundUrl, long duration) {
+ String sql = "INSERT INTO levels (name, background, duration) VALUES (?, ?, ?);";
+
+ int lastKey = -1;
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword());
+ PreparedStatement statement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);) {
+
+ statement.setString(1, levelname);
+ statement.setString(2, backgroundUrl);
+ statement.setLong(3, duration);
+
+ statement.execute();
+
+ ResultSet generatedKeys = statement.getGeneratedKeys();
+ if (generatedKeys.next()) {
+ lastKey = generatedKeys.getInt(1);
+ }
+ generatedKeys.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return lastKey;
+ }
+
+ public List readAllLevel() {
+ String sql = "SELECT * FROM levels ORDER BY P_level_id;";
+ List allLevels = new Vector();
+
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword());
+ Statement statement = con.createStatement();
+ ResultSet rs = statement.executeQuery(sql)) {
+
+ while (rs.next()) {
+
+ Level level = new Level();
+ level.setLevel_id(rs.getInt("P_level_id")); // ID von Level
+ level.setName(rs.getString("name")); // Name von Level
+ level.setDuration(rs.getInt("duration")); // Dauer von Level
+ level.setBackgroundImage(rs.getString("background")); // Hintergrundsbild
+
+ // Targets auslesen und dem Level hinzufügen
+ ITargetPersistance targetDB = new TargetDB(this.dbAccess);
+
+ level.setTargets(targetDB.readAllTargetsPerLevel(level.getLevel_id()));
+
+ allLevels.add(level);
+ }
+
+ } catch (SQLException e) {
+ e.getMessage();
+ e.printStackTrace();
+ }
+ return allLevels;
+ }
+
+ public void updateLevel(Level lvl) {
+ String sql = "UPDATE levels SET name = ?, background = ?, duration = ? WHERE p_level_id = ?;";
+
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); PreparedStatement statement = con.prepareStatement(sql)) {
+
+ statement.setString(1, lvl.getName());
+ statement.setString(2, lvl.getBackgroundImage());
+ statement.setLong(3, lvl.getDuration());
+ statement.setInt(4, lvl.getLevel_id());
+
+ statement.executeUpdate();
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void deleteLevel(int level_id) {
+ String sql = "DELETE FROM levels WHERE P_level_id = " + level_id + ";";
+
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); Statement statement = con.createStatement()) {
+
+ statement.executeUpdate(sql);
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/model/persistenceDB/PersistanceDB.java b/src/main/java/model/persistenceDB/PersistanceDB.java
new file mode 100644
index 0000000..c763dc3
--- /dev/null
+++ b/src/main/java/model/persistenceDB/PersistanceDB.java
@@ -0,0 +1,44 @@
+package model.persistenceDB;
+
+import model.persistence.IAttemptPersistance;
+import model.persistence.ILevelPersistance;
+import model.persistence.IPersistance;
+import model.persistence.ITargetPersistance;
+import model.persistence.IUserPersistance;
+import toDo.UserDB;
+
+public class PersistanceDB implements IPersistance{
+
+ private LevelDB levelDB;
+ private UserDB userDB;
+ private AttemptDB attemptDB;
+ private TargetDB targetDB;
+
+ public PersistanceDB() {
+ AccessDB dbAccess = new AccessDB();
+ this.levelDB = new LevelDB(dbAccess);
+ this.userDB = new UserDB(dbAccess);
+ this.attemptDB = new AttemptDB(dbAccess);
+ this.targetDB = new TargetDB(dbAccess);
+ }
+
+ @Override
+ public IAttemptPersistance getAttemptPersistance() {
+ return this.attemptDB;
+ }
+
+ @Override
+ public ILevelPersistance getLevelPersistance() {
+ return this.levelDB;
+ }
+
+ @Override
+ public ITargetPersistance getTargetPersistance() {
+ return this.targetDB;
+ }
+
+ @Override
+ public IUserPersistance getUserPersistance() {
+ return this.userDB;
+ }
+}
diff --git a/src/main/java/model/persistenceDB/TargetDB.java b/src/main/java/model/persistenceDB/TargetDB.java
new file mode 100644
index 0000000..84cef10
--- /dev/null
+++ b/src/main/java/model/persistenceDB/TargetDB.java
@@ -0,0 +1,118 @@
+package model.persistenceDB;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Vector;
+
+import model.Hitbox;
+import model.Target;
+import model.persistence.ITargetPersistance;
+
+public class TargetDB implements ITargetPersistance {
+ private AccessDB dbAccess;
+
+ public TargetDB(AccessDB dbAccess) {
+ super();
+ if (dbAccess != null)
+ this.dbAccess = dbAccess;
+ else
+ this.dbAccess = new AccessDB();
+ }
+
+ public int createTarget(Target target, int level_id, int image_id) {
+ String sql = "INSERT INTO targets (F_level_id, image_address, x_position, y_position, width, height, time, duration) VALUES (?, ?, ?, ?, ?, ?, ?, ?);";
+ int lastKey = -1;
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword());
+ PreparedStatement statement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);) {
+
+ statement.setInt(1, level_id);
+ statement.setString(2, target.getImageAddress());
+ statement.setInt(3, target.getHitbox().getX());
+ statement.setInt(4, target.getHitbox().getY());
+ statement.setInt(5, target.getHitbox().getWidth());
+ statement.setInt(6, target.getHitbox().getHeight());
+ statement.setLong(7, target.getTime());
+ statement.setLong(8, target.getDuration());
+ statement.execute();
+
+ ResultSet generatedKeys = statement.getGeneratedKeys();
+ if (generatedKeys.next()) {
+ lastKey = generatedKeys.getInt(1);
+ }
+ generatedKeys.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return lastKey;
+ }
+
+ public List readAllTargetsPerLevel(int level_id) {
+ String sql = "SELECT * FROM targets WHERE F_level_id = ? ORDER BY P_target_id;";
+ List alltargets = new Vector();
+
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); PreparedStatement statement = con.prepareStatement(sql)) {
+
+ statement.setInt(1, level_id);
+
+ ResultSet rs = statement.executeQuery();
+
+ while (rs.next()) {
+
+ Target target = new Target();
+ target.setTarget_id(rs.getInt("P_target_id"));
+ target.setHitbox(new Hitbox(rs.getInt("x_position"), rs.getInt("y_position"), rs.getInt("width"),
+ rs.getInt("height")));
+ target.setTime(rs.getLong("time"));
+ target.setDuration(rs.getLong("duration"));
+ target.setImageAddress(rs.getString("image_address"));
+
+ alltargets.add(target);
+ }
+
+ } catch (SQLException e) {
+ e.getMessage();
+ e.printStackTrace();
+ }
+ return alltargets;
+ }
+
+ public void updateTarget(Target target) {
+ String sql = "UPDATE targets SET x_position = ?, y_position = ?, width = ?, height = ?, time = ?, duration = ?, image_address = ? WHERE P_target_id = ?;";
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); PreparedStatement statement = con.prepareStatement(sql)) {
+
+ statement.setInt(1, target.getHitbox().getX());
+ statement.setInt(2, target.getHitbox().getY());
+ statement.setInt(3, target.getHitbox().getWidth());
+ statement.setInt(4, target.getHitbox().getHeight());
+ statement.setLong(5, target.getTime());
+ statement.setLong(6, target.getDuration());
+ statement.setString(7, target.getImageAddress());
+ statement.setInt(8, target.getTarget_id());
+ statement.executeUpdate();
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void deleteTarget(int target_id) {
+ String sql = "DELETE FROM targets WHERE P_target_id = " + target_id + ";";
+
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); Statement statement = con.createStatement()) {
+ statement.executeUpdate(sql);
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/model/persistenceDummy/AttemptDummy.java b/src/main/java/model/persistenceDummy/AttemptDummy.java
new file mode 100644
index 0000000..dbd7995
--- /dev/null
+++ b/src/main/java/model/persistenceDummy/AttemptDummy.java
@@ -0,0 +1,52 @@
+package model.persistenceDummy;
+
+import java.util.Vector;
+
+import model.Level;
+import model.persistence.IAttemptPersistance;
+
+/**
+ * Klasse mit Dummywerten zum Testen der View und des Controllers
+ * @author Tim Tenbusch
+ *
+ */
+public class AttemptDummy implements IAttemptPersistance{
+
+ public int createHighscoreEntry(int F_user_id, int F_level_id, int shots, int hits, long reaction_time) {
+ // fleiüig speichern
+ return 1;
+ }
+
+ public Vector> getAllAttemptsPerLevel(Level level, int game_id) {
+ Vector> highscore = new Vector>();
+ Vector eintrag1 = new Vector();
+ Vector eintrag2 = new Vector();
+ eintrag1.addElement("1");
+ eintrag2.addElement("2");
+ eintrag1.addElement("Dummy Persistenz");
+ eintrag2.addElement("Vorname Nachname");
+ eintrag1.addElement("17.02.2021");
+ eintrag2.addElement("18.02.2021");
+ eintrag1.addElement("15:21");
+ eintrag2.addElement("17:01");
+ eintrag1.addElement("7");
+ eintrag2.addElement("9");
+ eintrag1.addElement("421");
+ eintrag2.addElement("13");
+ eintrag1.addElement("250");
+ eintrag2.addElement("270");
+ eintrag1.addElement("356");
+ eintrag2.addElement("481");
+ highscore.add(eintrag1);
+ highscore.add(eintrag2);
+ return highscore;
+ }
+
+ public int getPlayerPosition() {
+ return 1;
+ }
+
+ public void deleteHighscore(int level_id) {
+ //Omnomnom Anfrage gefressen
+ }
+}
diff --git a/src/main/java/model/persistenceDummy/LevelDummy.java b/src/main/java/model/persistenceDummy/LevelDummy.java
new file mode 100644
index 0000000..c0b8edf
--- /dev/null
+++ b/src/main/java/model/persistenceDummy/LevelDummy.java
@@ -0,0 +1,61 @@
+package model.persistenceDummy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import model.Level;
+import model.Target;
+import model.persistence.ILevelPersistance;
+
+public class LevelDummy implements ILevelPersistance {
+
+ public int createLevel(String levelname, String backgroundUrl, long duration) {
+ return 1;
+ }
+
+ public List readAllLevel() {
+ List levels = new ArrayList();
+ Level level1 = new Level();
+ level1.setLevel_id(1);
+ level1.setName("Level 1");
+ level1.setBackgroundImage("background_1.jpg");
+ level1.setDuration(10000);
+ List targets = new ArrayList();
+ Target t1 = new Target(100, 100, 150, 50, 1000, 2000, "ufo_1.png");
+ targets.add(t1);
+ Target t2 = new Target(5, 100, 150, 50, 2000, 2000, "ufo_2.png");
+ targets.add(t2);
+ Target t3 = new Target(800, 800, 150, 50, 3000, 2000, "ufo_3.png");
+ targets.add(t3);
+ Target t4 = new Target(600, 400, 150, 50, 4000, 2000, "ufo_4.png");
+ targets.add(t4);
+ Target t5 = new Target(220, 400, 150, 50, 5000, 2000, "ufo_5.png");
+ targets.add(t5);
+
+ level1.setTargets(targets);
+ levels.add(level1);
+ Level level2 = new Level();
+ level2.setLevel_id(2);
+ level2.setName("Level 2");
+ level2.setBackgroundImage("background_2.jpg");
+ level2.setDuration(5000);
+ level2.setTargets(targets);
+ levels.add(level2);
+ Level level3 = new Level();
+ level3.setLevel_id(3);
+ level3.setName("Level 3");
+ level3.setBackgroundImage("background_10.jpg");
+ level3.setDuration(10000);
+ level3.setTargets(targets);
+ levels.add(level3);
+ return levels;
+ }
+
+ public void updateLevel(Level lvl) {
+
+ }
+
+ public void deleteLevel(int level_id) {
+
+ }
+}
diff --git a/src/main/java/model/persistenceDummy/PersistanceDummy.java b/src/main/java/model/persistenceDummy/PersistanceDummy.java
new file mode 100644
index 0000000..a933195
--- /dev/null
+++ b/src/main/java/model/persistenceDummy/PersistanceDummy.java
@@ -0,0 +1,45 @@
+package model.persistenceDummy;
+
+import model.persistence.IAttemptPersistance;
+import model.persistence.ILevelPersistance;
+import model.persistence.IPersistance;
+import model.persistence.ITargetPersistance;
+import model.persistence.IUserPersistance;
+
+public class PersistanceDummy implements IPersistance{
+
+ private LevelDummy levelDummy;
+ private UserDummy userDummy;
+ private AttemptDummy attemptDummy;
+ private TargetDummy targetDummy;
+
+ public PersistanceDummy() {
+
+ this.levelDummy = new LevelDummy();
+ this.userDummy = new UserDummy();
+ this.attemptDummy = new AttemptDummy();
+ this.targetDummy = new TargetDummy();
+ }
+
+ @Override
+ public IAttemptPersistance getAttemptPersistance() {
+ return this.attemptDummy;
+ }
+
+ @Override
+ public ILevelPersistance getLevelPersistance() {
+ return this.levelDummy;
+ }
+
+ @Override
+ public ITargetPersistance getTargetPersistance() {
+ return this.targetDummy;
+ }
+
+ @Override
+ public IUserPersistance getUserPersistance() {
+ return this.userDummy;
+ }
+
+
+}
diff --git a/src/main/java/model/persistenceDummy/TargetDummy.java b/src/main/java/model/persistenceDummy/TargetDummy.java
new file mode 100644
index 0000000..3a3ca16
--- /dev/null
+++ b/src/main/java/model/persistenceDummy/TargetDummy.java
@@ -0,0 +1,38 @@
+package model.persistenceDummy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import model.Target;
+import model.persistence.ITargetPersistance;
+
+public class TargetDummy implements ITargetPersistance {
+
+ public int createTarget(Target target, int level_id, int image_id) {
+ return 1;
+ }
+
+ public List readAllTargetsPerLevel(int level_id) {
+ List targets = new ArrayList();
+ Target t1 = new Target(100, 100, 150, 50, 1000, 2000, "ufo_1.png");
+ targets.add(t1);
+ Target t2 = new Target(5, 100, 150, 50, 2000, 2000, "ufo_2.png");
+ targets.add(t2);
+ Target t3 = new Target(800, 800, 150, 50, 3000, 2000, "ufo_3.png");
+ targets.add(t3);
+ Target t4 = new Target(600, 400, 150, 50, 4000, 2000, "ufo_4.png");
+ targets.add(t4);
+ Target t5 = new Target(220, 400, 150, 50, 5000, 2000, "ufo_5.png");
+ targets.add(t5);
+ return targets;
+ }
+
+ public void updateTarget(Target target) {
+
+ }
+
+ public void deleteTarget(int target_id) {
+
+ }
+
+}
diff --git a/src/main/java/model/persistenceDummy/UserDummy.java b/src/main/java/model/persistenceDummy/UserDummy.java
new file mode 100644
index 0000000..9d7b77a
--- /dev/null
+++ b/src/main/java/model/persistenceDummy/UserDummy.java
@@ -0,0 +1,19 @@
+package model.persistenceDummy;
+
+import java.time.LocalDate;
+
+import model.persistence.IUserPersistance;
+import toDo.User;
+
+/**
+ * Dummyklasse zum Testen
+ * @author Tim Tenbusch
+ *
+ */
+public class UserDummy implements IUserPersistance {
+
+ public User readUser(String username) {
+ return new User(1, "Dummy", "Persistenz", LocalDate.now(), "Dummystr.", "12C", "11111", "Nowhere", username, "pass", 12000, "gefangen", 1.58);
+ }
+
+}
diff --git a/src/main/java/toDo/CreateUserWindow.java b/src/main/java/toDo/CreateUserWindow.java
new file mode 100644
index 0000000..cb26920
--- /dev/null
+++ b/src/main/java/toDo/CreateUserWindow.java
@@ -0,0 +1,6 @@
+package toDo;
+
+//TODO create a usermanagement
+public class CreateUserWindow {
+
+}
diff --git a/src/main/java/toDo/User.java b/src/main/java/toDo/User.java
new file mode 100644
index 0000000..e2cae63
--- /dev/null
+++ b/src/main/java/toDo/User.java
@@ -0,0 +1,153 @@
+package toDo;
+
+import java.time.LocalDate;
+
+public class User {
+
+ private int p_user_id;
+ private String first_name;
+ private String sur_name;
+ private LocalDate birthday;
+ private String street;
+ private String house_number;
+ private String postal_code;
+ private String city;
+ private String loginname;
+ private String password;
+ private int salary_expectations;
+ private String marital_status;
+ private double final_grade;
+
+ public User(int p_user_id, String first_name, String sur_name, LocalDate birthday, String street,
+ String house_number, String postal_code, String city, String loginname, String password,
+ int salary_expectations, String marital_status, double final_grade) {
+ super();
+ this.p_user_id = p_user_id;
+ this.first_name = first_name;
+ this.sur_name = sur_name;
+ this.birthday = birthday;
+ this.street = street;
+ this.house_number = house_number;
+ this.postal_code = postal_code;
+ this.city = city;
+ this.loginname = loginname;
+ this.password = password;
+ this.salary_expectations = salary_expectations;
+ this.marital_status = marital_status;
+ this.final_grade = final_grade;
+ }
+
+ public User(int p_user_id, String login, String password) {
+ super();
+ this.p_user_id = p_user_id;
+ this.loginname = login;
+ this.password = password;
+ }
+
+ public User() {
+ }
+
+ public int getP_user_id() {
+ return p_user_id;
+ }
+
+ public void setP_user_id(int p_user_id) {
+ this.p_user_id = p_user_id;
+ }
+
+ public String getFirst_name() {
+ return first_name;
+ }
+
+ public void setFirst_name(String first_name) {
+ this.first_name = first_name;
+ }
+
+ public String getSur_name() {
+ return sur_name;
+ }
+
+ public void setSur_name(String sur_name) {
+ this.sur_name = sur_name;
+ }
+
+ public LocalDate getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(LocalDate birthday) {
+ this.birthday = birthday;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getHouse_number() {
+ return house_number;
+ }
+
+ public void setHouse_number(String house_number) {
+ this.house_number = house_number;
+ }
+
+ public String getPostal_code() {
+ return postal_code;
+ }
+
+ public void setPostal_code(String postal_code) {
+ this.postal_code = postal_code;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getLoginname() {
+ return loginname;
+ }
+
+ public void setLoginname(String loginname) {
+ this.loginname = loginname;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public double getFinal_grade() {
+ return final_grade;
+ }
+
+ public void setFinal_grade(double final_grade) {
+ this.final_grade = final_grade;
+ }
+
+ public String getMarital_status() {
+ return marital_status;
+ }
+
+ public void setMarital_status(String marital_status) {
+ this.marital_status = marital_status;
+ }
+
+ public int getSalary_expectations() {
+ return salary_expectations;
+ }
+
+ public void setSalary_expectations(int salary_expectations) {
+ this.salary_expectations = salary_expectations;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/toDo/UserController.java b/src/main/java/toDo/UserController.java
new file mode 100644
index 0000000..456872e
--- /dev/null
+++ b/src/main/java/toDo/UserController.java
@@ -0,0 +1,43 @@
+package toDo;
+
+import model.persistence.IUserPersistance;
+
+/**
+ * controller for users
+ * @author Clara Zufall
+ * TODO implement this class
+ */
+public class UserController {
+
+ private IUserPersistance userPersistance;
+
+ public UserController(IUserPersistance userPersistance) {
+ this.userPersistance = userPersistance;
+ }
+
+ public void createUser(User user) {
+
+ }
+
+ /**
+ * liest einen User aus der Persistenzschicht und gibt das Userobjekt zurück
+ * @param username eindeutige Loginname
+ * @param passwort das richtige Passwort
+ * @return Userobjekt, null wenn der User nicht existiert
+ */
+ public User readUser(String username, String passwort) {
+ return null;
+ }
+
+ public void changeUser(User user) {
+
+ }
+
+ public void deleteUser(User user) {
+
+ }
+
+ public boolean checkPassword(String username, String passwort) {
+ return false;
+ }
+}
diff --git a/src/main/java/toDo/UserDB.java b/src/main/java/toDo/UserDB.java
new file mode 100644
index 0000000..ed463cb
--- /dev/null
+++ b/src/main/java/toDo/UserDB.java
@@ -0,0 +1,56 @@
+package toDo;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import model.persistence.IUserPersistance;
+import model.persistenceDB.AccessDB;
+
+/**
+ * databaseconnection for userobjects, Story usermanagement
+ * @author Clara Zufall
+ * TODO finish this class
+ */
+public class UserDB implements IUserPersistance{
+
+ private AccessDB dbAccess;
+
+ public UserDB(AccessDB dbAccess) {
+ this.dbAccess = dbAccess;
+ }
+
+ /**
+ * read userdata by unique username
+ *
+ * @param username
+ * @return userobject, null if user didn't exists
+ */
+ public User readUser(String username) {
+ String sql = "SELECT * FROM users WHERE login_name = ? ;";
+ User user = null;
+ try (Connection con = DriverManager.getConnection(this.dbAccess.getFullURL(), this.dbAccess.getUser(),
+ this.dbAccess.getPassword()); PreparedStatement statement = con.prepareStatement(sql)) {
+
+ statement.setString(1, username);
+
+ ResultSet rs = statement.executeQuery();
+
+ while (rs.next()) {
+ user = new User(rs.getInt("P_user_id"), rs.getString("first_name"), rs.getString("sur_name"),
+ rs.getDate("birthday").toLocalDate(), rs.getString("street"), rs.getString("house_number"),
+ rs.getString("postal_code"), rs.getString("city"), rs.getString("login_name"),
+ rs.getString("password"), rs.getInt("salary_expectations"), rs.getString("marital_status"),
+ rs.getBigDecimal("final_grade").doubleValue());
+ }
+
+ } catch (SQLException ex) {
+ System.err.println(ex.getMessage());
+ }
+
+ return user;
+ }
+
+}
diff --git a/src/main/java/view/StartAlienDefence.java b/src/main/java/view/StartAlienDefence.java
new file mode 100644
index 0000000..a7f81d9
--- /dev/null
+++ b/src/main/java/view/StartAlienDefence.java
@@ -0,0 +1,18 @@
+package view;
+
+import controller.AlienDefenceController;
+import model.persistence.IPersistance;
+import model.persistenceDummy.PersistanceDummy;
+import view.menue.MainMenu;
+
+public class StartAlienDefence {
+
+ public static void main(String[] args) {
+
+ IPersistance alienDefenceModel = new PersistanceDummy();//TODO new PersistanceDB();
+ AlienDefenceController alienDefenceController = new AlienDefenceController(alienDefenceModel);
+ MainMenu mainMenu = new MainMenu(alienDefenceController);
+
+ mainMenu.setVisible(true);
+ }
+}
diff --git a/src/main/java/view/game/GameGUI.java b/src/main/java/view/game/GameGUI.java
new file mode 100644
index 0000000..c9412c2
--- /dev/null
+++ b/src/main/java/view/game/GameGUI.java
@@ -0,0 +1,93 @@
+package view.game;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.awt.Toolkit;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+
+import controller.GameController;
+
+/**
+ * GUI der Klasse _______
+ *
+ * @author Tenbusch
+ *
+ */
+public class GameGUI extends JFrame {
+
+ private static final long serialVersionUID = 1L;
+ private GameJPanel spielfeld;
+ private GameController gc;
+ public final long STARTTIME;
+ private final int WIDTH = 1280;
+ private final int HEIGHT = 960;
+
+ // Konstruktor
+ public GameGUI(GameController gc) {
+ super("Spiel v0.0 - FPS: ");
+
+ setCursor(Toolkit.getDefaultToolkit().createCustomCursor(new ImageIcon("pictures/crosshair.png").getImage(),
+ new Point(10, 10), "Cursor"));
+
+ // Fenstergestaltung
+ setSize(WIDTH, HEIGHT);
+ setLocation(10, 10);
+ setResizable(false);
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ // Controller registrieren
+ this.gc = gc;
+
+ setBackground(new Color(200, 200, 200));
+
+ gc.setHasWon(false);
+
+ spielfeld = new GameJPanel(gc);
+ getContentPane().add(spielfeld);
+ setVisible(true);
+
+ // Startzeit setzen
+ STARTTIME = System.currentTimeMillis();
+ }
+
+ public void start() {
+
+ long lastStep = System.currentTimeMillis() - 1;
+
+ // Spielfeld vorbereiten
+ gc.startLevel();
+
+ while (true) {
+
+ // FPS berechnen
+ long delta = System.currentTimeMillis() - lastStep;
+ lastStep = System.currentTimeMillis();
+ setTitle("Spiel v0.0 - FPS: " + (1000 / delta));
+
+ // Spiellogik
+ this.gc.doLogik(delta);
+
+ repaint();
+
+ try {
+ Thread.sleep(1);
+ } catch (Exception e) {
+
+ }
+
+ if (gc.isHasWon() || gc.timeleft() <= -1) {
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignored) {
+ }
+ dispose();
+ break;
+ }
+
+ }
+
+ }
+
+}
diff --git a/src/main/java/view/game/GameJPanel.java b/src/main/java/view/game/GameJPanel.java
new file mode 100644
index 0000000..0b593e7
--- /dev/null
+++ b/src/main/java/view/game/GameJPanel.java
@@ -0,0 +1,106 @@
+package view.game;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import controller.GameController;
+import model.Target;
+
+@SuppressWarnings("serial")
+public class GameJPanel extends JPanel {
+
+ // Attribute die zum Zeichnen aus dem Controller geholt werden müssen (konkrete
+ // Objekte erst in init() erzeugen)
+ private GameController gc;
+ private MouseClickListener mouseClickListener;
+ private List rechteckePainter;
+ private BufferedImage img, win, loose;
+ private JLabel lblTimeleft;
+
+ public GameJPanel(GameController gc) {
+ super(); // do the JPanel-stuff
+ this.gc = gc;
+ this.mouseClickListener = new MouseClickListener(gc);
+ this.addMouseListener(this.mouseClickListener);
+ this.lblTimeleft = new JLabel(gc.timeleft() + "s");
+ this.lblTimeleft.setHorizontalAlignment(SwingConstants.RIGHT);
+ this.lblTimeleft.setBounds(1000, 10, 200, 40);
+ this.lblTimeleft.setFont(new Font("Comic Sans Serif", Font.BOLD, 30));
+ init();
+
+ }
+
+ /**
+ * Spielfläche initialisieren
+ */
+ public void init() {
+ try {
+ this.img = ImageIO.read(new File("./pictures/" + this.gc.getCurrLevel().getBackgroundImage()));
+ this.win = ImageIO.read(new File("./pictures/YouWin.png"));
+ this.loose = ImageIO.read(new File("./pictures/YouLoose.png"));
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ LinkedList rechteckePainter = new LinkedList();
+ for (Target t : gc.getTargets()) {
+ rechteckePainter.add(new TargetPainter(t));
+ }
+ this.rechteckePainter = rechteckePainter;
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+
+ // Abfrage Gewinn oder
+ if (gc.timeleft() <= 0 || gc.isHasWon()) {
+
+ g.setColor(Color.GRAY);
+ if (gc.isHasWon()) {
+ g.drawImage(this.win, 300, 120, null);
+ } else {
+ g.drawImage(this.loose, 300, 120, null);
+ }
+ g.setFont(new Font("Arial", Font.PLAIN, 16));
+ // g.drawString(gc.getShotsFired() + " Schüsse mit " + gc.getAccuracy() + " %
+ // Treffergenauigkeit", 300, 850);
+
+ } else {
+
+ // Spielfeldhintergrund zeichnen
+ if (img != null) {
+ g.drawImage(this.img, 0, 0, null);
+ } else {
+ g.setColor(Color.GREEN);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ }
+
+ // System.out.println(gc.time());
+ // Targets zeichnen
+ for (TargetPainter rp : this.rechteckePainter) {
+ rp.paint(g, gc.time());
+ }
+
+ // Sekundenanzeige
+ if (gc.timeleft() <= 5)
+ g.setColor(Color.RED);
+ else
+ g.setColor(Color.WHITE);
+ g.setFont(new Font("Comic Sans Serif", Font.PLAIN, 30));
+ g.drawString(gc.timeleft() + "", 1210, 40);
+
+ }
+ }
+}
diff --git a/src/main/java/view/game/MouseClickListener.java b/src/main/java/view/game/MouseClickListener.java
new file mode 100644
index 0000000..a04e174
--- /dev/null
+++ b/src/main/java/view/game/MouseClickListener.java
@@ -0,0 +1,21 @@
+package view.game;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import controller.GameController;
+
+public class MouseClickListener extends MouseAdapter {
+
+ private GameController gc;
+
+ public MouseClickListener(GameController gc) {
+ this.gc = gc;
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ gc.fireShot(e.getX(), e.getY());
+ }
+
+}
diff --git a/src/main/java/view/game/TargetPainter.java b/src/main/java/view/game/TargetPainter.java
new file mode 100644
index 0000000..b2a66e1
--- /dev/null
+++ b/src/main/java/view/game/TargetPainter.java
@@ -0,0 +1,56 @@
+package view.game;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import model.Target;
+
+public class TargetPainter {
+
+ private Target target;
+ private BufferedImage image;
+ private BufferedImage imageDestroyed;
+
+ public TargetPainter(Target target) {
+ this.target = target;
+ try {
+ this.image = ImageIO.read(new File("./pictures/" + target.getImageAddress()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ try {
+ this.imageDestroyed = ImageIO.read(new File("./pictures/explosion.png"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void paint(Graphics g, long time) {
+
+ long targetStartTime = target.getTime();
+ long targetEndTime = target.getTime() + target.getDuration();
+
+ // Prüft, ob das Target erscheint.
+ if ((time < targetStartTime || time > targetEndTime))
+ return;
+
+ if (this.target.isHit() && time < targetEndTime) {
+
+ g.drawImage(this.imageDestroyed, this.target.getHitbox().getX(), this.target.getHitbox().getY(),
+ this.target.getHitbox().getWidth(), this.target.getHitbox().getHeight(), null);
+
+ return;
+
+ }
+
+ g.drawImage(this.image, this.target.getHitbox().getX(), this.target.getHitbox().getY(),
+ this.target.getHitbox().getWidth(), this.target.getHitbox().getHeight(), null);
+ }
+
+}
diff --git a/src/main/java/view/menue/Highscore.java b/src/main/java/view/menue/Highscore.java
new file mode 100644
index 0000000..f26fc08
--- /dev/null
+++ b/src/main/java/view/menue/Highscore.java
@@ -0,0 +1,80 @@
+package view.menue;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import controller.AttemptController;
+import model.Level;
+
+public class Highscore extends JFrame {
+
+ // Attribute
+ private AttemptController attemptController;
+ private Level level;
+
+ public Highscore(AttemptController attemptController, Level level) {
+ this(attemptController, level, 0);
+ }
+
+ // Konstruktor
+ public Highscore(AttemptController attemptController, Level level, int game_id) {
+ this.attemptController = attemptController;
+ this.level = level;
+
+ // Zweidimensioaler Vector, mit Inhalt der Tabelle wird geholt.
+ Vector> vecRow = attemptController.getAllAttemptsPerLevel(level, game_id);
+
+ int mark = attemptController.getPlayerPosition();
+
+ setLayout(new BorderLayout(5, 10));
+
+ // Spaltenüberschriften
+ Vector title = new Vector<>();
+ title.add("Rang");
+ title.add("Spieler");
+ title.add("Datum");
+ title.add("Uhrzeit");
+ title.add("Trefferwert");
+ title.add("Genauigkeitswert");
+ title.add("Reaktionswert");
+ title.add("Highscore-Wert");
+
+ // Tablle basierend auf zweidimensionalem Vector
+ JTable table = new JTable(vecRow, title);
+ if (mark >= 0)
+ table.setRowSelectionInterval(mark, mark);
+ setMinimumSize(new Dimension(650, 500));
+ getContentPane().add(new JScrollPane(table), BorderLayout.NORTH);
+ setTitle("Highscore-Liste"); // Titel
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ pack();
+ setVisible(true);
+
+ JButton btnZielndern = new JButton("Highscoreliste löschen");
+ btnZielndern.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnAendern_Clicked(arg0);
+ }
+ });
+
+ JPanel pnlSouth = new JPanel();
+ pnlSouth.add(btnZielndern);
+
+ // fügt Panel mit Button hinzu
+ add(pnlSouth, BorderLayout.SOUTH);
+ }
+
+ public void btnAendern_Clicked(ActionEvent evt) {
+ this.attemptController.deleteHighscore(level.getLevel_id());
+ dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/view/menue/LevelChooser.java b/src/main/java/view/menue/LevelChooser.java
new file mode 100644
index 0000000..3e1f6bd
--- /dev/null
+++ b/src/main/java/view/menue/LevelChooser.java
@@ -0,0 +1,113 @@
+package view.menue;
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.table.DefaultTableModel;
+
+import controller.LevelController;
+import model.Level;
+
+@SuppressWarnings("serial")
+public class LevelChooser extends JPanel {
+
+ private LevelController lvlControl;
+ private LeveldesignWindow leveldesignWindow;
+ private JTable tblLevels;
+ private DefaultTableModel jTableData;
+
+ /**
+ * Create the panel.
+ *
+ * @param leveldesignWindow
+ */
+ public LevelChooser(LevelController lvlControl, LeveldesignWindow leveldesignWindow) {
+ this.lvlControl = lvlControl;
+ this.leveldesignWindow = leveldesignWindow;
+
+ setLayout(new BorderLayout());
+
+ JPanel pnlButtons = new JPanel();
+ add(pnlButtons, BorderLayout.SOUTH);
+
+ JButton btnNewLevel = new JButton("Neues Level");
+ btnNewLevel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnNewLevel_Clicked();
+ }
+ });
+ pnlButtons.add(btnNewLevel);
+
+ JButton btnUpdateLevel = new JButton("ausgew\u00E4hltes Level bearbeiten");
+ btnUpdateLevel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ btnUpdateLevel_Clicked();
+ }
+ });
+ pnlButtons.add(btnUpdateLevel);
+
+ JButton btnDeleteLevel = new JButton("Level l\u00F6schen");
+ btnDeleteLevel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ btnDeleteLevel_Clicked();
+ }
+ });
+ pnlButtons.add(btnDeleteLevel);
+
+ JLabel lblLevelauswahl = new JLabel("Levelauswahl");
+ lblLevelauswahl.setFont(new Font("Arial", Font.BOLD, 18));
+ lblLevelauswahl.setHorizontalAlignment(SwingConstants.CENTER);
+ add(lblLevelauswahl, BorderLayout.NORTH);
+
+ JScrollPane spnLevels = new JScrollPane();
+ add(spnLevels, BorderLayout.CENTER);
+
+ tblLevels = new JTable();
+ tblLevels.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ spnLevels.setViewportView(tblLevels);
+
+ this.updateTableData();
+ }
+
+ private String[][] getLevelsAsTableModel() {
+ List levels = this.lvlControl.readAllLevels();
+ String[][] result = new String[levels.size()][];
+ int i = 0;
+ for (Level l : levels) {
+ result[i++] = l.getData();
+ }
+ return result;
+ }
+
+ public void updateTableData() {
+ this.jTableData = new DefaultTableModel(this.getLevelsAsTableModel(), Level.getLevelDescriptions());
+ this.tblLevels.setModel(jTableData);
+ }
+
+ public void btnNewLevel_Clicked() {
+ this.leveldesignWindow.startLevelEditor();
+ }
+
+ public void btnUpdateLevel_Clicked() {
+ int level_id = Integer
+ .parseInt((String) this.tblLevels.getModel().getValueAt(this.tblLevels.getSelectedRow(), 0));
+ this.leveldesignWindow.startLevelEditor(level_id);
+ }
+
+ public void btnDeleteLevel_Clicked() {
+ int level_id = Integer
+ .parseInt((String) this.tblLevels.getModel().getValueAt(this.tblLevels.getSelectedRow(), 0));
+ this.lvlControl.deleteLevel(level_id);
+ this.updateTableData();
+ }
+}
diff --git a/src/main/java/view/menue/LevelEditor.java b/src/main/java/view/menue/LevelEditor.java
new file mode 100644
index 0000000..5ef99a9
--- /dev/null
+++ b/src/main/java/view/menue/LevelEditor.java
@@ -0,0 +1,386 @@
+package view.menue;
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.SystemColor;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.DefaultTableModel;
+
+import controller.LevelController;
+import controller.TargetController;
+import model.Level;
+import model.Target;
+
+@SuppressWarnings("serial")
+public class LevelEditor extends JPanel {
+
+ private LevelController lvlControl;
+ private TargetController targetControl;
+ private LeveldesignWindow leveldesignWindow;
+ private Level lvl;
+ private JTable tblTargets;
+ private DefaultTableModel jTableData;
+ private JTextField tfdLevelname;
+ private JTextField tfdLevel_id;
+ private JTextField tfdLevelDuration;
+ private JTextField tfdTarget_id;
+ private JTextField tfdX;
+ private JTextField tfdY;
+ private JTextField tfdWidth;
+ private JTextField tfdHeight;
+ private JTextField tfdStarttime;
+ private JTextField tfdTargetDuration;
+ private JTextField tfdLevelBackground;
+ private JTextField tfdTargetImage;
+
+ /**
+ * Create the frame.
+ */
+ public LevelEditor(LeveldesignWindow leveldesignWindow, LevelController lvlControl, TargetController targetControl,
+ Level lvl) {
+ this.leveldesignWindow = leveldesignWindow;
+ this.lvlControl = lvlControl;
+ this.targetControl = targetControl;
+ this.lvl = lvl;
+
+ setBorder(new EmptyBorder(5, 5, 5, 5));
+ setLayout(new BorderLayout());
+
+ JLabel lblLeveleditor = new JLabel("Leveleditor");
+ lblLeveleditor.setHorizontalAlignment(SwingConstants.CENTER);
+ lblLeveleditor.setFont(new Font("Arial", Font.BOLD, 18));
+ add(lblLeveleditor, BorderLayout.NORTH);
+
+ JPanel pnlMain = new JPanel();
+ add(pnlMain, BorderLayout.CENTER);
+ pnlMain.setLayout(new GridLayout(0, 2, 20, 0));
+
+ tblTargets = new JTable();
+ tblTargets.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ tblTargets.getSelectionModel().addListSelectionListener(new RowListener());
+ jTableData = new DefaultTableModel(this.lvl.getTargetsAsTableModel(), Target.getTableDescriptions());
+ tblTargets.setModel(jTableData);
+
+ JScrollPane spnTargets = new JScrollPane(tblTargets);
+ pnlMain.add(spnTargets);
+
+ JPanel pnlInputs = new JPanel();
+ pnlMain.add(pnlInputs);
+ pnlInputs.setLayout(new BorderLayout(0, 0));
+
+ JPanel pnlInputMask = new JPanel();
+ pnlInputMask.setBackground(SystemColor.activeCaption);
+ pnlInputMask.setBorder(new EmptyBorder(10, 5, 10, 5));
+ pnlInputs.add(pnlInputMask, BorderLayout.NORTH);
+ pnlInputMask.setLayout(new GridLayout(0, 2, 0, 10));
+
+
+ JLabel lblLevelUeberschrift = new JLabel("Level");
+ lblLevelUeberschrift.setFont(new Font("Arial", Font.BOLD, 18));
+ pnlInputMask.add(lblLevelUeberschrift);
+
+ JLabel lblLevelUeberschrift2 = new JLabel("");
+ pnlInputMask.add(lblLevelUeberschrift2);
+
+ JLabel lblLevelid = new JLabel("Level ID");
+ pnlInputMask.add(lblLevelid);
+
+ tfdLevel_id = new JTextField(this.lvl.getLevel_id() + "");
+ tfdLevel_id.setEditable(false);
+ tfdLevel_id.setHorizontalAlignment(SwingConstants.RIGHT);
+ pnlInputMask.add(tfdLevel_id);
+ tfdLevel_id.setColumns(10);
+
+ JLabel lblLevelname = new JLabel("Name des Level");
+ pnlInputMask.add(lblLevelname);
+
+ tfdLevelname = new JTextField(this.lvl.getName());
+ tfdLevelname.setHorizontalAlignment(SwingConstants.RIGHT);
+ pnlInputMask.add(tfdLevelname);
+ tfdLevelname.setColumns(10);
+
+
+ JLabel lblLevelDuration = new JLabel("Spieldauer (Millisekunden)");
+ pnlInputMask.add(lblLevelDuration);
+
+ tfdLevelDuration = new JTextField(this.lvl.getDuration() + "");
+ tfdLevelDuration.setHorizontalAlignment(SwingConstants.RIGHT);
+ pnlInputMask.add(tfdLevelDuration);
+ tfdLevelDuration.setColumns(10);
+
+ JButton btnBack = new JButton("zurück zur Levelauswahl");
+ btnBack.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnBack_Clicked(arg0);
+ }
+ });
+
+
+ JLabel lblbackground = new JLabel("Hintergrundsbild");
+ pnlInputMask.add(lblbackground);
+
+ tfdLevelBackground = new JTextField();
+ tfdLevelBackground.setHorizontalAlignment(SwingConstants.RIGHT);
+ pnlInputMask.add(tfdLevelBackground);
+ tfdLevelBackground.setColumns(10);
+ pnlInputMask.add(btnBack);
+
+
+ JButton btnSaveLevelChanges = new JButton("\u00C4nderungen am Level speichern");
+ btnSaveLevelChanges.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnSaveLevelChanges_Clicked(arg0);
+ }
+ });
+ pnlInputMask.add(btnSaveLevelChanges);
+
+
+ JPanel pnlInputMaskTargets = new JPanel();
+ pnlInputMaskTargets.setBorder(new EmptyBorder(10, 5, 10, 5));
+ pnlInputMaskTargets.setBackground(SystemColor.inactiveCaption);
+ pnlInputs.add(pnlInputMaskTargets, BorderLayout.CENTER);
+ pnlInputMaskTargets.setLayout(new GridLayout(0, 2, 0, 10));
+
+
+ JLabel lblUeberschrift = new JLabel("Targets");
+ lblUeberschrift.setFont(new Font("Arial", Font.BOLD, 18));
+ pnlInputMaskTargets.add(lblUeberschrift);
+
+ JLabel lbllblUeberschrift2 = new JLabel("");
+ pnlInputMaskTargets.add(lbllblUeberschrift2);
+
+
+ JLabel lblTargetid = new JLabel("Target ID");
+ pnlInputMaskTargets.add(lblTargetid);
+
+ tfdTarget_id = new JTextField();
+ pnlInputMaskTargets.add(tfdTarget_id);
+ tfdTarget_id.setColumns(10);
+
+ tfdTarget_id.setEditable(false);
+
+
+ JLabel lblZiel = new JLabel("Ziel:");
+ pnlInputMaskTargets.add(lblZiel);
+
+ JLabel lblZiel2 = new JLabel("");
+ pnlInputMaskTargets.add(lblZiel2);
+
+
+ JLabel lblTargetpicture = new JLabel("Bilddatei des Ziels");
+ lblTargetpicture.setHorizontalAlignment(SwingConstants.LEFT);
+ pnlInputMaskTargets.add(lblTargetpicture);
+
+ tfdTargetImage = new JTextField();
+ tfdTargetImage.setHorizontalAlignment(SwingConstants.LEFT);
+ pnlInputMaskTargets.add(tfdTargetImage);
+ tfdTargetImage.setColumns(10);
+
+
+ JLabel lblBreite = new JLabel("Breite des Ziels");
+ pnlInputMaskTargets.add(lblBreite);
+
+ tfdWidth = new JTextField();
+ pnlInputMaskTargets.add(tfdWidth);
+ tfdWidth.setColumns(10);
+
+
+ JLabel lblHhe = new JLabel("Höhe des Ziels");
+ pnlInputMaskTargets.add(lblHhe);
+
+ tfdHeight = new JTextField();
+ pnlInputMaskTargets.add(tfdHeight);
+ tfdHeight.setColumns(10);
+
+
+ JLabel lblX = new JLabel("X Position des Ziels (max. 1280 - Breite) ");
+ pnlInputMaskTargets.add(lblX);
+
+ tfdX = new JTextField();
+ pnlInputMaskTargets.add(tfdX);
+ tfdX.setColumns(10);
+
+
+ JLabel lblY = new JLabel("Y Position des Ziels (max. 960 - Höhe)");
+ pnlInputMaskTargets.add(lblY);
+
+ tfdY = new JTextField();
+ pnlInputMaskTargets.add(tfdY);
+ tfdY.setColumns(10);
+
+
+ JLabel lblZeiten = new JLabel("Zeiten: ");
+ pnlInputMaskTargets.add(lblZeiten);
+
+ JLabel lblZeiten2 = new JLabel(" ");
+ pnlInputMaskTargets.add(lblZeiten2);
+
+
+ JLabel lblStartzeit = new JLabel("Startzeit in nach Spielstart (Millisekunden)");
+ pnlInputMaskTargets.add(lblStartzeit);
+
+ tfdStarttime = new JTextField();
+ pnlInputMaskTargets.add(tfdStarttime);
+ tfdStarttime.setColumns(10);
+
+
+ JLabel lblAnzeigedauer = new JLabel("Anzeigedauer (Millisekunden)");
+ pnlInputMaskTargets.add(lblAnzeigedauer);
+
+ tfdTargetDuration = new JTextField();
+ pnlInputMaskTargets.add(tfdTargetDuration);
+ tfdTargetDuration.setColumns(10);
+
+
+ JPanel panel_2 = new JPanel();
+ pnlInputs.add(panel_2, BorderLayout.SOUTH);
+
+ JButton btnNeuesZiel = new JButton("Neues Ziel");
+ btnNeuesZiel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnErstellen_Clicked(arg0);
+ }
+ });
+ panel_2.add(btnNeuesZiel);
+
+ JButton btnZielndern = new JButton("Ziel \u00E4ndern");
+ btnZielndern.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnAendern_Clicked(arg0);
+ }
+ });
+ panel_2.add(btnZielndern);
+
+ JButton btnDeleteTarget = new JButton("Ziel l\u00F6schen");
+ btnDeleteTarget.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ btnLoeschen_Clicked(arg0);
+ }
+ });
+ panel_2.add(btnDeleteTarget);
+
+ }
+
+ public Level getLvl() {
+ return lvl;
+ }
+
+ public void setLvl(Level lvl) {
+ this.lvl = lvl;
+ updateTableData();
+ this.tfdLevel_id.setText("" + lvl.getLevel_id());
+ this.tfdLevelname.setText(lvl.getName());
+ this.tfdLevelDuration.setText("" + lvl.getDuration());
+ this.tfdLevelBackground.setText(lvl.getBackgroundImage());
+ }
+
+ public void updateTableData() {
+ jTableData = new DefaultTableModel(this.lvl.getTargetsAsTableModel(), Target.getTableDescriptions());
+ tblTargets.setModel(jTableData);
+ }
+
+ public void targetAnzeigen_JTable(int row) {
+ this.tfdTarget_id.setText((String) tblTargets.getValueAt(row, 0));
+ this.tfdX.setText((String) tblTargets.getValueAt(row, 1));
+ this.tfdY.setText((String) tblTargets.getValueAt(row, 2));
+ this.tfdWidth.setText((String) tblTargets.getValueAt(row, 3));
+ this.tfdHeight.setText((String) tblTargets.getValueAt(row, 4));
+ this.tfdTargetImage.setText((String) tblTargets.getValueAt(row, 5));
+ this.tfdStarttime.setText((String) tblTargets.getValueAt(row, 6));
+ this.tfdTargetDuration.setText((String) tblTargets.getValueAt(row, 7));
+ }
+
+ public void targetAnzeigen_JTable(Target target) {
+ this.tfdTarget_id.setText(target.getTarget_id() + "");
+ this.tfdX.setText(target.getHitbox().getX() + "");
+ this.tfdY.setText(target.getHitbox().getY() + "");
+ this.tfdWidth.setText(target.getHitbox().getWidth() + "");
+ this.tfdHeight.setText(target.getHitbox().getHeight() + "");
+ this.tfdTargetImage.setText(target.getImageAddress());
+ this.tfdStarttime.setText(target.getTime() + "");
+ this.tfdTargetDuration.setText(target.getDuration() + "");
+ }
+
+ public Target targetAuslesen() {
+ Target currentTarget = null;
+ for (Target t : this.lvl.getTargets()) {
+ if (t.getTarget_id() == Integer.parseInt(tfdTarget_id.getText())) {
+ currentTarget = t;
+ }
+ }
+ if (currentTarget != null) {
+
+ currentTarget.getHitbox().setX(Integer.parseInt(tfdX.getText()));
+ currentTarget.getHitbox().setY(Integer.parseInt(tfdY.getText()));
+ currentTarget.getHitbox().setWidth(Integer.parseInt(tfdWidth.getText()));
+ currentTarget.getHitbox().setHeight(Integer.parseInt(tfdHeight.getText()));
+
+ currentTarget.setDuration(Long.parseLong(tfdTargetDuration.getText()));
+ currentTarget.setTime(Long.parseLong(tfdStarttime.getText()));
+ currentTarget.setImageAddress(tfdTargetImage.getText());
+ }
+ return currentTarget;
+ }
+
+ public void btnErstellen_Clicked(ActionEvent evt) {
+ Target target = this.targetControl.createTarget(this.lvl);
+ if (target != null)
+ targetAnzeigen_JTable(target);
+ updateTableData();
+ }
+
+ public void btnLoeschen_Clicked(ActionEvent evt) {
+ int target_id = Integer.parseInt(this.tfdTarget_id.getText());
+ this.targetControl.deleteTarget(this.lvl, target_id);
+ updateTableData();
+ // TODO clear Textfield-Data
+ }
+
+ public void btnAendern_Clicked(ActionEvent evt) {
+ this.targetControl.updateTarget(this.lvl, this.targetAuslesen());
+ updateTableData();
+ }
+
+ /**
+ * Zurück zur Levelauswahl
+ *
+ * @param evt
+ */
+ public void btnBack_Clicked(ActionEvent evt) {
+ this.leveldesignWindow.showLevelChooser();
+ }
+
+ public void btnSaveLevelChanges_Clicked(ActionEvent evt) {
+ this.lvl.setName(this.tfdLevelname.getText());
+ this.lvl.setBackgroundImage(this.tfdLevelBackground.getText());
+ this.lvl.setDuration(Integer.parseInt(this.tfdLevelDuration.getText()));
+
+ this.lvlControl.updateLevel(this.lvl);
+ }
+
+ private class RowListener implements ListSelectionListener {
+ public void valueChanged(ListSelectionEvent event) {
+ if (event.getValueIsAdjusting()) {
+ return;
+ }
+ if (tblTargets.getSelectedRow() < 0)
+ tblTargets.clearSelection();
+ else
+ targetAnzeigen_JTable(tblTargets.getSelectedRow());
+ }
+ }
+}
diff --git a/src/main/java/view/menue/LeveldesignWindow.java b/src/main/java/view/menue/LeveldesignWindow.java
new file mode 100644
index 0000000..cffc086
--- /dev/null
+++ b/src/main/java/view/menue/LeveldesignWindow.java
@@ -0,0 +1,74 @@
+package view.menue;
+
+import java.awt.CardLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.border.EmptyBorder;
+
+import controller.LevelController;
+import controller.TargetController;
+import model.Level;
+
+@SuppressWarnings("serial")
+public class LeveldesignWindow extends JFrame {
+
+ private LevelController lvlControl;
+ private JPanel contentPane;
+ private LevelChooser cardChooseLevel;
+ private LevelEditor cardLevelEditor;
+
+ private CardLayout cards;
+
+ /**
+ * Create the frame.
+ */
+ public LeveldesignWindow(LevelController lvlControl, TargetController targetControl) {
+ this.lvlControl = lvlControl;
+
+ setTitle("Leveldesigner");
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ setBounds(100, 100, 1200, 800);
+ contentPane = new JPanel();
+ contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
+ setContentPane(contentPane);
+ this.cards = new CardLayout();
+ contentPane.setLayout(cards);
+
+ this.cardChooseLevel = new LevelChooser(lvlControl, this);
+ contentPane.add(cardChooseLevel, "levelChooser");
+
+ this.cardLevelEditor = new LevelEditor(this, lvlControl, targetControl, Level.getDefaultLevel());
+ contentPane.add(cardLevelEditor, "levelEditor");
+
+ this.showLevelChooser();
+ this.setVisible(true);
+ }
+
+ /**
+ * display leveleditor with a new level
+ */
+ public void startLevelEditor() {
+ this.cardLevelEditor.setLvl(this.lvlControl.createLevel());
+ this.cards.show(contentPane, "levelEditor");
+ }
+
+ /**
+ * disply leveleditor with a new level
+ *
+ * @param level_id
+ */
+ public void startLevelEditor(int level_id) {
+ this.cardLevelEditor.setLvl(this.lvlControl.readLevel(level_id));
+ this.cards.show(contentPane, "levelEditor");
+ }
+
+ /**
+ * display a jTable with all Levels
+ */
+ public void showLevelChooser() {
+ this.cards.show(contentPane, "levelChooser");
+ this.cardChooseLevel.updateTableData();
+ }
+
+}
diff --git a/src/main/java/view/menue/MainMenu.java b/src/main/java/view/menue/MainMenu.java
new file mode 100644
index 0000000..e660b85
--- /dev/null
+++ b/src/main/java/view/menue/MainMenu.java
@@ -0,0 +1,237 @@
+package view.menue;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import controller.AlienDefenceController;
+import controller.GameController;
+import model.Level;
+import model.persistenceDB.PersistanceDB;
+import toDo.User;
+import view.game.GameGUI;
+
+@SuppressWarnings("serial")
+public class MainMenu extends JFrame {
+
+ private AlienDefenceController alienDefenceController;
+ private JTextField loginTextField;
+ private JPasswordField passwordTextField;
+ private int selectedLevel = 0;
+
+ private String[] getLevelNames(List arrLevel) {
+ String[] arrLevelNames = new String[arrLevel.size()];
+
+ for (int i = 0; i < arrLevel.size(); i++) {
+ arrLevelNames[i] = arrLevel.get(i).getName(); // Array aus Arraylist erstellt
+ }
+
+ return arrLevelNames;
+ }
+
+ // Konstruktor
+ public MainMenu(AlienDefenceController alienDefenceController) {
+
+ this.alienDefenceController = alienDefenceController;
+
+ // Frame Formatierungen
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setBounds(100, 100, 450, 300);
+ JPanel contentPane = new JPanel();
+ contentPane.setBackground(new Color(0, 0, 0));
+ contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
+ setContentPane(contentPane);
+ contentPane.setLayout(new GridBagLayout()); // GridBagLayout
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+ // JLable mit üBerschrift
+ JLabel lblheadline = new JLabel(" ALIEN DEFENCE");
+ lblheadline.setForeground(new Color(124, 252, 0));
+ lblheadline.setFont(new Font("Yu Gothic UI", Font.BOLD, 20));
+ c.gridx = 0;
+ c.gridy = 0;
+ contentPane.add(lblheadline, c);
+
+ // JPanel mit Logo
+ JPanel p = new JPanel() {
+ private static final long serialVersionUID = 1L;
+
+ private ImageIcon imageIcon = new ImageIcon("./pictures/logo.png");
+ private Image image = imageIcon.getImage();
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ if (image != null) {
+ g.drawImage(image, 5, 8, 145, 145, this);
+ }
+ }
+ };
+ c.ipady = 150; // make this component tall
+ c.ipadx = 120;
+ c.weightx = 0.0;
+ c.gridwidth = 15;
+ c.gridx = 0;
+ c.gridy = 1;
+ contentPane.add(p, c);
+
+ // Text Login
+ JLabel loginText = new JLabel("Login: "); // Einfacher Text
+ loginText.setForeground(Color.orange);
+ c.ipady = 0;
+ c.ipadx = 0;
+ c.gridwidth = 0;
+ c.gridx = 0;
+ c.gridy = 2;
+ contentPane.add(loginText, c);
+
+ // Textfeld
+ loginTextField = new JTextField(15);
+ c.gridy = 3;
+ contentPane.add(loginTextField, c);
+
+ // Text Passwort
+ JLabel passwordText = new JLabel("Passwort: "); // Einfacher Text
+ passwordText.setForeground(Color.orange);
+ c.gridy = 4;
+ contentPane.add(passwordText, c);
+
+ // Textfeld
+ passwordTextField = new JPasswordField(15);
+ c.gridy = 5;
+ contentPane.add(passwordTextField, c);
+
+ // Text Level
+ JLabel levelText = new JLabel("Level: "); // Einfacher Text
+ levelText.setForeground(Color.orange);
+ c.gridy = 6;
+ contentPane.add(levelText, c);
+
+ // Levelliste für die ComboBox abrufen
+ List arrLevel = this.alienDefenceController.getLevelController().readAllLevels();
+ String[] arrLevelNames = getLevelNames(arrLevel);
+
+ // Level Auswahlbox - ActionListener
+ JComboBox combo = new JComboBox(arrLevelNames);
+ c.gridy = 7;
+ contentPane.add(combo, c);
+ ActionListener actLisCombo = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ selectedLevel = combo.getSelectedIndex();
+ }
+ };
+ combo.addActionListener(actLisCombo); // Listener
+
+ // Button Spielen - ActionListener
+ JButton btnNewButton = new JButton("Spielen");
+ btnNewButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+
+ // User aus Datenbank holen
+ User user = alienDefenceController.getAlienDefenceModel().getUserPersistance().readUser(loginTextField.getText());
+
+ // Spielstarten, wenn Nutzer existiert und Passwort übereinstimmt
+ if (user != null && user.getPassword().equals(new String(passwordTextField.getPassword()))) {
+
+ Thread t = new Thread("GameThread") {
+ @Override
+ public void run() {
+
+ GameController gameController = alienDefenceController.startGame(arrLevel.get(selectedLevel), user);
+ new GameGUI(gameController).start();
+ }
+ };
+ t.start();
+ } else {
+ // Fehlermeldung - Zugangsdaten fehlerhaft
+ JOptionPane.showMessageDialog(null, "Zugangsdaten nicht korrekt", "Fehler",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ });
+ c.gridy = 8;
+ contentPane.add(btnNewButton, c);
+
+ // Button Testen - ActionListener
+ JButton btnTestButton = new JButton("Testen");
+ btnTestButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+
+ // Erstellt Modell von aktuellen Nutzer
+ User user = new User(1, "test", "pass");
+
+ Thread t = new Thread("GameThread") {
+
+ @Override
+ public void run() {
+
+ List arrLevel = alienDefenceController.getLevelController().readAllLevels();
+
+ GameController gameController = alienDefenceController.startGame(arrLevel.get(selectedLevel), user);
+ new GameGUI(gameController).start();
+ }
+ };
+ t.start();
+ }
+ });
+ c.gridy = 9;
+ contentPane.add(btnTestButton, c);
+
+ // Button Highscore
+ JButton btnNewButton_2 = new JButton("Highscore");
+
+ btnNewButton_2.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ new Highscore(alienDefenceController.getAttemptController(), arrLevel.get(selectedLevel));
+ }
+ });
+ // selectedLevel
+
+ c.gridy = 10;
+ contentPane.add(btnNewButton_2, c);
+
+ // Button Leveleditor
+ JButton btnNewButton_1 = new JButton("Leveleditor");
+ btnNewButton_1.setBackground(Color.ORANGE);
+ btnNewButton_1.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ new LeveldesignWindow(alienDefenceController.getLevelController(), alienDefenceController.getTargetController());
+ }
+ });
+ c.gridy = 11;
+ contentPane.add(btnNewButton_1, c);
+
+ // Button Beenden
+ JButton btnNewButton_3 = new JButton("Beenden");
+ btnNewButton_3.setBackground(Color.GRAY);
+ btnNewButton_3.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ });
+ c.gridy = 12;
+ c.anchor = GridBagConstraints.PAGE_END;
+ contentPane.add(btnNewButton_3, c);
+ this.pack();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/pictures/Bildquellen.txt b/src/main/resources/pictures/Bildquellen.txt
new file mode 100644
index 0000000..9852a34
--- /dev/null
+++ b/src/main/resources/pictures/Bildquellen.txt
@@ -0,0 +1,18 @@
+ufo_1.png: https://pixabay.com/de/illustrations/raumschiff-ufo-weltraum-weltall-3435510/
+ufo_2.png: https://pixabay.com/de/illustrations/ufo-raumschiff-astronaut-2718084/
+ufo_3.png: https://pixabay.com/de/illustrations/ufo-au%C3%9Ferirdischer-raum-raumschiff-3157681/
+ufo_4.png: https://pixabay.com/de/illustrations/ufo-au%C3%9Ferirdischer-raumschiff-raum-4199301/
+ufo_5.png: https://pixabay.com/de/illustrations/ufo-au%C3%9Ferirdisch-science-fiction-5113558/
+logo.png: https://pixabay.com/de/vectors/schild-verbot-verbotsschild-1283415/
+background_1.png: https://pixabay.com/de/photos/tianjin-d%C3%A4mmerung-stadt-landschaft-2185510/
+background_2.png: https://pixabay.com/de/photos/fluss-h%C3%BCgel-abend-california-1590010/
+background_3.png: https://pixabay.com/de/photos/im-freien-new-york-skyline-nyc-5129182/
+background_4.png: https://pixabay.com/de/illustrations/au%C3%9Ferirdischer-landschaft-planeten-4849881/
+background_5.png: https://pixabay.com/de/photos/milchstra%C3%9Fe-sterne-nacht-himmel-923738/
+background_6.png: https://pixabay.com/de/photos/schwarz-und-wei%C3%9F-dom-architektur-5089030/
+background_7.png: https://pixabay.com/de/illustrations/industrie-dystopie-ende-der-welt-5078196/
+background_8.png: https://pixabay.com/de/photos/italien-landschaft-landschaftlich-1758193/
+background_9.png: https://pixabay.com/de/photos/landschaft-herbst-nebel-dorf-615429/
+background_10.png: https://pixabay.com/de/illustrations/ufo-raumschiff-science-fiction-1942755/
+explosion.png: https://pixabay.com/de/vectors/explosion-detonation-hochkonjunktur-417894/
+
diff --git a/src/main/resources/pictures/YouLoose.png b/src/main/resources/pictures/YouLoose.png
new file mode 100644
index 0000000..567471b
Binary files /dev/null and b/src/main/resources/pictures/YouLoose.png differ
diff --git a/src/main/resources/pictures/YouWin.png b/src/main/resources/pictures/YouWin.png
new file mode 100644
index 0000000..14f560e
Binary files /dev/null and b/src/main/resources/pictures/YouWin.png differ
diff --git a/src/main/resources/pictures/background_1.jpg b/src/main/resources/pictures/background_1.jpg
new file mode 100644
index 0000000..3d55e46
Binary files /dev/null and b/src/main/resources/pictures/background_1.jpg differ
diff --git a/src/main/resources/pictures/background_10.jpg b/src/main/resources/pictures/background_10.jpg
new file mode 100644
index 0000000..dbd682b
Binary files /dev/null and b/src/main/resources/pictures/background_10.jpg differ
diff --git a/src/main/resources/pictures/background_2.jpg b/src/main/resources/pictures/background_2.jpg
new file mode 100644
index 0000000..f5fa7c7
Binary files /dev/null and b/src/main/resources/pictures/background_2.jpg differ
diff --git a/src/main/resources/pictures/background_3.jpg b/src/main/resources/pictures/background_3.jpg
new file mode 100644
index 0000000..a5dc5ad
Binary files /dev/null and b/src/main/resources/pictures/background_3.jpg differ
diff --git a/src/main/resources/pictures/background_4.jpg b/src/main/resources/pictures/background_4.jpg
new file mode 100644
index 0000000..f6261ea
Binary files /dev/null and b/src/main/resources/pictures/background_4.jpg differ
diff --git a/src/main/resources/pictures/background_5.jpg b/src/main/resources/pictures/background_5.jpg
new file mode 100644
index 0000000..c4338bf
Binary files /dev/null and b/src/main/resources/pictures/background_5.jpg differ
diff --git a/src/main/resources/pictures/background_6.jpg b/src/main/resources/pictures/background_6.jpg
new file mode 100644
index 0000000..0db1f20
Binary files /dev/null and b/src/main/resources/pictures/background_6.jpg differ
diff --git a/src/main/resources/pictures/background_7.jpg b/src/main/resources/pictures/background_7.jpg
new file mode 100644
index 0000000..ef26a52
Binary files /dev/null and b/src/main/resources/pictures/background_7.jpg differ
diff --git a/src/main/resources/pictures/background_8.jpg b/src/main/resources/pictures/background_8.jpg
new file mode 100644
index 0000000..21c5686
Binary files /dev/null and b/src/main/resources/pictures/background_8.jpg differ
diff --git a/src/main/resources/pictures/background_9.jpg b/src/main/resources/pictures/background_9.jpg
new file mode 100644
index 0000000..973ca68
Binary files /dev/null and b/src/main/resources/pictures/background_9.jpg differ
diff --git a/src/main/resources/pictures/ballon Bildquelle.txt b/src/main/resources/pictures/ballon Bildquelle.txt
new file mode 100644
index 0000000..ec913f5
--- /dev/null
+++ b/src/main/resources/pictures/ballon Bildquelle.txt
@@ -0,0 +1 @@
+Bild von Aimee Cozza auf Pixabay
\ No newline at end of file
diff --git a/src/main/resources/pictures/ballon.png b/src/main/resources/pictures/ballon.png
new file mode 100644
index 0000000..42e510a
Binary files /dev/null and b/src/main/resources/pictures/ballon.png differ
diff --git a/src/main/resources/pictures/crosshair.png b/src/main/resources/pictures/crosshair.png
new file mode 100644
index 0000000..9156d28
Binary files /dev/null and b/src/main/resources/pictures/crosshair.png differ
diff --git a/src/main/resources/pictures/explosion.png b/src/main/resources/pictures/explosion.png
new file mode 100644
index 0000000..6191527
Binary files /dev/null and b/src/main/resources/pictures/explosion.png differ
diff --git a/src/main/resources/pictures/italy Bildquelle.txt b/src/main/resources/pictures/italy Bildquelle.txt
new file mode 100644
index 0000000..1a57692
--- /dev/null
+++ b/src/main/resources/pictures/italy Bildquelle.txt
@@ -0,0 +1 @@
+Bild von David Mark auf Pixabay
\ No newline at end of file
diff --git a/src/main/resources/pictures/lemon.jpg b/src/main/resources/pictures/lemon.jpg
new file mode 100644
index 0000000..8819850
Binary files /dev/null and b/src/main/resources/pictures/lemon.jpg differ
diff --git a/src/main/resources/pictures/logo.png b/src/main/resources/pictures/logo.png
new file mode 100644
index 0000000..496f250
Binary files /dev/null and b/src/main/resources/pictures/logo.png differ
diff --git a/src/main/resources/pictures/ufo_1.png b/src/main/resources/pictures/ufo_1.png
new file mode 100644
index 0000000..d42e8e5
Binary files /dev/null and b/src/main/resources/pictures/ufo_1.png differ
diff --git a/src/main/resources/pictures/ufo_2.png b/src/main/resources/pictures/ufo_2.png
new file mode 100644
index 0000000..5f0219f
Binary files /dev/null and b/src/main/resources/pictures/ufo_2.png differ
diff --git a/src/main/resources/pictures/ufo_3.png b/src/main/resources/pictures/ufo_3.png
new file mode 100644
index 0000000..ec47f49
Binary files /dev/null and b/src/main/resources/pictures/ufo_3.png differ
diff --git a/src/main/resources/pictures/ufo_4.png b/src/main/resources/pictures/ufo_4.png
new file mode 100644
index 0000000..eb25ab2
Binary files /dev/null and b/src/main/resources/pictures/ufo_4.png differ
diff --git a/src/main/resources/pictures/ufo_5.png b/src/main/resources/pictures/ufo_5.png
new file mode 100644
index 0000000..d8308db
Binary files /dev/null and b/src/main/resources/pictures/ufo_5.png differ