├── README.md
├── index.html
├── script.js
└── styles.css
/README.md:
--------------------------------------------------------------------------------
1 | # snake
2 | Juego Snake con JS creado en este tutorial: https://youtu.be/pyas0IREz-o
3 |
4 |
5 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Snake
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 | Game Over
21 |
22 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | // HTML Elements
2 | const board = document.getElementById('board');
3 | const scoreBoard = document.getElementById('scoreBoard');
4 | const startButton = document.getElementById('start');
5 | const gameOverSign = document.getElementById('gameOver');
6 |
7 | // Game settings
8 | const boardSize = 10;
9 | const gameSpeed = 100;
10 | const squareTypes = {
11 | emptySquare: 0,
12 | snakeSquare: 1,
13 | foodSquare: 2
14 | };
15 | const directions = {
16 | ArrowUp: -10,
17 | ArrowDown: 10,
18 | ArrowRight: 1,
19 | ArrowLeft: -1,
20 | };
21 |
22 | // Game variables
23 | let snake;
24 | let score;
25 | let direction;
26 | let boardSquares;
27 | let emptySquares;
28 | let moveInterval;
29 |
30 | const drawSnake = () => {
31 | snake.forEach( square => drawSquare(square, 'snakeSquare'));
32 | }
33 |
34 | // Rellena cada cuadrado del tablero
35 | // @params
36 | // square: posicion del cuadrado,
37 | // type: tipo de cuadrado (emptySquare, snakeSquare, foodSquare)
38 | const drawSquare = (square, type) => {
39 | const [ row, column ] = square.split('');
40 | boardSquares[row][column] = squareTypes[type];
41 | const squareElement = document.getElementById(square);
42 | squareElement.setAttribute('class', `square ${type}`);
43 |
44 | if(type === 'emptySquare') {
45 | emptySquares.push(square);
46 | } else {
47 | if(emptySquares.indexOf(square) !== -1) {
48 | emptySquares.splice(emptySquares.indexOf(square), 1);
49 | }
50 | }
51 | }
52 |
53 | const moveSnake = () => {
54 | const newSquare = String(
55 | Number(snake[snake.length - 1]) + directions[direction])
56 | .padStart(2, '0');
57 | const [row, column] = newSquare.split('');
58 |
59 |
60 | if( newSquare < 0 ||
61 | newSquare > boardSize * boardSize ||
62 | (direction === 'ArrowRight' && column == 0) ||
63 | (direction === 'ArrowLeft' && column == 9 ||
64 | boardSquares[row][column] === squareTypes.snakeSquare) ) {
65 | gameOver();
66 | } else {
67 | snake.push(newSquare);
68 | if(boardSquares[row][column] === squareTypes.foodSquare) {
69 | addFood();
70 | } else {
71 | const emptySquare = snake.shift();
72 | drawSquare(emptySquare, 'emptySquare');
73 | }
74 | drawSnake();
75 | }
76 | }
77 |
78 | const addFood = () => {
79 | score++;
80 | updateScore();
81 | createRandomFood();
82 | }
83 |
84 | const gameOver = () => {
85 | gameOverSign.style.display = 'block';
86 | clearInterval(moveInterval)
87 | startButton.disabled = false;
88 | }
89 |
90 | const setDirection = newDirection => {
91 | direction = newDirection;
92 | }
93 |
94 | const directionEvent = key => {
95 | switch (key.code) {
96 | case 'ArrowUp':
97 | direction != 'ArrowDown' && setDirection(key.code)
98 | break;
99 | case 'ArrowDown':
100 | direction != 'ArrowUp' && setDirection(key.code)
101 | break;
102 | case 'ArrowLeft':
103 | direction != 'ArrowRight' && setDirection(key.code)
104 | break;
105 | case 'ArrowRight':
106 | direction != 'ArrowLeft' && setDirection(key.code)
107 | break;
108 | }
109 | }
110 |
111 | const createRandomFood = () => {
112 | const randomEmptySquare = emptySquares[Math.floor(Math.random() * emptySquares.length)];
113 | drawSquare(randomEmptySquare, 'foodSquare');
114 | }
115 |
116 | const updateScore = () => {
117 | scoreBoard.innerText = score;
118 | }
119 |
120 | const createBoard = () => {
121 | boardSquares.forEach( (row, rowIndex) => {
122 | row.forEach( (column, columnndex) => {
123 | const squareValue = `${rowIndex}${columnndex}`;
124 | const squareElement = document.createElement('div');
125 | squareElement.setAttribute('class', 'square emptySquare');
126 | squareElement.setAttribute('id', squareValue);
127 | board.appendChild(squareElement);
128 | emptySquares.push(squareValue);
129 | })
130 | })
131 | }
132 |
133 | const setGame = () => {
134 | snake = ['00', '01', '02', '03'];
135 | score = snake.length;
136 | direction = 'ArrowRight';
137 | boardSquares = Array.from(Array(boardSize), () => new Array(boardSize).fill(squareTypes.emptySquare));
138 | console.log(boardSquares);
139 | board.innerHTML = '';
140 | emptySquares = [];
141 | createBoard();
142 | }
143 |
144 | const startGame = () => {
145 | setGame();
146 | gameOverSign.style.display = 'none';
147 | startButton.disabled = true;
148 | drawSnake();
149 | updateScore();
150 | createRandomFood();
151 | document.addEventListener('keydown', directionEvent);
152 | moveInterval = setInterval( () => moveSnake(), gameSpeed);
153 | }
154 |
155 | startButton.addEventListener('click', startGame);
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | font-family: 'Share Tech Mono', monospace;
3 | }
4 |
5 | #board, .boardInfo {
6 | max-width: 500px;
7 | }
8 |
9 | #board {
10 | display: grid;
11 | grid-template-columns: repeat(10, 1fr);
12 | }
13 |
14 | #start, .boardInfo {
15 | font-size: 25px;
16 | }
17 |
18 | #gameOver {
19 | display: none;
20 | }
21 |
22 | .boardInfo {
23 | display: flex;
24 | justify-content: space-between;
25 | margin-top: 10px;
26 | }
27 |
28 | #start {
29 | background-color: #f35a69;
30 | border: none;
31 | color: white;
32 | }
33 |
34 | #scoreBoard {
35 | display: inline-flex;
36 | }
37 |
38 | .square {
39 | aspect-ratio: 1;
40 | }
41 |
42 | .emptySquare {
43 | background-color: #6d71b5;
44 | }
45 |
46 | .snakeSquare {
47 | background-color: #e3e773;
48 | border: 1px solid #000;
49 | }
50 |
51 | .foodSquare {
52 | background-color: #55e7e7;
53 | border: 1px solid #000;
54 | }
--------------------------------------------------------------------------------