Add new pipeline and other fun stuff
This commit is contained in:
parent
a8908f7e13
commit
52a4c876fa
40
src/main/dev/lh/Food.java
Normal file
40
src/main/dev/lh/Food.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package dev.lh;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.1
|
||||||
|
*/
|
||||||
|
public final class Food implements Updateable {
|
||||||
|
|
||||||
|
private final Color color;
|
||||||
|
private final int lengthBonus;
|
||||||
|
private final Rectangle bounds;
|
||||||
|
|
||||||
|
public Food(Color color, int lengthBonus, Rectangle bounds) {
|
||||||
|
this.color = color;
|
||||||
|
this.lengthBonus = lengthBonus;
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkCollision(Snake snake) {
|
||||||
|
if (bounds.intersects(snake.getHead())) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(Graphics2D g) {
|
||||||
|
g.setColor(color);
|
||||||
|
g.fill(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLengthBonus() { return lengthBonus; }
|
||||||
|
|
||||||
|
public Rectangle getBounds() { return bounds; }
|
||||||
|
}
|
@ -2,202 +2,68 @@ package dev.lh;
|
|||||||
|
|
||||||
import static java.awt.Color.*;
|
import static java.awt.Color.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.Color;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import dev.lh.ui.GameWindow;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 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 class FoodFactory {
|
public final 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
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enum contains all possible variations of foods. The higher the ordinal
|
* Initializes a food factory.
|
||||||
* of an element, the less it is worth.<br>
|
*
|
||||||
* <br>
|
* @param width the width of the viewport
|
||||||
* Project: <strong>Snake</strong><br>
|
* @param height the height of the viewport
|
||||||
* File: <strong>FoodFactory.java</strong><br>
|
* @since Snake 1.1
|
||||||
* Created: <strong>11 Mar 2020</strong><br>
|
|
||||||
*
|
|
||||||
* @author Leon Hofmeister
|
|
||||||
* @since Snake 1.0
|
|
||||||
*/
|
*/
|
||||||
public enum Food {
|
public FoodFactory(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use if white food is wanted.
|
* @return a new food item
|
||||||
*/
|
* @since Snake 1.1
|
||||||
white(
|
*/
|
||||||
WHITE, 40
|
public synchronized Food spawn() {
|
||||||
),
|
nextSpawnTime = System.currentTimeMillis() + random.nextInt(15000) + 1000;
|
||||||
|
int seed = random.nextInt(5);
|
||||||
/**
|
return new Food(
|
||||||
* Use if yellow food is wanted.
|
FOOD_COLORS[seed],
|
||||||
*/
|
FOOD_LENGTH_BONUSES[seed],
|
||||||
yellow(
|
new Rectangle(random.nextInt(width - 100) + 50,
|
||||||
YELLOW, 15
|
random.nextInt(height - 100) + 50,
|
||||||
),
|
seed * 10,
|
||||||
|
seed * 10
|
||||||
/**
|
)
|
||||||
* Use if orange food is wanted.
|
|
||||||
*/
|
|
||||||
orange(
|
|
||||||
ORANGE, 6
|
|
||||||
),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use if red food is wanted.
|
|
||||||
*/
|
|
||||||
red(
|
|
||||||
RED, 2
|
|
||||||
),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use if blue food is wanted.
|
|
||||||
*/
|
|
||||||
blue(
|
|
||||||
BLUE, 1
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* The color of the food item.
|
|
||||||
*/
|
|
||||||
public final Color color;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The length bonus of the food item.
|
|
||||||
*/
|
|
||||||
public final int lengthBonus;
|
|
||||||
|
|
||||||
private Food(Color color, int lengthBonus) {
|
|
||||||
this.color = color;
|
|
||||||
this.lengthBonus = lengthBonus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FoodFactory foodFactory = new FoodFactory();
|
|
||||||
|
|
||||||
private long timeOfNextFood;
|
|
||||||
|
|
||||||
private Point pFood;
|
|
||||||
|
|
||||||
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() {
|
|
||||||
nextFood = Food.values()[new Random().nextInt(Food.values().length)];
|
|
||||||
rectangleSize = nextFood.ordinal() + 2;
|
|
||||||
setTimeToNextFoodMillis();
|
|
||||||
return nextFood;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the amount of time that needs to pass before the next food object
|
* @return the time after which a new food item should be spawned
|
||||||
* will be constructed.
|
* @since Snake 1.1
|
||||||
*
|
|
||||||
* @since Snake 1.0
|
|
||||||
*/
|
*/
|
||||||
public void setTimeToNextFoodMillis() {
|
public long getNextSpawnTime() { return nextSpawnTime; }
|
||||||
timeOfNextFood = System.currentTimeMillis() + new Random().nextInt(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) {
|
|
||||||
assert (width > 100 && height > 100);
|
|
||||||
Random r = new Random();
|
|
||||||
return pFood = new Point(r.nextInt(width - 100) + 50, r.nextInt(height - 100) + 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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) {
|
|
||||||
g.setColor(nextFood.color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 snake head
|
|
||||||
* @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() {
|
|
||||||
return nextFood.lengthBonus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
46
src/main/dev/lh/Handler.java
Normal file
46
src/main/dev/lh/Handler.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
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.1
|
||||||
|
*/
|
||||||
|
public final class Handler implements Updateable {
|
||||||
|
|
||||||
|
private Snake snake = new Snake(7);
|
||||||
|
private FoodFactory foodFactory;
|
||||||
|
|
||||||
|
private volatile Food food;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@ 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>
|
||||||
@ -51,7 +50,6 @@ public class Snake implements Updateable {
|
|||||||
DOWN;
|
DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FoodFactory foodFactory = FoodFactory.getInstance();
|
|
||||||
private static Endscreen endscreen;
|
private static Endscreen endscreen;
|
||||||
private Direction direction = Direction.RIGHT;
|
private Direction direction = Direction.RIGHT;
|
||||||
private int length;
|
private int length;
|
||||||
@ -103,14 +101,8 @@ public class Snake implements Updateable {
|
|||||||
Main.getGame().close();
|
Main.getGame().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the current {@link Direction} of the snake
|
|
||||||
* @since Snake 1.0
|
|
||||||
*/
|
|
||||||
public Direction getRichtung() { return direction; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextFrame() {
|
public void tick() {
|
||||||
int velX = 0, velY = 0;
|
int velX = 0, velY = 0;
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case UP:
|
case UP:
|
||||||
@ -140,18 +132,11 @@ public class Snake implements Updateable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Test on Linux
|
// TODO: Test on Linux
|
||||||
if (!Main.getGame().getBounds().contains(tiles.get(0))) {
|
if (!Main.getGame().getBounds().contains(getHead())) {
|
||||||
gameOver();
|
gameOver();
|
||||||
System.out.println("Snake went out of bounds.");
|
System.out.println("Snake went out of bounds.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Move to Food class
|
|
||||||
// Case if snake eats food
|
|
||||||
if (foodFactory.checkCollision(tiles.get(0))) {
|
|
||||||
addLength(foodFactory.getAdditionalLength());
|
|
||||||
GameWindow game = Main.getGame();
|
|
||||||
game.newFood();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -160,9 +145,21 @@ public class Snake implements Updateable {
|
|||||||
tiles.forEach(g::fill);
|
tiles.forEach(g::fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current {@link Direction} of the snake
|
||||||
|
* @since Snake 1.0
|
||||||
|
*/
|
||||||
|
public Direction getDirection() { return direction; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param direction the new {@link Direction} of the snake
|
* @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 void setDirection(Direction direction) { this.direction = direction; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a rectangle representing the head of the snake
|
||||||
|
* @since Snake 1.1
|
||||||
|
*/
|
||||||
|
public Rectangle getHead() { return tiles.get(0); }
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ public interface Updateable {
|
|||||||
*
|
*
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
void nextFrame();
|
default void tick() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the object.
|
* Renders the object.
|
||||||
@ -28,5 +28,5 @@ public interface Updateable {
|
|||||||
* @param g the graphics object that is used to render this object
|
* @param g the graphics object that is used to render this object
|
||||||
* @since Snake 1.0
|
* @since Snake 1.0
|
||||||
*/
|
*/
|
||||||
void render(Graphics2D g);
|
default void render(Graphics2D g) {}
|
||||||
}
|
}
|
||||||
|
98
src/main/dev/lh/Viewport.java
Normal file
98
src/main/dev/lh/Viewport.java
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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.0
|
||||||
|
*/
|
||||||
|
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.0
|
||||||
|
*/
|
||||||
|
public Viewport(Updateable gameRoot) {
|
||||||
|
this.gameRoot = gameRoot;
|
||||||
|
setIgnoreRepaint(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the render task.
|
||||||
|
*
|
||||||
|
* @since Snake 1.1
|
||||||
|
*/
|
||||||
|
public void start() {
|
||||||
|
if (renderTask != null)
|
||||||
|
renderTask.cancel();
|
||||||
|
else
|
||||||
|
createBufferStrategy(2);
|
||||||
|
|
||||||
|
renderTask = new TimerTask() {
|
||||||
|
|
||||||
|
private long lastTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
double dt = (time - lastTime) * 1E-3;
|
||||||
|
lastTime = time;
|
||||||
|
|
||||||
|
gameRoot.tick();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
timer.schedule(renderTask, 0, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the render task.
|
||||||
|
*
|
||||||
|
* @since Snake 1.1
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
renderTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void render() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
package dev.lh.ui;
|
package dev.lh.ui;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.Dimension;
|
||||||
|
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.FoodFactory;
|
import dev.lh.*;
|
||||||
import dev.lh.Snake;
|
|
||||||
import dev.lh.Snake.Direction;
|
import dev.lh.Snake.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,21 +21,20 @@ 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 FoodFactory foodFactory = FoodFactory.getInstance();
|
private Viewport viewport;
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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);
|
||||||
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);
|
||||||
@ -44,19 +42,14 @@ public class GameWindow extends JFrame {
|
|||||||
setResizable(false);
|
setResizable(false);
|
||||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
|
|
||||||
add(new JPanel() {
|
// Initialize game objects
|
||||||
|
Snake snake = new Snake(7);
|
||||||
|
FoodFactory foodFactory = new FoodFactory(getWidth(), getHeight());
|
||||||
|
Handler handler = new Handler(snake, foodFactory);
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
// Initialize viewport
|
||||||
|
viewport = new Viewport(handler);
|
||||||
@Override
|
add(viewport);
|
||||||
protected void paintComponent(Graphics g) {
|
|
||||||
super.paintComponent(g);
|
|
||||||
g.setColor(Color.black);
|
|
||||||
g.fillRect(0, 0, getWidth(), getHeight());
|
|
||||||
s.render((Graphics2D) g);
|
|
||||||
foodFactory.paintFood(g);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addKeyListener(new KeyAdapter() {
|
addKeyListener(new KeyAdapter() {
|
||||||
|
|
||||||
@ -66,56 +59,40 @@ 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 (!s.getRichtung().equals(Direction.DOWN)) s.setDirection(Direction.UP);
|
if (!snake.getDirection().equals(Direction.DOWN))
|
||||||
|
snake.setDirection(Direction.UP);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_A:
|
case KeyEvent.VK_A:
|
||||||
case KeyEvent.VK_LEFT:
|
case KeyEvent.VK_LEFT:
|
||||||
if (!s.getRichtung().equals(Direction.RIGHT)) s.setDirection(Direction.LEFT);
|
if (!snake.getDirection().equals(Direction.RIGHT))
|
||||||
|
snake.setDirection(Direction.LEFT);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_S:
|
case KeyEvent.VK_S:
|
||||||
case KeyEvent.VK_DOWN:
|
case KeyEvent.VK_DOWN:
|
||||||
if (!s.getRichtung().equals(Direction.UP)) s.setDirection(Direction.DOWN);
|
if (!snake.getDirection().equals(Direction.UP))
|
||||||
|
snake.setDirection(Direction.DOWN);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_D:
|
case KeyEvent.VK_D:
|
||||||
case KeyEvent.VK_RIGHT:
|
case KeyEvent.VK_RIGHT:
|
||||||
if (!s.getRichtung().equals(Direction.LEFT)) s.setDirection(Direction.RIGHT);
|
if (!snake.getDirection().equals(Direction.LEFT))
|
||||||
|
snake.setDirection(Direction.RIGHT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
newFood();
|
|
||||||
timer = new Timer(
|
|
||||||
50,
|
|
||||||
evt -> {
|
|
||||||
s.nextFrame();
|
|
||||||
if (System.currentTimeMillis() >= foodFactory.getTimeOfNextFood())
|
|
||||||
newFood();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
timer.start();
|
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
viewport.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates new food.
|
* Disposes this frame.
|
||||||
*
|
|
||||||
* @since Snake 1.1
|
|
||||||
*/
|
|
||||||
public void newFood() {
|
|
||||||
foodFactory.generateFood();
|
|
||||||
foodFactory.generateFoodLocation(getWidth(), getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes this frame
|
|
||||||
*
|
*
|
||||||
* @since Snake 1.1
|
* @since Snake 1.1
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
timer.stop();
|
viewport.stop();
|
||||||
|
setVisible(false);
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user