极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 73139|回复: 29

Arduino贪吃蛇

[复制链接]
发表于 2015-10-29 18:45:50 | 显示全部楼层 |阅读模式
Arduino贪吃蛇



新特性:
* 吃到食物蛇身变长。
* 食物不会出现在蛇身上。
* 蛇每吃5个食物,移动速度增加一次。
* 场地无边界。
* 修复所有漏洞。
* 一键重置游戏。
* 增加摇杆控制。
* 增加手动加速功能。
* 摇杆实时高精度识别,加入防误触机制。
(源代码已开放,并且很耐心的为每一个句子写了详细注释)

Demo如下:



代码如下:

  1. /*
  2. *  name:     贪吃蛇
  3. *  version:  3.6 <NO BUG Version>
  4. *  Author:   Apple tec.<[email][email protected][/email]>
  5. *  Date:     2015-10-23
  6. *  Description:  BiColor IIC点阵
  7. *  note:     &#169;2015 Apple tec.All Rights
  8. *                  Designed by LJ
  9. */
  10. /*==================================================================================  贪吃蛇  =================================================================================================================*/
  11. #include <Wire.h>                                                       // I2C链接库
  12. #include "Adafruit_LEDBackpack.h"                                       // 点阵驱动库
  13. #include "Adafruit_GFX.h"                                               // Arduino图形库

  14. Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();               // 设置I2C点阵型号

  15. static const uint8_t __attribute__ ((progmem)) X [] = { B01000010, B01000010, B00100100, B00011000, B00011000, B00100100, B01000010, B01000010 };   // 字母 X 的logo代码,其实就是一个一个点的量灭组成的
  16.                                          
  17. int speedS = 8;                                                         // 贪吃蛇的初始速度
  18. int socre;                                                              // 游戏得分
  19. int xValue;                                                             // JoyStick-X
  20. int yValue;                                                             // JoyStick-Y
  21. int zPin = 4;                                                           // JoyStick-Z
  22. int Enabled;                                                            // 重启游戏使能
  23. int FX, FY;                                                             // 食物的坐标
  24. int SX, SY;                                                             // 蛇头的坐标
  25. int KEY, K;                                                             // 当前按键码和实际按键码
  26. char s[129] = {};                                                       // 蛇身体坐标集合,一共64个点,二维坐标128个元素 其中0没有用到 故为129个元素
  27. /***************************************************************************************************************************************************************************************************************/

  28. void setup() {

  29.   /*
  30.   pinMode(A2, OUTPUT);              // 让A2 A3输出  A2高电平 A3 低电平来达到VCC GND的目的  20ma的输出能力足够点阵使用了
  31.   pinMode(A3, OUTPUT);              // 在此模式下需将显示方向设置为 3
  32.   digitalWrite(A2, HIGH);
  33.   digitalWrite(A3, LOW);  
  34.   */
  35.   
  36.   pinMode(zPin, INPUT);
  37.   
  38.   RANDOM();                         // 获取一个随机食物坐标
  39.   K = 0;                            // 初始化按键码,实际上就是行进方向 方向初始化为0 即在首次操作摇杆前 蛇不移动
  40.   s[1] = 2;                         // x3
  41.   s[2] = 2;                         // y3
  42.   s[3] = 1;                         // x2
  43.   s[4] = 2;                         // y2
  44.   s[5] = 0;                         // x1
  45.   s[6] = 2;                         // y1 初始化蛇的身体坐标      
  46.   socre = 0;                        // 游戏起始得分
  47.   
  48.   matrix.begin(0x70);               // 设定IIC屏幕地址
  49.   matrix.clear();                   // 屏幕清屏
  50.   matrix.writeDisplay();            // 屏幕显示
  51.   matrix.setRotation(1);            // 设置屏幕显示方向  0向左显示 1向上显示 2向右显示 3向下显示 默认值为0 若输入错误值4 显示方向保持默认0
  52.   matrix.clear();
  53.   
  54.   Logo();                           // 绘制开机Logo
  55.   
  56.   matrix.writeDisplay();
  57.   delay(1000);
  58.   
  59.   matrix.setTextWrap(false);               // 设置字体平滑模式
  60.   matrix.setTextSize(1);                   // 设置字号
  61.   matrix.setTextColor(LED_GREEN);          // 设定LED颜色,0表示熄灭~
  62.   
  63.   for (int8_t x = 7; x >= -70; x--) {      // for (int8_t x = -75; x <= 7; x++) {} 向右滚屏
  64.     matrix.clear();
  65.     matrix.setCursor(x, 1);                // setCursor(int16_t x, int16_t y)
  66.     matrix.print( "READY!!! G0 " );
  67.     matrix.writeDisplay();
  68.     delay(70);
  69.   }
  70.   // 循环绘制文字,获得滚动效果
  71.   
  72.   matrix.clear();
  73.   for(int i = 1; i <= 6; i += 2)                      // 从蛇头开始绘制三个点 s[1], s[3], s[5]为x坐标 s[2], s[4], s[6]为y坐标 蛇身排序: {s[5],s[6]}  {s[3],s[4]}  {s[1],s[2]} (右侧为蛇头)
  74.   {
  75.     matrix.drawPixel(s[i], s[i + 1], LED_RED);      // drawPixel(int16_t x, int16_t y, uint16_t color)
  76.   }
  77.   matrix.writeDisplay();
  78.   delay(400);
  79. }
  80. // 循环绘制蛇的身体,实际上就是3个点咯~
  81. /***************************************************************************************************************************************************************************************************************/  

  82. void RANDOM() {
  83. A:   
  84.   FX = random(0, 7);
  85.   FY = random(0, 7);
  86.   
  87.   for(int i = 1; i <= 6 + 2 * socre; i+= 2)            // 防止食物出现在蛇身上
  88.   {
  89.     if( FX == s[i] and FY == s[i + 1])
  90.       goto A;                              
  91.   }
  92. }
  93. // 随机食物获取函数
  94. /***************************************************************************************************************************************************************************************************************/  

  95. void myDelay( int Time) {                             // 在蛇移动的延时期间 我们要做一些事情 比如食物的闪烁和摇杆方向的读取
  96.    
  97.   for(int t = 1; t <= Time; t++)
  98.   {
  99.     matrix.drawPixel(FX, FY, LED_GREEN);
  100.     matrix.writeDisplay();
  101.     delay(50);
  102.     matrix.drawPixel(FX, FY, 0);
  103.     matrix.writeDisplay();
  104.     delay(50);
  105.     joyStick();                                        // 读取摇杆方向        
  106.   }
  107. }
  108. // 这个是演示函数,实际上通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动,来让大家不断的看到~
  109. /***************************************************************************************************************************************************************************************************************/

  110. void Endelay( unsigned long duration) {                // 字幕滚动的延时期间 我们也要做一些事情 比如判断中央键是否被按下 按下则重置游戏
  111.   
  112.   unsigned long Start = millis();
  113.   while(millis() - Start <= duration) {
  114.     if(digitalRead(zPin) == LOW) {
  115.       delay(20);
  116.       if(digitalRead(zPin) == LOW) {
  117.         Enabled = 1;
  118.         }
  119.       }
  120.     }
  121. }
  122. // 重启游戏专用延时函数  
  123. /***************************************************************************************************************************************************************************************************************/

  124. void Logo() {
  125.                                                
  126.   matrix.drawPixel(6, 0, LED_YELLOW);          // X 右边笔画的动画
  127.   matrix.writeDisplay();
  128.   delay(35);
  129.   for ( int x = 1; x <= 6; x++) {               
  130.     matrix.drawPixel(7-x, x, LED_YELLOW);
  131.     matrix.writeDisplay();
  132.     delay(35);
  133.     }
  134.   matrix.drawPixel(1, 7, LED_YELLOW);
  135.   matrix.writeDisplay();
  136.   delay(35);

  137.   matrix.drawPixel(1, 0, LED_YELLOW);          // X 左边笔画的动画
  138.   matrix.writeDisplay();
  139.   delay(35);
  140.   for ( int x = 1; x <= 6; x++) {              
  141.     matrix.drawPixel(x, x, LED_YELLOW);
  142.     matrix.writeDisplay();
  143.     delay(35);
  144.     }
  145.   matrix.drawPixel(6, 7, LED_YELLOW);
  146.   matrix.writeDisplay();
  147.   delay(35);

  148.   for (int x = 1; x <= 45; x++) {                         // logo闪烁
  149.     matrix.clear();
  150.     matrix.writeDisplay();
  151.     delay(x);
  152.     matrix.drawBitmap(0, 0, X, 8, 8, LED_YELLOW);       // drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
  153.     matrix.writeDisplay();
  154.     delay(x);
  155.     }
  156. }
  157. // Logo绘制函数,看不懂可以跳过~~~不过还是蛮简单的,仔细看下就明白了~
  158. /***************************************************************************************************************************************************************************************************************/

  159. void joyStick() {
  160.   
  161.   xValue = analogRead(A0);                             // JoyStick-X   最左值为0 最右值为1023 中间值为515
  162.   yValue = analogRead(A1);                             // JoyStick-Y   最下值为0 最上值为1023 中间值为510
  163.    
  164.   if(yValue == 1023 && KEY != 5) {
  165.     K = 8;
  166.     }
  167.   else if(yValue == 0 && KEY != 8) {
  168.     K = 5;
  169.     }
  170.   else if(xValue == 0 && KEY != 6 && K != 0) {         // 首次操作摇杆前 不能向左移动蛇
  171.     K = 4;
  172.     }
  173.   else if(xValue == 1023 && KEY != 4) {
  174.     K = 6;
  175.     }
  176.    
  177.   if(digitalRead(zPin) == LOW)                         // 当按下中央键后 速度变为 2  松开后 速度恢复到当前值
  178.     speedS = 2;
  179.   else  
  180.     speedS = 8 - socre / 5;
  181. }
  182. // 这里是在比对按键方向是否和目前蛇的行进方向相反,如果相反就放弃按键  
  183. /***************************************************************************************************************************************************************************************************************/

  184. void gameover() {                                      // 一旦执行到Gameover 程序停止 需要按下中央键后以重启游戏
  185.   
  186.   Enabled = 0;
  187.   while(Enabled == 0) {
  188.    
  189.     for (int8_t x = 7; x >= -125 && Enabled == 0; x--) {
  190.       matrix.clear();
  191.       matrix.setCursor(x, 1);
  192.       matrix.print( "GAME OVER YOUR SOCRE:" );
  193.       matrix.writeDisplay();
  194.       Endelay(70);
  195.       }
  196.    
  197.     for (int8_t x = 7; x >= -39 && Enabled == 0; x--) {
  198.       matrix.clear();
  199.       matrix.setCursor(x, 1);
  200.       matrix.print(socre);
  201.       matrix.writeDisplay();
  202.       Endelay(70);
  203.       }
  204.     }
  205.     // GameOver函数,显示游戏结束和得分
  206.    
  207.     for(int i = 0; i < 129; i++) {
  208.       s[i] = 0;
  209.       }
  210.    
  211.     K = 0;                  // 重置摇杆方向
  212.     s[1] = 2;
  213.     s[2] = 2;
  214.     s[3] = 1;
  215.     s[4] = 2;
  216.     s[5] = 0;
  217.     s[6] = 2;               // 重置蛇的坐标
  218.     socre = 0;              // 重置游戏得分
  219. }
  220. /***************************************************************************************************************************************************************************************************************/  

  221. void loop() {

  222.   KEY = K;                                      // 蛇每移动一次 方向才能改变一次
  223.   matrix.clear();
  224.   
  225.   if(KEY == 8)                                  // 蛇向上运动
  226.   {
  227.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  228.     {
  229.       s[i] = s[i - 2];
  230.       s[i - 1] = s[i - 3];
  231.     }
  232.     s[2] = s[2] - 1;
  233.     if(s[2] < 0)                                // 超出边框的从另一边继续出现
  234.       s[2] = 7;
  235.   }
  236.   else if(KEY == 5)                             // 蛇向下运动
  237.   {
  238.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  239.     {
  240.       s[i] = s[i - 2];
  241.       s[i - 1] = s[i - 3];
  242.     }
  243.     s[2] = s[2] + 1;
  244.     if(s[2] > 7)                                // 超出边框的从另一边继续出现
  245.       s[2] = 0;
  246.   }
  247.   else if(KEY == 4)                             // 蛇向左运动
  248.   {
  249.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  250.     {
  251.       s[i] = s[i - 2];
  252.       s[i - 1] = s[i - 3];
  253.     }
  254.     s[1] = s[1] - 1;
  255.     if(s[1] < 0)                                // 超出边框的从另一边继续出现
  256.       s[1] = 7;
  257.   }
  258.   else if(KEY == 6)                             // 蛇向右运动
  259.   {
  260.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  261.     {
  262.       s[i] = s[i - 2];
  263.       s[i - 1] = s[i - 3];
  264.     }
  265.     s[1] = s[1] + 1;
  266.     if(s[1] > 7)                                // 超出边框的从另一边继续出现
  267.       s[1] = 0;
  268.   }
  269.   // 根据按键来移动蛇的身体
  270.   
  271.   for(int i = 1; i <= 6 + 2 * socre; i+= 2)     // 从蛇头开始绘制
  272.   {
  273.     matrix.drawPixel(s[i], s[i + 1], LED_RED);
  274.   }
  275.   matrix.writeDisplay();
  276.   
  277.   myDelay(speedS);                                //()内为延时次数 延时一次为100ms  实测200ms速度很合适 故将加速时速度设置为 2  
  278.   
  279.   SX = s[1];
  280.   SY = s[2];
  281.   // 获取蛇头的坐标
  282.   
  283.   for(int i = 3; i <= 6 + 2 * socre; i+= 2)
  284.   {
  285.     if( SX == s[i] && SY == s[i + 1])
  286.       gameover();                              
  287.   }
  288.   // 判断蛇头是否碰到自己的身体,碰到就跳转到GameOver
  289.   
  290.   if(SY == FY && SX == FX)
  291.   {
  292.     socre ++;
  293.     RANDOM();
  294.     if( !(socre % 5)) {                       // 根据得分加快蛇的速度 每吃5个食物 速度快100ms
  295.       speedS --;
  296.       if(speedS < 2)                          // 速度下限为200ms 如果速度小于200ms 速度值仍为200ms
  297.         speedS = 2;
  298.       }
  299.   }
  300.   // 判断是否吃到了食物~吃到了就会加分和重新随机生成食物~
  301. }
复制代码


用到的库文件如下:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-10-29 21:18:36 | 显示全部楼层
好工整,标注好有耐心。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-29 21:26:28 | 显示全部楼层
本帖最后由 Apple_tec. 于 2015-10-29 21:27 编辑
gucci99 发表于 2015-10-29 21:18
好工整,标注好有耐心。


哈哈 谢谢好评 既然要发就好好发呗
回复 支持 反对

使用道具 举报

发表于 2015-10-29 21:32:32 | 显示全部楼层
好东西,学习了
回复 支持 反对

使用道具 举报

发表于 2015-10-30 13:25:32 | 显示全部楼层
good job
回复 支持 反对

使用道具 举报

发表于 2015-11-1 09:19:12 | 显示全部楼层
转发学习了
回复 支持 反对

使用道具 举报

发表于 2015-11-2 14:48:22 | 显示全部楼层
请问这个点阵模块用的是MAX7219芯片驱动吗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-11-2 14:51:52 | 显示全部楼层
dbo 发表于 2015-11-2 14:48
请问这个点阵模块用的是MAX7219芯片驱动吗

不是的  是OC的IIC点阵
回复 支持 反对

使用道具 举报

发表于 2015-11-2 19:15:44 | 显示全部楼层
谢谢分享学习一下,论坛之前有人发过
回复 支持 反对

使用道具 举报

发表于 2015-11-7 21:08:31 | 显示全部楼层
针脚是多少。请问大神
回复 支持 反对

使用道具 举报

发表于 2015-11-14 12:03:51 | 显示全部楼层
好有创意啊
回复 支持 反对

使用道具 举报

发表于 2015-11-15 09:36:37 | 显示全部楼层
支持楼主。。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-11-19 18:14:56 | 显示全部楼层
卡卡西 发表于 2015-11-7 21:08
针脚是多少。请问大神

看程序啊。。。因为是HT16K33驱动的IIC点阵,就接Arduino的IIC接口啊。摇杆X轴接A0,Y轴接A1,Z轴接D4。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-11-19 18:18:06 | 显示全部楼层
dbo 发表于 2015-11-2 14:48
请问这个点阵模块用的是MAX7219芯片驱动吗

是HT16K33双色LED点阵驱动芯片
回复 支持 反对

使用道具 举报

发表于 2015-11-27 20:04:50 | 显示全部楼层
请问楼主的摇杆是哪买的,什么型号
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 07:16 , Processed in 0.045268 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表