Things used in this project

Schematics

Connections
LED ----- PHPoC Shield
VCC ----- 5V
GND ----- GND
SDA ----- A4(SDA)
SCL ----- A5(SCL)
Connection vumi18l98q

Code

PHPoC Shield source codeHTML
1. Upload PHPoC Shield source code
Please refert to the manual of PHPoC Debugger below and upload the source code(snake_game.php).
http://www.phpoc.com/support/manual/phpoc_debugger_manual/contents.php?id=major_upload

- snake_game.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; text-align: center; }
h1 { font-weight: bold; font-size: 25pt; }
h2 { font-weight: bold; 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 push_info = [];
var ws;
var push_length = 4;
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();
	
	for(var push_id = 0; push_id < push_length; push_id++)
	{
		push_info[push_id] = {state:false, identifier:null};
		update_push(push_id, false);
	}

	var remote = document.getElementById("remote");
	
    remote.addEventListener("touchstart", mouse_down);
    remote.addEventListener("touchend", mouse_up);
    remote.addEventListener("touchcancel", mouse_up);
    remote.addEventListener("mousedown", mouse_down);
    remote.addEventListener("mouseup", mouse_up);
}
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";

	for(var push_id = 0; push_id < push_length; push_id++)
		update_push(push_id, false);
}
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;

	for(var push_id = 0; push_id < push_length; push_id++)
		update_push(push_id, false);
}
function ws_onmessage(e_msg)
{
	e_msg = e_msg || window.event; // MessageEvent

	alert("msg : " + e_msg.data);
}
function update_push(push_id, state)
{
	var button = document.getElementById(push_id);
	var push = push_info[push_id];

	if(ws && (ws.readyState == 1))
	{
		if(state)
			button.style.backgroundColor = "#E9FF26";
		else
			button.style.backgroundColor = "grey";
	}
	else
		button.style.backgroundColor = "#555";

	push.state = state;

	if(!state)
		push.identifier = null;

	if(ws && (ws.readyState == 1))
	{
		if(state)
			ws.send(Number(push_id) + "\n"); 
	}
	
}
function mouse_down(event)
{
	//var debug = document.getElementById("debug");

	var push_id = event.target.id;	
	
	if(event.changedTouches)
	{
		
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			if(push_id < push_length)
			{
				var push = push_info[push_id];

				if(push.state == false)
				{
					update_push(push_id, true);
					push.identifier = touch.identifier;

				//	debug.innerHTML += ("+" + push_id + "/" + touch.identifier + " ");
				}
				else
				{
					update_push(push_id, false);
				}

				//debug.innerHTML += (push_id + " ");
			}
		}
	}
	else
	{
		if(push_id < push_length)
		{
				var push = push_info[push_id];
				if(push.state == false)
				{
					update_push(push_id, true);

					//debug.innerHTML += ("+" + push_id + "/" + touch.identifier + " ");
				}
				else
				{
					update_push(push_id, false);
				}
				
			//debug.innerHTML += (push_id + " ");
		}
	}

	event.preventDefault();
}

function mouse_up(event)
{
	var debug = document.getElementById("debug");
	var push_id;

	//debug.innerHTML = "";

	if(event.changedTouches)
	{
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			for(var push_id = 0; push_id < push_length; push_id++)
			{
				if(touch.identifier == push_info[push_id].identifier)
					break;
			}

			if(push_id < push_length)
			{
				update_push(push_id, false);
				//debug.innerHTML += ("-" + push_id + "/" + touch.identifier + " ");
			}
		}
	}
	else
	{
		for(var push_id = 0; push_id < push_length; push_id++)
		{
			if(push_info[push_id].state)
			{
				update_push(push_id, false);
				break;
			}
		}
	}

	event.preventDefault();
}

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 codeArduino
2. 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
/*************************************************** 
  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);
  }  
}

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

3D-Printed Prank Vibrating Cup
Easy
  • 1,289
  • 14

Full instructions

The instant your prankee lifts up this 3D-printed cup it starts violently vibrating! The electronics separate from the cup for easy washing.

Web-Based Internet Signboard
Easy
  • 170
  • 4

Full instructions

Build a web-based Internet Signboard with PHPoC.

Monitoring the Trash Can
Easy
  • 239
  • 7

Full instructions

Status of trash can in public area is monitored. When the trash can is full, an email is sent to trash manager or status of trash can.

The Magic Display With Arduino - The Mind Reader
Easy
  • 1,512
  • 6

Full instructions

The Magic Display With Arduino can figure out with a few clues what is your choose on a card with 64 options of numbers, letters or symbols.

Very First Hands On Arduino - Voice Activated LED
Easy
  • 770
  • 9

Full instructions

Use voice command to turn LED on or off.

Get Connected! WiFi Registration Using AP Mode!
Easy
  • 1,447
  • 16

Full instructions

Stop reflashing your devices everytime the WiFi password changes! Learn how to use anduinoWiFi and AP mode to initiate WiFi registration!

ProjectsCommunitiesContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login
Respect project
Feedback