Thought you might like to see some pics of the Batsocks TellyMate Shield hooked up to my 47" LCD TV:-
Thought you might like to see some pics of the Batsocks TellyMate Shield hooked up to my 47" LCD TV:-
The quality is really impressive.
I am wondering if somebody already started implementing some old fashioned apps, like tennis, or even come up with a ZX Spectrum "replacement".
I'm going to give 'Pong' a go for starters
Hi Mike, I starting working on that as well, how far along is yours?
Not even started yet :
Here is a version of pong for the TellyMate. The gameplay is based on some code Tom Igoe posted here: http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
/*
TellyPong
pong for the TellyMate shield
based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
modified by mem 20 May 2009
This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/
#define RIGHT_PIN 0 // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN 2
// define the edges of the screen:
#define HEIGHT 25
#define WIDTH 38
#define LEFT 0
#define RIGHT (WIDTH -1)
#define TOP 0
#define BOTTOM (HEIGHT-1)
#define PADDLESIZE 1 // this how many pixels the paddle extends top and bottom
#define SPEED 4000 // how many milliseconds it takes the ball to move across the screen
#define BALL 'o' // character code for ball
#define PADDLE 219 // character for paddle (see http://en.wikipedia.org/wiki/Code_page_437)
#define CHAR_ESC "\x1B" // escape character used in TellyMate commands
int ballX = WIDTH/2; // X position of the ball
int ballY = HEIGHT/2; // Y position of the ball
int ballDirectionY = 1; // X direction of the ball
int ballDirectionX = 1; // Y direction of the ball
int rightPaddleY = 0; // X position of the center of the right paddle
int leftPaddleY = 0; // Y position of the center of the right paddle
int prevRight = -1; // holds previous paddle position
int prevLeft = -1; // set to -1 to force display on startup
long timeStamp = 0; // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false; // state of the game
void setup() {
Serial.begin(57600); //57k6 baud
screen_clear();
Serial.println("TellyPong!");
cursor_show(false); // turn cursor off
delay(1000);
screen_clear();
}
void loop() {
// read input:
readSensors();
// move the ball:
if (gamePaused) {
if (millis() - timeStamp > interval*10) {
// if enough time has passed, start the game again:
gamePaused = false;
}
}
// if the game isn't paused, and enough time between ball moves
// has passed, move the ball and update the timestamp:
else {
if (millis() - timeStamp > interval) {
moveBall();
timeStamp = millis();
}
}
}
void readSensors() {
// read the sensors for X and Y values:
leftPaddleY = map(analogRead(LEFT_PIN), 0, 1023, 0, BOTTOM);
if( leftPaddleY != prevLeft){
drawPaddle(' ',0, prevLeft); // erase old paddle
drawPaddle(PADDLE,0, leftPaddleY);
prevLeft = leftPaddleY;
}
rightPaddleY = map(analogRead(RIGHT_PIN), 0, 1023, 0, BOTTOM);
if( rightPaddleY != prevRight){
drawPaddle(' ',RIGHT, prevRight); // erase old paddle
drawPaddle(PADDLE,RIGHT, rightPaddleY);
prevRight = rightPaddleY;
}
}
void moveBall() {
// check to see if the ball is in the horizontal range
// of the paddles:
// right:
if (ballX >= RIGHT - 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its X direction:
if ((ballY + ballDirectionY >= rightPaddleY - PADDLESIZE)
&& (ballY + ballDirectionY <= rightPaddleY + PADDLESIZE)) {
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}
// left:
if (ballX <= LEFT + 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its X direction:
if ((ballY + ballDirectionY >= leftPaddleY - PADDLESIZE )
&& (ballY + ballDirectionY <= leftPaddleY + PADDLESIZE )) {
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
}
}
// if the ball goes off the screen bottom,
// reverse its Y direction:
if (ballY == BOTTOM) {
ballDirectionY = -ballDirectionY;
}
// if the ball goes off the screen top,
// reverse its X direction:
if (ballY == TOP) {
ballDirectionY = -ballDirectionY;
}
// clear the ball's previous position:
screenShowXY(' ', ballX, ballY);
// if the ball goes off the screen left or right:
if ((ballX == LEFT) || (ballX == RIGHT)) {
// reset the ball:
ballX = WIDTH/2;
;
ballY = HEIGHT/2;
// pause and note the time you paused:
gamePaused = true;
timeStamp = millis();
}
// increment the ball's position in both directions:
ballX = ballX + ballDirectionX;
ballY = ballY + ballDirectionY;
// if the game isn't paused, set the ball
// in its new position:
if (!gamePaused) {
// set the new position:
screenShowXY(BALL, ballX, ballY);
}
}
void drawPaddle(char paddleChar, int x, int y)
{
for(int i =-PADDLESIZE; i <= PADDLESIZE; i++)
{
screenShowXY(paddleChar, x, y + i);
}
}
// TellyMate helper functions
void screenShowXY( char ch, int x, int y){
// display the given character at the screen x and y location
cursor_move(y,x);
Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
Serial.print( CHAR_ESC "E" );
}
void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
Serial.print( CHAR_ESC "Y" ) ;
Serial.print((unsigned char)(32 + row)) ;
Serial.print((unsigned char)(32 + col)) ;
}
void cursor_show( bool show )
{ // <ESC>e or <ESC>f
Serial.print( CHAR_ESC ) ;
Serial.print( show?'e':'f' ) ;
}
Nice one. I haven't got that shield but will modify it for my kit. Thanks!
I haven't got that shield but will modify it for my kit
what modificaitons ? it looks like we use the same shield.
The 'dangershield' mentioned in your code.
You only need to set the analog pin assignments for your pots. I am not using any of the other features of the DangerShield - but it would be cool to use the piezo to add sound for ball contacts, and perhaps use the swtiches to start and pause the game. hmmm
here a version that uses a speaker or piezo on pin 3 for sound.
/*
TellyPong
pong for the TellyMate shield
based on gameplay created by Tom Igoe http://www.tigoe.net/pcomp/code/category/Processing/454#more-454
modified by mem 20 May 2009
This example uses the TellyMate shield http://www.batsocks.co.uk/products/Other/TellyMate%20Shield.htm
*/
#define RIGHT_PIN 0 // pins connected to pots (2 and 0 are sliders 1 and 3 on dangershield)
#define LEFT_PIN 2
#define BUZZER_PIN 3 // digital pin connected to a piezo buzzer or speaker
#define PADDLE_SOUND 2000
#define EDGE_SOUND 500
// define the edges of the screen:
#define HEIGHT 25
#define WIDTH 38
#define LEFT 0
#define RIGHT (WIDTH -1)
#define TOP 0
#define BOTTOM (HEIGHT-1)
#define PADDLESIZE 1 // this how many pixels the paddle extends top and bottom
#define SPEED 4000 // how many milliseconds it takes the ball to move across the screen
#define BALL 'o' // character code for ball
#define PADDLE 219 // character for paddle (see http://en.wikipedia.org/wiki/Code_page_437)
#define CHAR_ESC "\x1B" // escape character used in TellyMate commands
int ballX = WIDTH/2; // X position of the ball
int ballY = HEIGHT/2; // Y position of the ball
int ballDirectionY = 1; // X direction of the ball
int ballDirectionX = 1; // Y direction of the ball
int rightPaddleY = 0; // X position of the center of the right paddle
int leftPaddleY = 0; // Y position of the center of the right paddle
int prevRight = -1; // holds previous paddle position
int prevLeft = -1; // set to -1 to force display on startup
long timeStamp = 0; // time stamp to control the pauses between ball moves
long interval = SPEED/WIDTH ; // interval in milliseconds between ball moves
boolean gamePaused = false; // state of the game
void setup() {
pinMode(BUZZER_PIN, OUTPUT); // if using speaker
Serial.begin(57600); //57k6 baud
screen_clear();
Serial.println("TellyPong!");
cursor_show(false); // turn cursor off
delay(1000);
screen_clear();
}
void loop() {
// read input:
readSensors();
// move the ball:
if (gamePaused) {
if (millis() - timeStamp > interval*10) {
// if enough time has passed, start the game again:
gamePaused = false;
}
}
// if the game isn't paused, and enough time between ball moves
// has passed, move the ball and update the timestamp:
else {
if (millis() - timeStamp > interval) {
moveBall();
timeStamp = millis();
}
}
}
void readSensors() {
// read the sensors for X and Y values:
leftPaddleY = map(analogRead(LEFT_PIN), 0, 1023, 0, BOTTOM);
if( leftPaddleY != prevLeft){
drawPaddle(' ',0, prevLeft); // erase old paddle
drawPaddle(PADDLE,0, leftPaddleY);
prevLeft = leftPaddleY;
}
rightPaddleY = map(analogRead(RIGHT_PIN), 0, 1023, 0, BOTTOM);
if( rightPaddleY != prevRight){
drawPaddle(' ',RIGHT, prevRight); // erase old paddle
drawPaddle(PADDLE,RIGHT, rightPaddleY);
prevRight = rightPaddleY;
}
}
void moveBall() {
// check to see if the ball is in the horizontal range
// of the paddles:
// right:
if (ballX >= RIGHT - 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its X direction:
if ((ballY + ballDirectionY >= rightPaddleY - PADDLESIZE)
&& (ballY + ballDirectionY <= rightPaddleY + PADDLESIZE)) {
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
playSound(PADDLE_SOUND);
}
}
// left:
if (ballX <= LEFT + 1) {
// if the ball's next Y position is between
// the top and bottom of the paddle, reverse its X direction:
if ((ballY + ballDirectionY >= leftPaddleY - PADDLESIZE )
&& (ballY + ballDirectionY <= leftPaddleY + PADDLESIZE )) {
// reverse the ball horizontal direction:
ballDirectionX = -ballDirectionX;
playSound(PADDLE_SOUND);
}
}
// if the ball goes off the screen bottom,
// reverse its Y direction:
if (ballY == BOTTOM) {
ballDirectionY = -ballDirectionY;
}
// if the ball goes off the screen top,
// reverse its X direction:
if (ballY == TOP) {
ballDirectionY = -ballDirectionY;
}
// clear the ball's previous position:
screenShowXY(' ', ballX, ballY);
// if the ball goes off the screen left or right:
if ((ballX == LEFT) || (ballX == RIGHT)) {
playMiss();
// reset the ball:
ballX = WIDTH/2;
;
ballY = HEIGHT/2;
// pause and note the time you paused:
gamePaused = true;
timeStamp = millis();
}
// increment the ball's position in both directions:
ballX = ballX + ballDirectionX;
ballY = ballY + ballDirectionY;
// if the game isn't paused, set the ball
// in its new position:
if (!gamePaused) {
// set the new position:
screenShowXY(BALL, ballX, ballY);
}
}
void drawPaddle(char paddleChar, int x, int y)
{
for(int i =-PADDLESIZE; i <= PADDLESIZE; i++)
{
screenShowXY(paddleChar, x, y + i);
}
}
void playSound(int period ){
digitalWrite(BUZZER_PIN,HIGH);
delayMicroseconds(period);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(period);
}
void playMiss(){
for(int i=0; i < 100; i++)
playSound(400);
for(int i=0; i < 100; i++)
playSound(3000 + i);
}
// TellyMate helper functions
void screenShowXY( char ch, int x, int y){
// display the given character at the screen x and y location
cursor_move(y,x);
Serial.print(ch);
}
void screen_clear( void )
{ // <ESC>E
Serial.print( CHAR_ESC "E" );
}
void cursor_move( uint8_t row , uint8_t col )
{ // <ESC>Yrc
Serial.print( CHAR_ESC "Y" ) ;
Serial.print((unsigned char)(32 + row)) ;
Serial.print((unsigned char)(32 + col)) ;
}
void cursor_show( bool show )
{ // <ESC>e or <ESC>f
Serial.print( CHAR_ESC ) ;
Serial.print( show?'e':'f' ) ;
}
Nice. I'll give that a try some time this week when I get a chance.