Compare commits
No commits in common. "develop" and "v0.9" have entirely different histories.
@ -2,7 +2,7 @@
|
|||||||
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
|
## Features
|
||||||
- normal playing experience of Snake but hardware-accelerated
|
- normal playing experience of Snake
|
||||||
- 5 different fruits that can be eaten to enlarge the Snake
|
- 5 different fruits that can be eaten to enlarge the Snake
|
||||||
- theoretically Start- and Endscreen, currently mostly unused
|
- 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
|
- theoretically visual display whether a result is good or bad, commented out for now as it does not appear to work as expected
|
||||||
@ -23,4 +23,4 @@ My advanced Hello World program is a version of the old game Snake.
|
|||||||
- as the name suggests, defines the visual appearance before and after games
|
- as the name suggests, defines the visual appearance before and after games
|
||||||
|
|
||||||
## JAR of the final version
|
## JAR of the final version
|
||||||
If you follow <a href="https://github.com/delvh/Snake/releases">**this link**</a> and click on release "Snake - Rattlesnake version", you can download the runnable JAR of how the project currently looks like.
|
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
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package dev.lh;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.Rectangle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a food item.
|
|
||||||
* <p>
|
|
||||||
* Project: <strong>Snake</strong><br>
|
|
||||||
* File: <strong>Food.java</strong><br>
|
|
||||||
* Created: <strong>01.07.2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public final class Food implements Updateable {
|
|
||||||
|
|
||||||
private final Color color;
|
|
||||||
private final int lengthBonus;
|
|
||||||
private final Rectangle bounds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a food item.
|
|
||||||
*
|
|
||||||
* @param color the color of the food item
|
|
||||||
* @param lengthBonus the length added to the snake when the food item is eaten
|
|
||||||
* @param bounds the bounds of the food item
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public Food(Color color, int lengthBonus, Rectangle bounds) {
|
|
||||||
this.color = color;
|
|
||||||
this.lengthBonus = lengthBonus;
|
|
||||||
this.bounds = bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(Graphics2D g) {
|
|
||||||
g.setColor(color);
|
|
||||||
g.fill(bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the length added to the snake when the food item is eaten
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public int getLengthBonus() { return lengthBonus; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the bounds of the food item
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public Rectangle getBounds() { return bounds; }
|
|
||||||
}
|
|
@ -1,69 +1,229 @@
|
|||||||
package dev.lh;
|
package dev.lh;
|
||||||
|
|
||||||
import static java.awt.Color.*;
|
import java.awt.*;
|
||||||
|
|
||||||
import java.awt.Color;
|
import dev.lh.ui.GameWindow;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates food items with predefined properties at random positions and calculates the next
|
|
||||||
* spawning time.
|
|
||||||
* <p>
|
|
||||||
* Project: <strong>Snake</strong><br>
|
* Project: <strong>Snake</strong><br>
|
||||||
* File: <strong>FoodFactory.java</strong><br>
|
* File: <strong>FoodFactory.java</strong><br>
|
||||||
* Created: <strong>11 Mar 2020</strong><br>
|
* Created: <strong>11 Mar 2020</strong><br>
|
||||||
*
|
*
|
||||||
* @author Leon Hofmeister
|
* @author Leon Hofmeister
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public final class FoodFactory {
|
public class FoodFactory {
|
||||||
|
|
||||||
private int width, height;
|
|
||||||
private long nextSpawnTime;
|
|
||||||
private Random random = new Random();
|
|
||||||
|
|
||||||
private static final Color[] FOOD_COLORS = {
|
|
||||||
WHITE, YELLOW, ORANGE, RED, BLUE
|
|
||||||
};
|
|
||||||
private static final int[] FOOD_LENGTH_BONUSES = {
|
|
||||||
40, 15, 6, 2, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a food factory.
|
* 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>
|
||||||
*
|
*
|
||||||
* @param width the width of the viewport
|
* @author Leon Hofmeister
|
||||||
* @param height the height of the viewport
|
* @since Snake 1.0
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
*/
|
||||||
public FoodFactory(int width, int height) {
|
public static enum Food {
|
||||||
this.width = width;
|
/**
|
||||||
this.height = height;
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a new food item
|
* Generates the amount of time that needs to pass before the next food object
|
||||||
* @since Snake 1.2
|
* will be constructed.
|
||||||
|
*
|
||||||
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public synchronized Food spawn() {
|
public void setTimeToNextFoodMillis() { timeOfNextFood = System.currentTimeMillis() + (int) Math.round(Math.random() * 15000 + 1000); }
|
||||||
nextSpawnTime = System.currentTimeMillis() + random.nextInt(15000) + 1000;
|
|
||||||
int seed = random.nextInt(5);
|
/**
|
||||||
return new Food(
|
* @return the type of the next food
|
||||||
FOOD_COLORS[seed],
|
* @since Snake 1.0
|
||||||
FOOD_LENGTH_BONUSES[seed],
|
*/
|
||||||
new Rectangle(random.nextInt(width - 100) + 50,
|
public Food getNextFood() { return nextFood; }
|
||||||
random.nextInt(height - 100) + 50,
|
|
||||||
10 + seed * 5,
|
/**
|
||||||
10 + seed * 5
|
* @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 time after which a new food item should be spawned
|
* @return the size of the corresponding food (length = width)
|
||||||
* @since Snake 1.2
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public long getNextSpawnTime() { return nextSpawnTime; }
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package dev.lh;
|
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the state of game objects.
|
|
||||||
* <p>
|
|
||||||
* Project: <strong>Snake</strong><br>
|
|
||||||
* File: <strong>Handler.java</strong><br>
|
|
||||||
* Created: <strong>01.07.2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public final class Handler implements Updateable {
|
|
||||||
|
|
||||||
private Snake snake = new Snake(7);
|
|
||||||
private FoodFactory foodFactory;
|
|
||||||
|
|
||||||
private volatile Food food;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a handler.
|
|
||||||
*
|
|
||||||
* @param snake the snake
|
|
||||||
* @param foodFactory the food factory
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public Handler(Snake snake, FoodFactory foodFactory) {
|
|
||||||
this.snake = snake;
|
|
||||||
this.foodFactory = foodFactory;
|
|
||||||
food = foodFactory.spawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick() {
|
|
||||||
snake.tick();
|
|
||||||
food.tick();
|
|
||||||
|
|
||||||
// Check for food collision
|
|
||||||
if (snake.getHead().intersects(food.getBounds())) {
|
|
||||||
snake.addLength(food.getLengthBonus());
|
|
||||||
food = foodFactory.spawn();
|
|
||||||
}
|
|
||||||
if (System.currentTimeMillis() > foodFactory.getNextSpawnTime())
|
|
||||||
food = foodFactory.spawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(Graphics2D g) {
|
|
||||||
snake.render(g);
|
|
||||||
food.render(g);
|
|
||||||
}
|
|
||||||
}
|
|
174
src/main/dev/lh/Snake.java
Normal file → Executable file
174
src/main/dev/lh/Snake.java
Normal file → Executable file
@ -1,12 +1,14 @@
|
|||||||
package dev.lh;
|
package dev.lh;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import dev.lh.ui.Endscreen;
|
import dev.lh.ui.Endscreen;
|
||||||
|
import dev.lh.ui.GameWindow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Snake</strong><br>
|
* Project: <strong>Snake</strong><br>
|
||||||
@ -28,34 +30,34 @@ public class Snake implements Updateable {
|
|||||||
* @author Leon Hofmeister
|
* @author Leon Hofmeister
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public enum Direction {
|
public static enum Direction {
|
||||||
/**
|
/**
|
||||||
* Use if the snake should head left.
|
* Use if the snake should head left.
|
||||||
*/
|
*/
|
||||||
LEFT,
|
Left,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use if the snake should head right.
|
* Use if the snake should head right.
|
||||||
*/
|
*/
|
||||||
RIGHT,
|
Right,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use if the snake should head up.
|
* Use if the snake should head up.
|
||||||
*/
|
*/
|
||||||
UP,
|
Up,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use if the snake should head down.
|
* Use if the snake should head down.
|
||||||
*/
|
*/
|
||||||
DOWN;
|
Down;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Endscreen endscreen;
|
private static FoodFactory foodFactory = FoodFactory.getInstance();
|
||||||
private Direction direction = Direction.RIGHT;
|
private static Endscreen endscreen;
|
||||||
private int length;
|
private Direction Richtung;
|
||||||
private final List<Rectangle> tiles = new ArrayList<>();
|
private int length;
|
||||||
|
private List<Point> tiles = new ArrayList<>();
|
||||||
private static final int TILE_SIZE = 10;
|
private final int snakeSize = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Snake with the given length in tiles.
|
* Constructs a new Snake with the given length in tiles.
|
||||||
@ -64,24 +66,61 @@ public class Snake implements Updateable {
|
|||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public Snake(int length) {
|
public Snake(int length) {
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
Richtung = Direction.Right;
|
||||||
// Add initial tiles
|
// adding the initial tiles of the snake
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
tiles.add(new Rectangle(320 - TILE_SIZE * i, 240, TILE_SIZE, TILE_SIZE));
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the given length to the current snake object.
|
|
||||||
*
|
*
|
||||||
* @param additional the number of tiles to add
|
* @since Snake 1.1
|
||||||
* @since Snake 1.0
|
|
||||||
*/
|
*/
|
||||||
public void addLength(int additional) {
|
private void gameOver() {
|
||||||
final Rectangle last = tiles.get(tiles.size() - 1);
|
endscreen = new Endscreen(length);
|
||||||
for (int i = 0; i < additional; i++)
|
endscreen.setVisible(true);
|
||||||
tiles.add(last);
|
Main.getGame().close();
|
||||||
length += additional;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,77 +128,44 @@ public class Snake implements Updateable {
|
|||||||
* @since Snake 1.1
|
* @since Snake 1.1
|
||||||
*/
|
*/
|
||||||
private boolean checkSelfCollision() {
|
private boolean checkSelfCollision() {
|
||||||
return tiles.stream().skip(1).anyMatch(tiles.get(0)::contains);
|
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);
|
||||||
* @since Snake 1.1
|
if (head.contains(new Rectangle(bodyIndex.x, bodyIndex.y, snakeSize, snakeSize))) return true;
|
||||||
*/
|
}
|
||||||
private void gameOver() {
|
return false;
|
||||||
Main.getGame().close();
|
|
||||||
endscreen = new Endscreen(length);
|
|
||||||
endscreen.setVisible(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void render(Graphics g) {
|
||||||
int velX = 0, velY = 0;
|
|
||||||
switch (direction) {
|
|
||||||
case UP:
|
|
||||||
velY = -TILE_SIZE;
|
|
||||||
break;
|
|
||||||
case DOWN:
|
|
||||||
velY = TILE_SIZE;
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
velX = -TILE_SIZE;
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
velX = TILE_SIZE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Add a new tile at the front
|
|
||||||
tiles.add(
|
|
||||||
0,
|
|
||||||
new Rectangle(tiles.get(0).x + velX, tiles.get(0).y + velY, TILE_SIZE, TILE_SIZE)
|
|
||||||
);
|
|
||||||
// Remove the last tile
|
|
||||||
tiles.remove(tiles.size() - 1);
|
|
||||||
// Case if snake is outside of the screen or touches itself
|
|
||||||
if (checkSelfCollision()) {
|
|
||||||
gameOver();
|
|
||||||
System.out.println("Snake collided with itself.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: Test on Linux
|
|
||||||
if (!Main.getGame().getBounds().contains(getHead())) {
|
|
||||||
gameOver();
|
|
||||||
System.out.println("Snake went out of bounds.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(Graphics2D g) {
|
|
||||||
g.setColor(Color.green);
|
g.setColor(Color.green);
|
||||||
tiles.forEach(g::fill);
|
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
|
* @return the current {@link Direction} of the snake
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public Direction getDirection() { return direction; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param direction the new {@link Direction} of the snake
|
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public void setDirection(Direction direction) { this.direction = direction; }
|
public Direction getRichtung() { return Richtung; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a rectangle representing the head of the snake
|
* @param richtung the new {@link Direction} of the snake
|
||||||
* @since Snake 1.2
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public Rectangle getHead() { return tiles.get(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package dev.lh;
|
package dev.lh;
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface contains everything that needs to be updated regularly.
|
* This interface contains everything that needs to updated regularly.<br>
|
||||||
* <p>
|
* <br>
|
||||||
* Project: <strong>Snake</strong><br>
|
* Project: <strong>Snake</strong><br>
|
||||||
* File: <strong>Updateable.java</strong><br>
|
* File: <strong>Updateable.java</strong><br>
|
||||||
* Created: <strong>11 Mar 2020</strong><br>
|
* Created: <strong>11 Mar 2020</strong><br>
|
||||||
@ -18,15 +18,15 @@ public interface Updateable {
|
|||||||
* Here should the actions be implemented that are supposed to happen when a new
|
* Here should the actions be implemented that are supposed to happen when a new
|
||||||
* frame gets created.
|
* frame gets created.
|
||||||
*
|
*
|
||||||
* @since Snake 1.2
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
default void tick() {}
|
void nextFrame();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the object.
|
* Renders the object.
|
||||||
*
|
*
|
||||||
* @param g the graphics object that is used to render this object
|
* @param g the {@link Graphics} object that is used to render this object
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
default void render(Graphics2D g) {}
|
void render(Graphics g);
|
||||||
}
|
}
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
package dev.lh;
|
|
||||||
|
|
||||||
import java.awt.Canvas;
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements a hardware-accelerated rendering loop.
|
|
||||||
* <p>
|
|
||||||
* Project: <strong>Snake</strong><br>
|
|
||||||
* File: <strong>Viewport.java</strong><br>
|
|
||||||
* Created: <strong>01.07.2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public class Viewport extends Canvas {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
// Enable OpenGL hardware acceleration
|
|
||||||
static {
|
|
||||||
System.setProperty("sun.java2d.trace", "timestamp,log,count");
|
|
||||||
System.setProperty("sun.java2d.transaccel", "True");
|
|
||||||
System.setProperty("sun.java2d.opengl", "True");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Updateable gameRoot;
|
|
||||||
private Timer timer = new Timer();
|
|
||||||
private TimerTask renderTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param gameRoot the game object responsible for updating the rest
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public Viewport(Updateable gameRoot) {
|
|
||||||
this.gameRoot = gameRoot;
|
|
||||||
setIgnoreRepaint(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the render task.
|
|
||||||
*
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public void start() {
|
|
||||||
if (renderTask != null) renderTask.cancel();
|
|
||||||
else createBufferStrategy(2);
|
|
||||||
|
|
||||||
renderTask = new TimerTask() {
|
|
||||||
|
|
||||||
// private long lastTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// final long time = System.currentTimeMillis();
|
|
||||||
// final double dt = (time - lastTime) * 1E-3;
|
|
||||||
// lastTime = time;
|
|
||||||
// TODO: Delta time adjustment
|
|
||||||
gameRoot.tick();
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
timer.schedule(renderTask, 0, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the render task.
|
|
||||||
*
|
|
||||||
* @since Snake 1.2
|
|
||||||
*/
|
|
||||||
public void stop() { renderTask.cancel(); }
|
|
||||||
|
|
||||||
private void render() {
|
|
||||||
final Graphics2D g = (Graphics2D) getBufferStrategy().getDrawGraphics();
|
|
||||||
|
|
||||||
// Clear the screen
|
|
||||||
g.setColor(Color.BLACK);
|
|
||||||
g.fillRect(0, 0, getWidth(), getHeight());
|
|
||||||
|
|
||||||
// Perform the actual rendering
|
|
||||||
gameRoot.render(g);
|
|
||||||
|
|
||||||
// Flip buffers
|
|
||||||
g.dispose();
|
|
||||||
getBufferStrategy().show();
|
|
||||||
|
|
||||||
// Synchronize with display refresh rate
|
|
||||||
getToolkit().sync();
|
|
||||||
}
|
|
||||||
}
|
|
62
src/main/dev/lh/ui/Endscreen.java
Normal file → Executable file
62
src/main/dev/lh/ui/Endscreen.java
Normal file → Executable file
@ -1,7 +1,6 @@
|
|||||||
package dev.lh.ui;
|
package dev.lh.ui;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.*;
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@ -21,9 +20,9 @@ public class Endscreen extends JDialog {
|
|||||||
|
|
||||||
private static final long serialVersionUID = -4457484397259161063L;
|
private static final long serialVersionUID = -4457484397259161063L;
|
||||||
|
|
||||||
// private static final int goodOrBadResult = 200;
|
private final JPanel contentPanel = new JPanel();
|
||||||
private final JPanel contentPanel = new JPanel();
|
private int score = 0;
|
||||||
private final int score;
|
private static final int goodOrBadResult = 200;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the dialog.
|
* Create the dialog.
|
||||||
@ -32,28 +31,49 @@ public class Endscreen extends JDialog {
|
|||||||
*/
|
*/
|
||||||
public Endscreen(int score) {
|
public Endscreen(int score) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
setTitle("Endscreen");
|
try {
|
||||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
// readInHighscoresPoints();
|
||||||
setBounds(100, 100, 700, 700);
|
// readInHighscoresPlayers();
|
||||||
getContentPane().setLayout(new BorderLayout());
|
|
||||||
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
||||||
contentPanel.setLayout(new BorderLayout(0, 0));
|
|
||||||
getContentPane().add(contentPanel, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
final JButton btnNewButton = new JButton("Play again");
|
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.setMnemonic(KeyEvent.VK_ENTER);
|
||||||
btnNewButton.addActionListener(e -> { Main.startGame(); dispose(); });
|
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));
|
btnNewButton.setFont(new Font("Times New Roman", Font.PLAIN, 15));
|
||||||
contentPanel.add(btnNewButton, BorderLayout.SOUTH);
|
contentPanel.add(btnNewButton, BorderLayout.SOUTH);
|
||||||
|
|
||||||
final JLabel lblDeinPunktestand = new JLabel("Dein Punktestand: " + String.valueOf(score));
|
JLabel lblDeinPunktestand = new JLabel("Dein Punktestand: " + String.valueOf(score));
|
||||||
lblDeinPunktestand.setFont(new Font("Times New Roman", Font.PLAIN, 25));
|
lblDeinPunktestand.setFont(new Font("Times New Roman", Font.PLAIN, 25));
|
||||||
contentPanel.add(lblDeinPunktestand, BorderLayout.NORTH);
|
contentPanel.add(lblDeinPunktestand, BorderLayout.NORTH);
|
||||||
|
|
||||||
// final Image resultImage = Toolkit.getDefaultToolkit()
|
//TODO: the display ofthe result image could work, but not guaranteed
|
||||||
// .getImage(this.getClass().getResource(score < goodOrBadResult ?
|
// Image resultImage = Toolkit.getDefaultToolkit()
|
||||||
// "/Try_Again.jpg" : "/1211548-200.png"));
|
// .getImage(this.getClass()
|
||||||
// resultImage.flush();
|
// .getResource((score < goodOrBadResult) ? "/Snake/src/main/resources/Try_Again.jpg" : "/Snake/src/main/resources/1211548-200.png"));
|
||||||
|
// resultImage.flush();
|
||||||
|
|
||||||
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,4 +81,10 @@ public class Endscreen extends JDialog {
|
|||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public int getScore() { return score; }
|
public int getScore() { return score; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param score the new highscore
|
||||||
|
* @since Snake 1.0
|
||||||
|
*/
|
||||||
|
public void setScore(int score) { this.score = score; }
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package dev.lh.ui;
|
package dev.lh.ui;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.*;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
|
||||||
import dev.lh.*;
|
import dev.lh.FoodFactory;
|
||||||
|
import dev.lh.Snake;
|
||||||
import dev.lh.Snake.Direction;
|
import dev.lh.Snake.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,20 +22,21 @@ import dev.lh.Snake.Direction;
|
|||||||
*/
|
*/
|
||||||
public class GameWindow extends JFrame {
|
public class GameWindow extends JFrame {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private Snake s = new Snake(7);
|
||||||
private Viewport viewport;
|
private FoodFactory foodFactory = FoodFactory.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param title the title of the frame
|
* @param title the title of the frame
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public GameWindow(String title) {
|
public GameWindow(String title) {
|
||||||
// Initialize window
|
|
||||||
super(title);
|
super(title);
|
||||||
|
newFood();
|
||||||
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
|
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
setBounds(new Rectangle(size));
|
setBounds(new Rectangle(size));
|
||||||
setLocation(0, 0);
|
setLocation(0, 0);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
setMinimumSize(size);
|
setMinimumSize(size);
|
||||||
setPreferredSize(size);
|
setPreferredSize(size);
|
||||||
setMaximumSize(size);
|
setMaximumSize(size);
|
||||||
@ -42,14 +44,19 @@ public class GameWindow extends JFrame {
|
|||||||
setResizable(false);
|
setResizable(false);
|
||||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
|
|
||||||
// Initialize game objects
|
add(new JPanel() {
|
||||||
Snake snake = new Snake(7);
|
|
||||||
FoodFactory foodFactory = new FoodFactory(getWidth(), getHeight());
|
|
||||||
Handler handler = new Handler(snake, foodFactory);
|
|
||||||
|
|
||||||
// Initialize viewport
|
private static final long serialVersionUID = 1L;
|
||||||
viewport = new Viewport(handler);
|
|
||||||
add(viewport);
|
@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() {
|
addKeyListener(new KeyAdapter() {
|
||||||
|
|
||||||
@ -59,40 +66,46 @@ public class GameWindow extends JFrame {
|
|||||||
switch (e.getKeyCode()) {
|
switch (e.getKeyCode()) {
|
||||||
case KeyEvent.VK_W:
|
case KeyEvent.VK_W:
|
||||||
case KeyEvent.VK_UP:
|
case KeyEvent.VK_UP:
|
||||||
if (!snake.getDirection().equals(Direction.DOWN))
|
if (!s.getRichtung().equals(Direction.Down)) s.setRichtung(Direction.Up);
|
||||||
snake.setDirection(Direction.UP);
|
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_A:
|
case KeyEvent.VK_A:
|
||||||
case KeyEvent.VK_LEFT:
|
case KeyEvent.VK_LEFT:
|
||||||
if (!snake.getDirection().equals(Direction.RIGHT))
|
if (!s.getRichtung().equals(Direction.Right)) s.setRichtung(Direction.Left);
|
||||||
snake.setDirection(Direction.LEFT);
|
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_S:
|
case KeyEvent.VK_S:
|
||||||
case KeyEvent.VK_DOWN:
|
case KeyEvent.VK_DOWN:
|
||||||
if (!snake.getDirection().equals(Direction.UP))
|
if (!s.getRichtung().equals(Direction.Up)) s.setRichtung(Direction.Down);
|
||||||
snake.setDirection(Direction.DOWN);
|
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_D:
|
case KeyEvent.VK_D:
|
||||||
case KeyEvent.VK_RIGHT:
|
case KeyEvent.VK_RIGHT:
|
||||||
if (!snake.getDirection().equals(Direction.LEFT))
|
if (!s.getRichtung().equals(Direction.Left)) s.setRichtung(Direction.Right);
|
||||||
snake.setDirection(Direction.RIGHT);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Timer timer = new Timer(50,
|
||||||
|
evt -> { s.nextFrame(); if (System.currentTimeMillis() >= foodFactory.getTimeOfNextFood()) newFood(); repaint(); });
|
||||||
|
timer.start();
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
viewport.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes this frame.
|
* Generates new food
|
||||||
*
|
*
|
||||||
* @since Snake 1.1
|
* @since Snake 1.1
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void newFood() {
|
||||||
viewport.stop();
|
foodFactory.generateFood();
|
||||||
setVisible(false);
|
foodFactory.generateFoodLocation(getWidth(), getHeight());
|
||||||
dispose();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes this frame
|
||||||
|
*
|
||||||
|
* @since Snake 1.1
|
||||||
|
*/
|
||||||
|
public void close() { dispose(); }
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ import dev.lh.Main;
|
|||||||
*/
|
*/
|
||||||
public class StartScreen extends JFrame {
|
public class StartScreen extends JFrame {
|
||||||
|
|
||||||
private static final long serialVersionUID = 6055940532003735543L;
|
private static final long serialVersionUID = 6055940532003735543L;
|
||||||
|
private JPanel contentPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the application.
|
* closes the application.
|
||||||
*/
|
*/
|
||||||
public static void close() { System.exit(0); }
|
public static void close() { System.exit(0); }
|
||||||
|
|
||||||
@ -32,32 +33,48 @@ public class StartScreen extends JFrame {
|
|||||||
* @param args the program arguments
|
* @param args the program arguments
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) { EventQueue.invokeLater(StartScreen::new); }
|
public static void main(String[] args) {
|
||||||
|
EventQueue.invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
StartScreen frame = new StartScreen();
|
||||||
|
frame.setVisible(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the frame.
|
* Create the frame.
|
||||||
*/
|
*/
|
||||||
public StartScreen() {
|
public StartScreen() {
|
||||||
setTitle("Snake - Startscreen");
|
try {
|
||||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
// readInHighscores();
|
||||||
setBounds(500, 200, 550, 550);
|
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);
|
||||||
|
|
||||||
final JPanel contentPane = new JPanel();
|
JButton buPlay = new JButton("Start Game");
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
buPlay.setBounds(158, 197, 190, 131);
|
||||||
setContentPane(contentPane);
|
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));
|
||||||
|
|
||||||
final JButton buPlay = new JButton("Start Game");
|
buPlay.addActionListener(a -> {
|
||||||
buPlay.setBounds(158, 197, 190, 131);
|
|
||||||
buPlay.setMnemonic(KeyEvent.VK_ENTER);
|
Main.startGame();
|
||||||
buPlay.setFont(new Font("Times New Roman", Font.PLAIN, 16));
|
setVisible(false);
|
||||||
buPlay.addActionListener(a -> {
|
dispose();
|
||||||
Main.startGame();
|
System.gc();
|
||||||
setVisible(false);
|
});
|
||||||
dispose();
|
contentPane.setLayout(null);
|
||||||
System.gc();
|
|
||||||
});
|
} catch (Exception e) {
|
||||||
contentPane.add(buPlay);
|
|
||||||
contentPane.setLayout(null);
|
e.printStackTrace();
|
||||||
setVisible(true);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user