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 | 	 * @author Leon Hofmeister | ||||||
| 	 * @since Snake 1.0 | 	 * @since Snake 1.0 | ||||||
| 	 */ | 	 */ | ||||||
| 	public static enum Food { | 	public enum Food { | ||||||
|   ```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
``` | |||||||
|  |  | ||||||
| 		/** | 		/** | ||||||
| 		 * Use if white food is wanted. | 		 * 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; | 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.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| @@ -31,30 +33,31 @@ public class Snake implements Updateable { | |||||||
| 		/** | 		/** | ||||||
| 		 * 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 FoodFactory	foodFactory	= FoodFactory.getInstance(); | 	private static FoodFactory foodFactory = FoodFactory.getInstance(); | ||||||
| 	private static Endscreen	endscreen; | 	private static Endscreen endscreen; | ||||||
| 	private Direction			direction; | 	private Direction direction = Direction.RIGHT; | ||||||
| 	private int					length; | 	private int length; | ||||||
| 	private List<Point>			tiles		= new ArrayList<>(); | 	private List<Rectangle> tiles = new ArrayList<>(); | ||||||
| 	private final int			snakeSize	= 10; |  | ||||||
|  | 	private static final int TILE_SIZE = 10; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Constructs a new Snake with the given length in tiles. | 	 * Constructs a new Snake with the given length in tiles. | ||||||
| @@ -63,21 +66,21 @@ 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; | ||||||
| 		direction	= Direction.Right; |  | ||||||
| 		// adding the initial tiles of the snake | 		// Add initial tiles | ||||||
| 		for (int i = 0; i < length; i++) | 		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 | 	 * @param additional the number of tiles to add | ||||||
| 	 * @since Snake 1.0 | 	 * @since Snake 1.0 | ||||||
| 	 */ | 	 */ | ||||||
| 	public void addLength(int additional) { | 	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++) | 		for (int i = 0; i < additional; i++) | ||||||
| 			tiles.add(last); | 			tiles.add(last); | ||||||
| 		length += additional; | 		length += additional; | ||||||
| @@ -88,17 +91,10 @@ public class Snake implements Updateable { | |||||||
| 	 * @since Snake 1.1 | 	 * @since Snake 1.1 | ||||||
| 	 */ | 	 */ | ||||||
| 	private boolean checkSelfCollision() { | 	private boolean checkSelfCollision() { | ||||||
| 		Point		headIndex	= tiles.get(0); | 		return tiles.stream().skip(1).anyMatch(tiles.get(0)::contains); | ||||||
| 		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; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * |  | ||||||
| 	 * @since Snake 1.1 | 	 * @since Snake 1.1 | ||||||
| 	 */ | 	 */ | ||||||
| 	private void gameOver() { | 	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() { | 	public void nextFrame() { | ||||||
| 		int velX = 0, velY = 0; | 		int velX = 0, velY = 0; | ||||||
| 		switch (direction) { | 		switch (direction) { | ||||||
| 			case Up: | 			case UP: | ||||||
| 				velY = -snakeSize; | 				velY = -TILE_SIZE; | ||||||
| 				break; | 				break; | ||||||
| 			case Down: | 			case DOWN: | ||||||
| 				velY = snakeSize; | 				velY = TILE_SIZE; | ||||||
| 				break; | 				break; | ||||||
| 			case Left: | 			case LEFT: | ||||||
| 				velX = -snakeSize; | 				velX = -TILE_SIZE; | ||||||
| 				break; | 				break; | ||||||
| 			case Right: | 			case RIGHT: | ||||||
| 				velX = snakeSize; | 				velX = TILE_SIZE; | ||||||
| 				break; | 				break; | ||||||
| 		} | 		} | ||||||
| 		Point next = (Point) tiles.get(0).clone(), cur; | 		// Add a new tile at the front | ||||||
| 		tiles.get(0).x	+= velX; | 		tiles.add( | ||||||
| 		tiles.get(0).y	+= velY; | 			0, | ||||||
|  | 			new Rectangle(tiles.get(0).x + velX, tiles.get(0).y + velY, TILE_SIZE, TILE_SIZE) | ||||||
| 		for (int i = 1; i < length; i++) { | 		); | ||||||
| 			cur = tiles.get(i); | 		// Remove the last tile | ||||||
| 			tiles.set(i, (Point) next.clone()); | 		tiles.remove(tiles.size() - 1); | ||||||
| 			next = cur; | 		// Case if snake is outside of the screen or touches itself | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// case if snake is outside of the screen or touches itself |  | ||||||
| 		if (checkSelfCollision()) { | 		if (checkSelfCollision()) { | ||||||
| 			gameOver(); | 			gameOver(); | ||||||
| 			System.out.println("Snake collided with itself."); | 			System.out.println("Snake collided with itself."); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		// TODO: the game bounds checking below appears to work on Windows, however | 		// TODO: Test on Linux | ||||||
| 		// throws a NullPointerException on Linux/UNIX systems |  | ||||||
| 		if (!Main.getGame().getBounds().contains(tiles.get(0))) { | 		if (!Main.getGame().getBounds().contains(tiles.get(0))) { | ||||||
| 			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 | 		// Case if snake eats food | ||||||
| 		if (foodFactory.checkCollision(new Rectangle(tiles.get(0).x, tiles.get(0).y, snakeSize, snakeSize))) { | 		if (foodFactory.checkCollision(tiles.get(0))) { | ||||||
| 			addLength(foodFactory.getAdditionalLength()); | 			addLength(foodFactory.getAdditionalLength()); | ||||||
| 			GameWindow game = Main.getGame(); | 			GameWindow game = Main.getGame(); | ||||||
| 			game.newFood(); | 			game.newFood(); | ||||||
| @@ -163,10 +155,9 @@ public class Snake implements Updateable { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void render(Graphics g) { | 	public void render(Graphics2D g) { | ||||||
| 		g.setColor(Color.green); | 		g.setColor(Color.green); | ||||||
| 		for (int i = 0; i < length; i++) | 		tiles.forEach(g::fill); | ||||||
| 			g.fillRect(tiles.get(i).x, tiles.get(i).y, snakeSize, snakeSize); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| package dev.lh; | package dev.lh; | ||||||
|  |  | ||||||
| import java.awt.Graphics; | import java.awt.Graphics2D; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This interface contains everything that needs to be updated regularly. |  * This interface contains everything that needs to be updated regularly. | ||||||
| @@ -25,8 +25,8 @@ public interface Updateable { | |||||||
| 	/** | 	/** | ||||||
| 	 * Renders the object. | 	 * 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 | 	 * @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) { | 			protected void paintComponent(Graphics g) { | ||||||
| 				super.paintComponent(g); | 				super.paintComponent(g); | ||||||
| 				g.setColor(Color.black); | 				g.setColor(Color.black); | ||||||
| 				g.fillRect(0, 0, super.getWidth(), super.getHeight()); | 				g.fillRect(0, 0, getWidth(), getHeight()); | ||||||
| 				s.render(g); | 				s.render((Graphics2D) g); | ||||||
| 				foodFactory.paintFood(g); | 				foodFactory.paintFood(g); | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| @@ -66,19 +66,19 @@ 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 (!s.getRichtung().equals(Direction.DOWN)) s.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 (!s.getRichtung().equals(Direction.RIGHT)) s.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 (!s.getRichtung().equals(Direction.UP)) s.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 (!s.getRichtung().equals(Direction.LEFT)) s.setDirection(Direction.RIGHT); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user