Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
30011a0788 | |||
2f8a613b56 | |||
8ff179a27d | |||
46223d60ca | |||
5e879e5a3d | |||
073d9fe188 | |||
6d162adde1 | |||
545ab6a32c |
24
.classpath
Executable file
24
.classpath
Executable file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src/main">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
1
.gitignore
vendored
Executable file
1
.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
||||
/target/
|
17
.project
Executable file
17
.project
Executable file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Snake</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>
|
8
.settings/org.eclipse.jdt.core.prefs
Executable file
8
.settings/org.eclipse.jdt.core.prefs
Executable file
@ -0,0 +1,8 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
3
.settings/org.eclipse.jdt.ui.prefs
Executable file
3
.settings/org.eclipse.jdt.ui.prefs
Executable file
File diff suppressed because one or more lines are too long
4
.settings/org.eclipse.m2e.core.prefs
Executable file
4
.settings/org.eclipse.m2e.core.prefs
Executable file
@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
21
LICENSE
Executable file
21
LICENSE
Executable file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 delvh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
26
README.md
Normal file → Executable file
26
README.md
Normal file → Executable file
@ -1,2 +1,26 @@
|
||||
# Snake
|
||||
My advanced Hello World program is a version of the old game Snake
|
||||
My advanced Hello World program is a version of the old game Snake.
|
||||
|
||||
## Features
|
||||
- normal playing experience of Snake
|
||||
- 5 different fruits that can be eaten to enlarge the Snake
|
||||
- theoretically Start- and Endscreen, currently mostly unused
|
||||
- theoretically visual display whether a result is good or bad, commented out for now as it does not appear to work as expected
|
||||
|
||||
## Classes
|
||||
- Snake:
|
||||
- stores the body parts, their position and the general direction of the Snake
|
||||
- checks, whether the Snake touches itself, the outer bounds or food
|
||||
- Main:
|
||||
- the class where public static void main(String[] args){} is located
|
||||
- stores the GameWindow used
|
||||
- GameWindow:
|
||||
- displays all visual components used in the game
|
||||
- stores the Snake object
|
||||
- FoodFactory:
|
||||
- generates new Food
|
||||
- other classes in the ui-package:
|
||||
- as the name suggests, defines the visual appearance before and after games
|
||||
|
||||
## JAR of the final version
|
||||
If you follow <a href="https://github.com/delvh/Snake/releases">**this link**</a> and click on release "Snake - almost finished", you can download the runnable JAR of how the completed project should look like. Unfortunately due to poor Version-Control-skills, the original code got lost and had to be rewritten, however it should resemble the executed code closely
|
||||
|
Binary file not shown.
33
pom.xml
Executable file
33
pom.xml
Executable file
@ -0,0 +1,33 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>Snake</groupId>
|
||||
<artifactId>Snake</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<build>
|
||||
<sourceDirectory>Snake/src</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>Snake/src</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>Snake/src/dev/lh/snake</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
229
src/main/dev/lh/FoodFactory.java
Executable file
229
src/main/dev/lh/FoodFactory.java
Executable file
@ -0,0 +1,229 @@
|
||||
package dev.lh;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import dev.lh.ui.GameWindow;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>FoodFactory.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public class FoodFactory {
|
||||
|
||||
/**
|
||||
* This enum contains all possible variations of foods. The higher the ordinal
|
||||
* of an element, the less it is worth.<br>
|
||||
* <br>
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>FoodFactory.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static enum Food {
|
||||
/**
|
||||
* Use if white food is wanted.
|
||||
*/
|
||||
white,
|
||||
|
||||
/**
|
||||
* Use if yellow food is wanted.
|
||||
*/
|
||||
yellow,
|
||||
|
||||
/**
|
||||
* Use if orange food is wanted.
|
||||
*/
|
||||
orange,
|
||||
|
||||
/**
|
||||
* Use if red food is wanted.
|
||||
*/
|
||||
red,
|
||||
|
||||
/**
|
||||
* Use if blue food is wanted.
|
||||
*/
|
||||
blue
|
||||
}
|
||||
|
||||
private static FoodFactory foodFactory = new FoodFactory();
|
||||
|
||||
private long timeOfNextFood;
|
||||
|
||||
Point pFood = null;
|
||||
|
||||
private Food nextFood = Food.white;
|
||||
|
||||
private int rectangleSize = 6;
|
||||
|
||||
private FoodFactory() {}
|
||||
|
||||
/**
|
||||
* @return the (singleton) instance of FoodFactory
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static FoodFactory getInstance() { return foodFactory; }
|
||||
|
||||
/**
|
||||
* @return a new {@link Food} object without its position
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Food generateFood() {
|
||||
int nextFoodIs = (int) Math.floor(Math.random() * 5);
|
||||
switch (nextFoodIs) {
|
||||
|
||||
case 0:
|
||||
nextFood = Food.white;
|
||||
break;
|
||||
case 1:
|
||||
nextFood = Food.yellow;
|
||||
break;
|
||||
case 2:
|
||||
nextFood = Food.orange;
|
||||
break;
|
||||
case 3:
|
||||
nextFood = Food.red;
|
||||
break;
|
||||
case 4:
|
||||
nextFood = Food.blue;
|
||||
break;
|
||||
default:
|
||||
nextFood = generateFood();
|
||||
}
|
||||
rectangleSize = nextFood.ordinal() + 2;
|
||||
setTimeToNextFoodMillis();
|
||||
return nextFood;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the amount of time that needs to pass before the next food object
|
||||
* will be constructed.
|
||||
*
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void setTimeToNextFoodMillis() { timeOfNextFood = System.currentTimeMillis() + (int) Math.round(Math.random() * 15000 + 1000); }
|
||||
|
||||
/**
|
||||
* @return the type of the next food
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Food getNextFood() { return nextFood; }
|
||||
|
||||
/**
|
||||
* @param nextFood the type the next food should have
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void setNext(Food nextFood) { this.nextFood = nextFood; }
|
||||
|
||||
/**
|
||||
* @return the time at which a new food object will be automatically created
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public long getTimeOfNextFood() { return timeOfNextFood; }
|
||||
|
||||
/**
|
||||
* @param width the width of the currently used {@link GameWindow}
|
||||
* @param height the height of the currently used {@link GameWindow}
|
||||
* @return the position of the new {@link Food} object
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Point generateFoodLocation(int width, int height) {
|
||||
pFood = new Point((int) Math.round(Math.random() * width), (int) Math.round(Math.random() * height));
|
||||
if (pFood.x < 50 || pFood.x > width - 50 || pFood.y < 50 || pFood.y > height - 50) {
|
||||
pFood.x = (pFood.x < 50) ? 50 : (pFood.x > width - 50) ? width - 50 : pFood.x;
|
||||
pFood.y = (pFood.y < 50) ? 50 : (pFood.y > height - 50) ? height - 50 : pFood.y;
|
||||
}
|
||||
return pFood;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of the corresponding food (length = width)
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public int getRectangleSize() { return rectangleSize; }
|
||||
|
||||
/**
|
||||
* @return the location of the currently displayed food
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Point getFoodLocation() { return pFood; }
|
||||
|
||||
/**
|
||||
* Sets the color of the given {@link Graphics} object according to the type of
|
||||
* food.
|
||||
*
|
||||
* @param g the graphics object to paint
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void colorOfFood(Graphics g) {
|
||||
switch (nextFood) {
|
||||
case white:
|
||||
g.setColor(Color.white);
|
||||
break;
|
||||
case yellow:
|
||||
g.setColor(Color.yellow);
|
||||
break;
|
||||
case orange:
|
||||
g.setColor(Color.orange);
|
||||
break;
|
||||
case red:
|
||||
g.setColor(Color.red);
|
||||
break;
|
||||
case blue:
|
||||
g.setColor(Color.blue);
|
||||
break;
|
||||
}// switch
|
||||
}
|
||||
|
||||
/**
|
||||
* @param g the {@link Graphics} object used to paint the current food object
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void paintFood(Graphics g) {
|
||||
colorOfFood(g);
|
||||
g.fillRect(pFood.x, pFood.y, 5 * rectangleSize, 5 * rectangleSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param snakeHead the the head of a {@link Snake} object
|
||||
* @return true if the current food intersects with the snakehead
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public boolean checkCollision(Rectangle snakeHead) {
|
||||
int s = rectangleSize * 5;
|
||||
Rectangle food = new Rectangle(pFood, new Dimension(s, s));
|
||||
return food.intersects(snakeHead);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the length that will be added to the snake
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public int getAdditionalLength() {
|
||||
int snakeAdditionalLength = 0;
|
||||
switch (nextFood) {
|
||||
case white:
|
||||
snakeAdditionalLength = 40;
|
||||
break;
|
||||
case yellow:
|
||||
snakeAdditionalLength = 15;
|
||||
break;
|
||||
case orange:
|
||||
snakeAdditionalLength = 6;
|
||||
break;
|
||||
case red:
|
||||
snakeAdditionalLength = 2;
|
||||
break;
|
||||
case blue:
|
||||
snakeAdditionalLength = 1;
|
||||
break;
|
||||
}
|
||||
return snakeAdditionalLength;
|
||||
}
|
||||
}
|
41
src/main/dev/lh/Main.java
Executable file
41
src/main/dev/lh/Main.java
Executable file
@ -0,0 +1,41 @@
|
||||
package dev.lh;
|
||||
|
||||
import dev.lh.ui.GameWindow;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>Main.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
private static GameWindow game;
|
||||
|
||||
/**
|
||||
* @param args the program arguments
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// if wanted, the StartScreen can be added here
|
||||
startGame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new game of Snake.
|
||||
*
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static void startGame() {
|
||||
game = new GameWindow("Snake");
|
||||
game.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently used game
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static GameWindow getGame() { return game; }
|
||||
}
|
171
src/main/dev/lh/Snake.java
Executable file
171
src/main/dev/lh/Snake.java
Executable file
@ -0,0 +1,171 @@
|
||||
package dev.lh;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.lh.ui.Endscreen;
|
||||
import dev.lh.ui.GameWindow;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>Snake.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public class Snake implements Updateable {
|
||||
|
||||
/**
|
||||
* This enum contains all possible directions for the {@link Snake}.<br>
|
||||
* <br>
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>Snake.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static enum Direction {
|
||||
/**
|
||||
* Use if the snake should head left.
|
||||
*/
|
||||
Left,
|
||||
|
||||
/**
|
||||
* Use if the snake should head right.
|
||||
*/
|
||||
Right,
|
||||
|
||||
/**
|
||||
* Use if the snake should head up.
|
||||
*/
|
||||
Up,
|
||||
|
||||
/**
|
||||
* Use if the snake should head down.
|
||||
*/
|
||||
Down;
|
||||
}
|
||||
|
||||
private static FoodFactory foodFactory = FoodFactory.getInstance();
|
||||
private static Endscreen endscreen;
|
||||
private Direction Richtung;
|
||||
private int length;
|
||||
private List<Point> tiles = new ArrayList<>();
|
||||
private final int snakeSize = 10;
|
||||
|
||||
/**
|
||||
* Constructs a new Snake with the given length in tiles.
|
||||
*
|
||||
* @param length the length of the snake in tiles
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Snake(int length) {
|
||||
this.length = length;
|
||||
Richtung = Direction.Right;
|
||||
// adding the initial tiles of the snake
|
||||
for (int i = 0; i < length; i++)
|
||||
tiles.add(new Point(320 - snakeSize * i, 240));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextFrame() {
|
||||
int velX = 0, velY = 0;
|
||||
switch (Richtung) {
|
||||
case Up:
|
||||
velY = -snakeSize;
|
||||
break;
|
||||
case Down:
|
||||
velY = snakeSize;
|
||||
break;
|
||||
case Left:
|
||||
velX = -snakeSize;
|
||||
break;
|
||||
case Right:
|
||||
velX = snakeSize;
|
||||
break;
|
||||
}
|
||||
Point next = (Point) tiles.get(0).clone(), cur;
|
||||
tiles.get(0).x += velX;
|
||||
tiles.get(0).y += velY;
|
||||
|
||||
for (int i = 1; i < length; i++) {
|
||||
cur = tiles.get(i);
|
||||
tiles.set(i, (Point) next.clone());
|
||||
next = cur;
|
||||
}
|
||||
|
||||
// case if snake is outside of the screen or touches itself
|
||||
if (checkSelfCollision()) gameOver();
|
||||
// TODO: the game bounds checking below appears to work on Windows, however throws a NullPointerException on Linux/UNIX systems
|
||||
// if (!Main.getGame().getBounds().contains(tiles.get(0))) gameOver();
|
||||
|
||||
// case if snake eats food
|
||||
if (foodFactory.checkCollision(new Rectangle(tiles.get(0).x, tiles.get(0).y, snakeSize, snakeSize))) {
|
||||
addLength(foodFactory.getAdditionalLength());
|
||||
GameWindow game = Main.getGame();
|
||||
game.newFood();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @since Snake 1.1
|
||||
*/
|
||||
private void gameOver() {
|
||||
endscreen = new Endscreen(length);
|
||||
endscreen.setVisible(true);
|
||||
Main.getGame().close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the snake collides with itself
|
||||
* @since Snake 1.1
|
||||
*/
|
||||
private boolean checkSelfCollision() {
|
||||
Point headIndex = tiles.get(0);
|
||||
Rectangle head = new Rectangle(headIndex.x, headIndex.y, snakeSize, snakeSize);
|
||||
for (int index = 1; index < tiles.size(); index++) {
|
||||
Point bodyIndex = tiles.get(index);
|
||||
if (head.contains(new Rectangle(bodyIndex.x, bodyIndex.y, snakeSize, snakeSize))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics g) {
|
||||
g.setColor(Color.green);
|
||||
for (int i = 0; i < length; i++)
|
||||
g.fillRect(tiles.get(i).x, tiles.get(i).y, snakeSize, snakeSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current {@link Direction} of the snake
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public Direction getRichtung() { return Richtung; }
|
||||
|
||||
/**
|
||||
* @param richtung the new {@link Direction} of the snake
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void setRichtung(Direction richtung) { Richtung = richtung; }
|
||||
|
||||
/**
|
||||
* Adds the given length to the current snake object
|
||||
*
|
||||
* @param additional the number of tiles to add
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void addLength(int additional) {
|
||||
Point last = tiles.get(tiles.size() - 1);
|
||||
for (int i = 0; i < additional; i++)
|
||||
tiles.add(last);
|
||||
length += additional;
|
||||
}
|
||||
}
|
32
src/main/dev/lh/Updateable.java
Executable file
32
src/main/dev/lh/Updateable.java
Executable file
@ -0,0 +1,32 @@
|
||||
package dev.lh;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* This interface contains everything that needs to updated regularly.<br>
|
||||
* <br>
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>Updateable.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public interface Updateable {
|
||||
|
||||
/**
|
||||
* Here should the actions be implemented that are supposed to happen when a new
|
||||
* frame gets created.
|
||||
*
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
void nextFrame();
|
||||
|
||||
/**
|
||||
* Renders the object.
|
||||
*
|
||||
* @param g the {@link Graphics} object that is used to render this object
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
void render(Graphics g);
|
||||
}
|
90
src/main/dev/lh/ui/Endscreen.java
Executable file
90
src/main/dev/lh/ui/Endscreen.java
Executable file
@ -0,0 +1,90 @@
|
||||
package dev.lh.ui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import dev.lh.Main;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>Endscreen.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake v1.1
|
||||
*/
|
||||
public class Endscreen extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = -4457484397259161063L;
|
||||
|
||||
private final JPanel contentPanel = new JPanel();
|
||||
private int score = 0;
|
||||
private static final int goodOrBadResult = 200;
|
||||
|
||||
/**
|
||||
* Create the dialog.
|
||||
*
|
||||
* @param score the highscore to set
|
||||
*/
|
||||
public Endscreen(int score) {
|
||||
this.score = score;
|
||||
try {
|
||||
// readInHighscoresPoints();
|
||||
// readInHighscoresPlayers();
|
||||
|
||||
setTitle("Endscreen");
|
||||
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
setBounds(100, 100, 700, 700);
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
getContentPane().add(contentPanel, BorderLayout.CENTER);
|
||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
Thread.getAllStackTraces().forEach((thread, stackTraceElement) -> thread.interrupt());
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
JButton btnNewButton = new JButton("Play again");
|
||||
btnNewButton.setMnemonic(KeyEvent.VK_ENTER);
|
||||
btnNewButton.addActionListener(e -> { Main.startGame(); dispose(); });
|
||||
contentPanel.setLayout(new BorderLayout(0, 0));
|
||||
// btnNewButton.setIcon(new
|
||||
// ImageIcon(ClassLoader.getSystemResource("/com/sun/javafx/webkit/prism/resources/mediaPlayDisabled.png")));
|
||||
btnNewButton.setIconTextGap(5);
|
||||
btnNewButton.setFont(new Font("Times New Roman", Font.PLAIN, 15));
|
||||
contentPanel.add(btnNewButton, BorderLayout.SOUTH);
|
||||
|
||||
JLabel lblDeinPunktestand = new JLabel("Dein Punktestand: " + String.valueOf(score));
|
||||
lblDeinPunktestand.setFont(new Font("Times New Roman", Font.PLAIN, 25));
|
||||
contentPanel.add(lblDeinPunktestand, BorderLayout.NORTH);
|
||||
|
||||
//TODO: the display ofthe result image could work, but not guaranteed
|
||||
// Image resultImage = Toolkit.getDefaultToolkit()
|
||||
// .getImage(this.getClass()
|
||||
// .getResource((score < goodOrBadResult) ? "/Snake/src/main/resources/Try_Again.jpg" : "/Snake/src/main/resources/1211548-200.png"));
|
||||
// resultImage.flush();
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the highscore of the current game
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public int getScore() { return score; }
|
||||
|
||||
/**
|
||||
* @param score the new highscore
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public void setScore(int score) { this.score = score; }
|
||||
}
|
111
src/main/dev/lh/ui/GameWindow.java
Executable file
111
src/main/dev/lh/ui/GameWindow.java
Executable file
@ -0,0 +1,111 @@
|
||||
package dev.lh.ui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import dev.lh.FoodFactory;
|
||||
import dev.lh.Snake;
|
||||
import dev.lh.Snake.Direction;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>GameWindow.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public class GameWindow extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Snake s = new Snake(7);
|
||||
private FoodFactory foodFactory = FoodFactory.getInstance();
|
||||
|
||||
/**
|
||||
* @param title the title of the frame
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public GameWindow(String title) {
|
||||
super(title);
|
||||
newFood();
|
||||
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
setBounds(new Rectangle(size));
|
||||
setLocation(0, 0);
|
||||
setLocationRelativeTo(null);
|
||||
setMinimumSize(size);
|
||||
setPreferredSize(size);
|
||||
setMaximumSize(size);
|
||||
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
|
||||
setResizable(false);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
add(new JPanel() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.setColor(Color.black);
|
||||
g.fillRect(0, 0, super.getWidth(), super.getHeight());
|
||||
s.render(g);
|
||||
foodFactory.paintFood(g);
|
||||
}
|
||||
});
|
||||
|
||||
addKeyListener(new KeyAdapter() {
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
super.keyPressed(e);
|
||||
switch (e.getKeyCode()) {
|
||||
case KeyEvent.VK_W:
|
||||
case KeyEvent.VK_UP:
|
||||
if (!s.getRichtung().equals(Direction.Down)) s.setRichtung(Direction.Up);
|
||||
break;
|
||||
case KeyEvent.VK_A:
|
||||
case KeyEvent.VK_LEFT:
|
||||
if (!s.getRichtung().equals(Direction.Right)) s.setRichtung(Direction.Left);
|
||||
break;
|
||||
case KeyEvent.VK_S:
|
||||
case KeyEvent.VK_DOWN:
|
||||
if (!s.getRichtung().equals(Direction.Up)) s.setRichtung(Direction.Down);
|
||||
break;
|
||||
case KeyEvent.VK_D:
|
||||
case KeyEvent.VK_RIGHT:
|
||||
if (!s.getRichtung().equals(Direction.Left)) s.setRichtung(Direction.Right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Timer timer = new Timer(50,
|
||||
evt -> { s.nextFrame(); if (System.currentTimeMillis() >= foodFactory.getTimeOfNextFood()) newFood(); repaint(); });
|
||||
timer.start();
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new food
|
||||
*
|
||||
* @since Snake 1.1
|
||||
*/
|
||||
public void newFood() {
|
||||
foodFactory.generateFood();
|
||||
foodFactory.generateFoodLocation(getWidth(), getHeight());
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes this frame
|
||||
*
|
||||
* @since Snake 1.1
|
||||
*/
|
||||
public void close() { dispose(); }
|
||||
}
|
80
src/main/dev/lh/ui/StartScreen.java
Executable file
80
src/main/dev/lh/ui/StartScreen.java
Executable file
@ -0,0 +1,80 @@
|
||||
package dev.lh.ui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import dev.lh.Main;
|
||||
|
||||
/**
|
||||
* Project: <strong>Snake</strong><br>
|
||||
* File: <strong>StartScreen.java</strong><br>
|
||||
* Created: <strong>11 Mar 2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public class StartScreen extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 6055940532003735543L;
|
||||
private JPanel contentPane;
|
||||
|
||||
/**
|
||||
* closes the application.
|
||||
*/
|
||||
public static void close() { System.exit(0); }
|
||||
|
||||
/**
|
||||
* Launches Snake.
|
||||
*
|
||||
* @param args the program arguments
|
||||
* @since Snake 1.0
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
try {
|
||||
StartScreen frame = new StartScreen();
|
||||
frame.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public StartScreen() {
|
||||
try {
|
||||
// readInHighscores();
|
||||
setTitle("Snake - Startscreen");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setBounds(500, 200, 550, 550);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
|
||||
JButton buPlay = new JButton("Start Game");
|
||||
buPlay.setBounds(158, 197, 190, 131);
|
||||
buPlay.setIcon(new ImageIcon(StartScreen.class.getResource("/com/sun/javafx/webkit/prism/resources/mediaPlayDisabled.png")));
|
||||
buPlay.setMnemonic(KeyEvent.VK_ENTER);
|
||||
buPlay.setFont(new Font("Times New Roman", Font.PLAIN, 16));
|
||||
|
||||
buPlay.addActionListener(a -> {
|
||||
|
||||
Main.startGame();
|
||||
setVisible(false);
|
||||
dispose();
|
||||
System.gc();
|
||||
});
|
||||
contentPane.setLayout(null);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/main/resources/1211548-200.png
Executable file
BIN
src/main/resources/1211548-200.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
BIN
src/main/resources/Try_Again.jpg
Executable file
BIN
src/main/resources/Try_Again.jpg
Executable file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Reference in New Issue
Block a user