Optimized Ticking and Rendering #5
| @@ -28,7 +28,7 @@ public class FoodFactory { | ||||
|   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
```   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
```   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
```   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
```   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
```   
				
					
						
						delvh
					
					
						commented  
						Review
						 ```suggestion
	 * @since Snake 1.2
``` | ||||
| 	 * @author Leon Hofmeister | ||||
| 	 * @since Snake 1.0 | ||||
| 	 */ | ||||
| 	public static enum Food { | ||||
|   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
``` | ||||
| 	public enum Food { | ||||
|   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
``` | ||||
|  | ||||
| 		/** | ||||
| 		 * Use if white food is wanted. | ||||
|   | ||||
|   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
``` | ||||
| @@ -1,6 +1,8 @@ | ||||
| package dev.lh; | ||||
|  | ||||
| import java.awt.*; | ||||
| import java.awt.Color; | ||||
| import java.awt.Graphics2D; | ||||
| import java.awt.Rectangle; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -31,30 +33,31 @@ public class Snake implements Updateable { | ||||
| 		/** | ||||
| 		 * Use if the snake should head left. | ||||
| 		 */ | ||||
| 		Left, | ||||
| 		LEFT, | ||||
|  | ||||
| 		/** | ||||
| 		 * Use if the snake should head right. | ||||
| 		 */ | ||||
| 		Right, | ||||
| 		RIGHT, | ||||
|  | ||||
| 		/** | ||||
| 		 * Use if the snake should head up. | ||||
| 		 */ | ||||
| 		Up, | ||||
| 		UP, | ||||
|  | ||||
| 		/** | ||||
| 		 * Use if the snake should head down. | ||||
| 		 */ | ||||
| 		Down; | ||||
| 		DOWN; | ||||
| 	} | ||||
|  | ||||
| 	private static FoodFactory foodFactory = FoodFactory.getInstance(); | ||||
| 	private static Endscreen endscreen; | ||||
| 	private Direction			direction; | ||||
| 	private Direction direction = Direction.RIGHT; | ||||
| 	private int length; | ||||
| 	private List<Point>			tiles		= new ArrayList<>(); | ||||
| 	private final int			snakeSize	= 10; | ||||
| 	private List<Rectangle> tiles = new ArrayList<>(); | ||||
|  | ||||
| 	private static final int TILE_SIZE = 10; | ||||
|  | ||||
| 	/** | ||||
| 	 * Constructs a new Snake with the given length in tiles. | ||||
| @@ -64,20 +67,20 @@ public class Snake implements Updateable { | ||||
| 	 */ | ||||
| 	public Snake(int length) { | ||||
| 		this.length = length; | ||||
| 		direction	= Direction.Right; | ||||
| 		// adding the initial tiles of the snake | ||||
|  | ||||
| 		// Add initial tiles | ||||
| 		for (int i = 0; i < length; i++) | ||||
| 			tiles.add(new Point(320 - snakeSize * i, 240)); | ||||
| 			tiles.add(new Rectangle(320 - TILE_SIZE * i, 240, TILE_SIZE, TILE_SIZE)); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Adds the given length to the current snake object | ||||
| 	 * Increases 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); | ||||
| 		Rectangle last = tiles.get(tiles.size() - 1); | ||||
| 		for (int i = 0; i < additional; i++) | ||||
| 			tiles.add(last); | ||||
| 		length += additional; | ||||
| @@ -88,17 +91,10 @@ public class Snake implements Updateable { | ||||
| 	 * @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; | ||||
| 		return tiles.stream().skip(1).anyMatch(tiles.get(0)::contains); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * @since Snake 1.1 | ||||
| 	 */ | ||||
| 	private void gameOver() { | ||||
|   ```suggestion
	 * @since Snake 1.2
```   ```suggestion
	 * @since Snake 1.2
``` | ||||
| @@ -117,45 +113,41 @@ public class Snake implements Updateable { | ||||
| 	public void nextFrame() { | ||||
| 		int velX = 0, velY = 0; | ||||
| 		switch (direction) { | ||||
| 			case Up: | ||||
| 				velY = -snakeSize; | ||||
| 			case UP: | ||||
| 				velY = -TILE_SIZE; | ||||
| 				break; | ||||
| 			case Down: | ||||
| 				velY = snakeSize; | ||||
| 			case DOWN: | ||||
| 				velY = TILE_SIZE; | ||||
| 				break; | ||||
| 			case Left: | ||||
| 				velX = -snakeSize; | ||||
| 			case LEFT: | ||||
| 				velX = -TILE_SIZE; | ||||
| 				break; | ||||
| 			case Right: | ||||
| 				velX = snakeSize; | ||||
| 			case RIGHT: | ||||
| 				velX = TILE_SIZE; | ||||
| 				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 | ||||
| 		// 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: the game bounds checking below appears to work on Windows, however | ||||
| 		// throws a NullPointerException on Linux/UNIX systems | ||||
| 		// TODO: Test on Linux | ||||
| 		if (!Main.getGame().getBounds().contains(tiles.get(0))) { | ||||
| 			gameOver(); | ||||
| 			System.out.println("Snake went out of bounds."); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// case if snake eats food | ||||
| 		if (foodFactory.checkCollision(new Rectangle(tiles.get(0).x, tiles.get(0).y, snakeSize, snakeSize))) { | ||||
| 		// 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(); | ||||
| @@ -163,10 +155,9 @@ public class Snake implements Updateable { | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void render(Graphics g) { | ||||
| 	public void render(Graphics2D g) { | ||||
| 		g.setColor(Color.green); | ||||
| 		for (int i = 0; i < length; i++) | ||||
| 			g.fillRect(tiles.get(i).x, tiles.get(i).y, snakeSize, snakeSize); | ||||
| 		tiles.forEach(g::fill); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| package dev.lh; | ||||
|  | ||||
| import java.awt.Graphics; | ||||
| import java.awt.Graphics2D; | ||||
|  | ||||
| /** | ||||
|  * This interface contains everything that needs to be updated regularly. | ||||
| @@ -25,8 +25,8 @@ public interface Updateable { | ||||
| 	/** | ||||
| 	 * Renders the object. | ||||
| 	 * | ||||
| 	 * @param g the {@link 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 | ||||
| 	 */ | ||||
| 	void render(Graphics g); | ||||
| 	void render(Graphics2D g); | ||||
| } | ||||
|   | ||||
| @@ -52,8 +52,8 @@ public class GameWindow extends JFrame { | ||||
| 			protected void paintComponent(Graphics g) { | ||||
| 				super.paintComponent(g); | ||||
| 				g.setColor(Color.black); | ||||
| 				g.fillRect(0, 0, super.getWidth(), super.getHeight()); | ||||
| 				s.render(g); | ||||
| 				g.fillRect(0, 0, getWidth(), getHeight()); | ||||
| 				s.render((Graphics2D) g); | ||||
| 				foodFactory.paintFood(g); | ||||
| 			} | ||||
| 		}); | ||||
| @@ -66,19 +66,19 @@ public class GameWindow extends JFrame { | ||||
| 				switch (e.getKeyCode()) { | ||||
| 					case KeyEvent.VK_W: | ||||
| 					case KeyEvent.VK_UP: | ||||
| 						if (!s.getRichtung().equals(Direction.Down)) s.setDirection(Direction.Up); | ||||
| 						if (!s.getRichtung().equals(Direction.DOWN)) s.setDirection(Direction.UP); | ||||
| 						break; | ||||
| 					case KeyEvent.VK_A: | ||||
| 					case KeyEvent.VK_LEFT: | ||||
| 						if (!s.getRichtung().equals(Direction.Right)) s.setDirection(Direction.Left); | ||||
| 						if (!s.getRichtung().equals(Direction.RIGHT)) s.setDirection(Direction.LEFT); | ||||
| 						break; | ||||
| 					case KeyEvent.VK_S: | ||||
| 					case KeyEvent.VK_DOWN: | ||||
| 						if (!s.getRichtung().equals(Direction.Up)) s.setDirection(Direction.Down); | ||||
| 						if (!s.getRichtung().equals(Direction.UP)) s.setDirection(Direction.DOWN); | ||||
| 						break; | ||||
| 					case KeyEvent.VK_D: | ||||
| 					case KeyEvent.VK_RIGHT: | ||||
| 						if (!s.getRichtung().equals(Direction.Left)) s.setDirection(Direction.Right); | ||||
| 						if (!s.getRichtung().equals(Direction.LEFT)) s.setDirection(Direction.RIGHT); | ||||
| 						break; | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user