17065浏览
查看: 17065|回复: 12

[项目] Arduino贪吃蛇

[复制链接]
本帖最后由 大连林海 于 2015-11-1 09:25 编辑

Arduino贪吃蛇图3
器材准备:










作品特性描述:
* 吃到食物蛇身变长。
* 食物不会出现在蛇身上。
* 蛇每吃5个食物,移动速度增加一次。
* 场地无边界。
* 修复所有漏洞。
* 一键重置游戏。
* 增加摇杆控制。
* 增加手动加速功能。
* 摇杆实时高精度识别,加入防误触机制。


附上视频




代码如下:
  1. /*
  2. *  name:     贪吃蛇
  3. *  version:  3.6 <NO BUG Version>
  4. *  Author:   Apple tec.<[email]godfights@163.com[/email]>
  5. *  Date:     2015-10-23
  6. *  Description:  BiColor IIC点阵
  7. *  note:     ©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. int speedS = 8;                                                         // 贪吃蛇的初始速度
  17. int socre;                                                              // 游戏得分
  18. int xValue;                                                             // JoyStick-X
  19. int yValue;                                                             // JoyStick-Y
  20. int zPin = 4;                                                           // JoyStick-Z
  21. int Enabled;                                                            // 重启游戏使能
  22. int FX, FY;                                                             // 食物的坐标
  23. int SX, SY;                                                             // 蛇头的坐标
  24. int KEY, K;                                                             // 当前按键码和实际按键码
  25. char s[129] = {};                                                       // 蛇身体坐标集合,一共64个点,二维坐标128个元素 其中0没有用到 故为129个元素
  26. /***************************************************************************************************************************************************************************************************************/
  27. void setup() {
  28.   /*
  29.   pinMode(A2, OUTPUT);              // 让A2 A3输出  A2高电平 A3 低电平来达到VCC GND的目的  20ma的输出能力足够点阵使用了
  30.   pinMode(A3, OUTPUT);              // 在此模式下需将显示方向设置为 3
  31.   digitalWrite(A2, HIGH);
  32.   digitalWrite(A3, LOW);  
  33.   */
  34.   pinMode(zPin, INPUT);
  35.   RANDOM();                         // 获取一个随机食物坐标
  36.   K = 0;                            // 初始化按键码,实际上就是行进方向 方向初始化为0 即在首次操作摇杆前 蛇不移动
  37.   s[1] = 2;                         // x3
  38.   s[2] = 2;                         // y3
  39.   s[3] = 1;                         // x2
  40.   s[4] = 2;                         // y2
  41.   s[5] = 0;                         // x1
  42.   s[6] = 2;                         // y1 初始化蛇的身体坐标      
  43.   socre = 0;                        // 游戏起始得分
  44.   matrix.begin(0x70);               // 设定IIC屏幕地址
  45.   matrix.clear();                   // 屏幕清屏
  46.   matrix.writeDisplay();            // 屏幕显示
  47.   matrix.setRotation(1);            // 设置屏幕显示方向  0向左显示 1向上显示 2向右显示 3向下显示 默认值为0 若输入错误值4 显示方向保持默认0
  48.   matrix.clear();
  49.   Logo();                           // 绘制开机Logo
  50.   matrix.writeDisplay();
  51.   delay(1000);
  52.   matrix.setTextWrap(false);               // 设置字体平滑模式
  53.   matrix.setTextSize(1);                   // 设置字号
  54.   matrix.setTextColor(LED_GREEN);          // 设定LED颜色,0表示熄灭~
  55.   for (int8_t x = 7; x >= -70; x--) {      // for (int8_t x = -75; x <= 7; x++) {} 向右滚屏
  56.     matrix.clear();
  57.     matrix.setCursor(x, 1);                // setCursor(int16_t x, int16_t y)
  58.     matrix.print( "READY!!! G0 " );
  59.     matrix.writeDisplay();
  60.     delay(70);
  61.   }
  62.   // 循环绘制文字,获得滚动效果
  63.   matrix.clear();
  64.   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]} (右侧为蛇头)
  65.   {
  66.     matrix.drawPixel(s[i], s[i + 1], LED_RED);      // drawPixel(int16_t x, int16_t y, uint16_t color)
  67.   }
  68.   matrix.writeDisplay();
  69.   delay(400);
  70. }
  71. // 循环绘制蛇的身体,实际上就是3个点咯~
  72. /***************************************************************************************************************************************************************************************************************/  
  73. void RANDOM() {
  74. A:   
  75.   FX = random(0, 7);
  76.   FY = random(0, 7);
  77.   for(int i = 1; i <= 6 + 2 * socre; i+= 2)            // 防止食物出现在蛇身上
  78.   {
  79.     if( FX == s[i] and FY == s[i + 1])
  80.       goto A;                              
  81.   }
  82. }
  83. // 随机食物获取函数
  84. /***************************************************************************************************************************************************************************************************************/  
  85. void myDelay( int Time) {                             // 在蛇移动的延时期间 我们要做一些事情 比如食物的闪烁和摇杆方向的读取
  86.   for(int t = 1; t <= Time; t++)
  87.   {
  88.     matrix.drawPixel(FX, FY, LED_GREEN);
  89.     matrix.writeDisplay();
  90.     delay(50);
  91.     matrix.drawPixel(FX, FY, 0);
  92.     matrix.writeDisplay();
  93.     delay(50);
  94.     joyStick();                                        // 读取摇杆方向        
  95.   }
  96. }
  97. // 这个是演示函数,实际上通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动,来让大家不断的看到~
  98. /***************************************************************************************************************************************************************************************************************/
  99. void Endelay( unsigned long duration) {                // 字幕滚动的延时期间 我们也要做一些事情 比如判断中央键是否被按下 按下则重置游戏
  100.   unsigned long Start = millis();
  101.   while(millis() - Start <= duration) {
  102.     if(digitalRead(zPin) == LOW) {
  103.       delay(20);
  104.       if(digitalRead(zPin) == LOW) {
  105.         Enabled = 1;
  106.         }
  107.       }
  108.     }
  109. }
  110. // 重启游戏专用延时函数  
  111. /***************************************************************************************************************************************************************************************************************/
  112. void Logo() {
  113.   matrix.drawPixel(6, 0, LED_YELLOW);          // X 右边笔画的动画
  114.   matrix.writeDisplay();
  115.   delay(35);
  116.   for ( int x = 1; x <= 6; x++) {               
  117.     matrix.drawPixel(7-x, x, LED_YELLOW);
  118.     matrix.writeDisplay();
  119.     delay(35);
  120.     }
  121.   matrix.drawPixel(1, 7, LED_YELLOW);
  122.   matrix.writeDisplay();
  123.   delay(35);
  124.   matrix.drawPixel(1, 0, LED_YELLOW);          // X 左边笔画的动画
  125.   matrix.writeDisplay();
  126.   delay(35);
  127.   for ( int x = 1; x <= 6; x++) {              
  128.     matrix.drawPixel(x, x, LED_YELLOW);
  129.     matrix.writeDisplay();
  130.     delay(35);
  131.     }
  132.   matrix.drawPixel(6, 7, LED_YELLOW);
  133.   matrix.writeDisplay();
  134.   delay(35);
  135.   for (int x = 1; x <= 45; x++) {                         // logo闪烁
  136.     matrix.clear();
  137.     matrix.writeDisplay();
  138.     delay(x);
  139.     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)
  140.     matrix.writeDisplay();
  141.     delay(x);
  142.     }
  143. }
  144. // Logo绘制函数,看不懂可以跳过~~~不过还是蛮简单的,仔细看下就明白了~
  145. /***************************************************************************************************************************************************************************************************************/
  146. void joyStick() {
  147.   xValue = analogRead(A0);                             // JoyStick-X   最左值为0 最右值为1023 中间值为515
  148.   yValue = analogRead(A1);                             // JoyStick-Y   最下值为0 最上值为1023 中间值为510
  149.   if(yValue == 1023 && KEY != 5) {
  150.     K = 8;
  151.     }
  152.   else if(yValue == 0 && KEY != 8) {
  153.     K = 5;
  154.     }
  155.   else if(xValue == 0 && KEY != 6 && K != 0) {         // 首次操作摇杆前 不能向左移动蛇
  156.     K = 4;
  157.     }
  158.   else if(xValue == 1023 && KEY != 4) {
  159.     K = 6;
  160.     }
  161.   if(digitalRead(zPin) == LOW)                         // 当按下中央键后 速度变为 2  松开后 速度恢复到当前值
  162.     speedS = 2;
  163.   else  
  164.     speedS = 8 - socre / 5;
  165. }
  166. // 这里是在比对按键方向是否和目前蛇的行进方向相反,如果相反就放弃按键  
  167. /***************************************************************************************************************************************************************************************************************/
  168. void gameover() {                                      // 一旦执行到Gameover 程序停止 需要按下中央键后以重启游戏
  169.   Enabled = 0;
  170.   while(Enabled == 0) {
  171.     for (int8_t x = 7; x >= -125 && Enabled == 0; x--) {
  172.       matrix.clear();
  173.       matrix.setCursor(x, 1);
  174.       matrix.print( "GAME OVER YOUR SOCRE:" );
  175.       matrix.writeDisplay();
  176.       Endelay(70);
  177.       }
  178.     for (int8_t x = 7; x >= -39 && Enabled == 0; x--) {
  179.       matrix.clear();
  180.       matrix.setCursor(x, 1);
  181.       matrix.print(socre);
  182.       matrix.writeDisplay();
  183.       Endelay(70);
  184.       }
  185.     }
  186.     // GameOver函数,显示游戏结束和得分
  187.     for(int i = 0; i < 129; i++) {
  188.       s[i] = 0;
  189.       }
  190.     K = 0;                  // 重置摇杆方向
  191.     s[1] = 2;
  192.     s[2] = 2;
  193.     s[3] = 1;
  194.     s[4] = 2;
  195.     s[5] = 0;
  196.     s[6] = 2;               // 重置蛇的坐标
  197.     socre = 0;              // 重置游戏得分
  198. }
  199. /***************************************************************************************************************************************************************************************************************/  
  200. void loop() {
  201.   KEY = K;                                      // 蛇每移动一次 方向才能改变一次
  202.   matrix.clear();
  203.   if(KEY == 8)                                  // 蛇向上运动
  204.   {
  205.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  206.     {
  207.       s[i] = s[i - 2];
  208.       s[i - 1] = s[i - 3];
  209.     }
  210.     s[2] = s[2] - 1;
  211.     if(s[2] < 0)                                // 超出边框的从另一边继续出现
  212.       s[2] = 7;
  213.   }
  214.   else if(KEY == 5)                             // 蛇向下运动
  215.   {
  216.     for(int i = 6 + 2 * socre; i > 3; i= i - 2)
  217.     {
  218.       s[i] = s[i - 2];
  219.       s[i - 1] = s[i - 3];
  220.     }
  221.     s[2] = s[2] + 1;
  222.     if(s[2] > 7)                                // 超出边框的从另一边继续出现
  223.       s[2] = 0;
  224.   }
  225.   else if(KEY == 4)                             // 蛇向左运动
  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[1] = s[1] - 1;
  233.     if(s[1] < 0)                                // 超出边框的从另一边继续出现
  234.       s[1] = 7;
  235.   }
  236.   else if(KEY == 6)                             // 蛇向右运动
  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[1] = s[1] + 1;
  244.     if(s[1] > 7)                                // 超出边框的从另一边继续出现
  245.       s[1] = 0;
  246.   }
  247.   // 根据按键来移动蛇的身体
  248.   for(int i = 1; i <= 6 + 2 * socre; i+= 2)     // 从蛇头开始绘制
  249.   {
  250.     matrix.drawPixel(s[i], s[i + 1], LED_RED);
  251.   }
  252.   matrix.writeDisplay();
  253.   myDelay(speedS);                                //()内为延时次数 延时一次为100ms  实测200ms速度很合适 故将加速时速度设置为 2  
  254.   SX = s[1];
  255.   SY = s[2];
  256.   // 获取蛇头的坐标
  257.   for(int i = 3; i <= 6 + 2 * socre; i+= 2)
  258.   {
  259.     if( SX == s[i] && SY == s[i + 1])
  260.       gameover();                              
  261.   }
  262.   // 判断蛇头是否碰到自己的身体,碰到就跳转到GameOver
  263.   if(SY == FY && SX == FX)
  264.   {
  265.     socre ++;
  266.     RANDOM();
  267.     if( !(socre % 5)) {                       // 根据得分加快蛇的速度 每吃5个食物 速度快100ms
  268.       speedS --;
  269.       if(speedS < 2)                          // 速度下限为200ms 如果速度小于200ms 速度值仍为200ms
  270.         speedS = 2;
  271.       }
  272.   }
  273.   // 判断是否吃到了食物~吃到了就会加分和重新随机生成食物~
  274. }
复制代码

用到的库文件:


下载附件adafruit_ledbackpack.zip下载附件adafruit_gfx.zip





丄帝De咗臂  高级技匠

发表于 2015-11-1 11:49:30

不错啊,你做的么
回复

使用道具 举报

hnyzcj  版主

发表于 2015-11-1 12:23:09

牛叉
回复

使用道具 举报

大连林海  初级技神
 楼主|

发表于 2015-11-1 16:42:41


看那么长的代码 你懂得
回复

使用道具 举报

大连林海  初级技神
 楼主|

发表于 2015-11-1 16:43:11


看我能把用到的东西都列出来 哈哈
回复

使用道具 举报

孙毅  初级技匠

发表于 2015-11-1 23:27:07

给跪了
回复

使用道具 举报

大连林海  初级技神
 楼主|

发表于 2015-11-2 07:49:08


高手在民间  是不是很厉害
回复

使用道具 举报

Jason_G  高级技师

发表于 2015-11-7 22:39:16

有意思,喜欢!
回复

使用道具 举报

Ash  管理员

发表于 2015-12-1 15:37:17

转载的项目还是要放一下原作者和链接啦~
回复

使用道具 举报

lin  中级技师

发表于 2016-8-18 09:04:51

挨炮科技的项目。。。
回复

使用道具 举报

20060606  高级技匠

发表于 2020-8-16 05:20:02

您用的是什么LED模块
回复

使用道具 举报

 初级技匠

发表于 2022-4-17 09:17:12

《高手在民间》
回复

使用道具 举报

 初级技匠

发表于 2022-4-17 09:25:14

高手两个含义
一个是创客高手
还一个是游戏高手
回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail