Created
August 24, 2018 16:30
-
-
Save nicolaisueper/a594673554884276210932f89d088ed9 to your computer and use it in GitHub Desktop.
ESP32 + Espruino + SSD1306 + 4 Push Buttons Snake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
E.on("init", () => { | |
const SSD1306 = require("SSD1306"); | |
const OLED_CLOCK_PIN = D22; | |
const OLED_DATA_PIN = D23; | |
const OLED_WIDTH = 128; | |
const OLED_HEIGHT = 64; | |
const LEFT = D12; | |
const RIGHT = D26; | |
const UP = D14; | |
const DOWN = D27; | |
const isPinPressed = pin => Boolean(digitalRead(pin)); | |
const setupDisplay = (displayOptions, setupCallback) => { | |
I2C1.setup(displayOptions); | |
let device = SSD1306.connect( | |
I2C1, | |
() => { | |
setupCallback(device); | |
}, | |
{ | |
address: 0x3c | |
} | |
); | |
}; | |
const randomSnakeBite = snake => { | |
const snakeHasX = X => snake.filter(part => part.x === X); | |
const snakeHasY = X => snake.filter(part => part.x === X); | |
let x; | |
let y; | |
do { | |
x = Math.floor(Math.random() * (OLED_WIDTH - 2)) + 1; | |
} while (!snakeHasX(x)); | |
do { | |
y = Math.floor(Math.random() * (OLED_HEIGHT - 2)) + 1; | |
} while (!snakeHasY(y)); | |
return { x: x, y: y }; | |
}; | |
const snake = display => { | |
let head = { x: OLED_WIDTH / 2 - 1, y: OLED_HEIGHT / 2 - 1 }; | |
let snake = [ | |
head, | |
{ x: head.x, y: head.y - 1 }, | |
{ x: head.x, y: head.y - 2 }, | |
{ x: head.x, y: head.y - 3 }, | |
{ x: head.x, y: head.y + 4 }, | |
{ x: head.x, y: head.y + 5 } | |
]; | |
let nextBite = randomSnakeBite(snake); | |
let orientation = UP; | |
let buttonPressInterval = setInterval(() => { | |
if (isPinPressed(LEFT) && orientation !== RIGHT) { | |
orientation = LEFT; | |
return; | |
} | |
if (isPinPressed(UP) && orientation !== DOWN) { | |
orientation = UP; | |
return; | |
} | |
if (isPinPressed(DOWN) && orientation !== UP) { | |
orientation = DOWN; | |
return; | |
} | |
if (isPinPressed(RIGHT) && orientation !== LEFT) { | |
orientation = RIGHT; | |
return; | |
} | |
}, 5); | |
let gameLoop = setInterval(() => { | |
const currentHead = snake[0]; | |
const nextHead = { | |
x: | |
orientation === LEFT | |
? currentHead.x - 1 | |
: orientation === RIGHT | |
? currentHead.x + 1 | |
: currentHead.x, | |
y: | |
orientation === UP | |
? currentHead.y - 1 | |
: orientation === DOWN | |
? currentHead.y + 1 | |
: currentHead.y | |
}; | |
snake = [nextHead].concat(snake); | |
if (nextHead.x === nextBite.x && nextHead.y === nextBite.y) { | |
nextBite = randomSnakeBite(snake); | |
} else { | |
snake.pop(); | |
} | |
display.clear(); | |
for (const part of snake) { | |
display.setPixel(part.x, part.y, 1); | |
} | |
display.setPixel(nextBite.x, nextBite.y, 1); | |
display.flip(); | |
}, 100); | |
}; | |
const showWelcome = display => { | |
display.clear(); | |
display.drawString( | |
"SnakESP", | |
Math.floor((OLED_WIDTH - "SnakESP".length * 4) / 2), | |
16 | |
); | |
display.drawString("Press 'LEFT' (x o o o) to play", 0, 32); | |
display.flip(); | |
const waitForLeftButton = setInterval(() => { | |
if (isPinPressed(LEFT)) { | |
display.clear(); | |
display.flip(); | |
clearInterval(waitForLeftButton); | |
snake(display); | |
} | |
}, 50); | |
}; | |
const start = display => { | |
showWelcome(display); | |
}; | |
setupDisplay( | |
{ | |
scl: OLED_CLOCK_PIN, | |
sda: OLED_DATA_PIN | |
}, | |
device => start(device) | |
); | |
}); | |
E.setFlags({ pretokenise: 1 }); | |
save(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
At this stage you are able to play the game without losing. Good for killing time.