The original snake game for the mbedgc

Dependencies:   mbed EthernetNetIf HTTPClient

Fork of SimpleLib_03272011 by J.P. Armstrong

mbedGC/mbedgc.cpp

Committer:
jp
Date:
2013-08-22
Revision:
1:3606fe561f47
Parent:
0:011be8250218

File content as of revision 1:3606fe561f47:

#include "mbed.h"
#include "mbedGC/mbedgc.h"
#include "Snake.h"
#include "sprites.h"
#include <string>
#include "EthernetNetIf.h"
#include "HTTPClient.h"

EthernetNetIf eth; 

void apples(int);
void startGame();
void endGame();
int networking();

void drawNumbers(int, int, unsigned char, int);
void drawStrings(int, int, unsigned char, string);
Snake snake;
int snake_x = 60;
int snake_y = 10;
int snake_direction = 0;
int snake_length = 10;
int snake_apples_eaten = 0;
float logic_percent = 0;
int score = 0;
unsigned char snake_color = 192;

bool game_paused = false;
bool faster = false;

const int num_apples = 10;


int main() {

//    networking();
 
    blankFB(); 
    soundNoteHalf = 0;
   
    NVIC_SetPriority(TIMER0_IRQn, 0);

    COLOR_INIT();
    TIMER0_INIT();
    TIMER0_SETPCLK(CCLK4);
    TIMER0_SETPRESCALE(3000); // 3000 : 134
    TIMER0_SETMATCH(0, 132);
    TIMER0_SETMATCHCONTROL(0, MATCH_RESET | MATCH_INTERRUPT); // Reset and Interrupt each 100ms
    TIMER0_ENABLE_INTERRUPT();
    TIMER0_START();

    setup();
    
    while (1){
        loop();
        
        if (hsync_count > 0xFFFFF)
            hsync_count = 0x80000;
     
         logic_count++;
        
       if (logic_count > 0xFFFFFF)
            logic_count = 0;
    }
    
}

void drawRectangle(int x, int y, int width, int height, unsigned char color) 
{
        
        if (x < 0 || y < 0)
            return; 
            
        for (int i = 0; i < height; i++) 
        {

               for (int j = 0; j < width; j++) 
               {
                                                                
                    framebuffer[ (y + i) % fbH ][ (x + j) % fbW ] = color;
                    
               }
        }
}

void drawCharacter(int x, int y, unsigned char color, char ch) {
   
    if (ch <= 'z' && ch >= 'a')
        ch = ch - 'a' + 10;
    else if (ch <= 'Z' && ch >= 'A')
        ch = ch - 'A' + 10;   
    else if (ch <= '9' && ch >= '0')
            ch = ch - '0';
    else if (ch == ' ')
        ch = 36;
    else if (ch == '.')
        ch = 37;
        
    for (int i = 0; i < 5; i++) {

        unsigned char buf = alphabet[ch][i];
        
  //      buf = numbers[ch][i] << 3;
        
        for (int j = 4; j >= 0; j--) {
            
            framebuffer[(y + i) % fbH ][ (x + j) % fbW ] = (buf % 2) * color;
            buf = ( buf >> 1 );
        }
            
        y %= fbH;
        
    }
}


void fill(unsigned char val) 
{

    for (int i = 0; i < fbH; i++) 
    {
 
        for (int j = 0; j < fbW; j++) 
        {
            framebuffer[i][j] = val;
        }
    }

}

void blankFB() 
{

    for (int i = 0; i < fbH; i++) 
    {
        for (int j = 0; j < fbW; j++) 
        {
            framebuffer[i][j] = 0;
        }
    }

}

TIMER0_INTERRUPT_HANDLER(void)
{
    TIMER0_CLEAR_INTERRUPT(MR0_INT);
    
    vSync = 1;
    for( int i = 0; i < fbH * 2; i++ )
    {
        COLOR_SET(0);
        hSync = 0;
        
        for (int tmp = 0; tmp < 90; tmp++) { // 206
            __nop();
        }
      
        hSync = 1;
        
        for (int tmp = 0; tmp < 110; tmp++) { // 206
            __nop();
        } 
        
        for( int j = 0; j < fbW; j++ )
        {
            unsigned char bp = framebuffer[ i / 2 ][ j ];
            COLOR_SET(bp);
            
            soundPin = (hsync_count % soundNote < soundNoteHalf) ? 1 : 0;
            
            hsync_count++;
            
            __nop();
            __nop();
            __nop();    
            __nop();
            __nop();    
          //  __nop();
            __nop();
        } 
    }
    COLOR_SET(0);  
    
    __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); //__nop();
//    __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
    
    vSync = 0;

}

int getButton(WiiClassicControllerReader* const ctrlr)
{
    //int bufSize = 0;
    //char* bufPtr = NULL;
    ctrlr->RequestRead();
        
    bool up = !ctrlr->getButtonDU();
    if (up)   return 2;
    
    bool down = !ctrlr->getButtonDD();
    if (down) return 0;
    
    bool left = !ctrlr->getButtonDL();
    if (left) return 3;
    
    bool right = !ctrlr->getButtonDR(); 
    if (right) return 1;
    
    if (!ctrlr->getButtonSTART()) {
        game_paused = !game_paused;
        wait(0.5);
    }
    
    return -1;
}

// MBEDGC SNAKE BY J.P. ARMSTRONG WWW.JPARMSTRONG.COM
// LICENSED UNDER GNU PUBLIC LICENSE.

void setup() 
{  
        
    drawStrings(28, 50, 28, "MBEDGC.COM");
    
    drawStrings(10, 70, 192, "JP. YIGAL. DANNY.");
    drawStrings(12, 78, 192, "SHAIN. ALFREDO.");

    wait(3);
    blankFB();
    
    drawStrings(30, 50, 192, "FIU SENIOR");
    drawStrings(28, 58, 192, "DESIGN 2011");

    wait(3);
    blankFB();
    startGame();
}

void loop() 
{
    // KEEP THE SNAKE IN THE FRAMEBUFFER.
    // IF IT'S CORD ARE BEYOND THE FRAMEBUFFER. ADJUST IT. 
    if (snake_y <= 0)
        snake_y = fbH - 1;
    
    if (snake_x <= 0)
        snake_x = fbW - 1;
        
    snake_y %= fbH;
    snake_x %= fbW;
    
    // GET VALUE FROM CONTROLLER
    int tmp_sd;
    do {
       tmp_sd = getButton(&ctrlrA);
    }
    while (game_paused);
    
    // MAKE SURE BUTTON WAS PRESSED OTHERWISE IGNORE IT.
    if (tmp_sd != -1) {
            
        // YOU CAN'T GO LEFT IF YOU'RE ALREADY GOING RIGHT AND VICE VERSA
        // YOU CAN'T GO   UP IF YOU'RE ALREADY GOING DOWN AND VICE VERSA
        if (!((snake_direction == 0 && tmp_sd == 2) || (snake_direction == 2 && tmp_sd == 0) ||
              (snake_direction == 3 && tmp_sd == 1) || (snake_direction == 1 && tmp_sd == 3)  )) {
            snake_direction = tmp_sd;
        }
    }
    
    // PRODUCE NO SOUND
    soundNoteHalf = 0;
    
    // INCREMENT OR DECREMENT SNAKE'S COORD DEPENDING ON DIRECTION
    switch (snake_direction) 
    {
        case 0:
            snake_y += 2;
            break;
        case 2:
            snake_y -= 2;
            break;
        case 1:
            snake_x += 2;
            break;
        case 3:
            snake_x -= 2;
            break;
    }
    
    // IF LOCATION SNAKE IS GOING IS AN APPLE. EAT IT.
    if (framebuffer[snake_y][snake_x] == 3) {
    
        snake_apples_eaten++;
        snake_length += 2;
        
        // DECREASE COUNTDOWN TIMER
        logic_count -= 50;
        
        if (logic_count < 0)
            logic_count = 0;
        
        score += 5;
        
        // BEEP
        soundNote = 3100;
        soundNoteHalf = 1550;
        
        // IF NO MORE APPLES ADD N MORE. "NEW LEVEL"
        if (snake_apples_eaten % num_apples == 0) {
            
            score += (snake_apples_eaten / 10) * (100 - 100 * ((float) logic_count / 1000));
            
            soundNote = 2000;
            soundNoteHalf = 1000;
        
            apples(num_apples);
           
        }
        
        drawNumbers(36, 105, 16, score);
        
    }
    // IF NOT AN APPLE, AND NOT EMPTY SPACE, THE SNAKE EITHER
    // HIT THE WALL OR IT ITSELF AND THE GAME IS LOST.
    else if (framebuffer[snake_y][snake_x] != 0) {
       
        
        endGame();
        startGame();
         
       
    }
    else {
        soundNote = 4000;
        soundNoteHalf = 0;
    }
    
    // ADVANCE THE SNAKE TO NEW POSITION
    snake.addHead(snake_x, snake_y);
    drawRectangle(snake_x, snake_y, 2, 2, snake_color);
      
    // REMOVE THE TAIL UNLESS IT ATE AN APPLE.
    while (snake_length <= snake.getSize()) { 
        drawRectangle(snake.getTailXCor(), snake.getTailYCor(), 2, 2, 0);
        snake.removeTail();
    }
    
    
    // COUNT DOWN
    logic_percent = (float) logic_count / 1000 ;
    drawRectangle(60, 106, 48, 4 , 0); 
     
    if ((logic_percent * 100) < 75.0) {
        drawRectangle(60, 106, 48 - 48 * logic_percent, 4 , 192); 
    }
    else {
    
        if ((logic_percent * 100) > 100) {
            endGame();
            startGame();
         }
        else {
          drawRectangle(60, 106, 48 - 48 * logic_percent, 4 , 3);
        }
        
        if (logic_count % 20 == 0) {
            soundNote = 4000;
            soundNoteHalf = 2000;
        }
        else {
            soundNoteHalf = 0;
        }
   }

   // ADD DELAY TO THE LOGIC
   wait(0.05);
}

// SETUP A NEW GAME
void startGame() {

        // blank framebuffer
        blankFB();
        
        // initialization variables
        snake_x = 60;
        snake_y = 12;
        snake_direction = 0;    
        snake_apples_eaten = 0;
        snake_length = 10;
        score = 0;

        
        // add apples
        apples(num_apples);
        
        // add head to beginning of snake linked list
        snake.addHead(snake_x, snake_y);

        
        // BLUE BORDERS
        drawRectangle(4, 10, 2, 90, 16);
        drawRectangle(4, 10, 104, 2, 16);
        
        drawRectangle(108, 10, 2, 90, 16);
        drawRectangle(4, 100, 106, 2, 16);
        
        // COUNTDOWN
        drawRectangle(59, 105, 50, 6 , 16); 
        drawRectangle(60, 106, 48, 4 , 0); 
        
        logic_count = 0;
        
           
       drawNumbers(36, 105, 16, score);
     
}

void endGame() {
    // blankFB();
     
     soundNote = 4000;
     soundNoteHalf = soundNote / 2;
        
     wait(0.1); 
        
     soundNoteHalf = 0;
 
     
     drawStrings(30, 40, 192, "GAME OVER");
     drawStrings(28, 50, 192, "MBEDGC.COM");
     drawNumbers(73, 60, 192, score);
  
  wait(3);
  blankFB();
  wait(0.1);
      
  LocalFileSystem local("local");               // Create the local filesystem under the name "local"

  FILE *fp = fopen("/local/hs.txt", "a");  // Open "out.txt" on the local file system for writing
  
  char buf[16];
  sprintf(buf, "AMS\t%05d\r\n", score);
  fprintf(fp, buf);
  
  fclose(fp);

}

void drawStrings(int x, int y, unsigned char color, string str) {
    
        for (int i = 0; i < str.size(); i++) {
            drawCharacter( x + (6 * i), y, color, str[i]);
        }
    
}

void drawNumbers(int x, int y, unsigned char color, int num) {
       
        for (int i = 1; i <= 5; i++) {
            drawCharacter( x - (6 * i), y, color, num % 10);
            num /= 10;
        }
}

// ADD N APPLES TO THE SCREEN
void apples(int number) {
    
    int i = 0;
    int x = 0, y = 0;
    
    do  {
       x = 2 * (rand() % (90 / 2)) + 6;
       y = 2 * (rand() % (86 / 2)) + 12;
       
       // MAKE SURE YOU DON'T ADD AN APPLE ON THE SNAKE OR WALL
       if (framebuffer[y][x] == 0) {
          drawRectangle(x, y, 2 , 2, 3);
          i++;
       }
       
    }
    while (i < number);
}


DigitalOut mled0(LED1);
DigitalOut mled1(LED2);
DigitalOut mled2(LED3);
DigitalOut mled3(LED4);


int networking() {
        
  mled0 = 1;
  
  printf("Init\n");

  printf("\r\nSetting up...\r\n");
  EthernetErr ethErr = eth.setup();
  
  mled1 = 1;
  
  if(ethErr)
  {
    printf("Error %d in setup.\n", ethErr);
  }
  mled2 = 1;
  printf("\r\nSetup OK\r\n");

  HTTPClient twitter;
  mled1 = 0;
  
  HTTPMap msg;
  mled0 = 0;
  msg["status"] = "I am tweeting from my mbedgc!"; //A good example of Key/Value pair use with Web APIs

  twitter.basicAuth("mbedgc", "mbgc321"); //We use basic authentication, replace with you account's parameters
  mled0 = 1;
 
  //No need to retieve data sent back by the server
  HTTPResult r = twitter.post("http://api.supertweet.net/1/statuses/update.xml", msg, NULL);
   
  if( r == HTTP_OK )
  {
    printf("Tweet sent with success!\n");
    
    mled3 = 1;
  }
  else
  {
    printf("Problem during tweeting, return code %d\n", r);
    mled2 = 0;
  }
  
  return 0;
}