Advertisement
bobbinz

Arduino Pong

Oct 7th, 2011
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 12.57 KB | None | 0 0
  1. //Arduino Pong
  2. //Alastair Parker and Adam Robbins
  3. //2010
  4.  
  5. // Video out voltage levels
  6. #define _SYNC 0x00
  7. #define _BLACK  0x01
  8. #define _GRAY  0x02
  9. #define _WHITE  0x03
  10.  
  11. // dimensions of the screen
  12. #define WIDTH 38
  13. #define HEIGHT 14
  14.  
  15. //number of lines to display
  16. #define DISPLAY_LINES 240
  17.  
  18. // update speed for the main loop of the game
  19. #define UPDATE_INTERVAL 1
  20.  
  21. // positions of the player paddles
  22. #define PLAYER_RIGHT_X 35
  23. #define PLAYER_LEFT_X 2
  24.  
  25. // maximum velocity of the ball
  26. #define MAX_VEL 12
  27.  
  28. // locations of the top and bottom virtual bars
  29. #define SCORE_BAR 3
  30. #define BASE_BAR 13
  31.  
  32. // time to wait while paused
  33. #define DONE_WAITING 30
  34. #define SCORE_WAITING 30
  35.  
  36. // max player life
  37. #define MAX_LIFE 6
  38.  
  39. //positions of player life bars
  40. #define PLAYER_LEFT_LIFE 2
  41. #define PLAYER_RIGHT_LIFE 23
  42.  
  43. // input pins for the player pots
  44. #define PLAYER_LEFT_PIN 1
  45. // currently the same pin
  46. #define PLAYER_RIGHT_PIN 2
  47.  
  48. //video pins
  49. #define DATA_PIN 9
  50. #define SYNC_PIN 8
  51.  
  52. // the video frameBuffer
  53. byte frameBuffer[WIDTH][HEIGHT];
  54.  
  55. // loop indices
  56. byte index, index2;
  57.  
  58. // pal video line loop
  59. byte line;
  60. // current drawing line in framebuffer
  61. byte newLine;
  62.  
  63. // flag used in wait loop to indicate that player just scored
  64. boolean justScored=false;
  65.  
  66. // positions for the left paddle
  67. byte playerLeft;
  68. byte playerLeftOld=-1;
  69. // life for the left player
  70. byte playerLeftLife = MAX_LIFE;
  71.  
  72. // positions of the right paddle
  73. byte playerRight;
  74. byte playerRightOld=-1;
  75. // life for the right player
  76. byte playerRightLife = MAX_LIFE;
  77.  
  78. // positions and velocity of the ball
  79. int ballXVel = -1;
  80. int ballYVel = -5;
  81. byte ballXPos = 14;
  82. byte ballYPos = 7;
  83.  
  84. // loop counters to control the velocity of the ball
  85. byte ballXLoop =MAX_VEL;
  86. byte ballYLoop =MAX_VEL;
  87.  
  88. // loop counter to for the main loop delay
  89. int waitingCount = 0;
  90.  
  91. // start postion of the loading bar
  92. byte loadingBar = 2;
  93.  
  94. // if the left player should be updated or the right
  95. boolean playerLeftTurn=true;
  96.  
  97. // if we should be waiting for something to happen
  98. boolean waiting=true;
  99. // if displaying the title
  100. boolean showingTitle = true;
  101.  
  102. // value of the counter controlling the freq of updates
  103. byte updateCounter=0;
  104.  
  105. // init the variables
  106. void initGame()
  107. {
  108.   playerLeftOld=-1;
  109.   playerLeftLife = MAX_LIFE;
  110.   playerRightOld=-1;
  111.   playerRightLife = MAX_LIFE;
  112.   ballXVel = -1;
  113.   ballYVel = -5;
  114.   ballXPos = 14;
  115.   ballYPos = 7;
  116.   ballXLoop =MAX_VEL;
  117.   ballYLoop =MAX_VEL;
  118.   waitingCount = 0;
  119.   loadingBar = 2;
  120.   playerLeftTurn=true;
  121.   waiting=true;
  122.   showingTitle = true;
  123.   justScored=false;
  124.   updateCounter=0;
  125. }
  126.  
  127. // draw a pixel to the buffer
  128. void setPixel(byte x,byte y)
  129. {
  130.   frameBuffer[x][y]= _WHITE;
  131. }
  132.  
  133. void grayPixel(byte x, byte y)
  134. {
  135.    frameBuffer[x][y]= _GRAY;
  136. }
  137.  
  138. // draw a black pixel to the buffer
  139. void clearPixel(byte x,byte y)
  140. {
  141.   frameBuffer[x][y]= _BLACK;
  142. }
  143.  
  144. // draw a paddle
  145. void drawPaddle(byte x,byte y,byte col)
  146. {
  147.   cli();
  148.   frameBuffer[x][y]= col;
  149.   frameBuffer[x][y+1]= col;
  150. }
  151.  
  152.  
  153. //draw the title message
  154. void drawArduinoPong()
  155. {
  156.   //arduino
  157.   setPixel(7,3);
  158.   setPixel(8,3);
  159.   setPixel(15,3);
  160.   setPixel(21,3);
  161.   setPixel(6,4);
  162.   setPixel(8,4);
  163.   setPixel(14,4);
  164.   setPixel(15,4);
  165.   setPixel(28,4);
  166.   setPixel(6,5);
  167.   setPixel(7,5);
  168.   setPixel(8,5);
  169.   setPixel(10,5);
  170.   setPixel(11,5);
  171.   setPixel(13,5);
  172.   setPixel(15,5);
  173.   setPixel(17,5);
  174.   setPixel(19,5);
  175.   setPixel(21,5);
  176.   setPixel(23,5);
  177.   setPixel(24,5);
  178.   setPixel(27,5);
  179.   setPixel(29,5);
  180.   setPixel(6,6);
  181.   setPixel(8,6);
  182.   setPixel(10,6);
  183.   setPixel(14,6);
  184.   setPixel(15,6);
  185.   setPixel(18,6);
  186.   setPixel(19,6);
  187.   setPixel(21,6);
  188.   setPixel(23,6);
  189.   setPixel(25,6);
  190.   setPixel(28,6);
  191.  
  192.   //pong
  193.   setPixel(10,8);
  194.   setPixel(11,8);
  195.   setPixel(15,8);
  196.   setPixel(16,8);
  197.   setPixel(19,8);
  198.   setPixel(22,8);
  199.   setPixel(24,8);
  200.   setPixel(25,8);
  201.   setPixel(26,8);
  202.   setPixel(10,9);
  203.   setPixel(12,9);
  204.   setPixel(14,9);
  205.   setPixel(17,9);
  206.   setPixel(19,9);
  207.   setPixel(20,9);
  208.   setPixel(22,9);
  209.   setPixel(24,9);
  210.   setPixel(10,10);
  211.   setPixel(11,10);
  212.   setPixel(14,10);
  213.   setPixel(17,10);
  214.   setPixel(19,10);
  215.   setPixel(21,10);
  216.   setPixel(22,10);
  217.   setPixel(24,10);
  218.   setPixel(26,10);
  219.   setPixel(10,11);
  220.   setPixel(15,11);
  221.   setPixel(16,11);
  222.   setPixel(19,11);
  223.   setPixel(22,11);
  224.   setPixel(24,11);
  225.   setPixel(25,11);
  226.   setPixel(26,11);
  227.   }
  228.  
  229. // do the main game logic regarding the ball and collisions
  230. void updateBall(boolean xEvent)
  231. {
  232.    
  233.   // if checking the x coords of the ball
  234.   if(xEvent)
  235.   {
  236.     /*
  237.     TODO
  238.  
  239.     have the yvel start 1t 1
  240.  
  241.     */
  242.  
  243.      //check for collision with left player
  244.      if(ballXPos <PLAYER_LEFT_X+2 & (playerLeft == ballYPos or playerLeft+1 == ballYPos))
  245.      {
  246.        
  247.      ballXVel = -1 * ballXVel;
  248.      ballXPos=PLAYER_LEFT_X+1;
  249.      }
  250.      //check for collision with right player
  251.      if(ballXPos > PLAYER_RIGHT_X-2  & (playerRight == ballYPos or playerRight+1 == ballYPos))
  252.      {
  253.        
  254.       ballXVel = -1 * ballXVel;
  255.      ballXPos=PLAYER_RIGHT_X-1;
  256.      }
  257.  
  258.      //move the ball in the x direction
  259.      if(ballXVel < 1)
  260.      {
  261.        
  262.      ballXPos--;
  263.      }
  264.      else
  265.      {
  266.        
  267.        ballXPos++;
  268.      }
  269.    }
  270.  
  271.   //if checking the y coords
  272.   if(!xEvent)
  273.   {
  274.      //check for top of screen hit
  275.      if( ballYPos <= SCORE_BAR )
  276.      {
  277.        
  278.      ballYVel = -1 * ballYVel;
  279.      ballYPos = SCORE_BAR;
  280.      }
  281.      //check for bottom of screen hit
  282.      if( ballYPos>BASE_BAR )
  283.      {
  284.        
  285.      ballYVel = -1 * ballYVel;
  286.      ballYPos = BASE_BAR+1;
  287.      }
  288.  
  289.      // move the ball in the y direction
  290.      if(ballYVel < 1)
  291.      { 
  292.        
  293.       ballYPos--;
  294.      }
  295.      else
  296.      {
  297.        
  298.      ballYPos++;
  299.      }
  300.   }
  301.  
  302.   //always check for scoring of points
  303.  
  304.   //right player scores
  305.   if(ballXPos==PLAYER_LEFT_X)//0
  306.   {
  307.     //reset the position of the ball
  308.     ballXPos = PLAYER_RIGHT_X - 5;
  309.     ballYPos=7;
  310.  
  311.     // change the other players life
  312.     clearPixel(PLAYER_LEFT_LIFE+2*playerLeftLife-2,SCORE_BAR-1);
  313.     playerLeftLife--;
  314.  
  315.     // indicate that someone scored so the wait doesn't start a new game
  316.     justScored=true;
  317.     // indicate that we should wait next loop
  318.     waiting=true;
  319.  
  320.     // check if game is over
  321.     if(playerLeftLife==0)
  322.     justScored=false;
  323.    }
  324.  
  325.  //left player scores
  326.  if(ballXPos==PLAYER_RIGHT_X)//38
  327.  {
  328.     //reset position of ball
  329.     ballXPos = PLAYER_LEFT_X + 5;
  330.     ballYPos=7;
  331.  
  332.     //update other players score
  333.     clearPixel(PLAYER_RIGHT_LIFE+2*(MAX_LIFE-playerRightLife)+2,SCORE_BAR-1);
  334.     playerRightLife--;
  335.  
  336.     // indicate that someone scored so the wain doesn't start a new game
  337.     justScored=true;
  338.     // indicate that we should wait next loop
  339.     waiting=true;
  340.  
  341.     // check for game over
  342.     if(playerRightLife==0)
  343.     justScored=false;
  344.  }
  345.  
  346. }
  347.  
  348. // draw the player life bars
  349. void initScreen()
  350. {
  351.   for(index=1;index<=MAX_LIFE;++index)
  352.   {
  353.     grayPixel(index*2,SCORE_BAR-1);
  354.     grayPixel(index*2+PLAYER_RIGHT_LIFE,SCORE_BAR-1);
  355.   }
  356. }
  357.  
  358.  
  359. // draw the ball
  360. void drawBall(byte col)
  361. {
  362.  frameBuffer[ballXPos][ballYPos]=col;
  363.  cli();
  364.  
  365. }
  366.  
  367. // clear the screen
  368. void clearScreen()
  369. {
  370.     for (index = 0; index < WIDTH; index++)
  371.     for (index2=0;index2<=HEIGHT;++index2)
  372.       {
  373.        frameBuffer[index][index2] = _BLACK;
  374.       }
  375. }
  376.  
  377. // the setup routine
  378. void setup()
  379. {
  380.   cli();
  381.   pinMode (SYNC_PIN, OUTPUT);
  382.   pinMode (DATA_PIN, OUTPUT);
  383.   digitalWrite (SYNC_PIN, HIGH);
  384.   digitalWrite (DATA_PIN, HIGH);
  385.   clearScreen();
  386.   drawArduinoPong();
  387. }
  388.  
  389. void loop()
  390. {
  391.    
  392.   // iterate over the lines on the tv
  393.   for ( line =0;line< DISPLAY_LINES;++line)
  394.     {
  395.  
  396.     // HSync
  397.     // front porch (1.5 us)
  398.     PORTB = _BLACK;
  399.     delayMicroseconds(1.5);
  400.     //sync (4.7 us)
  401.     PORTB = _SYNC;
  402.     delayMicroseconds(4.7);
  403.     // breezeway (.6us) + burst (2.5us) + colour back borch (1.6 us)
  404.     PORTB = _BLACK;
  405.     delayMicroseconds(0.6+2.5+1.6);
  406.  
  407.  
  408.     //calculate which line to draw to
  409.     newLine = line >>4;
  410.     delayMicroseconds(1);
  411.  
  412.     //display the array for this line
  413.     // a loop would have been smaller, but it messes the timing up
  414.      
  415.         PORTB = frameBuffer[0][newLine];
  416.     delayMicroseconds(1);
  417.     PORTB = frameBuffer[1][newLine];
  418.     delayMicroseconds(1);
  419.     PORTB = frameBuffer[2][newLine];
  420.     delayMicroseconds(1);
  421.     PORTB = frameBuffer[3][newLine];
  422.     delayMicroseconds(1);
  423.     PORTB = frameBuffer[4][newLine];
  424.     delayMicroseconds(1);
  425.     PORTB = frameBuffer[5][newLine];
  426.     delayMicroseconds(1);
  427.     PORTB = frameBuffer[6][newLine];
  428.     delayMicroseconds(1);
  429.     PORTB = frameBuffer[7][newLine];
  430.     delayMicroseconds(1);
  431.     PORTB = frameBuffer[8][newLine];
  432.     delayMicroseconds(1);
  433.     PORTB = frameBuffer[9][newLine];
  434.     delayMicroseconds(1);
  435.     PORTB = frameBuffer[10][newLine];
  436.     delayMicroseconds(1);
  437.     PORTB = frameBuffer[11][newLine];
  438.     delayMicroseconds(1);
  439.     PORTB = frameBuffer[12][newLine];
  440.     delayMicroseconds(1);
  441.     PORTB = frameBuffer[13][newLine];
  442.     delayMicroseconds(1);
  443.     PORTB = frameBuffer[14][newLine];
  444.     delayMicroseconds(1);
  445.     PORTB = frameBuffer[15][newLine];
  446.     delayMicroseconds(1);
  447.     PORTB = frameBuffer[16][newLine];
  448.     delayMicroseconds(1);
  449.     PORTB = frameBuffer[17][newLine];
  450.     delayMicroseconds(1);
  451.     PORTB = frameBuffer[18][newLine];
  452.     delayMicroseconds(1);
  453.     PORTB = frameBuffer[19][newLine];
  454.     delayMicroseconds(1);
  455.     PORTB = frameBuffer[20][newLine];
  456.     delayMicroseconds(1);
  457.     PORTB = frameBuffer[21][newLine];
  458.     delayMicroseconds(1);
  459.     PORTB = frameBuffer[22][newLine];
  460.     delayMicroseconds(1);
  461.  
  462. PORTB = frameBuffer[23][newLine];
  463.     delayMicroseconds(1);
  464.     PORTB = frameBuffer[24][newLine];
  465.     delayMicroseconds(1);
  466.     PORTB = frameBuffer[25][newLine];
  467.     delayMicroseconds(1);
  468.     PORTB = frameBuffer[26][newLine];
  469.     delayMicroseconds(1);
  470.     PORTB = frameBuffer[27][newLine];
  471.     delayMicroseconds(1);
  472.     PORTB = frameBuffer[28][newLine];
  473.     delayMicroseconds(1);
  474.     PORTB = frameBuffer[29][newLine];
  475.     delayMicroseconds(1);
  476.     PORTB = frameBuffer[30][newLine];
  477.     delayMicroseconds(1);
  478.     PORTB = frameBuffer[31][newLine];
  479.     delayMicroseconds(1);
  480.     PORTB = frameBuffer[32][newLine];
  481.     delayMicroseconds(1);
  482.     PORTB = frameBuffer[33][newLine];
  483.     delayMicroseconds(1);
  484.     PORTB = frameBuffer[34][newLine];
  485.     delayMicroseconds(1);
  486.     PORTB = frameBuffer[35][newLine];
  487.     delayMicroseconds(1);
  488.  
  489.  
  490.     // klugdge to correct timings
  491.  
  492.     PORTB = frameBuffer[36][newLine];
  493.     PORTB=PORTB;
  494.     PORTB=PORTB;
  495.     PORTB=PORTB;
  496.     delayMicroseconds(3);
  497.      }
  498.  
  499.  
  500.   //vsync
  501.   PORTB = _SYNC;
  502.  
  503.  
  504.   // if delaying for some reason
  505.   if(waiting)
  506.   {
  507.      
  508.     // increment the waiting counter
  509.     waitingCount++;
  510.  
  511.     // if waiting is over for a new game
  512.     if(waitingCount==DONE_WAITING & !justScored)
  513.     {
  514.       waitingCount=0;
  515.       // if on title screen
  516.       if(showingTitle)
  517.       {
  518.         // draw the loading bar
  519.         grayPixel(loadingBar,BASE_BAR);
  520.         loadingBar+=2;
  521.  
  522.         // done loading
  523.         if (loadingBar > 37)
  524.         {
  525.         showingTitle=false;
  526.         clearScreen();
  527.         initGame();
  528.         initScreen();
  529.         waiting=false;
  530.         }
  531.       }
  532.     }
  533.  
  534.     // waiting because someone scored
  535.     if(waitingCount==SCORE_WAITING & justScored)
  536.     {
  537.    
  538.        justScored=false;
  539.        waitingCount=0;
  540.        waiting=false;
  541.     }
  542.     // wait for the remainder of the sync period
  543.     delayMicroseconds(305);
  544.   }
  545.   // not waiting
  546.   else
  547.   {
  548.      
  549.     // increment the update delay counter
  550.     updateCounter++;
  551.     if( updateCounter >= UPDATE_INTERVAL)
  552.     {
  553.     //player movement
  554.     if(playerLeftTurn)
  555.     {
  556.            
  557.       drawPaddle(PLAYER_LEFT_X,playerLeftOld,_BLACK);
  558.       playerLeft = analogRead(PLAYER_LEFT_PIN)>>6;
  559.       if(playerLeft<SCORE_BAR)
  560.         playerLeft=SCORE_BAR;
  561.       if(playerLeft>BASE_BAR)
  562.         playerLeft=BASE_BAR;
  563.       drawPaddle(PLAYER_LEFT_X,playerLeft,_WHITE);
  564.       playerLeftOld=playerLeft;
  565.       playerLeftTurn=false;
  566. cli();
  567.     }
  568.     else
  569.     {
  570.    
  571.       drawPaddle(PLAYER_RIGHT_X,playerRightOld,_BLACK);
  572.       playerRight = analogRead(PLAYER_RIGHT_PIN)>>6;
  573.       if(playerRight<SCORE_BAR)
  574.         playerRight=SCORE_BAR;
  575.       if(playerRight>BASE_BAR)
  576.         playerRight=BASE_BAR;
  577.       drawPaddle(PLAYER_RIGHT_X,playerRight,_WHITE);
  578.       playerRightOld=playerRight;
  579.       playerLeftTurn=true;
  580. cli();
  581.     }
  582.     // remainder of sync period
  583.  
  584.     delayMicroseconds(10);
  585.     updateCounter=0;
  586.     }
  587.     else
  588.     // remainder of sync period
  589. cli();
  590.     delayMicroseconds(250);
  591.  
  592.     // perform ball x velocity delay
  593.     ballXLoop--;
  594.     if(ballXLoop <= abs(ballXVel) and ballXVel != 0)
  595.     {
  596.    
  597.       //ball movement;
  598.       drawBall(_BLACK);
  599.  
  600.       updateBall(true);
  601.  
  602.       ballXLoop=MAX_VEL;
  603.  
  604.     }
  605.  
  606.     // perform ball y velocity delay
  607.     ballYLoop--;
  608.     if(ballYLoop <= abs(ballYVel) and ballYVel != 0)
  609.     {
  610.    
  611.       //ball movement;
  612.       drawBall(_BLACK);
  613.  
  614.       updateBall(false);
  615. cli();
  616.       ballYLoop=MAX_VEL;
  617.  
  618.     }
  619.     // draw new ball
  620.     drawBall(_GRAY);
  621.  
  622.   }
  623. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement