moe

Forum Replies Created

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • in reply to: Help needed: Cleaning up code + collision check #1444
    moe
    Member

    Woah this sounds pretty heavy, I’ll try to implement the things you told me, I hope you can help me for further question!

    Thanks really much!

    in reply to: TVout Drawing #1018
    moe
    Member

    Unfortunately I think the game will take longer than you expect because I just have built the title screen and some little things, and I’ve not started developing the game yet… 😛

    I might have a big problem because everything I do have now already takes up 10.000 Bytes of 30.000 Bytes available. I don’t have any feeling for storage on the Hackvision platform, do you think my entire game will have enough free storage? Just asking because you already developed 2… And yeah if this would really happen, how can I save storage (without removing too much) and which things take up the most space?

    Thanks!

    in reply to: TVout Drawing #1016
    moe
    Member

    Wow thanks a lot trodoss for your quick reply and effort!

    I’ve already came up with a solution for the “[“, but your answer concerning the bitmaps does help me a lot! I soon will decorate my title screen with a nice picture 😀

    So yeah thank you really much, I hope if I’ve got any other question you’ll help me!

    Is there any way to contact you via skype or such? Just for talking about Hackvision or little Code related things… I’m also ok if you’d say “No”

    in reply to: Help a Newbie? #1127
    moe
    Member

    #define TV_W 136
    #define TV_H 98
    #define FRAME_X0 8
    #define FRAME_X1 128
    #define FRAME_Y0 9
    #define FRAME_Y1 89
    #define LEFT 3
    #define RIGHT 2
    #define UP 4
    #define DOWN 5
    #define FIRE 10

    struct Segment
    {
    boolean active;
    byte x;
    byte y;
    };

    prog_char s0[] PROGMEM = "ARDUINO WORM";
    prog_char s1[] PROGMEM = "GAME";
    prog_char s2[] PROGMEM = "OVER";
    prog_char s3[] PROGMEM = "SCORE: ";
    prog_char s4[] PROGMEM = "BREAKOUT";

    PROGMEM const char *strings[] = {
    s0,s1,s2,s3,s4};
    char s[16]; // general string buffer
    char scoreString[11];
    byte currentTonePriority = 0;
    byte ballX;
    byte ballY;
    byte movingDirection;
    boolean ballCollected = false;
    int currentScore;

    Segment worm[50];

    void (*game)();

    TVout TV;
    const byte width = 120; //Width of screen
    const byte height = 96; //Hight of screen
    int dx = -1; //Initial movement of ball
    int dy = -1; //Initial movement of ball
    int xb; //Balls starting possition
    int yb; //Balls starting possition
    boolean released; //If the ball has been released by the player
    boolean paused = false; //If the game has been paused
    byte xPaddle; //X position of paddle
    boolean isHit[5][12]; //Array of if bricks are hit or not
    boolean bounced=false; //Used to fix double bounce glitch
    byte lives = 3; //Amount of lives
    byte level = 1; //Current level
    unsigned int score=0; //Score for the game
    unsigned int brickCount; //Amount of bricks hit
    byte pad,pad2,pad3; //Button press buffer used to stop pause repeating
    byte oldpad,oldpad2,oldpad3;
    char text[16]; //General string buffer
    boolean start=false; //If in menu or in game
    boolean initialDraw=false;//If the inital draw has happened
    char initials[3]; //Initials used in high score

    //Ball Bounds used in collision detection
    byte leftBall;
    byte rightBall;
    byte topBall;
    byte bottomBall;

    //Brick Bounds used in collision detection
    byte leftBrick;
    byte rightBrick;
    byte topBrick;
    byte bottomBrick;

    float speedAdjust = 1.0;

    void setup()
    {
    // If pin 12 is pulled LOW, then the PAL jumper is shorted.
    pinMode(12, INPUT);
    digitalWrite(12, HIGH);

    //Set video mode
    if (digitalRead(12) == LOW) {
    TV.begin(PAL,width,height);
    }
    else {
    TV.begin(NTSC,width,height);
    }
    TV.select_font(font6x8);
    randomSeed(analogRead(0));

    playTone(1046, 20);
    TV.delay(1);
    playTone(1318, 20);
    TV.delay(1);
    playTone(1568, 20);
    TV.delay(1);
    playTone(2093, 20);

    byte m[2] = {0, 4};
    byte choice = menu(2, m);
    if (choice == 0) {
    game = &worms;
    TV.delay(10);
    initWorms();
    }
    if (choice == 1) {
    game = &breakout;
    TV.delay(10);
    }
    }

    byte menu(byte nChoices, byte *choices) {
    char choice = 0;
    TV.fill(0);
    byte x = 24;
    byte y;

    while (true) {
    for(byte i=0;i strcpy_P(s, (char *)pgm_read_word(&(strings[choices])));
    TV.print(32, 30+(i*8), s);
    }
    for(byte i=0;i y = 30+(i*8);
    if (i == choice) {
    // draw arrow next to selected game
    TV.set_pixel(x+4, y, 1);
    TV.set_pixel(x+5, y+1, 1);
    TV.draw_line(x, y+2, x+6, y+2, 1);
    TV.set_pixel(x+5, y+3, 1);
    TV.set_pixel(x+4, y+4, 1);
    }
    else {
    for(byte j=0;j<8;j++) {
    TV.draw_line(x, y+j, x+7, y+j, 0);
    }
    }
    }
    // get input
    if (pollFireButtonWorm(10)) {
    playTone(1046, 20);
    return choice;
    }
    if (Controller.upPressed()) {
    choice--;
    if (choice == -1) {
    choice = 0;
    }
    else {
    playTone(1046, 20);
    }
    }
    if (Controller.downPressed()) {
    choice++;
    if (choice == nChoices) {
    choice = nChoices-1;
    }
    else {
    playTone(1046, 20);
    }
    }
    }
    }

    void initWorms() {
    for(int x = 0; x < 5; x++) {
    worm[x].active = true;
    worm[x].x = 30-x;
    worm[x].y = 30;
    }
    for(int x = 5; x < 50; x++) {
    worm[x].active = false;
    worm[x].x = 0;
    worm[x].y = 0;
    }
    movingDirection = RIGHT;
    ballCollected = true;
    currentScore = 0;
    updateScore();
    }

    void loop() {
    game();
    }

    void worms() {
    TV.fill(0);
    drawFrame();
    drawScore();
    drawBallWorm();
    for(int x = 0; x < 50; x++) {
    if(worm[x].active)
    TV.set_pixel(worm[x].x,worm[x].y,1);
    }
    move();
    TV.delay_frame(4);
    }

    void drawBallWorm() {
    if(ballCollected) {
    ballX = random(FRAME_X0+1, FRAME_X1-1);
    ballY = random(FRAME_Y0+1, FRAME_Y1-1);
    ballCollected = false;
    }
    TV.set_pixel(ballX,ballY,1);
    }

    void drawFrame() {
    TV.draw_line(FRAME_X0, FRAME_Y0, FRAME_X1, FRAME_Y0, 1);
    TV.draw_line(FRAME_X0, FRAME_Y1, FRAME_X1, FRAME_Y1, 1);
    TV.draw_line(FRAME_X0, FRAME_Y0, FRAME_X0, FRAME_Y1, 1);
    TV.draw_line(FRAME_X1, FRAME_Y0, FRAME_X1, FRAME_Y1, 1);
    }

    void move() {
    if (Controller.upPressed()) {
    if(movingDirection != DOWN) {
    movingDirection = UP;
    }
    }
    else if(Controller.downPressed()) {
    if(movingDirection != UP) {
    movingDirection = DOWN;
    }
    }
    else if(Controller.leftPressed()) {
    if(movingDirection != RIGHT) {
    movingDirection = LEFT;
    }
    }
    else if(Controller.rightPressed()) {
    if(movingDirection != LEFT) {
    movingDirection = RIGHT;
    }
    }
    switch (movingDirection) {
    case UP:
    if(detectBallHit(worm[0].x, worm[0].y-1)) {
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].y = worm[0].y-1 ;
    }
    break;
    case DOWN:
    if(detectBallHit(worm[0].x, worm[0].y+1)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].y = worm[0].y+1 ;
    }
    break;
    case LEFT:
    if(detectBallHit(worm[0].x-1, worm[0].y)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].x = worm[0].x-1 ;
    }
    break;
    case RIGHT:
    if(detectBallHit(worm[0].x+1, worm[0].y)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].x = worm[0].x+1 ;
    }
    break;
    }
    if(worm[0].x > FRAME_X1-1 || worm[0].x < FRAME_X0+1 || worm[0].y > FRAME_Y1-1 || worm[0].y < FRAME_Y0+1 || checkForTailBite()) {
    gameOver();
    initWorms();
    return;
    }
    }

    boolean checkForTailBite() {
    for(int x = 1; x < 50; x++) {
    if(worm[0].x == worm[x].x && worm[0].y == worm[x].y) {
    return true;
    }
    }
    return false;
    }

    void shiftSegments() {
    for(int x = 49; x > 0; x--) {
    if(worm[x].active) {
    worm[x].x = worm[x-1].x;
    worm[x].y = worm[x-1].y;
    }
    }
    }

    void assignBallCoordinatesToFirstSegment() {
    worm[0].x = ballX;
    worm[0].y = ballY;
    }

    boolean detectBallHit(byte sx, byte sy) {
    if(sx == ballX && sy == ballY) {
    for(int x = 49; x > -1; x--) {
    if(worm[x].active) {
    worm[x+1].active = true;
    worm[x+1].x = worm[x].x;
    worm[x+1].y = worm[x].y;
    }
    }
    ballCollected = true;
    currentScore += 1;
    updateScore();
    playTone(1046, 10);
    TV.delay(1);
    playTone(1318, 10);
    TV.delay(1);
    playTone(1568, 10);
    TV.delay(1);
    playTone(2093, 10);
    return true;
    }
    else {
    return false;
    }
    }

    void drawScore() {
    TV.print(FRAME_X0, 0, scoreString);
    }

    void updateScore() {
    strcpy_P(scoreString, (char *)pgm_read_word(&(strings[3])));
    sprintf(s, "%d", currentScore);
    strcat(scoreString, s);
    }

    void gameOver() {
    TV.delay(1000);
    TV.fill(0);
    strcpy_P(s, (char *)pgm_read_word(&(strings[1])));
    TV.print(44, 40, s);
    strcpy_P(s, (char *)pgm_read_word(&(strings[2])));
    TV.print(72, 40, s);
    TV.delay(3000);
    }

    boolean pollFireButtonWorm(int n) {
    for(int i=0;i TV.delay_frame(1);
    if (Controller.firePressed()) {
    return true;
    }
    }
    return false;
    }

    void playTone(unsigned int frequency, unsigned long duration_ms) {
    // Default is to play tone with highest priority.
    playTone(frequency, duration_ms, 9);
    }

    void playTone(unsigned int frequency, unsigned long duration_ms, byte priority) {
    // priority is value 0-9, 9 being highest priority
    if (TCCR2B > 0) {
    // If a tone is currently playing, check priority
    if (priority < currentTonePriority) {
    return;
    }
    }
    currentTonePriority = priority;
    TV.tone(frequency, duration_ms);
    }

    void movePaddle()
    {
    //Move right
    if(xPaddle < width-12)
    {
    if(Controller.rightPressed())
    {
    xPaddle++;
    }
    }

    //Move left
    if(xPaddle > 0)
    {
    if(Controller.leftPressed())
    {
    xPaddle--;
    }
    }
    }

    void moveBall()
    {
    if(released)
    {
    //Move ball
    xb=xb + dx;
    yb=yb + dy;

    //Set bounds
    leftBall = xb;
    rightBall = xb+2;
    topBall = yb;
    bottomBall = yb+2;

    //Bounce off top edge
    if (yb<=0)
    {
    yb=2;
    dy=-dy;
    TV.tone(523, 20);
    }

    //Lose a life if bottom edge hit
    if (yb>=89)
    {
    TV.draw_rect(xPaddle,87,11,1,0);
    xPaddle = 54;
    yb=84;
    released = false;
    lives--;
    drawLives();
    TV.tone(175, 20);
    if (random(0, 2) == 0) {
    dx = 1;
    }
    else {
    dx = -1;
    }
    }

    //Bounce off left side
    if (xb<=0)
    {
    xb=2;
    dx=-dx;
    TV.tone(523, 20);
    }

    //Bounce off right side
    if (xb>=width-2)
    {
    xb=width-4;
    dx=-dx;
    TV.tone(523, 20);
    }
    //Bounce off paddle
    if (xb+1>=xPaddle && xb<=xPaddle+12 && yb+2>=87 && yb<=92){
    dy=-dy;
    dx=((xb-(xPaddle+6))/3); //Applies spin on the ball
    TV.tone(200, 20);
    }

    //Bounce off Bricks
    for (byte row = 0; row < 5; row++) {
    for (byte column = 0; column < 12; column++) {
    if (!isHit[row][column]){

    //Sets Brick bounds
    leftBrick = 10*column;
    rightBrick = 10*column+10;
    topBrick = 6*row+1;
    bottomBrick = 6*row+7;

    //If A collison has occured
    if (topBall <= bottomBrick && bottomBall>=topBrick && leftBall<=rightBrick && rightBall >=leftBrick){
    Score();
    brickCount++;
    isHit[row][column] = true;
    TV.draw_rect(10*column ,2+6*row,8,4,0);

    //Vertical collision
    if (bottomBall>bottomBrick || topBall //Only bounce once each ball move
    if(!bounced){
    dy=-dy;
    yb+=dy;
    bounced=true;
    TV.tone(261, 20);
    }
    }

    //Hoizontal collision
    if (leftBallrightBrick){

    //Only bounce once brick each ball move
    if(!bounced){
    dx=-dx;
    xb+=dx;
    bounced=true;
    TV.tone(261, 20);
    }
    }
    }
    }
    }
    }
    //Reset Bounce
    bounced=false;
    }
    else{
    //Ball follows paddle
    xb=xPaddle+5;

    //Release ball if FIRE pressed
    pad3 = Controller.firePressed();
    if(pad3 ==1 && oldpad3==0){
    released=true;

    //Apply random direction to ball on release
    if (random(0, 2) == 0) {
    dx = 1;
    }
    else {
    dx = -1;
    }
    //Makes sure the ball heads upwards
    dy = -1;
    }
    oldpad3=pad3;
    }
    }

    void drawBall()
    {
    TV.set_pixel(xb,yb,0);
    TV.set_pixel(xb+1,yb,0);
    TV.set_pixel(xb,yb+1,0);
    TV.set_pixel(xb+1,yb+1,0);

    moveBall();

    TV.set_pixel(xb,yb,1);
    TV.set_pixel(xb+1,yb,1);
    TV.set_pixel(xb,yb+1,1);
    TV.set_pixel(xb+1,yb+1,1);
    }

    void drawPaddle()
    {
    TV.draw_rect(xPaddle,87,11,1,0);
    movePaddle();
    TV.draw_rect(xPaddle,87,11,1,1);
    }

    void drawLives()
    {
    sprintf(text, "LIVES:%u", lives);
    TV.print(0, 90, text);
    }

    void drawGameOver()
    {
    TV.set_pixel(xb,yb,0);
    TV.set_pixel(xb+1,yb,0);
    TV.set_pixel(xb,yb+1,0);
    TV.set_pixel(xb+1,yb+1,0);
    TV.print(52, 42, "Game");
    TV.print(52, 54, "Over");
    delay(4000);
    }

    void pause()
    {
    paused = true;
    //Draw pause to the screen
    TV.print(52, 45, "PAUSE");
    while(paused){
    delay(15);
    //Unpause if FIRE is pressed
    pad2 = Controller.firePressed();
    if(pad2 ==1 && oldpad2==0 && released){
    TV.print(52, 45, " ");
    paused=false;
    }
    oldpad2=pad2;
    }
    }

    void Score()
    {
    score += (level*10);
    sprintf(text, "SCORE:%u", score);
    TV.print(80, 90, text);
    }

    void newLevel(){
    //Undraw paddle
    TV.draw_rect(xPaddle,87,11,1,0);

    //Undraw ball
    TV.set_pixel(xb,yb,0);
    TV.set_pixel(xb+1,yb,0);
    TV.set_pixel(xb,yb+1,0);
    TV.set_pixel(xb+1,yb+1,0);

    //Alter various variables to reset the game
    xPaddle = 54;
    yb=84;
    brickCount=0;
    released=false;

    //Draws new bricks and resets their values
    for (byte row = 0; row < 5; row++) {
    for (byte column = 0; column < 12; column++) {
    isHit[row][column] = false;
    TV.draw_rect(10*column ,2+6*row,8,4,1);
    }
    }

    //Draws the initial lives
    drawLives();

    //Draws the initial score
    sprintf(text, "SCORE:%u", score);
    TV.print(80, 90, text);
    }

    //Used to delay images while reading button input
    boolean pollFireButton(int n) {
    for(int i=0;i TV.delay(15);
    pad = Controller.firePressed();
    if(pad ==1 && oldpad==0){
    oldpad3=1; //Forces pad loop 3 to run once
    return true;
    }
    oldpad=pad;
    }
    return false;
    }

    //Function by nootropic design to display highscores
    boolean displayHighScores(byte file) {
    byte y = 10;
    byte x = 24;
    // Each block of EEPROM has 10 high scores, and each high score entry
    // is 5 bytes long: 3 bytes for initials and two bytes for score.
    int address = file*10*5;
    byte hi, lo;
    TV.fill(0);
    TV.select_font(font6x8);
    TV.print(32, 0, "HIGH SCORES");
    for(int i=0;i<10;i++) {
    sprintf(text, "%2d", i+1);
    TV.print(x, y+(i*8), text);

    hi = EEPROM.read(address + (5*i));
    lo = EEPROM.read(address + (5*i) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    score = 0;
    }
    else {
    score = (hi << 8) | lo;
    }
    initials[0] = (char)EEPROM.read(address + (5*i) + 2);
    initials[1] = (char)EEPROM.read(address + (5*i) + 3);
    initials[2] = (char)EEPROM.read(address + (5*i) + 4);

    if (score > 0) {
    sprintf(text, "%c%c%c %u", initials[0], initials[1], initials[2], score);
    TV.print(x+24, y+(i*8), text);
    }
    }
    if (pollFireButton(300)) {
    return true;
    }
    return false;
    }

    boolean titleScreen() {
    //Clears the screen
    TV.fill(0);

    //Draws the main title
    TV.bitmap(0, 0, title);
    if (pollFireButton(25)) {
    return true;
    }

    //Flash "Press FIRE" 5 times
    for(byte i=0;i<5;i++){
    //Draws "Press FIRE"
    TV.bitmap(31, 53, fire);
    if (pollFireButton(50)) {
    return true;
    }
    //Removes "Press FIRE"
    TV.draw_rect(31,53,57,8,0,0);
    if (pollFireButton(25)) {
    return true;
    }
    }
    return false;
    }

    //Function by nootropic design to add high scores
    void enterInitials() {
    char index = 0;

    TV.fill(0);
    TV.print(16, 0, "HIGH SCORE");
    sprintf(text, "%u", score);
    TV.print(88, 0, text);
    initials[0] = ' ';
    initials[1] = ' ';
    initials[2] = ' ';

    while (true) {
    TV.print_char(56, 20, initials[0]);
    TV.print_char(64, 20, initials[1]);
    TV.print_char(72, 20, initials[2]);
    for(byte i=0;i<3;i++) {
    TV.draw_line(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1);
    }
    TV.draw_line(56, 28, 88, 28, 0);
    TV.draw_line(56 + (index*8), 28, 56 + (index*8) + 6, 28, 1);
    TV.delay(150);
    if (Controller.leftPressed()) {
    index--;
    if (index < 0) {
    index = 0;
    } else {
    TV.tone(1046, 20);
    }
    }
    if (Controller.rightPressed()) {
    index++;
    if (index > 2) {
    index = 2;
    } else {
    TV.tone(1046, 20);
    }
    }
    if (Controller.upPressed()) {
    initials[index]++;
    TV.tone(523, 20);
    // A-Z 0-9 :-? !-/ ' '
    if (initials[index] == '0') {
    initials[index] = ' ';
    }
    if (initials[index] == '!') {
    initials[index] = 'A';
    }
    if (initials[index] == '[') {
    initials[index] = '0';
    }
    if (initials[index] == '@') {
    initials[index] = '!';
    }
    }
    if (Controller.downPressed()) {
    initials[index]--;
    TV.tone(523, 20);
    if (initials[index] == ' ') {
    initials[index] = '?';
    }
    if (initials[index] == '/') {
    initials[index] = 'Z';
    }
    if (initials[index] == 31) {
    initials[index] = '/';
    }
    if (initials[index] == '@') {
    initials[index] = ' ';
    }
    }
    if (Controller.firePressed()) {
    if (index < 2) {
    index++;
    TV.tone(1046, 20);
    } else {
    TV.tone(1046, 20);
    return;
    }
    }
    }

    }

    void enterHighScore(byte file) {
    // Each block of EEPROM has 10 high scores, and each high score entry
    // is 5 bytes long: 3 bytes for initials and two bytes for score.
    int address = file*10*5;
    byte hi, lo;
    char tmpInitials[3];
    unsigned int tmpScore = 0;

    // High score processing
    for(byte i=0;i<10;i++) {
    hi = EEPROM.read(address + (5*i));
    lo = EEPROM.read(address + (5*i) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    // The values are uninitialized, so treat this entry
    // as a score of 0.
    tmpScore = 0;
    } else {
    tmpScore = (hi << 8) | lo;
    }
    if (score > tmpScore) {
    enterInitials();
    for(byte j=i;j<10;j++) {
    hi = EEPROM.read(address + (5*j));
    lo = EEPROM.read(address + (5*j) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    tmpScore = 0;
    } else {
    tmpScore = (hi << 8) | lo;
    }
    tmpInitials[0] = (char)EEPROM.read(address + (5*j) + 2);
    tmpInitials[1] = (char)EEPROM.read(address + (5*j) + 3);
    tmpInitials[2] = (char)EEPROM.read(address + (5*j) + 4);

    // tmpScore and tmpInitials now hold what we want to write in the next slot.

    // write score and initials to current slot
    EEPROM.write(address + (5*j), ((score >> 8) & 0xFF));
    EEPROM.write(address + (5*j) + 1, (score & 0xFF));
    EEPROM.write(address + (5*j) + 2, initials[0]);
    EEPROM.write(address + (5*j) + 3, initials[1]);
    EEPROM.write(address + (5*j) + 4, initials[2]);

    score = tmpScore;
    initials[0] = tmpInitials[0];
    initials[1] = tmpInitials[1];
    initials[2] = tmpInitials[2];
    }
    score = 0;
    initials[0] = ' ';
    initials[1] = ' ';
    initials[2] = ' ';
    return;
    }
    }
    }



    void breakout()
    {
    //Title screen loop switches from title screen and high scores utill FIRE is pressed
    while (!start) {
    start = titleScreen();
    if (!start) {
    start = displayHighScores(2);
    }
    }

    //Inital level draw
    if (!initialDraw){

    //Clears the screen
    TV.fill(0);

    //Selects Font
    TV.select_font(font4x6);

    //Draws the new level
    newLevel();
    initialDraw=true;
    }

    if (lives>0){
    drawPaddle();

    //Pause game if FIRE pressed
    pad = Controller.firePressed();
    if(pad ==1 && oldpad==0 && released){
    oldpad2=1; //Forces pad loop 2 to run once
    pause();
    }
    oldpad=pad;

    drawBall();

    if(brickCount==60){
    level++;
    newLevel();
    }
    }
    else{
    drawGameOver();
    if (score > 0) {
    TV.select_font(font6x8);
    enterHighScore(2);
    }
    TV.select_font(font4x6);
    drawGameOver();
    initialDraw=false;
    start=false;
    lives=3;
    score=0;
    newLevel();
    }
    TV.delay_frame(1);
    }
    in reply to: Help a Newbie? #1126
    moe
    Member

    Sooooo yes I finished my game fusion! I followed what Michael said and yes it works.. I moved the code out of loop and integrated the function and the menu. And yes the Breakout-Game works, the Worms also, but the problem is the frame doesn’t show up correctly. Maybe you can try this code on your on Hackvision to see it (or I can upload a pic). But at least it’s playable and my “creation” works. I also tried the other “project” and now I understand the “syntax” of Arduino (at least a little bit). I want to thank you Michael and Trodoss again you guys did great work and yeah thanks helping me. Oh and yes and Michael if you plan to make a Hackvision v2: If it’s possible, could you please add a on/off switch? But thats just an idea I wanted to share..

    Code in next post…

    in reply to: Help a Newbie? #1123
    moe
    Member

    Wow this makes totally sense to me. Yes you are completely right. Ok I’ll try to fix that! Thanks for the good explanation and yeah this is all really new to me… So can you say that loop is kinda something like a “main” function ? And yes I wasn’t sure with these == and = because this is different in some other p. Languages… And the

    game = &breakout;

    is calling the function breakout ? What’s the difference between void and byte ? Thank you!

    in reply to: Help a Newbie? #1128
    moe
    Member

    Sorry, more than 20000 chars…

    Removed #include too much chars


    #define TV_W 136
    #define TV_H 98
    #define FRAME_X0 8
    #define FRAME_X1 128
    #define FRAME_Y0 9
    #define FRAME_Y1 89
    #define LEFT 3
    #define RIGHT 2
    #define UP 4
    #define DOWN 5
    #define FIRE 10

    const byte width = 120; //Width of screen
    const byte height = 96; //Hight of screen
    int dx = -1; //Initial movement of ball
    int dy = -1; //Initial movement of ball
    int xb; //Balls starting possition
    int yb; //Balls starting possition
    boolean released; //If the ball has been released by the player
    boolean paused = false; //If the game has been paused
    byte xPaddle; //X position of paddle
    boolean isHit[5][12]; //Array of if bricks are hit or not
    boolean bounced=false; //Used to fix double bounce glitch
    byte lives = 3; //Amount of lives
    byte level = 1; //Current level
    unsigned int score=0; //Score for the game
    unsigned int brickCount; //Amount of bricks hit
    byte pad,pad2,pad3; //Button press buffer used to stop pause repeating
    byte oldpad,oldpad2,oldpad3;
    char text[16]; //General string buffer
    boolean start=false; //If in menu or in game
    boolean initialDraw=false;//If the inital draw has happened
    char initials[3]; //Initials used in high score

    //Ball Bounds used in collision detection
    byte leftBall;
    byte rightBall;
    byte topBall;
    byte bottomBall;

    //Brick Bounds used in collision detection
    byte leftBrick;
    byte rightBrick;
    byte topBrick;
    byte bottomBrick;

    struct Segment
    {
    boolean active;
    byte x;
    byte y;
    };


    prog_char s0[] PROGMEM = "ARDUINO WORM";
    prog_char s1[] PROGMEM = "GAME";
    prog_char s2[] PROGMEM = "OVER";
    prog_char s3[] PROGMEM = "SCORE: ";
    prog_char s4[] PROGMEM = "BREAKOUT";

    PROGMEM const char *strings[] = {
    s0,s1,s2,s3,s4};
    char s[16]; // general string buffer
    char scoreString[11];
    byte currentTonePriority = 0;
    byte ballX;
    byte ballY;
    byte movingDirection;
    boolean ballCollected = false;
    int currentScore;
    int choice = true;

    Segment worm[50];

    void (*game)();
    TVout tv;

    // Allow the overall speed of the game to be adjusted.
    // Higher number (like 1.5) slow the game down. Lower numbers (like 0.6) speed it up.
    float speedAdjust = 1.0;

    void setup() {
    // If pin 12 is pulled LOW, then the PAL jumper is shorted.
    pinMode(12, INPUT);
    digitalWrite(12, HIGH);

    if (digitalRead(12) == LOW) {
    tv.begin(_PAL, TV_W, TV_H);
    // Since PAL processing is faster, we need to slow the game play down.
    speedAdjust = 1.4;
    }
    else {
    tv.begin(_NTSC, TV_W, TV_H);
    }

    tv.select_font(font6x8);
    randomSeed(analogRead(0));

    playTone(1046, 20);
    tv.delay(1);
    playTone(1318, 20);
    tv.delay(1);
    playTone(1568, 20);
    tv.delay(1);
    playTone(2093, 20);

    byte m[2] = {0,4};
    byte choice = menu(2, m);
    if (choice == 0) {
    game = &worms;
    tv.delay(10);
    initWorms();
    }
    if (choice == 1) {
    choice = false;
    tv.delay(10);
    initBreakout();
    }
    }

    byte menu(byte nChoices, byte *choices) {
    char choice = 0;
    tv.fill(0);
    byte x = 24;
    byte y;

    while (true) {
    for(byte i=0;i strcpy_P(s, (char *)pgm_read_word(&(strings[choices])));
    tv.print(32, 30+(i*8), s);
    }
    for(byte i=0;i y = 30+(i*8);
    if (i == choice) {
    // draw arrow next to selected game
    tv.set_pixel(x+4, y, 1);
    tv.set_pixel(x+5, y+1, 1);
    tv.draw_line(x, y+2, x+6, y+2, 1);
    tv.set_pixel(x+5, y+3, 1);
    tv.set_pixel(x+4, y+4, 1);
    }
    else {
    for(byte j=0;j<8;j++) {
    tv.draw_line(x, y+j, x+7, y+j, 0);
    }
    }
    }
    // get input
    if (pollFireButton(10)) {
    playTone(1046, 20);
    return choice;
    }
    if (Controller.upPressed()) {
    choice--;
    if (choice == -1) {
    choice = 0;
    }
    else {
    playTone(1046, 20);
    }
    }
    if (Controller.downPressed()) {
    choice++;
    if (choice == nChoices) {
    choice = nChoices-1;
    }
    else {
    playTone(1046, 20);
    }
    }
    }
    }

    void initWorms() {
    for(int x = 0; x < 5; x++) {
    worm[x].active = true;
    worm[x].x = 30-x;
    worm[x].y = 30;
    }
    for(int x = 5; x < 50; x++) {
    worm[x].active = false;
    worm[x].x = 0;
    worm[x].y = 0;
    }
    movingDirection = RIGHT;
    ballCollected = true;
    currentScore = 0;
    updateScore();
    }

    void initBreakout() {
    loop();
    }

    void loop() {
    if (choice = true){
    game();
    } else {
    //Title screen loop switches from title screen and high scores utill FIRE is pressed
    while (!start) {
    start = titleScreen();
    if (!start) {
    start = displayHighScores(2);
    }
    }

    //Inital level draw
    if (!initialDraw){

    //Clears the screen
    tv.fill(0);

    //Selects Font
    tv.select_font(font4x6);

    //Draws the new level
    newLevel();
    initialDraw=true;
    }

    if (lives>0){
    drawPaddle();

    //Pause game if FIRE pressed
    pad = Controller.firePressed();
    if(pad ==1 && oldpad==0 && released){
    oldpad2=1; //Forces pad loop 2 to run once
    pause();
    }
    oldpad=pad;

    drawBall1();

    if(brickCount==60){
    level++;
    newLevel();
    }
    }
    else{
    drawGameOver();
    if (score > 0) {
    tv.select_font(font6x8);
    enterHighScore(2);
    }
    tv.select_font(font4x6);
    drawGameOver();
    initialDraw=false;
    start=false;
    lives=3;
    score=0;
    newLevel();
    }
    tv.delay_frame(1);
    }
    }

    void worms() {
    tv.fill(0);
    drawFrame();
    drawScore();
    drawBall();
    for(int x = 0; x < 50; x++) {
    if(worm[x].active)
    tv.set_pixel(worm[x].x,worm[x].y,1);
    }
    move();
    tv.delay_frame(4);
    }

    void drawBall() {
    if(ballCollected) {
    ballX = random(FRAME_X0+1, FRAME_X1-1);
    ballY = random(FRAME_Y0+1, FRAME_Y1-1);
    ballCollected = false;
    }
    tv.set_pixel(ballX,ballY,1);
    }

    void drawFrame() {
    tv.draw_line(FRAME_X0, FRAME_Y0, FRAME_X1, FRAME_Y0, 1);
    tv.draw_line(FRAME_X0, FRAME_Y1, FRAME_X1, FRAME_Y1, 1);
    tv.draw_line(FRAME_X0, FRAME_Y0, FRAME_X0, FRAME_Y1, 1);
    tv.draw_line(FRAME_X1, FRAME_Y0, FRAME_X1, FRAME_Y1, 1);
    }

    void move() {
    if (Controller.upPressed()) {
    if(movingDirection != DOWN) {
    movingDirection = UP;
    }
    }
    else if(Controller.downPressed()) {
    if(movingDirection != UP) {
    movingDirection = DOWN;
    }
    }
    else if(Controller.leftPressed()) {
    if(movingDirection != RIGHT) {
    movingDirection = LEFT;
    }
    }
    else if(Controller.rightPressed()) {
    if(movingDirection != LEFT) {
    movingDirection = RIGHT;
    }
    }
    switch (movingDirection) {
    case UP:
    if(detectBallHit(worm[0].x, worm[0].y-1)) {
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].y = worm[0].y-1 ;
    }
    break;
    case DOWN:
    if(detectBallHit(worm[0].x, worm[0].y+1)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].y = worm[0].y+1 ;
    }
    break;
    case LEFT:
    if(detectBallHit(worm[0].x-1, worm[0].y)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].x = worm[0].x-1 ;
    }
    break;
    case RIGHT:
    if(detectBallHit(worm[0].x+1, worm[0].y)){
    assignBallCoordinatesToFirstSegment();
    }
    else {
    shiftSegments();
    worm[0].x = worm[0].x+1 ;
    }
    break;
    }
    if(worm[0].x > FRAME_X1-1 || worm[0].x < FRAME_X0+1 || worm[0].y > FRAME_Y1-1 || worm[0].y < FRAME_Y0+1 || checkForTailBite()) {
    gameOver();
    initWorms();
    return;
    }
    }

    boolean checkForTailBite() {
    for(int x = 1; x < 50; x++) {
    if(worm[0].x == worm[x].x && worm[0].y == worm[x].y) {
    return true;
    }
    }
    return false;
    }

    void shiftSegments() {
    for(int x = 49; x > 0; x--) {
    if(worm[x].active) {
    worm[x].x = worm[x-1].x;
    worm[x].y = worm[x-1].y;
    }
    }
    }

    void assignBallCoordinatesToFirstSegment() {
    worm[0].x = ballX;
    worm[0].y = ballY;
    }

    boolean detectBallHit(byte sx, byte sy) {
    if(sx == ballX && sy == ballY) {
    for(int x = 49; x > -1; x--) {
    if(worm[x].active) {
    worm[x+1].active = true;
    worm[x+1].x = worm[x].x;
    worm[x+1].y = worm[x].y;
    }
    }
    ballCollected = true;
    currentScore += 1;
    updateScore();
    playTone(1046, 10);
    tv.delay(1);
    playTone(1318, 10);
    tv.delay(1);
    playTone(1568, 10);
    tv.delay(1);
    playTone(2093, 10);
    return true;
    }
    else {
    return false;
    }
    }

    void drawScore() {
    tv.print(FRAME_X0, 0, scoreString);
    }

    void updateScore() {
    strcpy_P(scoreString, (char *)pgm_read_word(&(strings[3])));
    sprintf(s, "%d", currentScore);
    strcat(scoreString, s);
    }

    void gameOver() {
    tv.delay(1000);
    tv.fill(0);
    strcpy_P(s, (char *)pgm_read_word(&(strings[1])));
    tv.print(44, 40, s);
    strcpy_P(s, (char *)pgm_read_word(&(strings[2])));
    tv.print(72, 40, s);
    tv.delay(3000);
    }

    boolean pollFireButton(int n) {
    for(int i=0;i tv.delay_frame(1);
    if (Controller.firePressed()) {
    return true;
    }
    }
    return false;
    }

    void playTone(unsigned int frequency, unsigned long duration_ms) {
    // Default is to play tone with highest priority.
    playTone(frequency, duration_ms, 9);
    }

    void playTone(unsigned int frequency, unsigned long duration_ms, byte priority) {
    // priority is value 0-9, 9 being highest priority
    if (TCCR2B > 0) {
    // If a tone is currently playing, check priority
    if (priority < currentTonePriority) {
    return;
    }
    }
    currentTonePriority = priority;
    tv.tone(frequency, duration_ms);
    }

    void movePaddle()
    {
    //Move right
    if(xPaddle < width-12)
    {
    if(Controller.rightPressed())
    {
    xPaddle++;
    }
    }

    //Move left
    if(xPaddle > 0)
    {
    if(Controller.leftPressed())
    {
    xPaddle--;
    }
    }
    }

    void moveBall()
    {
    if(released)
    {
    //Move ball
    xb=xb + dx;
    yb=yb + dy;

    //Set bounds
    leftBall = xb;
    rightBall = xb+2;
    topBall = yb;
    bottomBall = yb+2;

    //Bounce off top edge
    if (yb<=0)
    {
    yb=2;
    dy=-dy;
    tv.tone(523, 20);
    }

    //Lose a life if bottom edge hit
    if (yb>=89)
    {
    tv.draw_rect(xPaddle,87,11,1,0);
    xPaddle = 54;
    yb=84;
    released = false;
    lives--;
    drawLives();
    tv.tone(175, 20);
    if (random(0, 2) == 0) {
    dx = 1;
    }
    else {
    dx = -1;
    }
    }

    //Bounce off left side
    if (xb<=0)
    {
    xb=2;
    dx=-dx;
    tv.tone(523, 20);
    }

    //Bounce off right side
    if (xb>=width-2)
    {
    xb=width-4;
    dx=-dx;
    tv.tone(523, 20);
    }
    //Bounce off paddle
    if (xb+1>=xPaddle && xb<=xPaddle+12 && yb+2>=87 && yb<=92){
    dy=-dy;
    dx=((xb-(xPaddle+6))/3); //Applies spin on the ball
    tv.tone(200, 20);
    }

    //Bounce off Bricks
    for (byte row = 0; row < 5; row++) {
    for (byte column = 0; column < 12; column++) {
    if (!isHit[row][column]){

    //Sets Brick bounds
    leftBrick = 10*column;
    rightBrick = 10*column+10;
    topBrick = 6*row+1;
    bottomBrick = 6*row+7;

    //If A collison has occured
    if (topBall <= bottomBrick && bottomBall>=topBrick && leftBall<=rightBrick && rightBall >=leftBrick){
    Score();
    brickCount++;
    isHit[row][column] = true;
    tv.draw_rect(10*column ,2+6*row,8,4,0);

    //Vertical collision
    if (bottomBall>bottomBrick || topBall //Only bounce once each ball move
    if(!bounced){
    dy=-dy;
    yb+=dy;
    bounced=true;
    tv.tone(261, 20);
    }
    }

    //Hoizontal collision
    if (leftBallrightBrick){

    //Only bounce once brick each ball move
    if(!bounced){
    dx=-dx;
    xb+=dx;
    bounced=true;
    tv.tone(261, 20);
    }
    }
    }
    }
    }
    }
    //Reset Bounce
    bounced=false;
    }
    else{
    //Ball follows paddle
    xb=xPaddle+5;

    //Release ball if FIRE pressed
    pad3 = Controller.firePressed();
    if(pad3 ==1 && oldpad3==0){
    released=true;

    //Apply random direction to ball on release
    if (random(0, 2) == 0) {
    dx = 1;
    }
    else {
    dx = -1;
    }
    //Makes sure the ball heads upwards
    dy = -1;
    }
    oldpad3=pad3;
    }
    }

    void drawBall1()
    {
    tv.set_pixel(xb,yb,0);
    tv.set_pixel(xb+1,yb,0);
    tv.set_pixel(xb,yb+1,0);
    tv.set_pixel(xb+1,yb+1,0);

    moveBall();

    tv.set_pixel(xb,yb,1);
    tv.set_pixel(xb+1,yb,1);
    tv.set_pixel(xb,yb+1,1);
    tv.set_pixel(xb+1,yb+1,1);
    }

    void drawPaddle()
    {
    tv.draw_rect(xPaddle,87,11,1,0);
    movePaddle();
    tv.draw_rect(xPaddle,87,11,1,1);
    }

    void drawLives()
    {
    sprintf(text, "LIVES:%u", lives);
    tv.print(0, 90, text);
    }

    void drawGameOver()
    {
    tv.set_pixel(xb,yb,0);
    tv.set_pixel(xb+1,yb,0);
    tv.set_pixel(xb,yb+1,0);
    tv.set_pixel(xb+1,yb+1,0);
    tv.print(52, 42, "Game");
    tv.print(52, 54, "Over");
    delay(4000);
    }

    void pause()
    {
    paused = true;
    //Draw pause to the screen
    tv.print(52, 45, "PAUSE");
    while(paused){
    delay(15);
    //Unpause if FIRE is pressed
    pad2 = Controller.firePressed();
    if(pad2 ==1 && oldpad2==0 && released){
    tv.print(52, 45, " ");
    paused=false;
    }
    oldpad2=pad2;
    }
    }

    void Score()
    {
    score += (level*10);
    sprintf(text, "SCORE:%u", score);
    tv.print(80, 90, text);
    }

    void newLevel(){
    //Undraw paddle
    tv.draw_rect(xPaddle,87,11,1,0);

    //Undraw ball
    tv.set_pixel(xb,yb,0);
    tv.set_pixel(xb+1,yb,0);
    tv.set_pixel(xb,yb+1,0);
    tv.set_pixel(xb+1,yb+1,0);

    //Alter various variables to reset the game
    xPaddle = 54;
    yb=84;
    brickCount=0;
    released=false;

    //Draws new bricks and resets their values
    for (byte row = 0; row < 5; row++) {
    for (byte column = 0; column < 12; column++) {
    isHit[row][column] = false;
    tv.draw_rect(10*column ,2+6*row,8,4,1);
    }
    }

    //Draws the initial lives
    drawLives();

    //Draws the initial score
    sprintf(text, "SCORE:%u", score);
    tv.print(80, 90, text);
    }

    //Function by nootropic design to display highscores
    boolean displayHighScores(byte file) {
    byte y = 10;
    byte x = 24;
    // Each block of EEPROM has 10 high scores, and each high score entry
    // is 5 bytes long: 3 bytes for initials and two bytes for score.
    int address = file*10*5;
    byte hi, lo;
    tv.fill(0);
    tv.select_font(font6x8);
    tv.print(32, 0, "HIGH SCORES");
    for(int i=0;i<10;i++) {
    sprintf(text, "%2d", i+1);
    tv.print(x, y+(i*8), text);

    hi = EEPROM.read(address + (5*i));
    lo = EEPROM.read(address + (5*i) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    score = 0;
    }
    else {
    score = (hi << 8) | lo;
    }
    initials[0] = (char)EEPROM.read(address + (5*i) + 2);
    initials[1] = (char)EEPROM.read(address + (5*i) + 3);
    initials[2] = (char)EEPROM.read(address + (5*i) + 4);

    if (score > 0) {
    sprintf(text, "%c%c%c %u", initials[0], initials[1], initials[2], score);
    tv.print(x+24, y+(i*8), text);
    }
    }
    if (pollFireButton(300)) {
    return true;
    }
    return false;
    }

    boolean titleScreen() {
    //Clears the screen
    tv.fill(0);

    //Draws the main title
    tv.bitmap(0, 0, title);
    if (pollFireButton(25)) {
    return true;
    }

    //Flash "Press FIRE" 5 times
    for(byte i=0;i<5;i++){
    //Draws "Press FIRE"
    tv.bitmap(31, 53, fire);
    if (pollFireButton(50)) {
    return true;
    }
    //Removes "Press FIRE"
    tv.draw_rect(31,53,57,8,0,0);
    if (pollFireButton(25)) {
    return true;
    }
    }
    return false;
    }

    //Function by nootropic design to add high scores
    void enterInitials() {
    char index = 0;

    tv.fill(0);
    tv.print(16, 0, "HIGH SCORE");
    sprintf(text, "%u", score);
    tv.print(88, 0, text);
    initials[0] = ' ';
    initials[1] = ' ';
    initials[2] = ' ';

    while (true) {
    tv.print_char(56, 20, initials[0]);
    tv.print_char(64, 20, initials[1]);
    tv.print_char(72, 20, initials[2]);
    for(byte i=0;i<3;i++) {
    tv.draw_line(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1);
    }
    tv.draw_line(56, 28, 88, 28, 0);
    tv.draw_line(56 + (index*8), 28, 56 + (index*8) + 6, 28, 1);
    tv.delay(150);
    if (Controller.leftPressed()) {
    index--;
    if (index < 0) {
    index = 0;
    } else {
    tv.tone(1046, 20);
    }
    }
    if (Controller.rightPressed()) {
    index++;
    if (index > 2) {
    index = 2;
    } else {
    tv.tone(1046, 20);
    }
    }
    if (Controller.upPressed()) {
    initials[index]++;
    tv.tone(523, 20);
    // A-Z 0-9 :-? !-/ ' '
    if (initials[index] == '0') {
    initials[index] = ' ';
    }
    if (initials[index] == '!') {
    initials[index] = 'A';
    }
    if (initials[index] == '[') {
    initials[index] = '0';
    }
    if (initials[index] == '@') {
    initials[index] = '!';
    }
    }
    if (Controller.downPressed()) {
    initials[index]--;
    tv.tone(523, 20);
    if (initials[index] == ' ') {
    initials[index] = '?';
    }
    if (initials[index] == '/') {
    initials[index] = 'Z';
    }
    if (initials[index] == 31) {
    initials[index] = '/';
    }
    if (initials[index] == '@') {
    initials[index] = ' ';
    }
    }
    if (Controller.firePressed()) {
    if (index < 2) {
    index++;
    tv.tone(1046, 20);
    } else {
    tv.tone(1046, 20);
    return;
    }
    }
    }

    }

    void enterHighScore(byte file) {
    // Each block of EEPROM has 10 high scores, and each high score entry
    // is 5 bytes long: 3 bytes for initials and two bytes for score.
    int address = file*10*5;
    byte hi, lo;
    char tmpInitials[3];
    unsigned int tmpScore = 0;

    // High score processing
    for(byte i=0;i<10;i++) {
    hi = EEPROM.read(address + (5*i));
    lo = EEPROM.read(address + (5*i) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    // The values are uninitialized, so treat this entry
    // as a score of 0.
    tmpScore = 0;
    } else {
    tmpScore = (hi << 8) | lo;
    }
    if (score > tmpScore) {
    enterInitials();
    for(byte j=i;j<10;j++) {
    hi = EEPROM.read(address + (5*j));
    lo = EEPROM.read(address + (5*j) + 1);
    if ((hi == 0xFF) && (lo == 0xFF)) {
    tmpScore = 0;
    } else {
    tmpScore = (hi << 8) | lo;
    }
    tmpInitials[0] = (char)EEPROM.read(address + (5*j) + 2);
    tmpInitials[1] = (char)EEPROM.read(address + (5*j) + 3);
    tmpInitials[2] = (char)EEPROM.read(address + (5*j) + 4);

    // tmpScore and tmpInitials now hold what we want to write in the next slot.

    // write score and initials to current slot
    EEPROM.write(address + (5*j), ((score >> 8) & 0xFF));
    EEPROM.write(address + (5*j) + 1, (score & 0xFF));
    EEPROM.write(address + (5*j) + 2, initials[0]);
    EEPROM.write(address + (5*j) + 3, initials[1]);
    EEPROM.write(address + (5*j) + 4, initials[2]);

    score = tmpScore;
    initials[0] = tmpInitials[0];
    initials[1] = tmpInitials[1];
    initials[2] = tmpInitials[2];
    }
    score = 0;
    initials[0] = ' ';
    initials[1] = ' ';
    initials[2] = ' ';
    return;
    }
    }
    }
    in reply to: Help a Newbie? #1135
    moe
    Member

    First of all thanks for the quick replies!

    Thanks for the example File, this is nearly exactly what I looked for but could you please add this “choice-menu” like the hackvision firmware? Thanks.

    This is my first problem (strange menu):


    #include
    #include
    #include
    #include
    #include
    #define TV_W 136
    #define TV_H 98
    #define FRAME_X0 8
    #define FRAME_X1 128
    #define FRAME_Y0 9
    #define FRAME_Y1 89
    #define LEFT 3
    #define RIGHT 2
    #define UP 4
    #define DOWN 5
    #define FIRE 10

    struct Segment
    {
    boolean active;
    byte x;
    byte y;
    };


    prog_char s0[] PROGMEM = "DRAW";

    PROGMEM const char *strings[] = {s0};
    char s[16]; // general string buffer
    char scoreString[11];
    byte currentTonePriority = 0;

    void (*game)();
    TVout tv;
    int count = 3;

    void setup() {
    // If pin 12 is pulled LOW, then the PAL jumper is shorted.
    pinMode(12, INPUT);
    digitalWrite(12, HIGH);

    if (digitalRead(12) == LOW) {
    tv.begin(_PAL, TV_W, TV_H);
    }
    else {
    tv.begin(_NTSC, TV_W, TV_H);
    }

    tv.select_font(font6x8);
    randomSeed(analogRead(0));

    byte m[1] = {0};
    byte choice = menu(1, m);
    if (choice == 0) {
    tv.delay(10);
    draw();
    }
    }

    byte menu(byte nChoices, byte *choices) {
    char choice = 0;
    tv.fill(0);
    byte x = 24;
    byte y;

    while (true) {
    for(byte i=0;i strcpy_P(s, (char *)pgm_read_word(&(strings[choices])));
    tv.print(32, 30+(i*8), s);
    }
    for(byte i=0;i y = 30+(i*8);
    if (i == choice) {
    // draw arrow next to selected game
    tv.set_pixel(x+4, y, 1);
    tv.set_pixel(x+5, y+1, 1);
    tv.draw_line(x, y+2, x+6, y+2, 1);
    tv.set_pixel(x+5, y+3, 1);
    tv.set_pixel(x+4, y+4, 1);
    }
    else {
    for(byte j=0;j<8;j++) {
    tv.draw_line(x, y+j, x+7, y+j, 0);
    }
    }
    }
    // get input
    if (pollFireButton(10)) {
    playTone(1046, 20);
    return choice;
    }
    if (Controller.upPressed()) {
    choice--;
    if (choice == -1) {
    choice = 0;
    }
    else {
    playTone(1046, 20);
    }
    }
    if (Controller.downPressed()) {
    choice++;
    if (choice == nChoices) {
    choice = nChoices-1;
    }
    else {
    playTone(1046, 20);
    }
    }
    }
    }

    void draw() {
    while (Controller.firePressed()) {
    tv.clear_screen();
    tv.draw_line(0,0,99,99,1);
    tv.delay(3600);
    tv.clear_screen();
    tv.delay(200);
    tv.print(10,10,"TEST");
    tv.delay(3600);
    tv.draw_circle(tv.hres()/2,tv.vres()/2,tv.vres()/3,WHITE);
    tv.delay(3600);
    tv.clear_screen();
    tv.print(count);
    count = count-1;
    }
    setup();
    }



    boolean pollFireButton(int n) {
    for(int i=0;i tv.delay_frame(1);
    if (Controller.firePressed()) {
    return true;
    }
    }
    return false;
    }

    void playTone(unsigned int frequency, unsigned long duration_ms) {
    // Default is to play tone with highest priority.
    playTone(frequency, duration_ms, 9);
    }

    void playTone(unsigned int frequency, unsigned long duration_ms, byte priority) {
    // priority is value 0-9, 9 being highest priority
    if (TCCR2B > 0) {
    // If a tone is currently playing, check priority
    if (priority < currentTonePriority) {
    return;
    }
    }
    currentTonePriority = priority;
    tv.tone(frequency, duration_ms);
    }

    void loop() {}

    Please don’t think what a noob and such things… I know programming languages and I understand much but C or C++ are a bit difficult to learn and really voluminous… So you don’t have to explain it like you would to a total newbie.

    And here comes my second (I tried to combine Worms & Breakout) -> Copy&Paste doesn’t work great… I tried it on my hackvision but it only gives an annoying beep all the time… No menu, no games…. So if anyone could help me fixing this? I know maybe the sketch size is too big but if you delete all the same parts and put these two together they should probably work… Am I right? I would really like this to have on my hackvision… It should look like the original firmware of HV. Thanks and here’s the code:

Viewing 8 posts - 1 through 8 (of 8 total)