lauraF
3 years ago
128 changed files with 4873 additions and 0 deletions
-
10.classpath
-
17.project
-
15.settings/org.eclipse.jdt.core.prefs
-
0Textdokument.txt
-
BINaudio/laser.wav
-
BINaudio/shot.wav
-
BINaudio/smash.wav
-
BINbin/base/GameLoop.class
-
BINbin/base/MultiLevelGame.class
-
BINbin/collider/CircleCollider.class
-
BINbin/collider/Collider.class
-
BINbin/collider/RectCollider.class
-
BINbin/controller/CollisionAwareEgoController.class
-
BINbin/controller/EgoController.class
-
BINbin/controller/EnemyController.class
-
BINbin/controller/FallingStarController.class
-
BINbin/controller/LimitedTimeController.class
-
BINbin/controller/MineController.class
-
BINbin/controller/ObjectController.class
-
BINbin/controller/SimpleShotController.class
-
BINbin/controller/ZickZackController.class
-
BINbin/controller/package-info.class
-
BINbin/gameobjects/AnimatedGameobject.class
-
BINbin/gameobjects/EgoObject.class
-
BINbin/gameobjects/FallingStar.class
-
BINbin/gameobjects/GameObject.class
-
BINbin/gameobjects/RectObject.class
-
BINbin/gameobjects/TextObject.class
-
30bin/log4j2.xml
-
BINbin/playground/Animation.class
-
BINbin/playground/HighscoreManager.class
-
BINbin/playground/Level1.class
-
BINbin/playground/Level2.class
-
BINbin/playground/Level3.class
-
BINbin/playground/Level4.class
-
BINbin/playground/LevelBoss.class
-
BINbin/playground/LevelHitTwice.class
-
BINbin/playground/Music$1.class
-
BINbin/playground/Music.class
-
BINbin/playground/Playground.class
-
BINbin/playground/SaveGame.class
-
BINbin/playground/SpaceInvadersLevel.class
-
BINbin/playground/SpaceInvadersLevelTest.class
-
BINbin/rendering/AnimationArtist.class
-
BINbin/rendering/Artist.class
-
BINbin/rendering/CircleArtist.class
-
BINbin/rendering/RectArtist.class
-
BINbin/rendering/TextArtist.class
-
BINbin/ui/AboutFrame$1.class
-
BINbin/ui/AboutFrame.class
-
BINbin/ui/GamePanel.class
-
BINbin/ui/GameUI.class
-
1highscore.txt
-
202lib/apache-log4j-2.13.3-bin/LICENSE.txt
-
17lib/apache-log4j-2.13.3-bin/NOTICE.txt
-
60lib/apache-log4j-2.13.3-bin/RELEASE-NOTES.md
-
BINlib/apache-log4j-2.13.3-bin/log4j-1.2-api-2.13.3.jar
-
BINlib/apache-log4j-2.13.3-bin/log4j-api-2.13.3.jar
-
BINlib/apache-log4j-2.13.3-bin/log4j-core-2.13.3.jar
-
185log/log4j.log
-
231src/base/GameLoop.java
-
30src/base/MultiLevelGame.java
-
88src/collider/CircleCollider.java
-
127src/collider/Collider.java
-
127src/collider/RectCollider.java
-
84src/controller/CollisionAwareEgoController.java
-
216src/controller/EgoController.java
-
36src/controller/EnemyController.java
-
24src/controller/FallingStarController.java
-
36src/controller/LimitedTimeController.java
-
47src/controller/MineController.java
-
110src/controller/ObjectController.java
-
16src/controller/SimpleShotController.java
-
32src/controller/ZickZackController.java
-
11src/controller/package-info.java
-
42src/gameobjects/AnimatedGameobject.java
-
34src/gameobjects/EgoObject.java
-
28src/gameobjects/FallingStar.java
-
377src/gameobjects/GameObject.java
-
76src/gameobjects/RectObject.java
-
70src/gameobjects/TextObject.java
-
30src/log4j2.xml
-
84src/playground/Animation.java
-
55src/playground/HighscoreManager.java
-
15src/playground/Level1.java
-
17src/playground/Level2.java
-
40src/playground/Level3.java
-
63src/playground/Level4.java
-
112src/playground/LevelBoss.java
-
65src/playground/LevelHitTwice.java
-
48src/playground/Music.java
-
374src/playground/Playground.java
-
62src/playground/SaveGame.java
-
678src/playground/SpaceInvadersLevel.java
-
81src/playground/SpaceInvadersLevelTest.java
-
93src/rendering/AnimationArtist.java
-
40src/rendering/Artist.java
-
34src/rendering/CircleArtist.java
-
33src/rendering/RectArtist.java
-
81src/rendering/TextArtist.java
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<classpath> |
|||
<classpathentry kind="src" path="src"/> |
|||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
|||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/> |
|||
<classpathentry kind="lib" path="lib/apache-log4j-2.13.3-bin/log4j-1.2-api-2.13.3.jar"/> |
|||
<classpathentry kind="lib" path="lib/apache-log4j-2.13.3-bin/log4j-api-2.13.3.jar"/> |
|||
<classpathentry kind="lib" path="lib/apache-log4j-2.13.3-bin/log4j-core-2.13.3.jar"/> |
|||
<classpathentry kind="output" path="bin"/> |
|||
</classpath> |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<projectDescription> |
|||
<name>GameProject</name> |
|||
<comment></comment> |
|||
<projects> |
|||
</projects> |
|||
<buildSpec> |
|||
<buildCommand> |
|||
<name>org.eclipse.jdt.core.javabuilder</name> |
|||
<arguments> |
|||
</arguments> |
|||
</buildCommand> |
|||
</buildSpec> |
|||
<natures> |
|||
<nature>org.eclipse.jdt.core.javanature</nature> |
|||
</natures> |
|||
</projectDescription> |
@ -0,0 +1,15 @@ |
|||
eclipse.preferences.version=1 |
|||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
|||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate |
|||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=12 |
|||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
|||
org.eclipse.jdt.core.compiler.compliance=12 |
|||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
|||
org.eclipse.jdt.core.compiler.debug.localVariable=generate |
|||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
|||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
|||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled |
|||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
|||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning |
|||
org.eclipse.jdt.core.compiler.release=enabled |
|||
org.eclipse.jdt.core.compiler.source=12 |
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<configuration status="OFF"> |
|||
<appenders> |
|||
|
|||
<Console name="Console" target="SYSTEM_OUT"> |
|||
<PatternLayout pattern="%d %-5level %logger{36} - %msg%n" /> |
|||
</Console> |
|||
|
|||
<File name="File" fileName="log\log4j.log"> |
|||
<PatternLayout pattern="%d %-5level %logger{36} - %msg%n" /> |
|||
</File> |
|||
|
|||
</appenders> |
|||
|
|||
<loggers> |
|||
|
|||
<root level="warn"> |
|||
<appender-ref ref="Console" /> |
|||
<appender-ref ref="File" /> |
|||
</root> |
|||
|
|||
<Logger name="base.GameLoop" level="info"> |
|||
</Logger> |
|||
|
|||
<Logger name="playground" level="info"> |
|||
</Logger> |
|||
|
|||
</loggers> |
|||
</configuration> |
@ -0,0 +1 @@ |
|||
22500 |
@ -0,0 +1,202 @@ |
|||
|
|||
Apache License |
|||
Version 2.0, January 2004 |
|||
http://www.apache.org/licenses/ |
|||
|
|||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, |
|||
and distribution as defined by Sections 1 through 9 of this document. |
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by |
|||
the copyright owner that is granting the License. |
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all |
|||
other entities that control, are controlled by, or are under common |
|||
control with that entity. For the purposes of this definition, |
|||
"control" means (i) the power, direct or indirect, to cause the |
|||
direction or management of such entity, whether by contract or |
|||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|||
outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity |
|||
exercising permissions granted by this License. |
|||
|
|||
"Source" form shall mean the preferred form for making modifications, |
|||
including but not limited to software source code, documentation |
|||
source, and configuration files. |
|||
|
|||
"Object" form shall mean any form resulting from mechanical |
|||
transformation or translation of a Source form, including but |
|||
not limited to compiled object code, generated documentation, |
|||
and conversions to other media types. |
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or |
|||
Object form, made available under the License, as indicated by a |
|||
copyright notice that is included in or attached to the work |
|||
(an example is provided in the Appendix below). |
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object |
|||
form, that is based on (or derived from) the Work and for which the |
|||
editorial revisions, annotations, elaborations, or other modifications |
|||
represent, as a whole, an original work of authorship. For the purposes |
|||
of this License, Derivative Works shall not include works that remain |
|||
separable from, or merely link (or bind by name) to the interfaces of, |
|||
the Work and Derivative Works thereof. |
|||
|
|||
"Contribution" shall mean any work of authorship, including |
|||
the original version of the Work and any modifications or additions |
|||
to that Work or Derivative Works thereof, that is intentionally |
|||
submitted to Licensor for inclusion in the Work by the copyright owner |
|||
or by an individual or Legal Entity authorized to submit on behalf of |
|||
the copyright owner. For the purposes of this definition, "submitted" |
|||
means any form of electronic, verbal, or written communication sent |
|||
to the Licensor or its representatives, including but not limited to |
|||
communication on electronic mailing lists, source code control systems, |
|||
and issue tracking systems that are managed by, or on behalf of, the |
|||
Licensor for the purpose of discussing and improving the Work, but |
|||
excluding communication that is conspicuously marked or otherwise |
|||
designated in writing by the copyright owner as "Not a Contribution." |
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity |
|||
on behalf of whom a Contribution has been received by Licensor and |
|||
subsequently incorporated within the Work. |
|||
|
|||
2. Grant of Copyright License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
copyright license to reproduce, prepare Derivative Works of, |
|||
publicly display, publicly perform, sublicense, and distribute the |
|||
Work and such Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. Subject to the terms and conditions of |
|||
this License, each Contributor hereby grants to You a perpetual, |
|||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|||
(except as stated in this section) patent license to make, have made, |
|||
use, offer to sell, sell, import, and otherwise transfer the Work, |
|||
where such license applies only to those patent claims licensable |
|||
by such Contributor that are necessarily infringed by their |
|||
Contribution(s) alone or by combination of their Contribution(s) |
|||
with the Work to which such Contribution(s) was submitted. If You |
|||
institute patent litigation against any entity (including a |
|||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
|||
or a Contribution incorporated within the Work constitutes direct |
|||
or contributory patent infringement, then any patent licenses |
|||
granted to You under this License for that Work shall terminate |
|||
as of the date such litigation is filed. |
|||
|
|||
4. Redistribution. You may reproduce and distribute copies of the |
|||
Work or Derivative Works thereof in any medium, with or without |
|||
modifications, and in Source or Object form, provided that You |
|||
meet the following conditions: |
|||
|
|||
(a) You must give any other recipients of the Work or |
|||
Derivative Works a copy of this License; and |
|||
|
|||
(b) You must cause any modified files to carry prominent notices |
|||
stating that You changed the files; and |
|||
|
|||
(c) You must retain, in the Source form of any Derivative Works |
|||
that You distribute, all copyright, patent, trademark, and |
|||
attribution notices from the Source form of the Work, |
|||
excluding those notices that do not pertain to any part of |
|||
the Derivative Works; and |
|||
|
|||
(d) If the Work includes a "NOTICE" text file as part of its |
|||
distribution, then any Derivative Works that You distribute must |
|||
include a readable copy of the attribution notices contained |
|||
within such NOTICE file, excluding those notices that do not |
|||
pertain to any part of the Derivative Works, in at least one |
|||
of the following places: within a NOTICE text file distributed |
|||
as part of the Derivative Works; within the Source form or |
|||
documentation, if provided along with the Derivative Works; or, |
|||
within a display generated by the Derivative Works, if and |
|||
wherever such third-party notices normally appear. The contents |
|||
of the NOTICE file are for informational purposes only and |
|||
do not modify the License. You may add Your own attribution |
|||
notices within Derivative Works that You distribute, alongside |
|||
or as an addendum to the NOTICE text from the Work, provided |
|||
that such additional attribution notices cannot be construed |
|||
as modifying the License. |
|||
|
|||
You may add Your own copyright statement to Your modifications and |
|||
may provide additional or different license terms and conditions |
|||
for use, reproduction, or distribution of Your modifications, or |
|||
for any such Derivative Works as a whole, provided Your use, |
|||
reproduction, and distribution of the Work otherwise complies with |
|||
the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. Unless You explicitly state otherwise, |
|||
any Contribution intentionally submitted for inclusion in the Work |
|||
by You to the Licensor shall be under the terms and conditions of |
|||
this License, without any additional terms or conditions. |
|||
Notwithstanding the above, nothing herein shall supersede or modify |
|||
the terms of any separate license agreement you may have executed |
|||
with Licensor regarding such Contributions. |
|||
|
|||
6. Trademarks. This License does not grant permission to use the trade |
|||
names, trademarks, service marks, or product names of the Licensor, |
|||
except as required for reasonable and customary use in describing the |
|||
origin of the Work and reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. Unless required by applicable law or |
|||
agreed to in writing, Licensor provides the Work (and each |
|||
Contributor provides its Contributions) on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|||
implied, including, without limitation, any warranties or conditions |
|||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|||
PARTICULAR PURPOSE. You are solely responsible for determining the |
|||
appropriateness of using or redistributing the Work and assume any |
|||
risks associated with Your exercise of permissions under this License. |
|||
|
|||
8. Limitation of Liability. In no event and under no legal theory, |
|||
whether in tort (including negligence), contract, or otherwise, |
|||
unless required by applicable law (such as deliberate and grossly |
|||
negligent acts) or agreed to in writing, shall any Contributor be |
|||
liable to You for damages, including any direct, indirect, special, |
|||
incidental, or consequential damages of any character arising as a |
|||
result of this License or out of the use or inability to use the |
|||
Work (including but not limited to damages for loss of goodwill, |
|||
work stoppage, computer failure or malfunction, or any and all |
|||
other commercial damages or losses), even if such Contributor |
|||
has been advised of the possibility of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. While redistributing |
|||
the Work or Derivative Works thereof, You may choose to offer, |
|||
and charge a fee for, acceptance of support, warranty, indemnity, |
|||
or other liability obligations and/or rights consistent with this |
|||
License. However, in accepting such obligations, You may act only |
|||
on Your own behalf and on Your sole responsibility, not on behalf |
|||
of any other Contributor, and only if You agree to indemnify, |
|||
defend, and hold each Contributor harmless for any liability |
|||
incurred by, or claims asserted against, such Contributor by reason |
|||
of your accepting any such warranty or additional liability. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work. |
|||
|
|||
To apply the Apache License to your work, attach the following |
|||
boilerplate notice, with the fields enclosed by brackets "[]" |
|||
replaced with your own identifying information. (Don't include |
|||
the brackets!) The text should be enclosed in the appropriate |
|||
comment syntax for the file format. We also recommend that a |
|||
file or class name and description of purpose be included on the |
|||
same "printed page" as the copyright notice for easier |
|||
identification within third-party archives. |
|||
|
|||
Copyright 1999-2005 The Apache Software Foundation |
|||
|
|||
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 |
|||
|
|||
http://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. |
@ -0,0 +1,17 @@ |
|||
Apache Log4j |
|||
Copyright 1999-2017 Apache Software Foundation |
|||
|
|||
This product includes software developed at |
|||
The Apache Software Foundation (http://www.apache.org/). |
|||
|
|||
ResolverUtil.java |
|||
Copyright 2005-2006 Tim Fennell |
|||
|
|||
Dumbster SMTP test server |
|||
Copyright 2004 Jason Paul Kitchen |
|||
|
|||
TypeUtil.java |
|||
Copyright 2002-2012 Ramnivas Laddad, Juergen Hoeller, Chris Beams |
|||
|
|||
picocli (http://picocli.info) |
|||
Copyright 2017 Remko Popma |
@ -0,0 +1,60 @@ |
|||
<!--- |
|||
Licensed to the Apache Software Foundation (ASF) under one or more |
|||
contributor license agreements. See the NOTICE file distributed with |
|||
this work for additional information regarding copyright ownership. |
|||
The ASF licenses this file to You 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 |
|||
|
|||
http://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. |
|||
--> |
|||
# Apache Log4j 2.13.3 Release Notes |
|||
|
|||
The Apache Log4j 2 team is pleased to announce the Log4j 2.13.3 release! |
|||
|
|||
Apache Log4j is a well known framework for logging application behavior. Log4j 2 is an upgrade |
|||
to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides |
|||
many other modern features such as support for Markers, lambda expressions for lazy logging, |
|||
property substitution using Lookups, multiple patterns on a PatternLayout and asynchronous |
|||
Loggers. Another notable Log4j 2 feature is the ability to be "garbage-free" (avoid allocating |
|||
temporary objects) while logging. In addition, Log4j 2 will not lose events while reconfiguring. |
|||
|
|||
The artifacts may be downloaded from https://logging.apache.org/log4j/2.x/download.html. |
|||
|
|||
This release contains a fix for bug LOG4J2-2838. |
|||
|
|||
Due to a break in compatibility in the SLF4J binding, Log4j now ships with two versions of the SLF4J to Log4j adapters. |
|||
log4j-slf4j-impl should be used with SLF4J 1.7.x and earlier and log4j-slf4j18-impl should be used with SLF4J 1.8.x and |
|||
later. |
|||
|
|||
Note that the default XML, JSON and YAML formats changed in the 2.11.0 release: they no longer have the "timeMillis" |
|||
attribute and instead have an "Instant" element with "epochSecond" and "nanoOfSecond" attributes. If the previous |
|||
behavior is desired the "includeTimeMillis" attribute may be set to true on each of the respective Layouts. |
|||
|
|||
The Log4j 2.13.3 API, as well as many core components, maintains binary compatibility with previous releases. |
|||
|
|||
## GA Release 2.13.3 |
|||
|
|||
Changes in this version include: |
|||
|
|||
|
|||
### Fixed Bugs |
|||
* [LOG4J2-2838](https://issues.apache.org/jira/browse/LOG4J2-2838): |
|||
Fix NullPointerException in ThreadContextDataInjector. |
|||
|
|||
|
|||
--- |
|||
|
|||
Apache Log4j 2.13.3 requires a minimum of Java 8 to build and run. Log4j 2.3 was the |
|||
last release that supported Java 6 and Log4j 2.12.1 is the last release to support Java 7. |
|||
|
|||
For complete information on Apache Log4j 2, including instructions on how to submit bug |
|||
reports, patches, or suggestions for improvement, see the Apache Apache Log4j 2 website: |
|||
|
|||
https://logging.apache.org/log4j/2.x/ |
@ -0,0 +1,185 @@ |
|||
2022-04-24 15:15:37,957 INFO base.GameLoop - GUI starts |
|||
2022-04-24 15:15:43,111 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:15:43,111 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:15:43,144 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:15:43,147 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:15:43,148 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:15:43,150 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:15:43,151 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:15:43,153 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:15:43,154 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:15:43,156 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:15:43,159 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:15:43,160 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:15:43,161 WARN playground.HighscoreManager - WARNING: Highscore file was not found and reset |
|||
2022-04-24 15:15:43,162 INFO playground.HighscoreManager - Highscore file was opened and saved score: 0 |
|||
2022-04-24 15:15:43,164 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:28,157 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:28,158 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:28,159 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:47,660 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:47,660 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:47,661 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:48,868 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:48,869 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:48,869 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:50,412 INFO base.GameLoop - GUI PAUSE |
|||
2022-04-24 15:16:52,109 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:52,109 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:52,110 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:53,652 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:53,652 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:53,653 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:54,315 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:16:54,315 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:16:54,316 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:16:58,388 INFO base.GameLoop - GUI starts |
|||
2022-04-24 15:17:00,103 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:17:00,104 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:17:00,130 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:17:00,133 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:17:00,135 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:17:00,136 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:17:00,138 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:17:00,139 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:17:00,140 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:17:00,141 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:17:00,144 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:17:00,146 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:17:00,149 INFO playground.SpaceInvadersLevel - HIGHSCORE0 |
|||
2022-04-24 15:17:26,519 INFO playground.HighscoreManager - Highscore file was opened and saved score: 6000 |
|||
2022-04-24 15:17:26,519 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:17:26,520 INFO base.GameLoop - reached end of levels |
|||
2022-04-24 15:17:26,520 INFO base.GameLoop - Game ends. Bye. |
|||
2022-04-24 15:20:47,899 INFO base.GameLoop - GUI starts |
|||
2022-04-24 15:20:54,103 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:20:54,104 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:20:54,135 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:20:54,138 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:20:54,140 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:20:54,142 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:20:54,144 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:20:54,145 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:20:54,147 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:20:54,148 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:20:54,151 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:20:54,153 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:20:54,155 INFO playground.SpaceInvadersLevel - HIGHSCORE6000 |
|||
2022-04-24 15:21:22,977 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:21:22,977 INFO base.GameLoop - reached end of levels |
|||
2022-04-24 15:21:22,977 INFO base.GameLoop - Game ends. Bye. |
|||
2022-04-24 15:28:41,348 INFO base.GameLoop - GUI starts |
|||
2022-04-24 15:28:43,030 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:28:43,030 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:28:43,058 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:28:43,062 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:28:43,063 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:28:43,064 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:28:43,065 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:28:43,067 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:28:43,068 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:28:43,069 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:28:43,071 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:28:43,073 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:28:43,076 INFO playground.SpaceInvadersLevel - HIGHSCORE6000 |
|||
2022-04-24 15:28:56,264 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:28:56,265 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:28:56,267 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:28:56,268 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:28:56,269 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:28:56,270 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:28:56,272 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:28:56,273 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:28:56,274 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:28:56,275 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:28:56,277 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:28:56,278 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:28:56,279 INFO playground.SpaceInvadersLevel - HIGHSCORE6000 |
|||
2022-04-24 15:29:17,828 INFO playground.HighscoreManager - Highscore file was opened and saved score: 12000 |
|||
2022-04-24 15:29:17,828 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:29:17,828 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:29:17,830 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:29:17,831 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:29:17,832 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:29:17,833 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:29:17,834 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:29:17,835 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:29:17,835 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:29:17,836 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:29:17,838 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:29:17,839 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:29:17,840 INFO playground.SpaceInvadersLevel - HIGHSCORE12000 |
|||
2022-04-24 15:29:52,038 INFO playground.HighscoreManager - Highscore file was opened and saved score: 17500 |
|||
2022-04-24 15:29:52,038 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:29:52,038 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:29:52,040 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:29:52,041 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:29:52,042 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:29:52,043 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:29:52,043 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:29:52,044 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:29:52,045 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:29:52,046 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:29:52,048 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:29:52,049 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:29:52,049 INFO playground.SpaceInvadersLevel - HIGHSCORE17500 |
|||
2022-04-24 15:30:16,985 INFO playground.HighscoreManager - Highscore file was opened and saved score: 22500 |
|||
2022-04-24 15:30:16,985 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:30:16,985 INFO base.GameLoop - reached end of levels |
|||
2022-04-24 15:30:16,985 INFO base.GameLoop - Game ends. Bye. |
|||
2022-04-24 15:32:41,524 INFO base.GameLoop - GUI starts |
|||
2022-04-24 15:32:42,806 INFO base.GameLoop - GUI NEW |
|||
2022-04-24 15:32:42,807 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:32:42,835 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:32:42,838 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:32:42,839 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:32:42,841 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:32:42,842 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:32:42,844 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:32:42,845 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:32:42,846 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:32:42,849 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:32:42,850 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:32:42,852 INFO playground.SpaceInvadersLevel - HIGHSCORE22500 |
|||
2022-04-24 15:32:57,951 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:32:57,952 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:32:57,954 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:32:57,956 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:32:57,957 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:32:57,958 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:32:57,959 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:32:57,960 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:32:57,961 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:32:57,962 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:32:57,964 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:32:57,965 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:32:57,966 INFO playground.SpaceInvadersLevel - HIGHSCORE22500 |
|||
2022-04-24 15:33:11,120 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:33:11,120 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:33:11,123 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:33:11,124 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:33:11,124 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:33:11,125 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:33:11,126 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:33:11,127 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:33:11,128 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:33:11,129 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:33:11,131 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:33:11,132 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:33:11,133 INFO playground.SpaceInvadersLevel - HIGHSCORE22500 |
|||
2022-04-24 15:33:28,392 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:33:28,392 INFO playground.SpaceInvadersLevel - PREPARE |
|||
2022-04-24 15:33:28,394 INFO playground.Animation - img added .\video/sweetAlien0.png |
|||
2022-04-24 15:33:28,395 INFO playground.Animation - img added .\video/sweetAlien1.png |
|||
2022-04-24 15:33:28,396 INFO playground.Animation - img added .\video/sweetAlien2.png |
|||
2022-04-24 15:33:28,397 INFO playground.Animation - img added .\video/sweetAlien3.png |
|||
2022-04-24 15:33:28,398 INFO playground.Animation - img added .\video/sweetAlien4.png |
|||
2022-04-24 15:33:28,399 INFO playground.Animation - img added .\video/sweetAlien5.png |
|||
2022-04-24 15:33:28,399 INFO playground.Animation - img added .\video/sweetAlien6.png |
|||
2022-04-24 15:33:28,400 INFO playground.Animation - img added .\video/sweetAlien7.png |
|||
2022-04-24 15:33:28,402 INFO playground.Animation - img added .\video/heart0.png |
|||
2022-04-24 15:33:28,403 INFO playground.Animation - img added .\video/heart1.png |
|||
2022-04-24 15:33:28,404 INFO playground.SpaceInvadersLevel - HIGHSCORE22500 |
|||
2022-04-24 15:33:34,404 INFO playground.SpaceInvadersLevel - no enemies left, level done. |
|||
2022-04-24 15:33:34,404 INFO base.GameLoop - reached end of levels |
|||
2022-04-24 15:33:34,404 INFO base.GameLoop - Game ends. Bye. |
@ -0,0 +1,231 @@ |
|||
package base; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.ListIterator; |
|||
import org.apache.logging.log4j.LogManager; |
|||
import org.apache.logging.log4j.Logger; |
|||
import gameobjects.GameObject; |
|||
import playground.Level1; |
|||
import playground.Playground; |
|||
import ui.GameUI; |
|||
|
|||
|
|||
/** |
|||
* Main class starting any game, contains main(). Apart from that, this class manages all |
|||
* non-logical functionalities which should be hidden from a game designer like: |
|||
* <ul> |
|||
* <li>Setting up windows, panels, buttons, action callbacks, ... |
|||
* <li>Reading keyboard inputs |
|||
* <li>Redrawing game window if necessary |
|||
* <li>managing the game time and calling the appropriate {@link GameObject} or {@link Playground} |
|||
* methods periodically, at every time step of the game. |
|||
* </ul> |
|||
* There will normally never be a need to modify this file, a designer/game programmer should always |
|||
* redefine the {@link GameObject} and {@link Playground} classes and implement new functionality |
|||
* there. To make a long story short<br> |
|||
*/ |
|||
public class GameLoop { |
|||
|
|||
/** Pixel width of Game GUI ( above 0) */ |
|||
public static int SIZEX = 300; |
|||
/** Pixel height of Game GUI (above 0) */ |
|||
public static int SIZEY = 200; |
|||
|
|||
/** |
|||
* before call to {@link #runGame(String[])} this List should be initialized (in constructor). |
|||
*/ |
|||
private List<Playground> levels = new ArrayList<Playground>(0); |
|||
|
|||
private static Logger logger = LogManager.getLogger(GameLoop.class); |
|||
|
|||
/** constructor which calls {@link #defineLevels()}, which adds all levels of this game. |
|||
*/ |
|||
public GameLoop() { |
|||
this.defineLevels(); |
|||
} |
|||
|
|||
/** |
|||
* First resets (clears) the already existing level instances of this game's list of levels ({@link #resetLevels()}), |
|||
* then adds one instance of {@link Level1} by calling {@link #addLevel()}. |
|||
* Should be called only before playing starts (e.g. in constructor or before {@link #runGame(String[]) } is called. |
|||
* |
|||
* <br><strong>Note:</strong> Subclasses of {@link GameLoop} should override this method to define own levels for their game. |
|||
*/ |
|||
void defineLevels() { |
|||
this.resetLevels(); |
|||
this.addLevel(new Level1()); |
|||
} |
|||
|
|||
/** |
|||
* Adds the given level instance to the end of the currently already stored list of levels to play. |
|||
* Should be called only before playing starts (e.g. in constructor or before {@link #runGame(String[]) } is called. |
|||
* |
|||
* @param level instance of Playground (a level) to add. |
|||
*/ |
|||
void addLevel(Playground level) { |
|||
this.levels.add(level); |
|||
} |
|||
|
|||
/** |
|||
* Removes all levels from the list of levels to play! Do not call this method while {@link #runGame(String[]) } is running! |
|||
*/ |
|||
void resetLevels() { |
|||
this.levels.clear(); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* loops over all {@link #levels} and implements the game loop to update continuously the level |
|||
* during play time |
|||
* |
|||
* @param args command line arguments forwarded (currently ignored) |
|||
* @throws IOException if hitghscore.txt cannot be written. |
|||
*/ |
|||
public void runGame(String[] args) throws IOException { |
|||
|
|||
logger.info("GUI starts"); |
|||
GameUI gameUI = new GameUI(SIZEX, SIZEY); // probably change to your new GUI class |
|||
|
|||
double gameTime = -1; |
|||
Playground currentPlayground = null; |
|||
|
|||
// loop over different levels |
|||
ListIterator<Playground> levelIterator = levels.listIterator(); |
|||
while (true) { |
|||
logger.debug("LevelIndex is " + (levelIterator.nextIndex()) + " (of " + levels.size() + " levels)"); |
|||
gameTime = 0; |
|||
long start = System.nanoTime(); |
|||
|
|||
// loop over single level |
|||
while (true) { |
|||
|
|||
int act = GameUI.getNewAction(); |
|||
|
|||
// Query GameUI for high-level user commands; new game/reset/etc... |
|||
if (act == GameUI.ACTION_RESET) { |
|||
// ReStart Game in same Level |
|||
logger.info("GUI RESET"); |
|||
currentPlayground.prepareLevel("level" + (levelIterator.nextIndex()-1)); |
|||
GameUI.resetAction(); |
|||
} |
|||
|
|||
if (act == GameUI.ACTION_NEW) { |
|||
// new game |
|||
logger.info("GUI NEW"); |
|||
start = System.nanoTime(); |
|||
levelIterator = levels.listIterator(); // reset |
|||
currentPlayground = levelIterator.next(); // again level |
|||
currentPlayground.prepareLevel("level" + (levelIterator.nextIndex()-1)); |
|||
gameUI.setPlayground(currentPlayground); |
|||
GameUI.resetAction(); |
|||
break; |
|||
} |
|||
|
|||
if (act == GameUI.ACTION_BUTTON) { |
|||
// Event of Button pressed --> PAUSE! |
|||
logger.info("GUI PAUSE"); |
|||
if (currentPlayground != null) { |
|||
boolean p = currentPlayground.isPaused(); |
|||
p = !p; |
|||
currentPlayground.setPaused(p); |
|||
} |
|||
GameUI.resetAction(); |
|||
} |
|||
|
|||
if (act == GameUI.ACTION_SAVE) { |
|||
logger.info("GUI SAVE"); |
|||
// UNDONE save current state (not yet working/implemented) |
|||
GameUI.resetAction(); |
|||
} |
|||
|
|||
if (act == GameUI.ACTION_LOAD) { |
|||
logger.info("GUI LOAD"); |
|||
// load game state (currently simply resets) |
|||
GameUI.resetAction(); |
|||
} |
|||
|
|||
// if game has been created: execute a single iteration of the game loop |
|||
if (currentPlayground != null) { |
|||
// calc time that was used for painting the game, in seconds since last loop |
|||
long end = System.nanoTime(); |
|||
double realTS = ((double) (end - start) / 1000000000.); |
|||
|
|||
// time calc for one loop of the while |
|||
start = System.nanoTime(); |
|||
|
|||
|
|||
|
|||
if (currentPlayground.levelFinished() || currentPlayground.gameOver() == true) { |
|||
break; // leave level; breaks WHILE |
|||
} |
|||
|
|||
// paint current state of level and start time measurement |
|||
gameUI.waitWhilePainting(); |
|||
|
|||
|
|||
gameUI.grabFocus(); // needed to grab input events in next step |
|||
|
|||
// communicate inputs to level |
|||
currentPlayground.processKeyEvents(gameUI.getKeyEvents()); |
|||
currentPlayground.processMouseEvents(gameUI.getMouseEvents()); |
|||
|
|||
if (currentPlayground.isPaused() == false) { |
|||
|
|||
// update objects and level |
|||
currentPlayground.updateObjects(); |
|||
currentPlayground.applyGameLogic(); |
|||
|
|||
|
|||
// update game time |
|||
gameTime += realTS; |
|||
// communicate gameTime and timestep to level |
|||
currentPlayground.setTimestep(realTS); |
|||
currentPlayground.setGameTime(gameTime); |
|||
Playground.setGlobalFlag("gameTime", Double.valueOf(realTS)); |
|||
logger.trace("gameTime is now "+gameTime); |
|||
|
|||
} // if |
|||
} // if |
|||
|
|||
} // inner while loop within level |
|||
|
|||
// after level is done: leave outer loop if game over |
|||
if (currentPlayground.gameOver() == true) { |
|||
break; // outer while ends game |
|||
} |
|||
|
|||
// after level is done: reset level and go to next, if there is one |
|||
if (currentPlayground.levelFinished() == true) { |
|||
currentPlayground.reset(); |
|||
|
|||
// increase level counter, go on to next one |
|||
logger.debug("level finished. now new LevelIndex is " + levelIterator.nextIndex()); |
|||
if (levelIterator.nextIndex() >= levels.size()) { |
|||
logger.info("reached end of levels"); |
|||
break; // outer while ends game; |
|||
} |
|||
currentPlayground = levelIterator.next(); |
|||
currentPlayground.prepareLevel("level" + (levelIterator.nextIndex()-1)); |
|||
} |
|||
|
|||
} // outer loop over levels |
|||
logger.info("Game ends. Bye."); |
|||
System.exit(0); |
|||
} // main() |
|||
|
|||
|
|||
/** |
|||
* main to start the whole application. |
|||
* initializes the {@link #levels} ArrayList of Playground instances (levels) to be played with one level {@link SpaceInvadersLevel} in constructor of {@link #GameLoop}. |
|||
* |
|||
* @param args Java default command line args, forwarded to {@link #runGame(String[])} |
|||
* @throws IOException in case highscore.txt cannot be written. |
|||
*/ |
|||
public static void main(String[] args) throws IOException { |
|||
GameLoop gl = new GameLoop(); |
|||
gl.runGame(args); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,30 @@ |
|||
//Coding Team 66 |
|||
package base; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
//importieren der neuen Level aus dem Package Playground |
|||
import playground.Level1; |
|||
import playground.Level3; |
|||
import playground.LevelBoss; |
|||
import playground.LevelHitTwice; |
|||
|
|||
|
|||
public class MultiLevelGame extends GameLoop{ |
|||
|
|||
//main wie bei GameLoop, nur das stattdessen Instanz von MulitLevelGame erstellt wird |
|||
public static void main(String[] args) throws IOException { |
|||
MultiLevelGame gl = new MultiLevelGame(); |
|||
gl.runGame(args); |
|||
} |
|||
|
|||
@Override //Überschreiben der Methode defineLevels |
|||
void defineLevels() { |
|||
this.resetLevels(); |
|||
this.addLevel(new Level1()); |
|||
this.addLevel(new LevelHitTwice()); |
|||
this.addLevel(new Level3()); |
|||
this.addLevel(new LevelBoss()); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,88 @@ |
|||
package collider; |
|||
|
|||
import java.awt.Color; |
|||
import gameobjects.*; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
|
|||
/** Collider for round objects */ |
|||
public class CircleCollider extends Collider { |
|||
|
|||
double x; |
|||
double y; |
|||
double vx; |
|||
double vy; |
|||
|
|||
double r; |
|||
|
|||
private static Logger logger = LogManager.getLogger(Collider.class); |
|||
|
|||
/** |
|||
* Constructor which sets the radius to be respected for collisions. |
|||
* |
|||
* @param id String unique name for the collider instance |
|||
* @param o GameObject it belongs to |
|||
* @param radius radius in pixels to use as a size |
|||
*/ |
|||
public CircleCollider(String id, GameObject o, double radius) { |
|||
|
|||
super(id, o); |
|||
this.r = radius; |
|||
} |
|||
|
|||
/** simple concatenation of all attributes (x,y,r) */ |
|||
public String toString() { |
|||
return "circ:" + x + " " + y + "/" + r + " "; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* calculates the collission of this with other collider |
|||
* |
|||
* @param _c2 the other collider |
|||
* @return true if a collision was detected |
|||
* @throws Exception in case the math operations are invalid (due to illegal values of x y or |
|||
* radius) |
|||
*/ |
|||
public boolean checkCollisionCircCirc(Collider _c2) throws Exception { |
|||
CircleCollider c2 = (CircleCollider) _c2; |
|||
CircleCollider c1 = this; |
|||
logger.trace(c1.x + " " + c1.y + " " + c1.r + " " + c2.x + " " + c2.y+ " " + c2.r); |
|||
int kathete1 = (int) (Math.abs(c2.gameobject.getX() - c1.gameobject.getX())); |
|||
int kathete2 = (int) (Math.abs(c2.gameobject.getX() - c1.gameobject.getY())); |
|||
int hypothenuse = (int) (c1.r + c2.r); |
|||
|
|||
logger.trace(kathete1 + " " + kathete2 + " " + hypothenuse + " "); |
|||
|
|||
if (((kathete1 ^ 2) + (kathete2 ^ 2)) <= (hypothenuse ^ 2)) { |
|||
logger.trace("Collision"); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
public boolean collidesWith(Collider other) { |
|||
|
|||
// circ circ |
|||
try { |
|||
return checkCollisionCircCirc(other); |
|||
} catch (Exception e) { |
|||
} |
|||
|
|||
try { |
|||
return other.collidesWith(this); |
|||
} catch (Exception e) { |
|||
} |
|||
|
|||
throw new RuntimeException("Collider type not implemented!"); |
|||
} |
|||
|
|||
private Color color = Color.WHITE; |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,127 @@ |
|||
package collider; |
|||
|
|||
import java.awt.Graphics2D; |
|||
import java.util.LinkedList; |
|||
import gameobjects.GameObject; |
|||
import playground.Playground; |
|||
import controller.ObjectController; |
|||
|
|||
/** |
|||
* abstract base class for all Colliders to detect collisions between GameObjects |
|||
* |
|||
* |
|||
*/ |
|||
public abstract class Collider { |
|||
|
|||
/** unique internal name for Collider */ |
|||
public String id = null; |
|||
/** GameObject it belongs to */ |
|||
protected GameObject gameobject = null; |
|||
/** PlayGround instance it belongs to */ |
|||
protected Playground playground = null; |
|||
/** the ObjectController to the corresponding GameObject (can be null) */ |
|||
protected ObjectController controller = null; |
|||
|
|||
protected double dx = 0.; |
|||
double dy = 0.; |
|||
|
|||
/** |
|||
* |
|||
* @param id unique name for Collider (internally) |
|||
* @param o GameObject instance it belongs to |
|||
*/ |
|||
public Collider(String id, GameObject o) { |
|||
this.gameobject = o; |
|||
|
|||
this.id = id; |
|||
this.controller = o.getObjectController(); |
|||
this.playground = o.getPlayground(); |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* setter for offset values to be used relative to GameObject center. default is zero. |
|||
* |
|||
* @param dx offset in X direction (default 0) |
|||
* @param dy offset in Y direction (default 0) |
|||
* @return this instance of Collider |
|||
*/ |
|||
public Collider setOffsets(double dx, double dy) { |
|||
this.dx = dx; |
|||
this.dy = dy; |
|||
return this; |
|||
} |
|||
|
|||
public String toString() { |
|||
return "baseColl"; |
|||
} |
|||
|
|||
/** |
|||
* returns the corresponding game objects X coordinate (center) plus this colliders offset in X |
|||
* (probably zero). |
|||
* |
|||
* @return X value |
|||
*/ |
|||
public double getX() { |
|||
return this.gameobject.getX() + this.dx; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* returns the corresponding game objects Y coordinate (center) plus this colliders offset in Y |
|||
* (probably zero). |
|||
* |
|||
* @return Y value |
|||
*/ |
|||
public double getY() { |
|||
return this.gameobject.getY() + this.dy; |
|||
} |
|||
|
|||
/** |
|||
* returns the internal unique name |
|||
* |
|||
* @return the String with the name |
|||
*/ |
|||
public String getId() { |
|||
return id; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* setter for corresponding GameObject |
|||
* |
|||
* @param gameObject to be saved in attribute |
|||
*/ |
|||
public void setObject(GameObject gameObject) { |
|||
this.gameobject = gameObject; |
|||
} |
|||
|
|||
/** |
|||
* setter for GameController |
|||
* |
|||
* @param controller to be saved in attribute |
|||
*/ |
|||
public void setController(ObjectController controller) { |
|||
this.controller = controller; |
|||
} |
|||
|
|||
/** |
|||
* setter for Playground instance this collider belongs to |
|||
* |
|||
* @param playground instance to be stored in attribute |
|||
*/ |
|||
public void setPlayground(Playground playground) { |
|||
this.playground = playground; |
|||
} |
|||
|
|||
/** |
|||
* checks the collission with another collider instance. |
|||
* |
|||
* @param other the instance to compare to |
|||
* @return true if the colliders collide (touch or overlap) |
|||
*/ |
|||
abstract public boolean collidesWith(Collider other); |
|||
|
|||
|
|||
} |
@ -0,0 +1,127 @@ |
|||
package collider; |
|||
|
|||
import java.awt.Color; |
|||
|
|||
import gameobjects.*; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** a {@link Collider} for Rectangles, usually used for {@link RectObject} instances. |
|||
* @see gameobjects.RectObject#generateColliders() |
|||
*/ |
|||
public class RectCollider extends Collider { |
|||
|
|||
//double x; |
|||
//double y; |
|||
//double vx; |
|||
//double vy; |
|||
double w, h; |
|||
|
|||
private Color color = Color.WHITE; |
|||
|
|||
private static Logger logger = LogManager.getLogger(RectCollider.class); |
|||
|
|||
/** |
|||
* initializes this RectCollider. |
|||
* calls superclass constructor of {@link Collider#Collider(String, GameObject)} with params String id and GameObject o. |
|||
* |
|||
* @param id String unique name for this RectCollider |
|||
* @param o GameObject instance this RectCollider belongs to (cannot be null) |
|||
* @param w width in pixels for the collider dimensions (> 0) |
|||
* @param h height in pixels for the collider dimensions (>0) |
|||
*/ |
|||
public RectCollider(String id, GameObject o, double w, double h) { |
|||
super(id, o); |
|||
this.w = w; |
|||
this.h = h; |
|||
} |
|||
|
|||
public String toString() { |
|||
return " " + w + " " + h + " "; |
|||
} |
|||
|
|||
/** |
|||
* checks collision with other Collider, which needs to be a RectCollider, too. |
|||
* @param other RectCollider (is casted) to calculate collision with |
|||
* @return true if collission is detected |
|||
*/ |
|||
public boolean checkCollisionRectRect(Collider other) { |
|||
RectCollider r1 = this; |
|||
RectCollider r2 = (RectCollider) other; |
|||
|
|||
if ((((r1.getX() + r1.w / 2.) >= (r2.getX() - r2.w / 2.)) && ((r1.getX() + r1.w / 2.) <= (r2 |
|||
.getX() + r2.w / 2.))) |
|||
|| (((r2.getX() + r2.w / 2.) >= (r1.getX() - r1.w / 2.)) && ((r2.getX() + r2.w / 2.) <= (r1 |
|||
.getX() + r1.w / 2.)))) { |
|||
if ((((r1.getY() + r1.h / 2.) >= (r2.getY() - r2.h / 2.)) && ((r1.getY() + r1.h / 2.) <= (r2 |
|||
.getY() + r2.h / 2.))) |
|||
|| (((r2.getY() + r2.h / 2.) >= (r1.getY() - r1.h / 2.)) && ((r2.getY() + r2.h / 2.) <= (r1 |
|||
.getY() + r1.h / 2.)))) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* checks collision with other Collider, which needs to be a CircleCollider |
|||
* @param other CircleCollider (is casted) to calculate collision with |
|||
* @return true if collission is detected |
|||
*/ |
|||
public boolean checkCollisionRectCirc(Collider other) { |
|||
RectCollider r = this; |
|||
CircleCollider c = (CircleCollider) (other); |
|||
double circleDistX = Math.abs(c.getX() - (r.getX() )); |
|||
double circleDistY = Math.abs(c.getY() - (r.getY() ) ); |
|||
|
|||
logger.trace("c.x:"+c.x+" "+"c.y:"+c.y+" "+"c.r:"+c.r+" "+"r.x:"+r.getX()+" "+"r.y:"+r.getY()+" "+"r.w:"+r.w+" "+"r.h:"+r.h+" "+"circleDistX:"+circleDistX+" "+"circleDistY:"+circleDistY); |
|||
|
|||
if (circleDistX > (r.w / 2 + c.r)) |
|||
return false; |
|||
if (circleDistY > (r.h / 2 + c.r)) |
|||
return false; |
|||
|
|||
if (circleDistX <= (r.w / 2)) { |
|||
logger.trace("Collision Rect with circle"); |
|||
return true; |
|||
} |
|||
if (circleDistY <= (r.h / 2)) { |
|||
logger.trace("Collision Rect with circle (second)"); |
|||
return true; |
|||
} |
|||
|
|||
double cornerDistSqr = Math.pow(circleDistX - r.w / 2, 2) + Math.pow(circleDistY - r.h / 2, 2); // Satz |
|||
// des |
|||
// Pythagoras |
|||
return (cornerDistSqr <= c.r * c.r); // falls true zurueckgegeben: Kollision |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
public boolean collidesWith(Collider other) { |
|||
|
|||
// rect circ |
|||
try { |
|||
return checkCollisionRectCirc(other); |
|||
} catch (Exception e) { |
|||
// do nothing |
|||
} |
|||
|
|||
// rect rect |
|||
try { |
|||
return checkCollisionRectRect(other); |
|||
} catch (Exception e) { |
|||
// do nothing |
|||
} |
|||
|
|||
try { |
|||
return other.collidesWith(this); |
|||
} catch (Exception e) { |
|||
// do nothing |
|||
} |
|||
|
|||
throw new RuntimeException("Collider type not implemented!"); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,84 @@ |
|||
package controller; |
|||
|
|||
import playground.*; |
|||
import gameobjects.*; |
|||
import java.util.*; |
|||
import java.awt.event.*; |
|||
import java.io.File; |
|||
|
|||
|
|||
/** |
|||
* An EgoController which cannot move through obstacle objects (is collission aware). Only respects |
|||
* GameObjects that have the String 'obstacle' in their name. |
|||
* |
|||
*/ |
|||
public class CollisionAwareEgoController extends EgoController { |
|||
|
|||
double savex, savey, savevx, savevy; |
|||
double lastSpaceAt = -1; |
|||
private File shot = null; |
|||
|
|||
|
|||
/** |
|||
* |
|||
* @param egoRad radius of ego object to be used. |
|||
*/ |
|||
public CollisionAwareEgoController(double egoRad) { |
|||
super(egoRad); |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param egoRad radius of ego object to be used. |
|||
* @param soundOnShot WAV file to be played on shot |
|||
*/ |
|||
public CollisionAwareEgoController(double egoRad, File soundOnShot) { |
|||
super(egoRad); |
|||
this.shot = soundOnShot; |
|||
} |
|||
|
|||
public void saveDynamicState() { |
|||
this.savex = this.getX(); |
|||
this.savey = this.getY(); |
|||
this.savevx = this.getVX(); |
|||
this.savevy = this.getVY(); |
|||
} |
|||
|
|||
|
|||
public void restoreDynamicState() { |
|||
this.setX(savex); |
|||
this.setY(savey); |
|||
this.setVX(savevx); |
|||
this.setVY(savevy); |
|||
} |
|||
|
|||
|
|||
public boolean stopObject() { |
|||
boolean s = super.stopObject(); |
|||
|
|||
Playground pg = this.getPlayground(); |
|||
|
|||
LinkedList<GameObject> obstacles = pg.collectObjects("obstacle", false); |
|||
|
|||
this.saveDynamicState(); |
|||
this.applySpeedVector(); |
|||
|
|||
for (GameObject ob : obstacles) { |
|||
if (ob.collisionDetection(this.gameObject)) { |
|||
this.restoreDynamicState(); |
|||
return true; |
|||
} |
|||
} |
|||
this.restoreDynamicState(); |
|||
return s; |
|||
} |
|||
|
|||
public void onSpace(KeyEvent e, GameObject ego) { |
|||
double cgt = ego.getGameTime(); |
|||
if ((cgt - this.lastSpaceAt) > 0.1) { |
|||
super.onSpace(e, ego); |
|||
Music.music(this.shot); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,216 @@ |
|||
package controller; |
|||
|
|||
import java.awt.Color; |
|||
import java.awt.event.KeyEvent; |
|||
import playground.*; |
|||
import gameobjects.*; |
|||
import java.util.*; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* Controller using key events for up, down, left, right and space (shooting) to control the ego |
|||
* object behavior. |
|||
*/ |
|||
public class EgoController extends ObjectController { |
|||
// either rad is zero or width/height is zero (guaranteed by constructors) |
|||
private double rad = 0; |
|||
private double width = 0; |
|||
private double height = 0; |
|||
|
|||
private Integer pressedKey = null; |
|||
private Integer lastPressedKey = null; |
|||
private static Logger logger = LogManager.getLogger(EgoController.class); |
|||
|
|||
|
|||
/** |
|||
* constructor that gives the ego controller a radius to stop the ego object when it reaches the level boundaries. |
|||
* @param egoRad radius to use as a boundary stop for level borders (usually use the same dimensions as your ego object) |
|||
*/ |
|||
public EgoController(double egoRad) { |
|||
this.rad = egoRad; |
|||
} |
|||
|
|||
/** |
|||
* constructor that gives the ego controller a width and height to stop the ego object when it reaches the level boundaries. |
|||
* @param width width to use as a boundary stop for level borders (usually use the same dimensions as your ego object) |
|||
* @param height height to use as a boundary stop for level borders (usually use the same dimensions as your ego object) |
|||
*/ |
|||
public EgoController(double width, double height) { |
|||
this.width = width; |
|||
this.height = height; |
|||
} |
|||
|
|||
|
|||
public void onUp(KeyEvent kc, GameObject ego) { |
|||
ego.setVX(0.0); |
|||
ego.setVY(-SpaceInvadersLevel.EGOSPEED); |
|||
} |
|||
|
|||
public void onDown(KeyEvent kc, GameObject ego) { |
|||
ego.setVX(0.0); |
|||
ego.setVY(SpaceInvadersLevel.EGOSPEED); |
|||
} |
|||
|
|||
public void onLeft(KeyEvent kc, GameObject ego) { |
|||
ego.setVY(0.0); |
|||
ego.setVX(-SpaceInvadersLevel.EGOSPEED); |
|||
} |
|||
|
|||
public void onRight(KeyEvent kc, GameObject ego) { |
|||
ego.setVY(0.0); |
|||
ego.setVX(SpaceInvadersLevel.EGOSPEED); |
|||
} |
|||
|
|||
public void onStop(KeyEvent kc, GameObject ego) { |
|||
ego.setVY(0.0); |
|||
ego.setVX(0.0); |
|||
ego.setComponentProperty("controller", "setDummy", "NEW"); |
|||
ego.setComponentProperty("controller", "setDummy2", "XXX"); |
|||
} |
|||
|
|||
|
|||
/** checks the position and respects level boundaries and own radius or width/height set on constructor. |
|||
* |
|||
* @return true if the object reached the boundaries of the level, false otherwise |
|||
*/ |
|||
public boolean stopObject() { |
|||
// check whether ego object is at level boundaries |
|||
// can use radius (rad) and width or height in one check as either rad or width/height is zero. |
|||
int pgSizeX = this.getPlayground().getSizeX(); |
|||
int pgSizeY = this.getPlayground().getSizeY(); |
|||
double ts = this.getTimestep(); |
|||
if (this.getX() + rad + (width/2d) + this.getVX() * ts >= pgSizeX |
|||
|| this.getX() - rad - (width/2d) + this.getVX() * ts < 0) { |
|||
return true; |
|||
} |
|||
if (this.getY() + rad + (height/2d) + this.getVY() * ts >= pgSizeY |
|||
|| this.getY() - rad - (height/2d) + this.getVY() * ts < 0) { |
|||
return true; |
|||
} |
|||
return false; |
|||
|
|||
} |
|||
|
|||
|
|||
/** behavior for shooting on key space |
|||
* |
|||
* @param e KeyEvent of the space key |
|||
* @param ego EgoObject instance (used to determine position of shot object's start) |
|||
*/ |
|||
public void onSpace(KeyEvent e, GameObject ego) { |
|||
pressedKey = lastPressedKey; |
|||
lastPressedKey = null; |
|||
|
|||
// create unique name for object |
|||
// read Flag nextShot read (if not existing already it will be set) |
|||
// it will be updated by 1 and saved |
|||
Integer nextShot = |
|||
(Integer) this.getPlayground().getOrCreateLevelFlag("nextShot", Integer.valueOf(0)); |
|||
String shotName = "simpleShot" + nextShot++; |
|||
this.getPlayground().setLevelFlag("nextShot", nextShot); |
|||
|
|||
SimpleShotController simpleshot = new SimpleShotController(); |
|||
GameObject ss = new RectObject(shotName, this.getPlayground(), ego.getX(), ego.getY(), 0, |
|||
-1. * SpaceInvadersLevel.SHOTSPEED, 4, 12, Color.CYAN).addController(simpleshot); |
|||
ss.generateColliders(); |
|||
this.getPlayground().addObject(ss); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* updates position based on key events (mouse currently ignored) |
|||
*/ |
|||
public void updateObject() { |
|||
|
|||
logger.trace("Playground inst is"+this.getPlayground()) ; |
|||
Stack<KeyEvent> keyEvents = this.getPlayground().getKeyEvents(); |
|||
|
|||
GameObject ego = this.gameObject; |
|||
|
|||
while (!keyEvents.isEmpty()) { |
|||
|
|||
KeyEvent e = keyEvents.pop(); |
|||
boolean pressed = false; |
|||
boolean released = true; |
|||
int kc = e.getKeyCode(); |
|||
|
|||
if (e.paramString().indexOf("PRESSED") >= 0) { |
|||
pressed = true; |
|||
released = false; |
|||
} |
|||
|
|||
/** |
|||
* Generelle Idee: Wenn eine Taste gedrückt wird wird sie gespeichert. wenn die zuvor |
|||
* gespeicherte Taste wieder losgelassen wird stoppt das Ego-Objekt. Falls vor dem Loslassen |
|||
* eine andere Taste gedrückt wird, wird diese gespeichert und die alte vergessen. Dh das |
|||
* loslassen der alten Taste stoppt das Objekt nicht. Spezialfall: space, das loslassen von |
|||
* space stoppt das Objekt nicht! |
|||
*/ |
|||
|
|||
if (pressed == true) { |
|||
lastPressedKey = pressedKey; |
|||
pressedKey = kc; |
|||
} |
|||
|
|||
/** |
|||
* Nur eine losgelassene Taste die auch vorher gedrückt wurde stoppt das Objekt. Eine |
|||
* losgelassene Taste die nicht vorher gedrückt wurde bzw vergessen wurde stoppt das Objekt |
|||
* nicht |
|||
*/ |
|||
if (released == true) { |
|||
if (pressedKey != null) { |
|||
if (pressedKey.equals(kc)) { |
|||
ego.setVX(0); |
|||
ego.setVY(0); |
|||
pressedKey = null; |
|||
} |
|||
} |
|||
continue; |
|||
} |
|||
|
|||
if (kc == KeyEvent.VK_LEFT) { |
|||
this.onLeft(e, ego); |
|||
} |
|||
|
|||
if (kc == KeyEvent.VK_RIGHT) { |
|||
this.onRight(e, ego); |
|||
} |
|||
|
|||
if (kc == KeyEvent.VK_UP) { |
|||
this.onUp(e, ego); |
|||
} |
|||
|
|||
if (kc == KeyEvent.VK_DOWN) { |
|||
this.onDown(e, ego); |
|||
} |
|||
|
|||
// stop |
|||
if (kc == KeyEvent.VK_Z) { |
|||
this.onStop(e, ego); |
|||
|
|||
} |
|||
|
|||
|
|||
// shot |
|||
if (kc == KeyEvent.VK_SPACE) { |
|||
// space is not registered! Releasing space does not stop the egoobject |
|||
this.onSpace(e, ego); |
|||
} |
|||
} |
|||
|
|||
|
|||
boolean stop = this.stopObject(); |
|||
|
|||
if (stop) { |
|||
this.setVX(0); |
|||
this.setVY(0); |
|||
} |
|||
|
|||
// updateSpeed and position |
|||
applySpeedVector(); |
|||
|
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,36 @@ |
|||
package controller; |
|||
|
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* This class controls the space invaders. |
|||
*/ |
|||
public class EnemyController extends ObjectController { |
|||
|
|||
private static Logger logger = LogManager.getLogger(EnemyController.class); |
|||
|
|||
@Override |
|||
public void updateObject() { |
|||
logger.trace("updatre" + gameObject.getId()); |
|||
if ((gameObject.getX() > this.getPlayground().getSizeX() * 0.9) && (gameObject.getVX() > 0)) { |
|||
logger.trace("toleft!" + gameObject.getX()); |
|||
gameObject.setVX(-this.getVX()); |
|||
} |
|||
if ((gameObject.getX() < this.getPlayground().getSizeX() * 0.1) && (gameObject.getVX() < 0)) { |
|||
logger.trace("toright!" + gameObject.getX()); |
|||
gameObject.setVX(-this.getVX()); |
|||
} |
|||
|
|||
// if it reaches the bottom, delete it and deduct points |
|||
if (gameObject.getY() >= this.getPlayground().getSizeY()) { |
|||
this.getPlayground().deleteObject(gameObject.getId()); |
|||
// add to points counter |
|||
Integer pts = (Integer) this.getPlayground().getGlobalFlag("points"); |
|||
this.getPlayground().setGlobalFlag("points", pts - 200); |
|||
} |
|||
|
|||
applySpeedVector(); |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
package controller; |
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
|
|||
/** |
|||
* Controls background stars. When they touch the bottom of the display they reappear on top. |
|||
*/ |
|||
public class FallingStarController extends ObjectController { |
|||
int rad = 3; |
|||
private static Logger logger = LogManager.getLogger(FallingStarController.class); |
|||
|
|||
|
|||
@Override |
|||
public void updateObject() { |
|||
logger.trace( |
|||
"+" + this.gameObject.getId() + " HO " + this.gameObject + "/" + this.getPlayground()); |
|||
if (this.getY() + rad >= this.getPlayground().getSizeY()) { |
|||
this.setY(10); |
|||
} |
|||
applySpeedVector(); |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
package controller; |
|||
|
|||
/** |
|||
* Controls and abject that is deleted after a lifetime specified in the constructor, and when it |
|||
* leaves the display. |
|||
*/ |
|||
public class LimitedTimeController extends ObjectController { |
|||
int rad = 3; |
|||
double g0 = -1; |
|||
double duration = 0; |
|||
|
|||
/** |
|||
* Constructor. |
|||
* |
|||
* @param g0 int initial game time at creation |
|||
* @param duration int duration in seconds |
|||
*/ |
|||
public LimitedTimeController(double g0, double duration) { |
|||
this.g0 = g0; |
|||
this.duration = duration; |
|||
} |
|||
|
|||
@Override |
|||
public void updateObject() { |
|||
double gameTime = this.getPlayground().getGameTime(); |
|||
applySpeedVector(); |
|||
|
|||
if (gameObject.getY() >= getPlayground().getSizeY() || gameObject.getY() < 0 |
|||
|| gameObject.getX() >= getPlayground().getSizeX() || gameObject.getX() < 0 |
|||
|| (gameTime - g0) > duration) { |
|||
|
|||
this.getPlayground().deleteObject(this.gameObject.getId()); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,47 @@ |
|||
package controller; |
|||
|
|||
import controller.ObjectController; |
|||
import gameobjects.GameObject; |
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
public class MineController extends ObjectController { |
|||
int rad = 3; |
|||
|
|||
double xSpeed = 0.; |
|||
double lineSpeed = 0; |
|||
private static Logger logger = LogManager.getLogger(MineController.class); |
|||
|
|||
|
|||
public MineController(double lineSpeed) { |
|||
this.lineSpeed = lineSpeed; |
|||
} |
|||
|
|||
@Override |
|||
public void updateObject() { |
|||
|
|||
if (gameObject.getY() >= this.getPlayground().getSizeY() - 10) { |
|||
this.gameObject.setVY(0); |
|||
if (xSpeed == 0.) { |
|||
GameObject ego = getPlayground().getObject("ego"); |
|||
double egoXPos = ego.getX(); |
|||
if (egoXPos > this.gameObject.getX()) { |
|||
xSpeed = 50; |
|||
} else { |
|||
xSpeed = -50; |
|||
} |
|||
this.gameObject.setVX(xSpeed); |
|||
|
|||
} |
|||
this.gameObject.setVX(xSpeed); |
|||
|
|||
} |
|||
if (this.gameObject.getX() < 0 || (this.gameObject.getX() > this.getPlayground().getSizeX())) { |
|||
logger.debug("deleting" + this.gameObject.getId()); |
|||
getPlayground().deleteObject(this.gameObject.getId()); |
|||
} |
|||
|
|||
applySpeedVector(); |
|||
} |
|||
} |
@ -0,0 +1,110 @@ |
|||
package controller; |
|||
|
|||
import gameobjects.GameObject; |
|||
import playground.Playground; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* Class that controls the LOGICAL behavior of an object independently of how it is displayed or |
|||
* drawn. The most important method here is {@link #updateObject}: this method is, by various |
|||
* indirections, called exactly once per game time step for every object that is on the playground. |
|||
* It has, by virtue of the member variables {@link #gameObject} full access to |
|||
* <ul> |
|||
* <li>the object it is controlling |
|||
* <li>the playground this object belongs to |
|||
* </ul> |
|||
* Typically, updateObject would check whether an object leaves the screen to react appropriately. |
|||
* In that case the object can be marked for deletion (by adding it to the flag "deleted" that is |
|||
* always defined for any playground), but of course other reactions are possible like rebounding, |
|||
* emerging on the other side, ... |
|||
*/ |
|||
|
|||
public abstract class ObjectController { |
|||
protected GameObject gameObject = null; |
|||
protected String dummy = ""; |
|||
|
|||
private static Logger logger = LogManager.getLogger(ObjectController.class); |
|||
|
|||
public void setObject(GameObject gameObject) { |
|||
this.gameObject = gameObject; |
|||
} |
|||
|
|||
|
|||
public void setDummy(String x) { |
|||
logger.debug("DUMMY called!!"); |
|||
this.dummy = x; |
|||
logger.debug("DUMMY is now:" + dummy); |
|||
} |
|||
|
|||
/** |
|||
* Is called once every game time step by the game itself. NEVER call this directly, not |
|||
* necessary!<br> |
|||
* The method can do whatever it likes, including nothing. The attribute {@link #gameObject} |
|||
* contains a reference to the controlled object, which allows access to the Playground the object |
|||
* belongs to (useful for getting the pixel size in x and y of the playing field.<br> |
|||
* <strong>Recommended:</strong> when implementing this method, call at the end |
|||
* {@link #applySpeedVector() } method. This is a helper method that sets the new x,y coordinates |
|||
* for the {@link #gameObject} correctly. |
|||
*/ |
|||
public abstract void updateObject(); |
|||
|
|||
/** |
|||
* Convenience method: simply moves the object forward one step from its present position, using |
|||
* its present speed. |
|||
*/ |
|||
public void applySpeedVector() { |
|||
double ts = this.getPlayground().getTimestep(); |
|||
this.setX(this.getX() + this.getVX() * ts); |
|||
gameObject.setY(this.getY() + this.getVY() * ts); |
|||
} |
|||
|
|||
|
|||
public double getTimestep() { |
|||
return this.gameObject.getPlayground().getTimestep(); |
|||
} |
|||
|
|||
public double getX() { |
|||
return this.gameObject.getX(); |
|||
} |
|||
|
|||
public double getY() { |
|||
return this.gameObject.getY(); |
|||
} |
|||
|
|||
public double getVX() { |
|||
return this.gameObject.getVX(); |
|||
} |
|||
|
|||
public double getVY() { |
|||
return this.gameObject.getVY(); |
|||
} |
|||
|
|||
public void setX(double x) { |
|||
this.gameObject.setX(x); |
|||
} |
|||
|
|||
|
|||
public void setY(double y) { |
|||
this.gameObject.setY(y); |
|||
} |
|||
|
|||
public void setVX(double vx) { |
|||
this.gameObject.setVX(vx); |
|||
} |
|||
|
|||
public void setVY(double vy) { |
|||
this.gameObject.setVY(vy); |
|||
} |
|||
|
|||
public Playground getPlayground() { |
|||
return this.gameObject.getPlayground(); |
|||
} |
|||
|
|||
public void setPlayground(Playground playground) { |
|||
this.gameObject.setPlayground(playground); |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package controller; |
|||
|
|||
public class SimpleShotController extends ObjectController { |
|||
int rad = 3; |
|||
|
|||
@Override |
|||
public void updateObject() { |
|||
if (gameObject.getY() < 0) { |
|||
// LinkedList<String> deleteList = (LinkedList<String>) playground.getFlag("delete"); |
|||
// deleteList.add(gameObject.getId()); |
|||
getPlayground().deleteObject(this.gameObject.getId()); |
|||
} else { |
|||
applySpeedVector(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
package controller; |
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
public class ZickZackController extends EnemyController { |
|||
protected double g0; |
|||
protected double dt; |
|||
protected double lastMod = -1; |
|||
|
|||
private static Logger logger = LogManager.getLogger(ZickZackController.class); |
|||
|
|||
public ZickZackController(double gameTime, double dt) { |
|||
super(); |
|||
this.dt = dt; |
|||
this.g0 = gameTime; |
|||
} |
|||
|
|||
public void updateObject() { |
|||
double gameTime = this.getPlayground().getGameTime(); |
|||
logger.trace("current Object x: "+gameObject.getX()); |
|||
double mod = (gameTime - this.g0) % this.dt; |
|||
if (mod < lastMod) { |
|||
gameObject.setVX(-1.0 * gameObject.getVX()); |
|||
logger.trace("inverting VX"); |
|||
} |
|||
lastMod = mod; |
|||
|
|||
super.updateObject(); |
|||
|
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
/** |
|||
* The controller package contains Object controllers that govern an objects behavior, without being |
|||
* involved in its collision or drawing properties. Object controllers react to user actions/inputs |
|||
* and govern for example the movement of {@link gameobjects.GameObject} instances. They can access |
|||
* their parent objects' properties and, by indirection, the properties and methods of the |
|||
* associated level. <br> |
|||
* Controllers should be designed in such a way that they implement behavior that is |
|||
* level-independent. All level-dependent behavior should be implemented in |
|||
* {@link playground.Playground#applyGameLogic}. |
|||
*/ |
|||
package controller; |
@ -0,0 +1,42 @@ |
|||
package gameobjects; |
|||
|
|||
import java.util.LinkedList; |
|||
import playground.Playground; |
|||
import playground.Animation; |
|||
import collider.Collider; |
|||
import collider.RectCollider; |
|||
import rendering.*; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
|
|||
public class AnimatedGameobject extends GameObject { |
|||
|
|||
protected AnimationArtist animArtist; |
|||
private static Logger logger = LogManager.getLogger(AnimationArtist.class); |
|||
|
|||
|
|||
// auto-generates collider according to box width/height |
|||
public GameObject generateColliders() { |
|||
logger.debug("Created animated Obj "+ this.animArtist.getW()+" "+this.animArtist.getH()) ; |
|||
double w = this.animArtist.getW() ; |
|||
double h = this.animArtist.getH() ; |
|||
this.addCollider(new RectCollider("RectColl_" + this.id, this, w, |
|||
h)) ; |
|||
|
|||
logger.info("ANIMGO-COLL ID="+this.getId()+" WH= "+w+"/"+h) ; |
|||
return this ; |
|||
} |
|||
|
|||
|
|||
public AnimatedGameobject(String id, Playground pg, double x, double y, double vx, double vy, |
|||
double scale, Animation anim, double t0, String abspielmodus) { |
|||
super(id, pg, x, y, vx, vy); // Konstruktor-Aufruf GameObject |
|||
|
|||
this.artist = new AnimationArtist(this, anim, t0, abspielmodus, scale); |
|||
this.animArtist = (AnimationArtist) (this.artist); |
|||
|
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,34 @@ |
|||
package gameobjects; |
|||
|
|||
|
|||
import java.awt.Color; |
|||
import collider.*; |
|||
import java.awt.Graphics2D; |
|||
import java.awt.image.BufferedImage; |
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.util.LinkedList; |
|||
import javax.imageio.ImageIO; |
|||
import collider.Collider; |
|||
import controller.ObjectController; |
|||
import playground.Playground; |
|||
import rendering.*; |
|||
|
|||
public class EgoObject extends GameObject { |
|||
|
|||
double egoRad = 0; |
|||
|
|||
public EgoObject(String id, Playground pg, double x, double y, double vx, double vy, |
|||
double egoRad) { |
|||
super(id, pg, x, y, vx, vy); |
|||
this.egoRad = egoRad; |
|||
this.artist = new CircleArtist(this, egoRad, Color.WHITE); |
|||
} |
|||
|
|||
public GameObject generateColliders() { |
|||
CircleCollider coll = new CircleCollider("coll", this, this.egoRad); |
|||
this.addCollider(coll); |
|||
return this; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,28 @@ |
|||
package gameobjects; |
|||
|
|||
import java.awt.Color; |
|||
import java.util.LinkedList; |
|||
import collider.*; |
|||
import playground.Playground; |
|||
import rendering.*; |
|||
|
|||
public class FallingStar extends GameObject { |
|||
|
|||
private Color color = Color.WHITE; |
|||
|
|||
protected double rad = -1; |
|||
|
|||
|
|||
public FallingStar(String id, Playground playground, double x, double y, double vx, double vy, |
|||
Color color, double rad) { |
|||
super(id, playground, x, y, vx, vy); |
|||
this.rad = rad; |
|||
this.color = color; |
|||
LinkedList<Collider> cols = new LinkedList<Collider>(); |
|||
CircleCollider cc = new CircleCollider("cc", this, rad); |
|||
cols.add(cc); |
|||
setColliders(cols); |
|||
this.artist = new CircleArtist(this, rad, color); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,377 @@ |
|||
package gameobjects; |
|||
|
|||
import java.awt.Graphics2D; |
|||
import java.awt.image.BufferedImage; |
|||
import java.util.LinkedList; |
|||
import java.lang.reflect.*; |
|||
import rendering.*; |
|||
import collider.Collider; |
|||
import controller.ObjectController; |
|||
import playground.Playground; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* The class {@link GameObject} represents a (possibly animated) object appearing in a level of the |
|||
* game. It is therefore attached to an instance of the class {@link Playground}. A GameObject has |
|||
* at least the following properties: |
|||
* <ul> |
|||
* <li>2D screen position |
|||
* <li>2D speed |
|||
* <li>a name that is unique within a certain {@link Playground}<br> |
|||
* <li>a reference to the {@link Playground} object it belongs to<br> |
|||
* <li>a reference to an instance of {@link controller.ObjectController} that handles the movement |
|||
* logic of the object<br> |
|||
* <li>a (circular) radius for simple collision checking. This may be handled differently in |
|||
* subclasses<br> |
|||
* </ul> |
|||
* The main task of GameObject, or its subclasses, is to draw the object on the screen, which is |
|||
* handles by the {@link #draw(Graphics2D)} method. It is this method that must be redefined if a |
|||
* new appearance should be realized. For introducing new behavior, it is sufficient to supply a |
|||
* different {@link controller.ObjectController} instance when constructing a GameObject. |
|||
*/ |
|||
public abstract class GameObject { |
|||
|
|||
public static final int RADIUS = 0; |
|||
public static final int RECTANGLE = 1; |
|||
public static final int MASK = 2; |
|||
|
|||
protected Artist artist = null; |
|||
|
|||
public String id = null; |
|||
protected double x = 0; |
|||
protected double vx = 0; |
|||
protected double y = 0; |
|||
protected double vy = 0; |
|||
protected BufferedImage mask = null; // UNDONE implement usage of mask |
|||
protected boolean active = true; |
|||
// public int collisionMode = GameObject.RADIUS; |
|||
protected Playground playground = null; |
|||
|
|||
private ObjectController controller = null; |
|||
public LinkedList<Collider> scol; |
|||
|
|||
private static Logger logger = LogManager.getLogger(GameObject.class); |
|||
|
|||
/** |
|||
* Constructor to initialize a GameObject, respectively set the current {@link Playground} |
|||
* instance this GameObject belongs to. |
|||
* |
|||
* @param id unique ID for this GameObject (should not be null or empty String) |
|||
* @param playground the Playground the GameObject belongs to (should not be null) |
|||
* @param x initial screen position in direction horizontal (positive value including zero) |
|||
* @param y initial screen position in direction vertical (positive value including zero) |
|||
* @param vx initial speed (velocity) in direction horizontal (can be negative, zero, positive) |
|||
* @param vy initial speed (velocity) in direction horizontal (can be negative, zero, positive) |
|||
*/ |
|||
public GameObject(String id, Playground playground, double x, double y, double vx, double vy) { |
|||
setX(x); |
|||
setY(y); |
|||
setVX(vx); |
|||
setVY(vy); |
|||
this.id = id; |
|||
this.controller = null; |
|||
this.scol = new LinkedList<Collider>(); |
|||
this.setPlayground(playground); |
|||
} |
|||
|
|||
/** |
|||
* Constructor to initialize a GameObject, respectively set the current Playground instance this |
|||
* GameObject belongs to. |
|||
* |
|||
* @param id unique ID for this GameObject (should not be null or empty String) |
|||
* @param playground the Playground the GameObject belongs to (should not be null) |
|||
* @param controller controller instance to be used for this GameObject (can be null) |
|||
* @param x initial screen position in direction horizontal (positive value including zero) |
|||
* @param y initial screen position in direction vertical (positive value including zero) |
|||
* @param vx initial speed (velocity) in direction horizontal (can be negative, zero, positive) |
|||
* @param vy initial speed (velocity) in direction horizontal (can be negative, zero, positive) |
|||
*/ |
|||
public GameObject(String id, Playground playground, ObjectController controller, double x, |
|||
double y, double vx, double vy) { |
|||
this(id, playground, x, y, vx, vy); |
|||
this.controller = controller; |
|||
if (this.controller != null) { |
|||
this.controller.setObject(this); |
|||
this.controller.setPlayground(playground); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* sets colliders. |
|||
* |
|||
* @param l LinkedList of Colliders. |
|||
*/ |
|||
public void setColliders(LinkedList<Collider> l) { |
|||
this.scol = l; |
|||
} |
|||
|
|||
/** |
|||
* generates and sets collider(s) for this GameObject. This implementation does nothing. Intended |
|||
* to be overridden by subclasses. |
|||
* |
|||
* @return instance of this GameObject (this). |
|||
*/ |
|||
public GameObject generateColliders() { |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Sets the controller to use for this GameObject's logical behavior. |
|||
* |
|||
* @param c instance to be used. |
|||
* @return the current instance (this). |
|||
*/ |
|||
public GameObject addController(ObjectController c) { |
|||
this.controller = c; |
|||
this.controller.setObject(this); |
|||
this.controller.setPlayground(playground); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Sets the artist to be used for drawing the object onto visible canvas area. |
|||
* |
|||
* @param a instance to be used for calling {@link rendering.Artist#draw(Graphics2D)}. |
|||
* @return the current instance (this). |
|||
*/ |
|||
public GameObject addArtist(Artist a) { |
|||
this.artist = a; |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* saves the collider in the internal list of Colliders to be used for this GameObject. |
|||
* |
|||
* @param c instance to be added to internal list |
|||
*/ |
|||
public void addCollider(Collider c) { |
|||
if (this.scol == null) { |
|||
this.scol = new LinkedList<Collider>(); |
|||
} |
|||
this.scol.add(c); |
|||
} |
|||
|
|||
public Playground getPlayground() { |
|||
return playground; |
|||
} |
|||
|
|||
public void setPlayground(Playground playground) { |
|||
this.playground = playground; |
|||
} |
|||
|
|||
/** |
|||
* calls via reflection a method of a component if this GameObjects instance and provides the |
|||
* given value as String parameter. |
|||
* |
|||
* @param comp class name of GameObject component. Currently only "controller" is supported, |
|||
* otherwise nothing happens. |
|||
* @param property method name of the component to call. |
|||
* @param value argument to pass to the method as String parameter. |
|||
*/ |
|||
public void setComponentProperty(String comp, String property, Object value) { |
|||
if (comp.equals("controller")) { |
|||
Class<? extends Object> clO = this.controller.getClass(); |
|||
for (Method m : clO.getMethods()) { |
|||
if (m.getName().indexOf(property) != -1) { |
|||
logger.debug("Method " + property + " found!!"); |
|||
try { |
|||
m.invoke(this.getObjectController(), value); |
|||
} catch (Exception e) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
public void setObjectFlag(String flag, Object value) { |
|||
this.playground.setLevelFlag(this.id + "/" + flag, value); |
|||
} |
|||
|
|||
|
|||
public Object getObjectFlag(String flag) { |
|||
return this.playground.getLevelFlag(this.id + "/" + flag); |
|||
} |
|||
|
|||
|
|||
public Object getOrCreateObjectFlag(String flag, Object createValue) { |
|||
return this.playground.getOrCreateLevelFlag(this.id + "/" + flag, createValue); |
|||
} |
|||
|
|||
|
|||
|
|||
public boolean isActive() { |
|||
return active; |
|||
} |
|||
|
|||
|
|||
public GameObject setActive(boolean flag) { |
|||
this.active = flag; |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* return the unique object ID. |
|||
* |
|||
* @return unique object ID |
|||
*/ |
|||
public String getId() { |
|||
return id; |
|||
} |
|||
|
|||
/** |
|||
* gets the screen X position. |
|||
* |
|||
* @return screen x position |
|||
*/ |
|||
public double getX() { |
|||
return x; |
|||
} |
|||
|
|||
/** |
|||
* gets the screen Y position. |
|||
* |
|||
* @return screen Y position |
|||
*/ |
|||
public double getY() { |
|||
return y; |
|||
} |
|||
|
|||
/** |
|||
* gets the screen X speed in pixels per frame. |
|||
* |
|||
* @return screen x speed |
|||
*/ |
|||
public double getVX() { |
|||
return vx; |
|||
} |
|||
|
|||
/** |
|||
* gets the screen Y speed in pixels per frame. |
|||
* |
|||
* @return screen y speed |
|||
*/ |
|||
public double getVY() { |
|||
return vy; |
|||
} |
|||
|
|||
/** |
|||
* set screen x position. |
|||
* |
|||
* @param x new position |
|||
*/ |
|||
public void setX(double x) { |
|||
if (this.active == true) { |
|||
this.x = x; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* set screen y position. |
|||
* |
|||
* @param y new position |
|||
*/ |
|||
public void setY(double y) { |
|||
if (this.active == true) { |
|||
this.y = y; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* set screen x speed in pixel per frame |
|||
* |
|||
* @param vx new x speed |
|||
*/ |
|||
public void setVX(double vx) { |
|||
if (this.active == true) { |
|||
this.vx = vx; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* set screen y speed in pixel per frame. |
|||
* |
|||
* @param vy new y speed. |
|||
*/ |
|||
public void setVY(double vy) { |
|||
if (this.active == true) { |
|||
this.vy = vy; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Sets a new object controller (replaces any former one). |
|||
* |
|||
* @param controller An instance of {@link controller.ObjectController} or one of its subclasses. |
|||
*/ |
|||
public void setObjectController(ObjectController controller) { |
|||
this.controller = controller; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Access to object controller. |
|||
* |
|||
* @return the controller for this object. |
|||
*/ |
|||
public ObjectController getObjectController() { |
|||
return this.controller; |
|||
} |
|||
|
|||
|
|||
public double getGameTime() { |
|||
return this.playground.getGameTime(); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* Collision detection implemented by iteration through the own list of {@link collider.Collider} |
|||
* and calling their {@link collider.Collider#collidesWith(Collider)} method to check collision |
|||
* with the given parameter instance of other {@link GameObject}. |
|||
* |
|||
* @param other instance of the other GameObject to check collision with |
|||
* @return true if collision is detected, false otherwise |
|||
*/ |
|||
public boolean collisionDetection(GameObject other) { |
|||
if (this.scol == null) { |
|||
return false; |
|||
} |
|||
for (Collider c : this.scol) { |
|||
logger.trace(other.id); |
|||
for (Collider o : other.scol) { |
|||
if (c.collidesWith(o)) { |
|||
logger.trace(c.id + " " + o.id); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
return false; |
|||
|
|||
} |
|||
|
|||
/** |
|||
* triggers this GameObjects own controller (if set) to update the object. |
|||
* |
|||
* @see GameObject#controller |
|||
*/ |
|||
public void updateObject() { |
|||
if (this.controller != null) { |
|||
controller.updateObject(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Draws the object in its current state. Is called by the game engine, should NOT be called |
|||
* otherwise. |
|||
* |
|||
* @param g object that has all the necessary drawing functionalities |
|||
*/ |
|||
public void draw(Graphics2D g) { |
|||
if (this.artist != null) { |
|||
this.artist.draw(g); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,76 @@ |
|||
package gameobjects; |
|||
|
|||
import java.awt.Color; |
|||
import java.io.File; |
|||
import collider.RectCollider; |
|||
import playground.Playground; |
|||
import playground.SpaceInvadersLevel; |
|||
import rendering.RectArtist; |
|||
|
|||
/** |
|||
* A rectangle object. <br> |
|||
* If {@link #generateColliders()} is called, it generates a RectCollider with id-prefix |
|||
* "shotcollider_" and registers it for this RectObject. |
|||
* |
|||
*/ |
|||
public class RectObject extends GameObject { |
|||
|
|||
/** width in pixels of the RectObject (> 0) */ |
|||
protected double width; |
|||
/** height in pixels of the RectObject (> 0) */ |
|||
protected double height; |
|||
|
|||
/** |
|||
* Initializes the RectObject with a suitable RectArtist for drawing the RectObject. |
|||
* |
|||
* @param id String unique name to be used. |
|||
* @param pg {@link Playground} instance this RectObject belongs to (the level it belongs to). |
|||
* @param x position in horizontal direction in pixels (zero or positive number). |
|||
* @param y position in vertical direction in pixels (zero or positive number). |
|||
* @param vx speed/velocity in horizontal direction in pixels (negative, zero or positive number). |
|||
* @param vy speed/velocity in vertical direction in pixels (negative, zero or positive number). |
|||
* @param width in pixels |
|||
* @param height in pixels |
|||
* @param color solid color for the whole object, used to initialize an instance of |
|||
* {@link rendering.RectArtist} used for this RectObject. |
|||
*/ |
|||
public RectObject(String id, Playground pg, double x, double y, double vx, double vy, |
|||
double width, double height, Color color) { |
|||
super(id, pg, x, y, vx, vy); |
|||
|
|||
this.width = width; |
|||
this.height = height; |
|||
|
|||
this.artist = new RectArtist(this, width, height, color); |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* generates a new {@link RectCollider} with id-prefix "shotcollider_" and registers it for 'this' |
|||
* [@link RectObject}. The {@link RectCollider} uses the same dimensions ({@link #width} and {@link #height}) as this RectObject. |
|||
* |
|||
* @return this RectObject itself |
|||
*/ |
|||
public RectObject generateColliders() { |
|||
this.scol.add(new RectCollider("shotcollider_" + id, this, this.width, this.height)); |
|||
return this; |
|||
} |
|||
|
|||
/** Getter for the width |
|||
* |
|||
* @return double width value as set by constructor |
|||
*/ |
|||
public double getWidth() { |
|||
return this.width; |
|||
} |
|||
|
|||
/** Getter for the height |
|||
* |
|||
* @return double height value as set by constructor |
|||
*/ |
|||
public double getHeight() { |
|||
return this.height; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,70 @@ |
|||
package gameobjects; |
|||
|
|||
import java.awt.Color; |
|||
import java.awt.Font; |
|||
import java.awt.Graphics2D; |
|||
import java.awt.font.FontRenderContext; |
|||
import java.awt.font.TextAttribute; |
|||
import java.text.AttributedString; |
|||
import java.util.LinkedList; |
|||
import collider.*; |
|||
import controller.ObjectController; |
|||
import playground.Playground; |
|||
import rendering.*; |
|||
|
|||
/** |
|||
* Convenience Class subclassing {@link GameObject}, directly instanciating {@link TextArtist} a |
|||
* subclass of {@link Artist} that draws a text. The controller is left undefined, the collider as |
|||
* well. However, a single call to the overwritten method {@link #generateColliders} will in fact |
|||
* generate a {@link RectCollider} of just the right size for the text. |
|||
* |
|||
*/ |
|||
public class TextObject extends GameObject { |
|||
|
|||
private String text = null; |
|||
protected double rx, ry; |
|||
|
|||
public String getText() { |
|||
return this.text; |
|||
} |
|||
|
|||
/** |
|||
* Constructor. |
|||
* |
|||
* @param id object name |
|||
* @param playground containing {@link Playground} instance |
|||
* @param x positionx |
|||
* @param y positiony |
|||
* @param vx speedx |
|||
* @param vy speedy |
|||
* @param size font size in Pixel |
|||
* @param text String to be displayed |
|||
* @param textColor text color, see java.awt.Color |
|||
*/ |
|||
public TextObject(String id, Playground playground, double x, double y, double vx, double vy, |
|||
String text, int size, Color textColor) { |
|||
super(id, playground, x, y, vx, vy); |
|||
|
|||
this.artist = new TextArtist(this, text, size, textColor); |
|||
|
|||
this.setColliders(new LinkedList<Collider>()); |
|||
|
|||
} |
|||
|
|||
|
|||
public void setText(String s) { |
|||
this.text = s; |
|||
((TextArtist) this.artist).setText(s); |
|||
} |
|||
|
|||
public TextObject generateColliders() { |
|||
// we need to Cast to TextArtist as we want to access Width and Height of text |
|||
TextArtist kruecke = (TextArtist) (this.artist); |
|||
|
|||
this.scol.clear(); |
|||
this.scol.add(new RectCollider("rect", this, kruecke.getTextWidth(), kruecke.getTextHeight())); |
|||
return this; |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<configuration status="OFF"> |
|||
<appenders> |
|||
|
|||
<Console name="Console" target="SYSTEM_OUT"> |
|||
<PatternLayout pattern="%d %-5level %logger{36} - %msg%n" /> |
|||
</Console> |
|||
|
|||
<File name="File" fileName="log\log4j.log"> |
|||
<PatternLayout pattern="%d %-5level %logger{36} - %msg%n" /> |
|||
</File> |
|||
|
|||
</appenders> |
|||
|
|||
<loggers> |
|||
|
|||
<root level="warn"> |
|||
<appender-ref ref="Console" /> |
|||
<appender-ref ref="File" /> |
|||
</root> |
|||
|
|||
<Logger name="base.GameLoop" level="info"> |
|||
</Logger> |
|||
|
|||
<Logger name="playground" level="info"> |
|||
</Logger> |
|||
|
|||
</loggers> |
|||
</configuration> |
@ -0,0 +1,84 @@ |
|||
package playground; |
|||
|
|||
|
|||
import java.awt.image.BufferedImage; |
|||
|
|||
import javax.imageio.ImageIO; |
|||
import java.io.File; |
|||
import java.io.*; |
|||
import java.io.FileNotFoundException; |
|||
import java.util.LinkedList; |
|||
import java.util.Locale; |
|||
import java.util.Scanner; |
|||
import java.nio.file.Path; |
|||
import java.nio.file.Paths; |
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
public class Animation { |
|||
|
|||
public LinkedList<String> fileList = null; |
|||
public LinkedList<Double> showtimeList = null; |
|||
public LinkedList<BufferedImage> imageList = null; |
|||
|
|||
private static Logger logger = LogManager.getLogger(Animation.class); |
|||
|
|||
public Animation(String datName) { |
|||
|
|||
Scanner scanner; |
|||
this.fileList = new LinkedList<String>(); |
|||
this.showtimeList = new LinkedList<Double>(); |
|||
this.imageList = new LinkedList<BufferedImage>(); |
|||
|
|||
try { |
|||
scanner = new Scanner(new File(datName), "UTF-8"); |
|||
|
|||
scanner.useLocale(Locale.GERMANY); |
|||
|
|||
String zeile; |
|||
double zeit; |
|||
int it = 0; |
|||
|
|||
while (scanner.hasNext()) { |
|||
if (scanner.hasNextDouble()) { |
|||
zeit = scanner.nextDouble(); |
|||
showtimeList.add(zeit); |
|||
} else { |
|||
zeile = scanner.next(); |
|||
Path basePath = Paths.get(datName); |
|||
String file = basePath.getParent().toString() + "/" + zeile; |
|||
fileList.add(file); |
|||
try { |
|||
this.imageList.add(ImageIO.read(new File(file))); |
|||
logger.info("img added " + file); |
|||
|
|||
} catch (IOException e) { |
|||
logger.warn(file + " not found!!"); |
|||
} |
|||
|
|||
it++; |
|||
logger.trace(basePath.getParent().toString() + "/" + zeile); |
|||
} |
|||
} |
|||
|
|||
scanner.close(); |
|||
|
|||
} catch (FileNotFoundException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
public LinkedList<String> getFileList() { |
|||
return this.fileList; |
|||
} |
|||
|
|||
public LinkedList<Double> getShowtimeList() { |
|||
return this.showtimeList; |
|||
} |
|||
|
|||
public LinkedList<BufferedImage> getImageList() { |
|||
return this.imageList; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,55 @@ |
|||
package playground; |
|||
|
|||
import java.io.*; |
|||
import java.util.Scanner; |
|||
|
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
|
|||
// Klasse um Highscore umzusetzen |
|||
public class HighscoreManager { |
|||
Scanner s; |
|||
private static Logger logger = LogManager.getLogger(HighscoreManager.class); |
|||
|
|||
public HighscoreManager() { |
|||
try { |
|||
File f = new File("./highscore.txt"); |
|||
if (!f.exists()) { |
|||
logger.warn("WARNING: Highscore file was not found and reset"); |
|||
writeHSToFile(0, -1); |
|||
} |
|||
s = new Scanner(f); |
|||
} catch (FileNotFoundException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
public int readHSFromFile() { |
|||
if (s.hasNext()) { |
|||
int highscore = s.nextInt(); |
|||
return highscore; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
public static void writeHSToFile(Integer pts, Integer highscore) { |
|||
String highscore2 = String.valueOf(pts); |
|||
BufferedWriter bw; |
|||
try { |
|||
if (pts > highscore) { |
|||
FileWriter fw = new FileWriter("./highscore.txt"); |
|||
bw = new BufferedWriter(fw); |
|||
bw.write(highscore2); |
|||
bw.close(); |
|||
logger.info("Highscore file was opened and saved score: " + highscore2); |
|||
} |
|||
} catch (IOException e) { |
|||
logger.error("File for Highscore not writeable! Score lost."); |
|||
} |
|||
} |
|||
|
|||
public void closeFile() { |
|||
s.close(); |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
package playground; |
|||
|
|||
|
|||
/** |
|||
* extends {@link SpaceInvadersLevel} with a boring start message |
|||
*/ |
|||
public class Level1 extends SpaceInvadersLevel { |
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "Get ready for boring level 1!"; |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package playground; |
|||
|
|||
|
|||
|
|||
/** |
|||
* extends extends {@link SpaceInvadersLevel} with a different startup message. |
|||
*/ |
|||
public class Level2 extends SpaceInvadersLevel { |
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "Get ready for level 2!"; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,40 @@ |
|||
package playground; |
|||
|
|||
import org.apache.logging.log4j.LogManager; |
|||
import org.apache.logging.log4j.Logger; |
|||
import controller.ObjectController; |
|||
import controller.ZickZackController; |
|||
import gameobjects.AnimatedGameobject; |
|||
import gameobjects.GameObject; |
|||
|
|||
|
|||
/** |
|||
* extends {@link SpaceInvadersLevel} with a ZigZack move of the enemies in |
|||
* {@link #createSingleEnemy(String, double, double, double, double, ObjectController, double)} and |
|||
* sets a different {@link #getStartupMessage()}. |
|||
*/ |
|||
public class Level3 extends SpaceInvadersLevel { |
|||
|
|||
private static Logger logger = LogManager.getLogger(Level3.class); |
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "Get ready for level 3!!!"; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
protected GameObject createSingleEnemy(String name, double x_enemy, double y_enemy, |
|||
double vx_enemy, double vy_enemy, ObjectController enemyController, double gameTime) { |
|||
logger.trace("creating enemy [" + name + "] with ZickZackController "); |
|||
ObjectController zzController = new ZickZackController(gameTime, 0.5); |
|||
GameObject go = new AnimatedGameobject(name, this, x_enemy, y_enemy, vx_enemy, vy_enemy, |
|||
ENEMYSCALE, this.enemyAnim, this.getGameTime(), "loop").addController(zzController) |
|||
.generateColliders(); |
|||
|
|||
return go.generateColliders(); |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,63 @@ |
|||
package playground; |
|||
|
|||
import gameobjects.GameObject; |
|||
import controller.LimitedTimeController; |
|||
import gameobjects.TextObject; |
|||
import java.awt.Color; |
|||
import org.apache.logging.log4j.LogManager; |
|||
import org.apache.logging.log4j.Logger; |
|||
|
|||
|
|||
|
|||
/** |
|||
* extends extends {@link SpaceInvadersLevel} |
|||
* <ul> |
|||
* <li>Hit aliens twice to kill them |
|||
* <li>they say AUA when not destroyed |
|||
* </ul> |
|||
*/ |
|||
public class Level4 extends SpaceInvadersLevel { |
|||
|
|||
/** constant defining the number of shots needed to destroy an enemy */ |
|||
public static final int MAX_HITS = 2; |
|||
|
|||
private static Logger logger = LogManager.getLogger(Level4.class); |
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "Jetzt gibts Saures!"; |
|||
} |
|||
|
|||
@Override |
|||
void actionIfEnemyIsHit(GameObject e, GameObject shot) { |
|||
double gameTime = this.getGameTime(); |
|||
|
|||
Object counterFlag = e.getOrCreateObjectFlag("counter", Integer.valueOf(1)); |
|||
|
|||
int counter = (Integer) counterFlag; |
|||
|
|||
if (counter >= MAX_HITS) { |
|||
logger.trace("enemy was hit before for " + counter + " times, which is above " |
|||
+ LevelHitTwice.MAX_HITS); |
|||
super.actionIfEnemyIsHit(e, shot); |
|||
} else { |
|||
logger.trace("enemy was hit before for "+counter+" times, which is below "+LevelHitTwice.MAX_HITS); |
|||
e.setObjectFlag("counter", Integer.valueOf(counter + 1)); |
|||
// spawn a bonus points object |
|||
double vx = 2 * (Math.random() - 0.5) * SHARDSPEED + e.getVX(); |
|||
double vy = 2 * (Math.random() - 0.5) * SHARDSPEED + e.getVY(); |
|||
logger.trace("creating new TextObject bonus" + e.getId()); |
|||
LimitedTimeController bonusTextController = |
|||
new LimitedTimeController(gameTime, SpaceInvadersLevel.EXPL_DURATION); |
|||
GameObject bonusText = new TextObject("bonus" + e.getId(), this, e.getX(), e.getY(), vx, vy, |
|||
"Aua", 20, Color.YELLOW).addController(bonusTextController); |
|||
|
|||
this.addObject(bonusText); |
|||
} |
|||
deleteObject(shot.getId()); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,112 @@ |
|||
package playground; |
|||
|
|||
import java.awt.Color; |
|||
import org.apache.logging.log4j.LogManager; |
|||
import org.apache.logging.log4j.Logger; |
|||
import controller.EgoController; |
|||
import controller.FallingStarController; |
|||
import controller.ObjectController; |
|||
import gameobjects.AnimatedGameobject; |
|||
import gameobjects.EgoObject; |
|||
import gameobjects.FallingStar; |
|||
import gameobjects.GameObject; |
|||
import gameobjects.TextObject; |
|||
|
|||
/** |
|||
* Class that realizes all the game logic of a very simple game level. The level contains for now |
|||
* only two objects that are {@link GameObject} subclasses: {@link FallingStar} and |
|||
* {@link EgoObject}. Functions performed by this class are: |
|||
* <ul> |
|||
* <li>initially set up the level, spawn all object etc., in method {@link #prepareLevel} |
|||
* <li>React to keyboard commands in method {@link #processKeyEvents(java.util.Stack)} |
|||
* <li>define basic object movement rules for all objects in the level in the various |
|||
* ObjectController subclasses: {@link EgoController} and {@link FallingStarController}. |
|||
* </ul> |
|||
*/ |
|||
public class LevelBoss extends SpaceInvadersLevel { |
|||
|
|||
private static int MAX_SHOTS = 10; |
|||
private static Logger logger = LogManager.getLogger(LevelBoss.class); |
|||
|
|||
@Override |
|||
void actionIfEnemyIsHit(GameObject e, GameObject shot) { |
|||
|
|||
Object counterFlag = e.getOrCreateObjectFlag("counter", Integer.valueOf(1)); |
|||
|
|||
int counter = (Integer) counterFlag; |
|||
|
|||
if (counter >= LevelBoss.MAX_SHOTS) { |
|||
logger.trace("enemy was hit before for " + counter + " times, which is equal or above " |
|||
+ LevelHitTwice.MAX_HITS); |
|||
super.actionIfEnemyIsHit(e, shot); |
|||
} else { |
|||
logger.trace("enemy was hit before for " + counter + " times, which is below " |
|||
+ LevelHitTwice.MAX_HITS); |
|||
e.setObjectFlag("counter", Integer.valueOf(counter + 1)); |
|||
} |
|||
deleteObject(shot.getId()); |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
double calcEnemyShotProb() { |
|||
return 1.5 * this.getTimestep(); |
|||
} |
|||
|
|||
@Override |
|||
protected double calcEnemySpeedX() { |
|||
return ENEMYSPEEDX * 2; |
|||
} |
|||
|
|||
@Override |
|||
protected double calcEnemySpeedY() { |
|||
return ENEMYSPEEDY * 2; |
|||
} |
|||
|
|||
@Override |
|||
protected int calcNrEnemies() { |
|||
return (int) 1; |
|||
} |
|||
|
|||
@Override |
|||
protected GameObject createEnemyShotObject(GameObject parentObject, String name, |
|||
ObjectController limitedTimeController) { |
|||
GameObject ego = this.getObject("ego"); |
|||
|
|||
double deltax = parentObject.getX() - ego.getX(); |
|||
double deltay = parentObject.getY() - ego.getY(); |
|||
|
|||
double norm = Math.sqrt(deltax * deltax + deltay * deltay); |
|||
deltax *= -ENEMYSHOTSPEED / norm; |
|||
deltay *= -ENEMYSHOTSPEED / norm; |
|||
|
|||
logger.trace("Creating EnemyShot as TextObject [" + name + "] in direction " + deltax + "/" |
|||
+ deltay + " towards ego"); |
|||
GameObject to = new TextObject(name, this, parentObject.getX(), parentObject.getY(), deltax, |
|||
deltay, "*", 20, Color.GREEN).generateColliders().addController(limitedTimeController); |
|||
return to; |
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
protected GameObject createSingleEnemy(String name, double x_enemy, double y_enemy, |
|||
double vx_enemy, double vy_enemy, ObjectController enemyController, double gameTime) { |
|||
|
|||
GameObject go = new AnimatedGameobject(name, this, this.canvasX / 2, 10, vx_enemy, 50, |
|||
ENEMYSCALE * 3, this.enemyAnim, this.getGameTime(), "loop").generateColliders() |
|||
.addController(enemyController); |
|||
|
|||
return go; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "BOSS LEVEL!"; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,65 @@ |
|||
package playground; |
|||
|
|||
import controller.FallingStarController; |
|||
import gameobjects.EgoObject; |
|||
import gameobjects.FallingStar; |
|||
import gameobjects.GameObject; |
|||
import gameobjects.RectObject; |
|||
import java.awt.Color; |
|||
import org.apache.logging.log4j.LogManager; |
|||
import org.apache.logging.log4j.Logger; |
|||
|
|||
|
|||
|
|||
/** |
|||
* extends {@link SpaceInvadersLevel} with 10 enemies that need two shots each to be destroyed. |
|||
* |
|||
*/ |
|||
|
|||
|
|||
public class LevelHitTwice extends SpaceInvadersLevel { |
|||
|
|||
/** constant defining the number of shots needed to destroy an enemy */ |
|||
public static final int MAX_HITS = 2; |
|||
|
|||
private static Logger logger = LogManager.getLogger(LevelHitTwice.class); |
|||
|
|||
/** constructor setting internal name to 'hitTwice' */ |
|||
public LevelHitTwice() { |
|||
super(); |
|||
this.level = "hitTwice"; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
protected String getStartupMessage() { |
|||
return "2 shots at alien required!!!"; |
|||
} |
|||
|
|||
@Override |
|||
protected int calcNrEnemies() { |
|||
return 10; |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
void actionIfEnemyIsHit(GameObject e, GameObject shot) { |
|||
Object counterFlag = e.getOrCreateObjectFlag("counter", Integer.valueOf(1)); |
|||
|
|||
int counter = (Integer) counterFlag; |
|||
|
|||
if (counter >= MAX_HITS) { |
|||
logger.trace("enemy was hit before for " + counter + " times, which is above " |
|||
+ LevelHitTwice.MAX_HITS); |
|||
super.actionIfEnemyIsHit(e, shot); |
|||
} else { |
|||
logger.trace("enemy was hit before for "+counter+" times, which is below "+LevelHitTwice.MAX_HITS); |
|||
e.setObjectFlag("counter", Integer.valueOf(counter + 1)); |
|||
} |
|||
deleteObject(shot.getId()); |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,48 @@ |
|||
package playground; |
|||
|
|||
import java.io.File; |
|||
import javax.sound.sampled.AudioInputStream; |
|||
import javax.sound.sampled.AudioSystem; |
|||
import javax.sound.sampled.Clip; |
|||
import javax.sound.sampled.FloatControl; |
|||
|
|||
public class Music { |
|||
private static final float volume = 0.02f; // scale 0 silence, 1 no change, 2 double. (linear). |
|||
|
|||
public static synchronized void music(File track) { |
|||
|
|||
final File trackname = track; |
|||
|
|||
new Thread(new Runnable() { |
|||
|
|||
@Override |
|||
public void run() { |
|||
while (true) { |
|||
|
|||
try { |
|||
|
|||
Clip clip = AudioSystem.getClip(); |
|||
AudioInputStream inputstream = AudioSystem.getAudioInputStream(trackname); |
|||
clip.open(inputstream); |
|||
FloatControl volumeControl = |
|||
(FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); |
|||
if (volumeControl != null) { |
|||
volumeControl.setValue(20f * (float) Math.log10(volume)); |
|||
} |
|||
clip.start(); |
|||
|
|||
Thread.sleep(clip.getMicrosecondLength() / 1); |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
}).start(); |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,374 @@ |
|||
package playground; |
|||
|
|||
import java.awt.Graphics2D; |
|||
import java.util.HashMap; |
|||
import java.util.LinkedList; |
|||
import java.util.Map; |
|||
import java.util.Stack; |
|||
import java.awt.event.*; |
|||
import gameobjects.GameObject; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* Playground represents a level of the game, focusing on the game LOGIC, i.e., not so much on the |
|||
* graphical representation. In particular, an instance of Playground |
|||
* <ul> |
|||
* <li>manages the different moving or static objects in a level (e.g., collisions, adding objects, |
|||
* removing objects). This is mainly done by the methods {@link #addObject}, {@link #deleteObject}. |
|||
* <li>processes keyboard inputs provided by GameLoop in {@link #processKeyEvents(Stack)} and |
|||
* {@link #processMouseEvents(Stack)} |
|||
* <li>represents the state of a level represented by <b>flags</b>. Each flag has a name (a String) |
|||
* and an arbitrary value of any type. Methods: {@link #setLevelFlag(String, Object)}, |
|||
* {@link #getLevelFlag(String)}. As an example, the current score is a flag usually named "points", |
|||
* with an Integer as a value. This value can be retrieved and manipulated using the above mentioned |
|||
* methods. |
|||
* </ul> |
|||
*/ |
|||
public abstract class Playground { |
|||
|
|||
public static final int FLAGS_GLOBAL = 1; |
|||
public static final int FLAGS_LEVEL = 2; |
|||
public static final int FLAGS_ALL = 3; |
|||
protected int canvasX = -1; |
|||
protected int canvasY = -1; |
|||
|
|||
/** only one set of objects exists concurrently so this can be static */ |
|||
protected static HashMap<String, GameObject> gameObjects = new HashMap<String, GameObject>(); |
|||
|
|||
/** only one set of objects exists concurrently so this can be static */ |
|||
protected static HashMap<String, Object> flags = new HashMap<String, Object>(); |
|||
|
|||
protected String level = ""; |
|||
protected double timeStep = 0; |
|||
protected double gameTime = 0; |
|||
LinkedList<GameObject> addables = new LinkedList<GameObject>(); |
|||
LinkedList<String> removables = new LinkedList<String>(); |
|||
// HashMap<Integer,Integer> keys ; |
|||
Stack<KeyEvent> keyEvents; |
|||
Stack<MouseEvent> mouseEvents; |
|||
|
|||
protected boolean pausedFlag = false; |
|||
|
|||
private static Logger logger = LogManager.getLogger(Playground.class); |
|||
|
|||
public Playground() { |
|||
this.canvasX = -1; |
|||
this.canvasY = -1; |
|||
} |
|||
|
|||
// here, the level communicates its size preference to the GameUI |
|||
// called automatically |
|||
public abstract int preferredSizeX(); |
|||
|
|||
public abstract int preferredSizeY(); |
|||
|
|||
/** |
|||
* Adds a graphics object to a level. |
|||
* |
|||
* @param o GameObject The object to be added |
|||
*/ |
|||
public void addObject(GameObject o) { |
|||
// gameObjects.put(o.getId(), o); |
|||
addables.addLast(o); |
|||
} |
|||
|
|||
/** |
|||
* Adds a graphics object to a level. |
|||
* |
|||
* @param o GameObject The object to be added |
|||
*/ |
|||
public void addObjectNow(GameObject o) { |
|||
gameObjects.put(o.getId(), o); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Puts objects with a certain substring in their name into a LinkedLisrt and returns them. |
|||
* |
|||
* @param substr The string that must be part of the object name if object is to be considered |
|||
* found. |
|||
* @param filterInactive if set true only active objects are considered. |
|||
* @return a reference to a LinkedList filled with all objects that have <b>substr</b> in their |
|||
* name |
|||
*/ |
|||
public LinkedList<GameObject> collectObjects(String substr, boolean filterInactive) { |
|||
LinkedList<GameObject> l = new LinkedList<GameObject>(); |
|||
for (Map.Entry<String, GameObject> entry : Playground.gameObjects.entrySet()) { // Iterator |
|||
// usage |
|||
GameObject obj = entry.getValue(); |
|||
if (obj.getId().contains(substr)) { |
|||
if (filterInactive == true) { |
|||
if (obj.isActive()) { |
|||
l.add(obj); |
|||
} |
|||
} else { |
|||
l.add(obj); |
|||
} |
|||
} |
|||
} |
|||
return l; |
|||
}; |
|||
|
|||
|
|||
/** |
|||
* Removes a graphics object from a level. |
|||
* |
|||
* @param id String The unique identifier of the object |
|||
*/ |
|||
public void deleteObject(String id) { |
|||
// gameObjects.remove(id); |
|||
removables.addLast(id); |
|||
} |
|||
|
|||
/** |
|||
* Removes a graphics object from a level immediately, CAUTION. |
|||
* |
|||
* @param id String The unique identifier of the object |
|||
*/ |
|||
public void deleteObjectNow(String id) { |
|||
gameObjects.remove(id); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Retrieves a graphics object by name. |
|||
* |
|||
* @param id String Unique id of the object |
|||
* @return reference to the requested game object, or null if not found |
|||
*/ |
|||
public GameObject getObject(String id) { |
|||
return gameObjects.get(id); |
|||
} |
|||
|
|||
/** |
|||
* Sets a level-wide permanent flag. |
|||
* |
|||
* @param flag String Q unique name in this level. If it exists value is overwritten. |
|||
* @param value Object Any Object can be the value of a flag! |
|||
*/ |
|||
|
|||
public static void setGlobalFlag(String flag, Object value) { |
|||
flags.put("/global/" + flag, value); |
|||
} |
|||
|
|||
public Object setLevelFlag(String flag, Object value) { |
|||
flags.put("/" + this.level + "/" + flag, value); |
|||
return value; |
|||
} |
|||
|
|||
/** |
|||
* mode can be: FLAGS_ALL (all), FLAGS_GLOBAL(global), FLAGs_LEVEL(level) |
|||
* |
|||
* @param mode can be only one of {@link #FLAGS_GLOBAL} {@link #FLAGS_ALL} or |
|||
* {@link #FLAGS_LEVEL } |
|||
*/ |
|||
public void resetFlags(int mode) { |
|||
LinkedList<String> delKeys = new LinkedList<String>(); |
|||
for (Map.Entry<String, Object> entry : Playground.flags.entrySet()) { |
|||
logger.trace(entry.getKey() + " IndexofGlobal = " + entry.getKey().indexOf("/global/")); |
|||
if ((mode == FLAGS_GLOBAL) && (entry.getKey().indexOf("/global/") != -1)) { |
|||
logger.debug("GLOBAL: scheduling for removal: " + entry.getKey()); |
|||
delKeys.add(entry.getKey()); |
|||
} else if ((mode == FLAGS_LEVEL) && (entry.getKey().indexOf("/global/") == -1)) { |
|||
logger.debug("LEVEL: scheduling for removal: " + entry.getKey()); |
|||
delKeys.add(entry.getKey()); |
|||
} else if (mode == FLAGS_ALL) { |
|||
logger.debug("ALL: scheduling for removal: " + entry.getKey()); |
|||
delKeys.add(entry.getKey()); |
|||
} |
|||
} |
|||
|
|||
for (String str : delKeys) { |
|||
logger.trace("removing key " + str); |
|||
flags.remove(str); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Retrieves a level-wide flag by name. |
|||
* |
|||
* @param flag String Unique flag id |
|||
* @return the value associated with <b>flag</b>, or <b>null</b> if the flag does not exist. |
|||
*/ |
|||
public static Object getGlobalFlag(String flag) { |
|||
return flags.get("/global/" + flag); |
|||
} |
|||
|
|||
/** checks for existence and if not creates the new global flag with the given initial value. Returns the value. |
|||
* afterwards it is guaranteed that no priorly existing value is overridden and that it definitely exists (created if not present before). |
|||
* |
|||
* @param flag String name for the global flag (created if not present) |
|||
* @param value Object value to be stored (used only if flag was not present) |
|||
* @return the current value of the flag (maybe the initial one in case flag was not there before) |
|||
*/ |
|||
public static Object getOrCreateGlobalFlag(String flag, Object value) { |
|||
Object tmp = getGlobalFlag(flag); |
|||
if (tmp == null) { |
|||
setGlobalFlag(flag, value); |
|||
return value; |
|||
} else { |
|||
return tmp; |
|||
} |
|||
} |
|||
|
|||
|
|||
public Object getLevelFlag(String flag) { |
|||
return flags.get("/" + this.level + "/" + flag); |
|||
} |
|||
|
|||
public Object getOrCreateLevelFlag(String flag, Object createValue) { |
|||
Object tmp = getLevelFlag(flag); |
|||
if (tmp == null) { |
|||
return setLevelFlag(flag, createValue); |
|||
} else { |
|||
return tmp; |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Reinitializes the level. |
|||
*/ |
|||
public void reset() { |
|||
gameObjects.clear(); |
|||
} |
|||
|
|||
public boolean isPaused() { |
|||
return this.pausedFlag; |
|||
} |
|||
|
|||
public void setPaused(boolean p) { |
|||
this.pausedFlag = p; |
|||
} |
|||
|
|||
public void togglePause() { |
|||
pausedFlag = !pausedFlag; |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* Method meant to be filled with own code, processes Keyboard inputs. |
|||
* |
|||
* @param keyEvents all collected {@link KeyEvent}s collected since last game loop. |
|||
*/ |
|||
|
|||
public void processKeyEvents(Stack<KeyEvent> keyEvents) { |
|||
this.keyEvents = keyEvents; |
|||
Playground.setGlobalFlag("inputs", keyEvents); |
|||
} |
|||
|
|||
|
|||
public void processMouseEvents(Stack<MouseEvent> mouseEvents) { |
|||
this.mouseEvents = mouseEvents; |
|||
Playground.setGlobalFlag("inputs", mouseEvents); |
|||
} |
|||
|
|||
|
|||
public Stack<KeyEvent> getKeyEvents() { |
|||
return this.keyEvents; |
|||
} |
|||
|
|||
public Stack<MouseEvent> getMouseEvents() { |
|||
return this.mouseEvents; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Method meant to be filled with own code, handles the entore game logic (collision checks, timed |
|||
* events, ...). |
|||
* |
|||
*/ |
|||
public abstract void applyGameLogic(); |
|||
|
|||
/** |
|||
* Sets up a single level. Prepares all objects etc. |
|||
* |
|||
* @param level String a string identifying the level number etc |
|||
*/ |
|||
public abstract void prepareLevel(String level); |
|||
|
|||
public abstract boolean gameOver(); |
|||
|
|||
public abstract boolean levelFinished(); |
|||
|
|||
public int getSizeX() { |
|||
return canvasX; |
|||
} |
|||
|
|||
public int getSizeY() { |
|||
return canvasY; |
|||
} |
|||
|
|||
/** |
|||
* Calls all object update methods in level. Internal, never call directly. |
|||
* |
|||
*/ |
|||
public void updateObjects() { |
|||
for (GameObject gameObject : gameObjects.values()) { // Iterator usage |
|||
if (gameObject.isActive() == true) { |
|||
gameObject.updateObject(); |
|||
logger.trace("updated object " + gameObject.scol); |
|||
} |
|||
} |
|||
|
|||
for (GameObject o : addables) { // Iterator usage |
|||
addObjectNow(o); |
|||
} |
|||
|
|||
for (String s : removables) { // Iterator usage |
|||
deleteObjectNow(s); |
|||
} |
|||
removables.clear(); |
|||
addables.clear(); |
|||
} |
|||
|
|||
public void setTimestep(double s) { |
|||
timeStep = s; |
|||
} |
|||
|
|||
public double getTimestep() { |
|||
return timeStep; |
|||
} |
|||
|
|||
/** set the game time value (in seconds) |
|||
* |
|||
* @param s seconds the game is running |
|||
*/ |
|||
public void setGameTime(double s) { |
|||
this.gameTime = s; |
|||
} |
|||
|
|||
/** returns time in seconds since level start */ |
|||
public double getGameTime() { |
|||
return this.gameTime; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* To be redefined!! Draws mainly h level background and global information like points etc. |
|||
* |
|||
* @param g2 Graphics2D abstract drawing object of java Swing, used to carry out all drawing |
|||
* operations. |
|||
*/ |
|||
public abstract void redrawLevel(Graphics2D g2); |
|||
|
|||
/** |
|||
* Internal, do not call directly. |
|||
* |
|||
* @param g2 Graphics2D abstract drawing object of java Swing, used to carry out all drawing |
|||
* operations. |
|||
*/ |
|||
public void redraw(Graphics2D g2) { |
|||
redrawLevel(g2); |
|||
for (GameObject gameObject : gameObjects.values()) { |
|||
if (gameObject.isActive()) { |
|||
gameObject.draw(g2); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,62 @@ |
|||
package playground; |
|||
|
|||
import java.io.FileInputStream; |
|||
import java.io.FileNotFoundException; |
|||
import java.io.FileOutputStream; |
|||
import java.io.IOException; |
|||
import java.io.ObjectInputStream; |
|||
import java.io.ObjectOutputStream; |
|||
import java.util.ArrayList; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
public class SaveGame { |
|||
|
|||
private static String datnam = "aktuellerSpielzustand.ser"; |
|||
private static Logger logger = LogManager.getLogger(SaveGame.class); |
|||
|
|||
|
|||
@SuppressWarnings("unchecked") |
|||
public static void save() { |
|||
|
|||
// gameobjects.AnimatedGameobject |
|||
ArrayList<String> objArrList = null; |
|||
ObjectInputStream in = null; |
|||
try { |
|||
in = new ObjectInputStream(new FileInputStream(datnam)); |
|||
objArrList = (ArrayList<String>) in.readObject(); |
|||
} catch (FileNotFoundException ex) { |
|||
logger.warn("Savegame file not (yet) existing!"); |
|||
} catch (Exception ex) { |
|||
logger.error(ex); |
|||
} finally { |
|||
try { |
|||
if (in != null) |
|||
in.close(); |
|||
} catch (IOException e) { |
|||
} |
|||
} |
|||
if (objArrList == null) |
|||
objArrList = new ArrayList<String>(); |
|||
|
|||
objArrList.add(new String("ArrayListgroesse: " + objArrList.size())); |
|||
logger.debug(objArrList); |
|||
|
|||
ObjectOutputStream aus = null; |
|||
try { |
|||
aus = new ObjectOutputStream(new FileOutputStream(datnam)); |
|||
aus.writeObject(objArrList); |
|||
} catch (IOException ex) { |
|||
logger.error(ex); |
|||
} finally { |
|||
try { |
|||
if (aus != null) { |
|||
aus.flush(); |
|||
aus.close(); |
|||
} |
|||
} catch (IOException e) { |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,678 @@ |
|||
package playground; |
|||
|
|||
// import utilities.* ; |
|||
import java.awt.Color; |
|||
import java.awt.Font; |
|||
import java.awt.Graphics2D; |
|||
import java.awt.Polygon; |
|||
import java.awt.RenderingHints; |
|||
import java.awt.font.TextAttribute; |
|||
import java.awt.image.BufferedImage; |
|||
import java.io.*; |
|||
import java.text.AttributedString; |
|||
import java.util.LinkedList; |
|||
import controller.EnemyController; |
|||
import controller.FallingStarController; |
|||
import controller.LimitedTimeController; |
|||
import controller.ObjectController; |
|||
import controller.EgoController; |
|||
import controller.CollisionAwareEgoController; |
|||
import gameobjects.AnimatedGameobject; |
|||
import gameobjects.FallingStar; |
|||
import gameobjects.GameObject; |
|||
import gameobjects.EgoObject; |
|||
import gameobjects.TextObject; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
/** |
|||
* Class that realizes all the game logic of a very simple game level. The level contains for now |
|||
* only two objects that are {@link GameObject} subclasses: {@link FallingStar} and |
|||
* {@link EgoObject}. Functions performed by this class are: |
|||
* <ul> |
|||
* <li>initially set up the level, spawn all object etc., in method {@link #prepareLevel} |
|||
* <li>React to game events in {@link #actionIfEgoCollidesWithCollect(GameObject, GameObject)} , |
|||
* {@link #actionIfEgoCollidesWithEnemy(GameObject, GameObject)}, etc. |
|||
* <li>define basic object movement rules for all objects in the level in the various |
|||
* ObjectController subclasses: {@link EgoController} and {@link FallingStarController}. |
|||
* </ul> |
|||
*/ |
|||
public class SpaceInvadersLevel extends Playground { |
|||
|
|||
public static final double SHOTSPEED = 175; |
|||
public static final double EGOSPEED = 220; |
|||
protected static final int LEVEL2STARS = 80; |
|||
protected static final double BONUS_DURATION = 1.; |
|||
protected static final double ENEMYSPEEDX = 60; |
|||
protected static final double ENEMYSPEEDY = 40; |
|||
protected static final double ENEMYSCALE = 1.0; |
|||
protected static final double ENEMYSHOTSPEED = 75; |
|||
protected static final int NRSHARDS = 50; |
|||
protected static final double EXPL_DURATION = 1.; |
|||
protected static final int NR_ENEMIES = 30; |
|||
protected static final int NR_COLLECT = 5; |
|||
protected static final Color EXPL_COLOR = Color.RED; |
|||
protected static final double SHARDSPEED = 200; |
|||
protected static final double STARSPEED = 100; |
|||
protected static final double STARTTEXTSPEED = 75; |
|||
protected static final double STARTPERIOD = 5.; |
|||
protected static final double DYING_INTERVAL = 2.0; |
|||
protected static final int CANVASX = 700; |
|||
protected static final int CANVASY = 700; |
|||
protected static final double EGORAD = 15; |
|||
protected static final double LEVEL_INIT_TIME = 1.0; |
|||
|
|||
protected int nextShot = 0; |
|||
|
|||
protected boolean lost = false; |
|||
protected boolean doneLevel = false; |
|||
protected double starttime = 0; |
|||
protected File smash = null; |
|||
protected File laser = null; |
|||
|
|||
protected BufferedImage[] alienImage = null; |
|||
protected double[] alienshowTime = null; |
|||
|
|||
protected BufferedImage[] heartImage = null; |
|||
protected double[] heartshowTime = null; |
|||
|
|||
protected Animation enemyAnim = null; |
|||
protected Animation heartAnim = null; |
|||
|
|||
private static Logger logger = LogManager.getLogger(SpaceInvadersLevel.class); |
|||
|
|||
public SpaceInvadersLevel() { |
|||
super(); |
|||
this.canvasX = this.preferredSizeX(); |
|||
this.canvasY = this.preferredSizeY(); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* initially sets up the level. Not called by user interaction, but called every time a layer is |
|||
* restarted from scratch. So make sure that this is possible. Here, resources are loaded only |
|||
* once even if method is called several times. |
|||
* |
|||
* @param id String identifies level. |
|||
*/ |
|||
@Override |
|||
public void prepareLevel(String id) { |
|||
logger.info("PREPARE"); |
|||
reset(); |
|||
this.doneLevel = false; |
|||
this.lost = false; |
|||
resetFlags(FLAGS_LEVEL); |
|||
|
|||
// set up flags that some objects rely on |
|||
setLevelFlag("delete", new LinkedList<String>()); |
|||
setLevelFlag("replace", new LinkedList<String>()); |
|||
getOrCreateGlobalFlag("points", Integer.valueOf(0)); |
|||
setLevelFlag("enemyShotCounter", Integer.valueOf(0)); |
|||
setLevelFlag("gameStatus", "start"); |
|||
setLevelFlag("detailedStatus", "std"); |
|||
getOrCreateGlobalFlag("egoLives", Integer.valueOf(5)); |
|||
setLevelFlag("dying", Double.valueOf(-1)); |
|||
|
|||
// start time measure |
|||
this.starttime = this.getGameTime(); |
|||
|
|||
// music load |
|||
if (this.smash == null) { |
|||
this.smash = new File("./audio/smash.wav"); |
|||
} |
|||
if (this.laser == null) { |
|||
this.laser = new File("./audio/laser.wav"); |
|||
} |
|||
|
|||
// ----- Alien |
|||
if (this.enemyAnim == null) { |
|||
String dateiName = "./video/sweetAlien.txt"; |
|||
this.enemyAnim = new Animation(dateiName); |
|||
} |
|||
|
|||
// -----Heart |
|||
if (this.heartAnim == null) { |
|||
String heartName = "./video/heart.txt"; |
|||
this.heartAnim = new Animation(heartName); |
|||
} |
|||
|
|||
// load highscore and update |
|||
HighscoreManager dh = new HighscoreManager(); |
|||
int alltimeHighscore = dh.readHSFromFile(); |
|||
setGlobalFlag("highscore", alltimeHighscore); |
|||
logger.info("HIGHSCORE" + alltimeHighscore); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* (re)draws the level but NOT the objects, they draw themselves. Called by the main game loop. |
|||
* This method mainly draws the background and the scoreboard. |
|||
* |
|||
* @param g2 Graphics2D object that can, and should be, draw on. |
|||
*/ |
|||
@Override |
|||
public void redrawLevel(Graphics2D g2) { |
|||
// Set anti-alias! |
|||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); |
|||
// Set anti-alias for text |
|||
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, |
|||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); |
|||
|
|||
// fill background with black |
|||
int[] x = {0, canvasX, canvasX, 0}; |
|||
int[] y = {0, 0, canvasY, canvasY}; |
|||
Polygon bg = new Polygon(x, y, 4); |
|||
g2.setColor(Color.BLACK); |
|||
g2.fill(bg); |
|||
|
|||
// draw score in upper left part of playground |
|||
Integer pts = (Integer) getGlobalFlag("points"); |
|||
Font drawFont = new Font("SansSerif", Font.PLAIN, 20); |
|||
AttributedString as = new AttributedString("Points: " + pts); |
|||
as.addAttribute(TextAttribute.FONT, drawFont); |
|||
as.addAttribute(TextAttribute.FOREGROUND, Color.yellow); |
|||
g2.drawString(as.getIterator(), 10, 20); |
|||
|
|||
// draw lives counter in upper left part of playground |
|||
Integer lives = (Integer) getGlobalFlag("egoLives"); |
|||
Font drawFont2 = new Font("SansSerif", Font.PLAIN, 20); |
|||
AttributedString as2 = new AttributedString("Lives: " + lives); |
|||
as2.addAttribute(TextAttribute.FONT, drawFont2); |
|||
as2.addAttribute(TextAttribute.FOREGROUND, Color.yellow); |
|||
g2.drawString(as2.getIterator(), canvasX - 100, 20); |
|||
|
|||
// draw highscore in left part of playground under score |
|||
Integer highscore = (Integer) getGlobalFlag("highscore"); |
|||
Font drawFont3 = new Font("SansSerif", Font.PLAIN, 20); |
|||
AttributedString as3 = new AttributedString("Highscore: " + highscore); |
|||
as3.addAttribute(TextAttribute.FONT, drawFont3); |
|||
as3.addAttribute(TextAttribute.FOREGROUND, Color.yellow); |
|||
g2.drawString(as3.getIterator(), 10, 40); |
|||
|
|||
if (isPaused()) { |
|||
Font drawFont4 = new Font("SansSerif", Font.PLAIN, 50); |
|||
AttributedString as4 = new AttributedString("Das Spiel wurde pausiert."); |
|||
as4.addAttribute(TextAttribute.FONT, drawFont4); |
|||
as4.addAttribute(TextAttribute.FOREGROUND, Color.red); |
|||
g2.drawString(as4.getIterator(), 30, 400); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* applies the logic of the level: For now, this is just about deleting shots that are leaving the |
|||
* screen and calling methods 'actionIf..' in case objects collide. |
|||
* |
|||
*/ |
|||
@Override |
|||
public void applyGameLogic() { |
|||
double gameTime = this.getGameTime(); |
|||
String gameStatus = (String) getLevelFlag("gameStatus"); |
|||
String subStatus = (String) getLevelFlag("detailedStatus"); |
|||
|
|||
if (gameStatus.equals("start") == true) { |
|||
setupInitialState(); |
|||
|
|||
} else if (gameStatus.equals("starting") == true) { |
|||
|
|||
if ((gameTime - starttime) > LEVEL_INIT_TIME) { |
|||
setLevelFlag("gameStatus", "init"); |
|||
} |
|||
|
|||
} else if (gameStatus.equals("init") == true) { |
|||
|
|||
this.createEnemies(); |
|||
this.createCollectables(); |
|||
|
|||
setLevelFlag("gameStatus", "playing"); |
|||
|
|||
} else if (gameStatus.equals("playing") == true) { |
|||
GameObject s = this.getObject("ego"); |
|||
|
|||
if (subStatus.equals("std")) { |
|||
|
|||
// check for collisions of enemy and shots, reuse shots list from before.. |
|||
LinkedList<GameObject> enemies = collectObjects("enemy", false); |
|||
|
|||
// check whether all enemies have been destroyed or escaped |
|||
if (enemies.size() == 0) { |
|||
HighscoreManager hsm = new HighscoreManager(); |
|||
HighscoreManager.writeHSToFile((Integer) Playground.getGlobalFlag("points"), |
|||
(Integer) Playground.getGlobalFlag("highscore")); |
|||
this.doneLevel = true; |
|||
logger.info("no enemies left, level done."); |
|||
} |
|||
|
|||
// loop over enemies to check for collisions or suchlike ... |
|||
LinkedList<GameObject> shots = collectObjects("simpleShot", true); |
|||
for (GameObject e : enemies) { |
|||
// if ego collides with enemy.. |
|||
if (s.collisionDetection(e)) { |
|||
actionIfEgoCollidesWithEnemy(e, s); |
|||
} |
|||
|
|||
// if shot collides with enemy |
|||
for (GameObject shot : shots) { |
|||
if (e.collisionDetection(shot)) { |
|||
actionIfEnemyIsHit(e, shot); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// collecting hearts |
|||
LinkedList<GameObject> collects = collectObjects("collect", false); |
|||
for (GameObject c : collects) { |
|||
if (s.collisionDetection(c)) { |
|||
actionIfEgoCollidesWithCollect(c, s); |
|||
} |
|||
} |
|||
|
|||
// loop over enemies and, with a certain probability, launch an enemy shot for each one |
|||
for (GameObject e : enemies) { |
|||
createEnemyShot(e); |
|||
} |
|||
|
|||
// check for collisions between ego object and enemy shots |
|||
LinkedList<GameObject> eshots = collectObjects("enmyShot", true); |
|||
for (GameObject eshot : eshots) { |
|||
|
|||
if (s.collisionDetection(eshot)) { |
|||
logger.trace("COLLISION" + eshot.scol.get(0) + "/" + s.scol.get(0)); |
|||
actionIfEgoObjectIsHit(eshot, s); |
|||
} |
|||
} |
|||
} // if substatus.. |
|||
else if (subStatus.equals("dying")) { |
|||
Double t0 = (Double) getLevelFlag("t0"); |
|||
if (gameTime - t0 > DYING_INTERVAL) { |
|||
LinkedList<GameObject> enemies = collectObjects("enemy", false); |
|||
setLevelFlag("detailedStatus", "std"); |
|||
s.setActive(true); |
|||
|
|||
for (GameObject e : enemies) { |
|||
logger.trace("activating" + e.getId()); |
|||
e.setActive(true); |
|||
} |
|||
} |
|||
} |
|||
|
|||
} // if (gameStatus == "playing") |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
public boolean gameOver() { |
|||
return lost; |
|||
} |
|||
|
|||
|
|||
public boolean levelFinished() { |
|||
return doneLevel; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* calculates and returns the preferred size of the level (in pixel) for X-direction |
|||
*/ |
|||
public int preferredSizeX() { |
|||
return CANVASX; |
|||
} |
|||
|
|||
/** |
|||
* calculates and returns the preferred size of the level (in pixel) for Y-direction |
|||
*/ |
|||
public int preferredSizeY() { |
|||
return CANVASY; |
|||
} |
|||
|
|||
|
|||
/** Adds ego object and stars and displays startup message. Is called from applyGameLogic */ |
|||
protected void setupInitialState() { |
|||
double gameTime = this.getGameTime(); |
|||
setLevelFlag("gameStatus", "starting"); |
|||
|
|||
this.createStars(); |
|||
|
|||
// set up ego object |
|||
this.createEgoObject(); |
|||
|
|||
// add text object to playground |
|||
ObjectController ctrl = new LimitedTimeController(gameTime, 3.); |
|||
GameObject readyText = new TextObject("ready?", this, getSizeX() / 2, 0, 0, 100, |
|||
this.getStartupMessage(), 50, Color.RED).addController(ctrl); |
|||
addObject(readyText); |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* simply returns the text that should be displayed at level start |
|||
* |
|||
* @return a string that is displayed at start. Should be not longer than 30 characters. |
|||
*/ |
|||
protected String getStartupMessage() { |
|||
return "Get ready for level X!"; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* returns a number representing the speed of an enemy object in X direction (pixels/second) |
|||
* |
|||
* @return a positive value |
|||
*/ |
|||
protected double calcEnemySpeedX() { |
|||
return SpaceInvadersLevel.ENEMYSPEEDX; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* returns a number representing the speed of an enemy object in Y direction (pixels/second) |
|||
* |
|||
* @return a positive value |
|||
*/ |
|||
protected double calcEnemySpeedY() { |
|||
return SpaceInvadersLevel.ENEMYSPEEDY; |
|||
} |
|||
|
|||
/** |
|||
* returns the maximum number of enemy instances (which are created at level start) |
|||
* |
|||
* @return a positive value |
|||
*/ |
|||
protected int calcNrEnemies() { |
|||
return SpaceInvadersLevel.NR_ENEMIES; |
|||
} |
|||
|
|||
/** |
|||
* returns the maximum number of collectables' instances (which are created at level start) |
|||
* |
|||
* @return a positive value |
|||
*/ |
|||
protected int calcNrCollect() { |
|||
return SpaceInvadersLevel.NR_COLLECT; |
|||
} |
|||
|
|||
|
|||
protected GameObject createEnemyShotObject(GameObject parentObject, String name, |
|||
ObjectController limitedTimeController) { |
|||
GameObject to = |
|||
new TextObject(name, this, parentObject.getX(), parentObject.getY(), 0, ENEMYSHOTSPEED, "I", |
|||
20, Color.YELLOW).generateColliders().addController(limitedTimeController); |
|||
/* |
|||
* // also possible: GameObject to = new RectObject(name, this, parentObject.getX(), |
|||
* parentObject.getY(), 0, ENEMYSHOTSPEED, 4, 20, |
|||
* Color.YELLOW).addController(limitedTimeController) ; to.generateColliders(); |
|||
*/ |
|||
return to; |
|||
} |
|||
|
|||
|
|||
protected void createEnemyShot(GameObject e) { |
|||
double gameTime = this.getGameTime(); |
|||
|
|||
double PROB = calcEnemyShotProb(); |
|||
double diceThrow = Math.random(); |
|||
Integer nrEnemyShots = (Integer) (getLevelFlag("enemyShotCounter")); |
|||
if (diceThrow < PROB) { |
|||
setLevelFlag("enemyShotCounter", Integer.valueOf(++nrEnemyShots)); |
|||
|
|||
LimitedTimeController limitedTimeController = new LimitedTimeController(gameTime, 10.); |
|||
|
|||
GameObject textObject = |
|||
createEnemyShotObject(e, "enmyShot" + nrEnemyShots, limitedTimeController); |
|||
|
|||
addObject(textObject); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* calculates and returns the probability that an enemy shots. Used by |
|||
* {@link SpaceInvadersLevel#createEnemyShot(GameObject)}. |
|||
* |
|||
* @return a positive value between 0 (no chance) to 1 (for sure). |
|||
*/ |
|||
double calcEnemyShotProb() { |
|||
return 0.1 * this.getTimestep(); |
|||
} |
|||
|
|||
|
|||
ObjectController createEnemyController() { |
|||
return new EnemyController(); |
|||
} |
|||
|
|||
|
|||
GameObject createSingleEnemy(String name, double x_enemy, double y_enemy, double vx_enemy, |
|||
double vy_enemy, ObjectController enemyController, double gameTime) { |
|||
|
|||
GameObject tmp = |
|||
new AnimatedGameobject(name, this, x_enemy, y_enemy, vx_enemy, vy_enemy, ENEMYSCALE, |
|||
this.enemyAnim, gameTime, "loop").addController(enemyController).generateColliders(); |
|||
return tmp; |
|||
} |
|||
|
|||
GameObject createSingleCollect(String name) { |
|||
double gameTime = this.getGameTime(); |
|||
double cspeedy = 20.; |
|||
double x_collect = Math.random() * this.canvasX; |
|||
double y_collect = Math.random() * this.canvasY / 3; |
|||
double vx_collect = 2 * (Math.random() - 0.5) * 0; |
|||
double vy_collect = Math.random() * cspeedy; |
|||
|
|||
GameObject tmp = new AnimatedGameobject(name, this, x_collect, y_collect, vx_collect, |
|||
vy_collect, 0.3, this.heartAnim, gameTime, "loop").generateColliders() |
|||
.addController(new EnemyController()); |
|||
return tmp; |
|||
} |
|||
|
|||
|
|||
void createEnemies() { |
|||
// create enemies |
|||
double gameTime = this.getGameTime(); |
|||
double speedx = this.calcEnemySpeedX(); |
|||
double speedy = this.calcEnemySpeedY(); |
|||
for (int i = 0; i < this.calcNrEnemies(); i++) { |
|||
double x_enemy = Math.random() * this.canvasX; |
|||
double y_enemy = Math.random() * this.canvasY / 3; |
|||
double vx_enemy = 2 * (Math.random() - 0.5) * speedx; |
|||
double vy_enemy = Math.random() * speedy; |
|||
|
|||
ObjectController enemyController = createEnemyController(); |
|||
GameObject enemy = createSingleEnemy("enemy" + i, x_enemy, y_enemy, vx_enemy, vy_enemy, |
|||
enemyController, gameTime); |
|||
addObject(enemy); |
|||
} |
|||
} |
|||
|
|||
void createCollectables() { |
|||
double gameTime = this.getGameTime(); |
|||
// create collectables |
|||
for (int i = 0; i < this.calcNrCollect(); i++) { |
|||
|
|||
|
|||
GameObject collect = createSingleCollect("collect" + i); |
|||
|
|||
addObject(collect); |
|||
} |
|||
} |
|||
|
|||
|
|||
void createEgoObject() { |
|||
// add ego to playground at lower bottom |
|||
EgoController egoController = |
|||
new CollisionAwareEgoController(SpaceInvadersLevel.EGORAD, this.laser); |
|||
|
|||
GameObject ego = new EgoObject("ego", this, canvasX / 2, canvasY - (EGORAD * 2), 0, 0, EGORAD) |
|||
.addController(egoController).generateColliders(); |
|||
|
|||
addObject(ego); |
|||
} |
|||
|
|||
|
|||
void createStars() { |
|||
// add stars to playground |
|||
for (int i = 1; i <= LEVEL2STARS; i++) { |
|||
FallingStarController fsc = new FallingStarController(); |
|||
|
|||
GameObject star = new FallingStar("star" + i, this, Math.random() * canvasX, |
|||
Math.random() * 15, 0.0, Math.random() * STARSPEED, Color.WHITE, 1.).addController(fsc); |
|||
|
|||
addObject(star); |
|||
} |
|||
} |
|||
|
|||
|
|||
void createExplosion(double gameTime, GameObject e, String basename, double interval, |
|||
Color color) { |
|||
// spawn a cloud of exploded shards |
|||
for (int i = 0; i < NRSHARDS; i++) { |
|||
double vx = 2 * (Math.random() - 0.5) * SHARDSPEED + e.getVX(); |
|||
double vy = 2 * (Math.random() - 0.5) * SHARDSPEED + e.getVY(); |
|||
addObject( |
|||
new FallingStar("shard" + gameTime + "/" + i, this, e.getX(), e.getY(), vx, vy, color, 2) |
|||
.addController(new LimitedTimeController(gameTime, interval))); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* implements game behavior if an enemy object is hit by a players' shot. It creates an explosion |
|||
* effect, plays a sound and adds 200 points to the current score (and it removes the enemy object |
|||
* and the shot object). |
|||
* |
|||
* @param e enemy which was hit |
|||
* @param shot the shot object that hit the enemy |
|||
*/ |
|||
void actionIfEnemyIsHit(GameObject e, GameObject shot) { |
|||
|
|||
double gameTime = this.getGameTime(); |
|||
createExplosion(gameTime, e, "shard", DYING_INTERVAL, Color.RED); |
|||
|
|||
Music.music(smash); |
|||
|
|||
// delete enemy |
|||
deleteObject(e.getId()); |
|||
|
|||
// delete shot |
|||
deleteObject(shot.getId()); |
|||
|
|||
// add to points counter |
|||
Integer pts = (Integer) getGlobalFlag("points"); |
|||
setGlobalFlag("points", pts + 200); |
|||
|
|||
} |
|||
|
|||
/** |
|||
* implements game behavior if ego object of player touches a collectable |
|||
* {@link gameobjects.GameObject }. Here it adds one extra life and displays a text for a limited |
|||
* time on screen "Extra life!!". The duration is set in constant |
|||
* {@link SpaceInvadersLevel#EXPL_DURATION}. |
|||
* |
|||
* |
|||
* @param collect item touched by ego |
|||
* @param ego the players ego object |
|||
*/ |
|||
void actionIfEgoCollidesWithCollect(GameObject collect, GameObject ego) { |
|||
double gameTime = this.getGameTime(); |
|||
|
|||
if (this.getObject("bonustext") == null) { |
|||
|
|||
// spawn a bonus points object |
|||
double vx = 2 * (Math.random() - 0.5) * SHARDSPEED + collect.getVX(); |
|||
double vy = 2 * (Math.random() - 0.5) * SHARDSPEED + collect.getVY(); |
|||
|
|||
|
|||
LimitedTimeController bonusTextController = |
|||
new LimitedTimeController(gameTime, SpaceInvadersLevel.EXPL_DURATION); |
|||
GameObject bonusText = new TextObject("bonustext", this, collect.getX(), collect.getY(), vx, |
|||
vy, "Extra life!!", 20, Color.YELLOW).addController(bonusTextController); |
|||
|
|||
addObject(bonusText); |
|||
|
|||
// delete collect |
|||
deleteObject(collect.getId()); |
|||
|
|||
// add to points counter |
|||
Integer lives = (Integer) getGlobalFlag("egoLives"); |
|||
lives++; |
|||
setGlobalFlag("egoLives", lives); |
|||
} |
|||
|
|||
} |
|||
|
|||
/** |
|||
* implements behaviour of game when ego object is touching an enemy. It displays a text "AUAA!!" |
|||
* for a certain time on the game screen. Time span is defined as constant in |
|||
* {@link SpaceInvadersLevel#BONUS_DURATION } . |
|||
* |
|||
* @param enemy the enemy that was hit |
|||
* @param ego the ego object of the player |
|||
*/ |
|||
void actionIfEgoCollidesWithEnemy(GameObject enemy, GameObject ego) { |
|||
|
|||
/** |
|||
* set temporary text over ego. This object lives only for a short time. While it lives, further |
|||
* collisions are ignored. Otherwise a single collision would result in a lot of deducted |
|||
* points... |
|||
*/ |
|||
|
|||
double gameTime = this.getGameTime(); |
|||
GameObject auaObj = this.getObject("AUA-EGO"); |
|||
|
|||
if (auaObj == null) { |
|||
addObject(new TextObject("AUA-EGO", this, ego.getX(), ego.getY() - 20, ego.getVX(), |
|||
ego.getVY(), "AUAA!!", 10, Color.RED) |
|||
.addController(new LimitedTimeController(gameTime, BONUS_DURATION))); |
|||
// deduct points |
|||
Integer pts = (Integer) getGlobalFlag("points"); |
|||
setGlobalFlag("points", pts - 500); |
|||
} |
|||
|
|||
} |
|||
|
|||
/** |
|||
* implements what happens if the eog object of player is hit by a shot. It removes the shot from |
|||
* screen, reduces lives by 1, removes the ego and end current playing. |
|||
* |
|||
* @param eshot the shot object that hits the ego |
|||
* @param ego the ego object of the player |
|||
*/ |
|||
void actionIfEgoObjectIsHit(GameObject eshot, GameObject ego) { |
|||
logger.debug("collision of " + eshot.getId() + " and " + ego.getId()); |
|||
|
|||
double gameTime = this.getGameTime(); |
|||
this.deleteObject(eshot.getId()); |
|||
|
|||
Integer oldLives = (Integer) getGlobalFlag("egoLives"); |
|||
int newLives = oldLives - 1; |
|||
setGlobalFlag("egoLives", newLives); |
|||
logger.debug("set egoLives to " + newLives + " (was " + oldLives + ")"); |
|||
|
|||
if (newLives <= 0) { |
|||
lost = true; |
|||
HighscoreManager.writeHSToFile((Integer) Playground.getGlobalFlag("points"), |
|||
(Integer) Playground.getGlobalFlag("highscore")); |
|||
|
|||
} |
|||
|
|||
LinkedList<GameObject> eshots = collectObjects("enmyShot", true); |
|||
for (GameObject _eshot : eshots) { |
|||
deleteObject(_eshot.getId()); |
|||
} |
|||
setLevelFlag("detailedStatus", "dying"); |
|||
setLevelFlag("t0", gameTime); |
|||
ego.setActive(false); |
|||
createExplosion(gameTime, ego, "egoexp", DYING_INTERVAL, Color.WHITE); |
|||
LinkedList<GameObject> enemies = collectObjects("enemy", false); |
|||
for (GameObject enemy : enemies) { |
|||
enemy.setY(0); |
|||
enemy.setActive(false); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,81 @@ |
|||
package playground; |
|||
|
|||
import static org.junit.Assert.assertTrue; |
|||
import java.awt.Color; |
|||
import org.junit.jupiter.api.AfterAll; |
|||
import org.junit.jupiter.api.BeforeAll; |
|||
import org.junit.jupiter.api.Test; |
|||
import gameobjects.EgoObject; |
|||
import gameobjects.GameObject; |
|||
import gameobjects.RectObject; |
|||
|
|||
/** |
|||
* Tests {@link SpaceInvadersLevel} for |
|||
* <ol> |
|||
* <li>calcEnemySpeedX() returns the same value as constant SpaceInvadersLevel.ENEMYSPEEDX |
|||
* <li>calcEnemySpeedY() returns the same value as constant SpaceInvadersLevel.ENEMYSPEEDY |
|||
* <li>calcNrEnemies() returns the same value as constant SpaceInvadersLevel.NR_ENEMIES |
|||
* <li>actionIfEnemyIsHit() adds 200 points to score |
|||
* <li>actionIfEgoObjectIsHit() reduces number of lives (egoLives) |
|||
* </ol> |
|||
* @author jkonert |
|||
* |
|||
*/ |
|||
class SpaceInvadersLevelTest { |
|||
|
|||
private static SpaceInvadersLevel myLevel; |
|||
|
|||
@BeforeAll |
|||
static void setUpBeforeClass() throws Exception { |
|||
myLevel = new SpaceInvadersLevel(); |
|||
SpaceInvadersLevel.setGlobalFlag("egoLives", 5); |
|||
SpaceInvadersLevel.setGlobalFlag("points", 500); |
|||
SpaceInvadersLevel.setGlobalFlag("highscore", 5000); |
|||
} |
|||
|
|||
@AfterAll |
|||
static void tearDownAfterClass() throws Exception { |
|||
// nothing |
|||
} |
|||
|
|||
@Test |
|||
void testCalcEnemySpeedX() { |
|||
assertTrue("EnemySpeedX is as in SpaceInvadersLevel defined", myLevel.calcEnemySpeedX() == SpaceInvadersLevel.ENEMYSPEEDX); |
|||
} |
|||
|
|||
@Test |
|||
void testCalcEnemySpeedY() { |
|||
assertTrue("EnemySpeedY is as in SpaceInvadersLevel defined", myLevel.calcEnemySpeedY() == SpaceInvadersLevel.ENEMYSPEEDY); |
|||
} |
|||
|
|||
@Test |
|||
void testCalcNrEnemies() { |
|||
assertTrue("NrOfEnemies is as in SpaceInvadersLevel defined", myLevel.calcNrEnemies() == SpaceInvadersLevel.NR_ENEMIES); |
|||
} |
|||
|
|||
|
|||
@Test |
|||
void testActionIfEnemyIsHitPointsUp() { |
|||
Integer numPointsBefore = (Integer)myLevel.getGlobalFlag("points"); |
|||
GameObject dummyShot = new RectObject("shot1", myLevel, 0,0,0,0, 12, 12, Color.WHITE); |
|||
GameObject dummyEnemy = new RectObject("ego1", myLevel, 0,0,0,0, 12, 12, Color.BLACK); |
|||
myLevel.addObject(dummyShot); |
|||
myLevel.addObject(dummyEnemy); |
|||
myLevel.actionIfEnemyIsHit(dummyEnemy, dummyShot);; // this is the call under test |
|||
Integer numPointsAfter = (Integer)myLevel.getGlobalFlag("points"); // changed? |
|||
assertTrue("numPoints is up +200 after EnemyIsHit", numPointsAfter == numPointsBefore + 200); // points are set +200 , check. |
|||
} |
|||
|
|||
@Test |
|||
void testActionIfEgoObjectIsHitLivesDown() { |
|||
Integer numLivesBefore = (Integer)myLevel.getGlobalFlag("egoLives"); |
|||
GameObject dummyShot = new RectObject("shot1", myLevel, 0,0,0,0, 12, 12, Color.RED); |
|||
GameObject dummyEgo = new EgoObject("ego1", myLevel, 0,0,0,0, 5); |
|||
myLevel.addObject(dummyShot); |
|||
myLevel.actionIfEgoObjectIsHit(dummyShot, dummyEgo); // this is the call under test |
|||
Integer numLivesAfter = (Integer)myLevel.getGlobalFlag("egoLives"); // changed? |
|||
assertTrue("numLives is reduced by one ifEgoIsHit", numLivesAfter == numLivesBefore - 1); // lives is reduced by one |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,93 @@ |
|||
package rendering; |
|||
|
|||
import gameobjects.GameObject; |
|||
import playground.Animation; |
|||
import java.awt.Graphics2D; |
|||
import java.awt.image.BufferedImage; |
|||
import java.util.LinkedList; |
|||
import org.apache.logging.log4j.Logger; |
|||
import org.apache.logging.log4j.LogManager; |
|||
|
|||
public class AnimationArtist extends Artist { |
|||
|
|||
protected LinkedList<BufferedImage> imageArray; |
|||
protected LinkedList<Double> showtime; |
|||
protected double t0; |
|||
|
|||
protected int loopFrame = 0; |
|||
|
|||
protected double w = 0, h = 0, scale = 0; |
|||
protected String playmode = ""; // can be loop, forward, backward |
|||
private static Logger logger = LogManager.getLogger(AnimationArtist.class); |
|||
|
|||
|
|||
public AnimationArtist(GameObject go, Animation anim, double t0, String playmode, double scale) { |
|||
super(go); |
|||
|
|||
this.imageArray = anim.getImageList(); |
|||
this.showtime = anim.getShowtimeList(); |
|||
this.t0 = t0; |
|||
logger.debug("AnimationArtist start = ") ; |
|||
this.loopFrame = 0; |
|||
|
|||
for (int i = 0; i < imageArray.size(); i++) { |
|||
logger.trace("ANIMRAWWH="+imageArray.get(i).getWidth()) ; |
|||
this.w = Math.max(this.w, imageArray.get(i).getWidth()); |
|||
this.h = Math.max(imageArray.get(i).getHeight(), this.h); |
|||
} |
|||
|
|||
logger.debug("AnimationArtist RAW WH = "+this.w+"/"+this.h) ; |
|||
|
|||
this.playmode = playmode; |
|||
this.w *= scale; |
|||
this.h *= scale; |
|||
} |
|||
|
|||
public double getW() { |
|||
return w; |
|||
} |
|||
|
|||
public double getH() { |
|||
return h; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void draw(Graphics2D g) { |
|||
double i2 = this.getGameTime(); |
|||
|
|||
double elapsedTime = i2 - t0; |
|||
|
|||
// Diff chance from sec to millis |
|||
double mseconds = (double) elapsedTime; |
|||
logger.debug("showtime= "+showtime.get(loopFrame)+" elapsed= "+elapsedTime+" i2= "+i2); |
|||
|
|||
if (playmode.equals("loop")) { |
|||
if (mseconds >= showtime.get(loopFrame)) { |
|||
loopFrame++; |
|||
if (loopFrame >= imageArray.size()) |
|||
loopFrame = 0; |
|||
t0 = i2; |
|||
} |
|||
} |
|||
|
|||
if (playmode.equals("forward")) { |
|||
if (mseconds >= showtime.get(loopFrame) && loopFrame < imageArray.size() - 1) { |
|||
loopFrame++; |
|||
t0 = i2; |
|||
} |
|||
} |
|||
|
|||
if (playmode.equals("backward")) { |
|||
if (mseconds >= showtime.get(loopFrame) && loopFrame > 1) { |
|||
loopFrame--; |
|||
t0 = i2; |
|||
} |
|||
} |
|||
|
|||
g.drawImage(imageArray.get(loopFrame), (int) Math.round(this.getX() - w / 2.), |
|||
(int) Math.round(this.getY() - h / 2.), (int) w, (int) h, null); |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,40 @@ |
|||
package rendering; |
|||
|
|||
import gameobjects.GameObject; |
|||
import java.awt.Graphics2D; |
|||
|
|||
public abstract class Artist { |
|||
protected GameObject gameObject; |
|||
|
|||
Artist(GameObject go) { |
|||
this.gameObject = go; |
|||
} |
|||
|
|||
public double getX() { |
|||
return this.gameObject.getX(); |
|||
} |
|||
|
|||
|
|||
public double getY() { |
|||
return this.gameObject.getY(); |
|||
} |
|||
|
|||
|
|||
public double getVX() { |
|||
return this.gameObject.getX(); |
|||
} |
|||
|
|||
public double getVY() { |
|||
return this.gameObject.getX(); |
|||
} |
|||
|
|||
|
|||
public double getGameTime() { |
|||
return this.gameObject.getGameTime(); |
|||
} |
|||
|
|||
|
|||
|
|||
public abstract void draw(Graphics2D g); |
|||
|
|||
} |
@ -0,0 +1,34 @@ |
|||
package rendering; |
|||
|
|||
import gameobjects.GameObject; |
|||
import java.awt.Color; |
|||
import java.awt.Graphics2D; |
|||
|
|||
public class CircleArtist extends Artist { |
|||
|
|||
protected double egoRad; |
|||
protected Color color; |
|||
|
|||
public CircleArtist(GameObject go) { |
|||
super(go); |
|||
this.egoRad = 15.0; |
|||
} |
|||
|
|||
public CircleArtist(GameObject go, double egoRad, Color color) { |
|||
super(go); |
|||
this.egoRad = egoRad; |
|||
this.color = color; |
|||
} |
|||
|
|||
@Override |
|||
public void draw(Graphics2D g) { |
|||
g.setColor(this.color); |
|||
double x = this.getX(); |
|||
double y = this.getY(); |
|||
int posX = (int) (x - egoRad); |
|||
int posY = (int) (y - egoRad); |
|||
int rad = (int) (2 * egoRad); |
|||
g.fillOval(posX, posY, rad, rad); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,33 @@ |
|||
package rendering; |
|||
|
|||
import gameobjects.GameObject; |
|||
import java.awt.Color; |
|||
import java.awt.Graphics2D; |
|||
|
|||
public class RectArtist extends Artist { |
|||
|
|||
protected Color color; |
|||
protected double width, height; |
|||
|
|||
public RectArtist(GameObject go, double width, double height, Color color) { |
|||
super(go); |
|||
this.color = color; |
|||
this.width = width; |
|||
this.height = height; |
|||
} |
|||
|
|||
@Override |
|||
public void draw(Graphics2D g) { |
|||
g.setColor(this.color); |
|||
|
|||
// g.drawLine((int) (Math.round(this.getX())), (int) (Math.round(this.getY()-this.height/2.)), |
|||
// (int) Math.round(this.getX()), |
|||
// (int) Math.round(this.getY() + this.height/2.)); |
|||
int x = (int) this.getX(); |
|||
int y = (int) this.getY(); |
|||
g.fillRect((int) (this.getX() - this.width / 2.), (int) (this.getY() - this.height / 2.), |
|||
(int) this.width, (int) this.height); |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,81 @@ |
|||
package rendering; |
|||
|
|||
import gameobjects.GameObject; |
|||
import java.awt.Color; |
|||
import java.awt.Font; |
|||
import java.awt.Graphics2D; |
|||
import java.awt.font.FontRenderContext; |
|||
import java.awt.font.TextAttribute; |
|||
import java.text.AttributedString; |
|||
|
|||
/** |
|||
* Rendering an object as a text of a specified color, size and font. |
|||
*/ |
|||
public class TextArtist extends Artist { |
|||
|
|||
private String text = null; |
|||
private int size = 1; |
|||
private Color textColor = null; |
|||
protected double textWidth, textHeight; |
|||
Font serifFont = null; |
|||
|
|||
public TextArtist(GameObject go, String text, int size, Color textColor) { |
|||
super(go); |
|||
this.size = size; |
|||
this.text = text; |
|||
|
|||
this.serifFont = new Font("Serif", Font.PLAIN, size); |
|||
FontRenderContext frc = new FontRenderContext(null, false, false); |
|||
this.textWidth = (int) (serifFont.getStringBounds(text, frc).getWidth()); |
|||
this.textHeight = (int) (serifFont.getStringBounds(text, frc).getHeight()); |
|||
|
|||
this.textColor = textColor; |
|||
} |
|||
|
|||
|
|||
public String getText() { |
|||
return this.text; |
|||
} |
|||
|
|||
public void setText(String s) { |
|||
this.text = s; |
|||
} |
|||
|
|||
|
|||
|
|||
public double getTextWidth() { |
|||
return textWidth; |
|||
} |
|||
|
|||
|
|||
public void setTextWidth(double textWidth) { |
|||
this.textWidth = textWidth; |
|||
} |
|||
|
|||
|
|||
|
|||
public double getTextHeight() { |
|||
return textHeight; |
|||
} |
|||
|
|||
|
|||
public void setTextHeight(double textHeight) { |
|||
this.textHeight = textHeight; |
|||
} |
|||
|
|||
/** |
|||
* Draw the text. |
|||
* |
|||
* @param g The Swing graphics context. |
|||
*/ |
|||
@Override |
|||
public void draw(Graphics2D g) { |
|||
AttributedString as = new AttributedString(this.text); |
|||
as.addAttribute(TextAttribute.FONT, this.serifFont); |
|||
as.addAttribute(TextAttribute.FOREGROUND, this.textColor); |
|||
|
|||
g.drawString(as.getIterator(), (int) Math.round(this.getX() - this.textWidth / 2.), |
|||
(int) Math.round(this.getY() + this.textHeight / 2.)); |
|||
} |
|||
|
|||
} |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue