YFROBOT创客社区

标题: Arduino驱动8*8点阵模块 附原理图及一个打乒乓球的游戏代码 [打印本页]

作者: YFRobot    时间: 2014-2-20 20:35
标题: Arduino驱动8*8点阵模块 附原理图及一个打乒乓球的游戏代码
本帖最后由 AllBlue 于 2020-2-4 09:32 编辑

一位来自葡萄牙的arduino爱好者,在他的BLOG中分享了一个基于Arduino平台的游戏,下面是他的作品:
[attach]809[/attach]
原文地址:http://blog.bsoares.com.br/ardui ... d-matrix-on-arduino
利用常见的8*8点阵作为“游戏机”的显示屏,两个10K的电位器作为双方的“球拍”,控制器采用的是Arduino的Duemilanove兼容板。当顺时针拧电位器时,球拍向左移动;反向则向右移动。
游戏代码:
  1. /**
  2. * Ping Pong with 8x8 Led Dot Matrix on Arduino
  3. *
  4. * @author  Bruno Soares
  5. * @website www.bsoares.com.br
  6. */

  7. #include "TimerOne.h"

  8. #define PIN_LEFT 4
  9. #define PIN_RIGHT 5

  10. unsigned int left = 0;
  11. unsigned int right = 0;
  12. int angle = 0;
  13. int radians;

  14. byte rows[8] = {9, 14, 8, 12, 1, 7, 2, 5};
  15. byte cols[8] = {13, 3, 4, 10, 6, 11, 15, 16};
  16. byte pins[16] = {5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};
  17. byte screen[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  18. volatile byte screenRow = 0;
  19. volatile byte screenCol = 0;

  20. int _angle;
  21. int _px;
  22. int _py;
  23. int _w = 7;
  24. int _h = 7;
  25. int _wall[] = {3, 3};
  26. int _count = 0;
  27. int _speed = 3;
  28. int _countPoints = 0;


  29. void setup() {
  30.   Timer1.initialize(100);
  31.   for (int i = 2; i <= 17; i++)
  32.     pinMode(i, OUTPUT);
  33.   Timer1.attachInterrupt(doubleBuffer);
  34.   
  35.   Serial.begin(9600);
  36.   
  37.   face();
  38.   reset();
  39. }

  40. void doubleBuffer() {
  41.   digitalWrite(translatePin(rows[screenRow]), LOW);
  42.   digitalWrite(translatePin(cols[screenCol]), HIGH);
  43.   
  44.   screenCol++;
  45.   if (screenCol >= 8) {
  46.     screenCol = 0;
  47.     screenRow++;
  48.     if (screenRow >= 8) {
  49.       screenRow = 0;
  50.     }
  51.   }
  52.   
  53.   if((screen[screenRow] >> screenCol) & B1 == B1) {
  54.     digitalWrite(translatePin(rows[screenRow]), HIGH);
  55.     digitalWrite(translatePin(cols[screenCol]), LOW);
  56.   } else {
  57.     digitalWrite(translatePin(rows[screenRow]), LOW);
  58.     digitalWrite(translatePin(cols[screenCol]), HIGH);
  59.   }
  60. }

  61. byte translatePin(byte original) {
  62.   return pins[original - 1];
  63. }

  64. void allOFF() {
  65.   for (int i = 0; i < 8; i++)
  66.     screen[i] = 0;
  67. }

  68. void on(byte row, byte column) {
  69.     screen[column-1] |= (B1 << (row - 1));
  70. }

  71. void off(byte row, byte column) {
  72.     screen[column-1] &= ~(B1 << (row - 1));
  73. }

  74. void calcWall()
  75. {
  76.   left = analogRead(PIN_LEFT);
  77.   right = analogRead(PIN_RIGHT);
  78.   left = constrain(map(left, 223, 800, 0, 6), 0, 6);
  79.   right = constrain(map(right, 223, 800, 6, 0), 0, 6);
  80.   
  81.   clearWall();
  82.   
  83.   on(1, left + 1);
  84.   on(1, left + 2);
  85.   on(8, right + 1);
  86.   on(8, right + 2);
  87.   
  88.   _wall[0] = left;
  89.   _wall[1] = right;
  90.   show();
  91. }

  92. void clearWall()
  93. {
  94.   for (int i = 0; i < 8; i++)
  95.     screen[i] &= B01111110;
  96. }

  97. void clearGame()
  98. {
  99.   for (int i = 0; i < 8; i++)
  100.     screen[i] &= B10000001;
  101. }

  102. void loop() {
  103.   calcWall();
  104.   enterFrameHandler();
  105.   delay(50);
  106. }

  107. void enterFrameHandler()
  108. {
  109.   if (_count++ < _speed)
  110.     return;
  111.   
  112.   _count = 0;
  113.   checkCollision();
  114.   calcAngleIncrement();
  115.   show();
  116. }

  117. void retorted(int angle)
  118. {
  119.   Serial.println(angle);
  120.   _angle = angle;
  121.   
  122.   if (++_countPoints % 5 == 0 && _speed > 1)
  123.     _speed--;
  124. }

  125. void resetAnim()
  126. {
  127.   for (int i = 0; i < 8; i++)
  128.   {
  129.     screen[i] = B11111111;
  130.     delay(25);
  131.   }
  132.   for (int i = 0; i < 8; i++)
  133.   {
  134.     screen[i] = B00000000;
  135.     delay(25);
  136.   }
  137. }

  138. void face()
  139. {
  140.   on(1, 1);
  141.   on(1, 2);
  142.   on(2, 1);
  143.   on(2, 2);
  144.   on(7, 1);
  145.   on(7, 2);
  146.   on(8, 1);
  147.   on(8, 2);
  148.   on(1, 1);
  149.   on(1, 2);
  150.   on(4, 4);
  151.   on(4, 5);
  152.   on(5, 4);
  153.   on(5, 5);
  154.   on(2, 7);
  155.   on(7, 7);
  156.   on(3, 8);
  157.   on(4, 8);
  158.   on(5, 8);
  159.   on(6, 8);
  160.   delay(5000);
  161. }

  162. void reset()
  163. {
  164.   resetAnim();
  165.   
  166.   _px = random(3, 5);
  167.   _py = random(3, 5);
  168.   _angle = random(0, 2) == 0 ? 0 : 180;
  169.   _speed = 5;
  170.   _countPoints = 0;
  171.   
  172.   show();
  173.   delay(500);
  174. }

  175. void show()
  176. {
  177.   clearGame();
  178.   on(_px + 1, _py + 1);
  179. }

  180. void checkCollision()
  181. {
  182.   if (_px == _w - 1)
  183.   {
  184.     if (_angle == 315 || _angle == 0 || _angle == 45)
  185.     {
  186.       if (_py == _wall[1] || _py == _wall[1] + 1)
  187.       {
  188.         if (_angle == 0 && _py == _wall[1])
  189.           retorted(225);
  190.         else if (_angle == 0 && _py == _wall[1] + 1)
  191.           retorted(135);
  192.         else if (_angle == 45 && _py == _wall[1])
  193.           retorted(135);
  194.         else if (_angle == 45 && _py == _wall[1] + 1)
  195.           retorted(180);
  196.         else if (_angle == 315 && _py == _wall[1])
  197.           retorted(180);
  198.         else if (_angle == 315 && _py == _wall[1] + 1)
  199.           retorted(225);
  200.       }
  201.     }
  202.   }
  203.   else if (_px == 1)
  204.   {
  205.     if (_angle == 225 || _angle == 180 || _angle == 135)
  206.     {
  207.       if (_py == _wall[0] || _py == _wall[0] + 1)
  208.       {
  209.         if (_angle == 180 && _py == _wall[0])
  210.           retorted(315);
  211.         else if (_angle == 180 && _py == _wall[0] + 1)
  212.           retorted(45);
  213.         else if (_angle == 135 && _py == _wall[0])
  214.           retorted(45);
  215.         else if (_angle == 135 && _py == _wall[0] + 1)
  216.           retorted(0);
  217.         else if (_angle == 225 && _py == _wall[0])
  218.           retorted(0);
  219.         else if (_angle == 225 && _py == _wall[0] + 1)
  220.           retorted(315);
  221.       }
  222.     }
  223.   }
  224.   
  225.   if (_px == _w)
  226.   {
  227.     reset();
  228.   }
  229.   else if (_px == 0)
  230.   {
  231.     reset();
  232.   }
  233.   else if (_py == _h)
  234.   {
  235.     if (_angle == 45)
  236.       _angle = 315;
  237.     else if (_angle == 135)
  238.       _angle = 225;
  239.   }
  240.   else if (_py == 0)
  241.   {
  242.     if (_angle == 225)
  243.       _angle = 135;
  244.     else if (_angle == 315)
  245.       _angle = 45;
  246.   }
  247. }

  248. void calcAngleIncrement()
  249. {
  250.   if (_angle == 0 || _angle == 360)
  251.   {
  252.     _px += 1;
  253.   }
  254.   else if (_angle == 45)
  255.   {
  256.     _px += 1;
  257.     _py += 1;
  258.   }
  259.   else if (_angle == 135)
  260.   {
  261.     _px -= 1;
  262.     _py += 1;
  263.   }
  264.   else if (_angle == 180)
  265.   {
  266.     _px -= 1;
  267.   }
  268.   else if (_angle == 225)
  269.   {
  270.     _px -= 1;
  271.     _py -= 1;
  272.   }
  273.   else if (_angle == 315)
  274.   {
  275.     _px += 1;
  276.     _py -= 1;
  277.   }
  278. }
复制代码
对应引脚接线:(下图左侧红框内表示arduino接口,14为A0,15为A1 ...依次类推,“球拍”接A4及A5)
[attach]810[/attach]

因为点阵显示单元就占用了arduino 主板16个IO引脚,如果想扩展比分显示单元,或者将电位器换成按键,几乎无法实现。我们可以利用74HC595来对点阵的引脚进行简化,通过下面的电路,我们在实际控制的时候只需要用到3根信号线即可搞定。
*因为是动态扫描显示,图中的8个限流电阻可以舍去,还可以提高亮度。
[attach]811[/attach]

实物接线,用按键代替了电位器(更符合人们的操作习惯),另外加入一个液晶,可以实时的将游戏比分记录下来。
[attach]812[/attach]

代码下载:[attach]813[/attach]

作者: hero_sun    时间: 2016-1-28 14:11
有视频吗?
作者: 狱锁狂龙    时间: 2020-2-3 13:15
nice ^^^^^^^^nice




欢迎光临 YFROBOT创客社区 (http://yfrobot.com.cn/) Powered by Discuz! X3.1