Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 |
It is the snake game on the 8x8 matrix LED by smartphone motion.
When user tilts the smartphone to one of 4 directions, the direction value is sent to Arduino through HTML5 WebSocket. Then the snake changes its direction.
For more information about the Snake game, please visit the link below: https://www.hackster.io/hmkim/8x8-matrix-led-snake-game-html5-web-socket-67e679
This project is almost the same with as the project in the link above; the only difference is its PHPoC source code.
PHPoC Shield source code
HTML1. Upload PHPoC Shield source code
Please refert to the manual of PHPoC Debugger below and upload the source code(snake_game_gyro.php).
http://www.phpoc.com/support/manual/phpoc_debugger_manual/contents.php?id=major_upload
- snake_game_gyro.php
Please refert to the manual of PHPoC Debugger below and upload the source code(snake_game_gyro.php).
http://www.phpoc.com/support/manual/phpoc_debugger_manual/contents.php?id=major_upload
- snake_game_gyro.php
<!DOCTYPE html>
<html>
<head>
<title>PHPoC Shield - Snake Game</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<style>
body { font-family: verdana, Helvetica, Arial, sans-serif, gulim; font-weight: bold; text-align: center; }
h1 { font-size: 25pt; }
h2 { font-size: 15pt; }
#remote { margin:0 auto; width: 500px; background: #333; border-radius: 2%; }
.direct {
display: inline-block; width: 100px; height: 100px;
font-size: 50px; color: white; line-height: 90px;
background: #eee; margin: 8px; border-radius: 10%;
text-align: center; font-weight: bold;
margin: 10px 60px;
}
</style>
<script>
var ws;
var button;
function init()
{
if(ws == null)
{
ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/snake", "text.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
function connect_onclick()
{
if(ws == null)
{
var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
//var debug = document.getElementById("debug");
if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "["))
{
// network resource identifier to UNC path name conversion
ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
ws_host_addr = ws_host_addr.replace(/:/g, "-");
ws_host_addr += ".ipv6-literal.net";
}
//debug.innerHTML = "<br>" + navigator.platform + " " + ws_host_addr;
ws = new WebSocket("ws://" + ws_host_addr + "/snake", "text.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
function ws_onopen()
{
document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
document.getElementById("bt_connect").innerHTML = "Disconnect";
}
function ws_onclose()
{
document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
document.getElementById("bt_connect").innerHTML = "Connect";
ws.onopen = null;
ws.onclose = null;
ws.onmessage = null;
ws = null;
}
function ws_onmessage(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent
alert("msg : " + e_msg.data);
}
var beta = 0;
var gamma = 0;
var resolution = 2;
if (window.DeviceOrientationEvent)
{
window.addEventListener('deviceorientation', orientationUpdate, true);
}
function orientationUpdate(event)
{
if(Math.abs((event.beta - beta)) > resolution)
beta = event.beta;
if(Math.abs((event.gamma - gamma)) > resolution)
gamma = event.gamma;
//var debug = document.getElementById("debug");
//debug.innerHTML = beta + "/" + gamma;
for (i=0; i<4; i++)
{
button = document.getElementById(i);
button.style.backgroundColor = "grey";
}
if (beta < 0) // top
{
button = document.getElementById(0);
button.style.backgroundColor = "#E9FF26";
ws.send("0");
}
else if (gamma < -35 && beta < 50) // left
{
button = document.getElementById(1);
button.style.backgroundColor = "#E9FF26";
ws.send("1");
}
else if (gamma > 35 && beta < 50) // right
{
button = document.getElementById(2);
button.style.backgroundColor = "#E9FF26";
ws.send("2");
}
else if (beta > 60) // bottom
{
button = document.getElementById(3);
button.style.backgroundColor = "#E9FF26";
ws.send("3");
}
}
window.onload = init;
</script>
</head>
<body>
<h1>Snake Game</h1>
<br /><br />
<div id="remote">
<div class="direct" id="0">↑</div><br />
<div class="direct" id="1">←</div>
<div class="direct" id="2">→</div><br />
<div class="direct" id="3">↓</div>
</div>
<br /><br />
<h2>WebSocket <font id="ws_state" color="gray">CLOSED</font></h2>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
<span id="debug"></span>
</body>
</html>
Arduino Source code
Arduino2. Upload Arduino source code
- Add Arduino library
Please add releted libraries from [Sketch] > [Include Library] > [Manager Libraries...]
Adafruit_LEDBackpack library, Adafruit-GFX-Library, PHPoC Library
(Learn more : https://learn.adafruit.com/adafruit-led-backpack/bi-color-8x8-matrix)
- Upload Arduino sketch
- Add Arduino library
Please add releted libraries from [Sketch] > [Include Library] > [Manager Libraries...]
Adafruit_LEDBackpack library, Adafruit-GFX-Library, PHPoC Library
(Learn more : https://learn.adafruit.com/adafruit-led-backpack/bi-color-8x8-matrix)
- Upload Arduino sketch
/***************************************************
This is a library for our I2C LED Backpacks
Designed specifically to work with the Adafruit LED Matrix backpacks
----> http://www.adafruit.com/products/872
----> http://www.adafruit.com/products/871
----> http://www.adafruit.com/products/870
These displays use I2C to communicate, 2 pins are required to
interface. There are multiple selectable I2C addresses. For backpacks
with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
with 3 Address Select pins: 0x70 thru 0x77
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
// Snake on 8x8Matrix
// 2013-06-15 JorgVisch (http://fritzing.org/projects/snake-8x8-led-matrix-ada-fruit)
// 2017-04-12 Amy Kim
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>
#include "SPI.h"
#include "Phpoc.h"
PhpocServer server(80);
// LED face
static const uint8_t PROGMEM
smile_bmp[] =
{ B00111100,
B01000010,
B10100101,
B10000001,
B10100101,
B10011001,
B01000010,
B00111100 },
frown_bmp[] =
{ B00111100,
B01000010,
B10100101,
B10000001,
B10011001,
B10100101,
B01000010,
B00111100 };
// direction
const int TOP = 0;
const int RIGHT = 1;
const int BOTTOM = 2;
const int LEFT = 3;
// Snake
const int MAX_SNAKE_LENGTH = 15;
// Variables
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix(); // Display
int direction = TOP; // direction of movement
int snakeX[MAX_SNAKE_LENGTH]; // X-coordinates of snake
int snakeY[MAX_SNAKE_LENGTH]; // Y-coordinates of snake
int snakeLength = 1; // nr of parts of snake
unsigned long prevTime = 0; // for gamedelay (ms)
unsigned long delayTime = 500; // Game step in ms
int fruitX, fruitY;
unsigned long fruitPrevTime = 0;
unsigned long fruitBlinkTime = 1000/250;
int fruitLed = LED_RED;
int matrixColor;
void setup(){
Serial.begin(9600);
while(!Serial)
;
Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
server.beginWebSocket("snake");
Serial.print("WebSocket server address : ");
Serial.println(Phpoc.localIP());
Serial.println("Game is started.");
randomSeed(analogRead(0));
// Init led matrix
matrix.begin(0x70);
matrix.setRotation(3);
// init snake
snakeX[0] = 4;
snakeY[0] = 7;
for(int i=1; i<MAX_SNAKE_LENGTH; i++)
snakeX[i] = snakeY[i] = -1;
makeFruit();
printString("S");
}
void loop(){
checkButtons();
unsigned long currentTime = millis();
if(currentTime - prevTime >= delayTime)
{
nextstep();
prevTime = currentTime;
}
draw();
}
void checkButtons(){
// wait for a new client:
PhpocClient client = server.available();
if (client)
{
if (client.available() > 0)
{
// read the bytes incoming from the client:
char thisChar = client.read();
if(thisChar == '0')
direction = TOP;
if(thisChar == '1')
direction = LEFT;
if(thisChar == '2')
direction = RIGHT;
if(thisChar == '3')
direction = BOTTOM;
}
}
}
void draw(){
matrix.clear();
drawSnake();
drawFruit();
matrix.writeDisplay();
}
void drawSnake(){
for(int i=0; i<snakeLength; i++)
matrix.drawPixel(snakeX[i], snakeY[i], LED_GREEN);
}
void drawFruit(){
if(inPlayField(fruitX, fruitY)){
unsigned long currenttime = millis();
if(currenttime - fruitPrevTime >= fruitBlinkTime)
{
fruitLed = (fruitLed == LED_RED) ? LED_OFF : LED_RED;
fruitPrevTime = currenttime;
}
matrix.drawPixel(fruitX, fruitY, fruitLed);
}
}
boolean inPlayField(int x, int y){
return (x>=0) && (x<8) && (y>=0) && (y<8);
}
void nextstep(){
for(int i = snakeLength; i > 0; i--)
{
if((direction == RIGHT) && (snakeX[0]-snakeLength == 7))
snakeX[0] = -1;
else if((direction == LEFT) && (snakeX[0]+ snakeLength == 0))
snakeX[0] = 8;
else
snakeX[i] = snakeX[i-1];
if((direction == TOP) && (snakeY[0]+snakeLength == 0))
snakeY[0] = 8;
else if((direction == BOTTOM) && (snakeY[0]-snakeLength == 7))
snakeY[0] = -1;
else
snakeY[i] = snakeY[i-1];
}
switch(direction)
{
case TOP:
snakeY[0] = snakeY[0]-1;
break;
case RIGHT:
snakeX[0] = snakeX[0]+1;
break;
case BOTTOM:
snakeY[0] = snakeY[0]+1;
break;
case LEFT:
snakeX[0]=snakeX[0]-1;
break;
}
if((snakeX[0] == fruitX) && (snakeY[0] == fruitY))
{
snakeLength++;
if(snakeLength < MAX_SNAKE_LENGTH)
makeFruit();
else
fruitX = fruitY = -1;
}
snakeCheck();
}
void makeFruit(){
int x, y;
x = random(0, 8);
y = random(0, 8);
while(isPartOfSnake(x, y)){
x = random(0, 8);
y = random(0, 8);
}
fruitX = x;
fruitY = y;
}
boolean isPartOfSnake(int x, int y){
for(int i=0; i<snakeLength-1; i++)
{
if((x == snakeX[i]) && (y == snakeY[i]))
return true;
}
return false;
}
void snakeCheck(){
for(int i=1; i<snakeLength; i++)
{
// snake touches itself
if((snakeX[0] == snakeX[i]) && (snakeY[0] == snakeY[i]))
userLose();
}
if (snakeLength == MAX_SNAKE_LENGTH)
userWin();
}
void userLose(){
Serial.println("Game Over");
printString("O");
matrix.clear();
matrix.drawBitmap(0, 0, frown_bmp, 8, 8, LED_RED);
matrix.writeDisplay();
delay(1000);
snakeLength = 1;
setup();
loop();
}
void userWin(){
Serial.println("You Win");
printString("W");
matrix.clear();
matrix.drawBitmap(0, 0, smile_bmp, 8, 8, LED_GREEN);
matrix.writeDisplay();
delay(1000);
snakeLength = 1;
setup();
loop();
}
void printString(String str){
String matrixComment;
matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
matrix.setTextSize(1);
if (str == "O")
{
matrixComment = "Game Over!";
matrixColor = LED_RED;
}
else if (str == "W")
{
matrixComment = "You Win!";
matrixColor = LED_GREEN;
}
else if (str == "S")
{
matrixComment = "Go!";
matrixColor = LED_YELLOW;
}
else
matrixColor = LED_YELLOW;
matrix.setTextColor(matrixColor);
for (int8_t x=7; x>=-60; x--)
{
matrix.clear();
matrix.setCursor(x,0);
matrix.print(matrixComment);
matrix.writeDisplay();
delay(70);
}
}
Comments
Please log in or sign up to comment.