韋編弎絕 发表于 2014-8-4 00:14:12

Arduino+OLED 简易贪吃蛇教程

本帖最后由 韋編弎絕 于 2014-8-9 19:13 编辑

    第一版实现了基本功能,操作上下左右按键实现蛇的移动,吃到食物增长。但没有实现碰壁、碰己的监测,食物固定不随机生成。



=========================准备=========================

一、所需硬件
1. Arduino Nano1个;
2. 0.96寸OLED (SPI接口) 1个;
3. 10*10*5mm 轻触开关4个。

二、所需软件
1. U8glib库;
2. Arduino 1.0.5 IDE。

三、硬件连接
1. OLED
      arduino       OLED
      D9      >   MOSI
      D10      >   SCK
      D11      >   DC
      D12      >   CS
      D13      >   RES

2. 轻触开关
      arduino       button
      D2      >   DOWN下
      D3      >   RIGHT   右
      D4      >   LEFT   左
      D5      >   UP      上
   
=======================必备知识=======================

    arduino Nano,OLED等的介绍不再赘述,网上很多,看一下贪食蛇游戏所需的 u8glib 库提供的方法,标题中未加参数,仅作简单介绍,详情请查看https://code.google.com/p/u8glib/wiki/userreference。
对u8glib熟悉的看官可以忽略~~~。
    引入u8glib的库之后,需要建立一个对象,并定义好引脚。
U8GLIB_SSD1306_128X64 u8g(10, 9, 12, 11, 13); //SCK = 10, MOSI = 9 , CS = 12, A0 = 11, RES = 13

1.u8g.drawBitmapP();
    1)方法定义 void U8GLIB::drawBitmapP(u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)    2)功能
         显示一个位图
    3)参数
         x:位图左上角的横坐标
         y:位图左上角的纵坐标
         cnt:在水平方向上的位图的字节数。该位图的宽度是cnt* 8(1字节=8位)
         h:位图的高
         *bitmap:位图对象
    4)例子const uint8_t rook_bitmap[] U8G_PROGMEM = {
0x00,         // 00000000
0x55,         // 01010101
0x7f,          // 01111111
0x3e,         // 00111110
0x3e,         // 00111110
0x3e,         // 00111110
0x3e,         // 00111110
0x7f         // 01111111
};
...
u8g.drawBitmapP(0,0, 1, 8, rook_bitmap);

2.u8g.drawFrame();
    1)方法定义void U8GLIB::drawFrame(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)    2)功能
         此函数是一个画方框的方法。
    3)参数
         x:方框左上角点的横坐标
         y:方框左上角点的纵坐标
         w:方框的宽
         h:方框的高
    4)例子u8g.drawFrame(10, 12, 30, 20); // 方框的长宽包括了边框所在的像素点
   
3.u8g.setFont();
    1)方法定义U8GLIB::setFont(const u8g_fntpgm_uint8_t *font)
    2)功能
         设置要显示字符的字体。
    3)参数
         *font:字体样式。u8glib提供的字体样式https://code.google.com/p/u8glib/wiki/fontsize

4.u8g.drawStr();
    1)方法定义u8g_uint_t U8GLIB::drawStr(u8g_uint_t x, u8g_uint_t y, const char *s)    2)功能
         显示字符
    3)参数
         x:字符左下角的横坐标
         y:字符左下角的纵坐标
         *s:要显示的字符
    4)例子U8GLIB u8g(...)
...
u8g.setFont(u8g_font_osb18);
u8g.drawStr(0, 20, "ABC");

5.u8g.setPrintPos();
    1)方法定义void U8GLIB::setPrintPos(u8g_uint_t x, u8g_uint_t y)    2)功能
         设置下文中print()的显示位置
    3)参数
         x:横坐标
         y:纵坐标

6.u8g.print();
    1)方法定义U8GLIB::print(...)    2)功能
         打印要显示的字符,包括变量值、字符串等。使用前需要使用setPrintPos()函数设置位置

7.u8g.firstPage();
    1)方法定义void U8GLIB::firstPage(void)    2)功能
          调用此过程,标志着图像循环的开始

8.u8g.nextPage();
    1)方法定义uint8_t U8GLIB::nextPage(void)    2)功能
          调用此过程,标志着图像循环的结束

    若要使图像正常显示,u8glib库提供了如下的代码格式void loop() {
        u8g.firstPage();
        do {
                //draw
        }while(u8g.nextPage());
}

=========================教程========================

1.贪吃蛇算法
本贪吃蛇代码参考使用一下教程。
    http://www.oschina.net/code/snippet_143423_4296
    http://v.mybdqn.com/v_show/id_86.html
    http://v.mybdqn.com/v_show/id_87.html

    贪吃蛇会按照一定的间隔时间朝着一个方向移动,通过上下左右操作控制蛇移动方向。蛇的移动有两种算法可以使用。
    1. 火车头拉着走。

    2. 加头去尾。


    相对来说用火车头拉的方式是比较流行也是初学者最好掌握的方式。首先确定一个蛇头的坐标,蛇头每移动一次,蛇头后的每一节为前一节的旧坐标。

2.定义结构体struct FOOD {
int x;
int y;
int yes;
};

FOOD food = {25, 30, 1};

struct SNAKE {
int x;
int y;
int node;
int dir;
int lefe;
};

SNAKE snake = {{9,5}, {30,30}, 2, RIGHT, 0};

3.组成贪吃蛇的单位//组成单位,4X4像素点的方块。
const uint8_t ele[] PROGMEM = {
0xf0, //B1111000
0xb0, //B1011000
0xd0, //B1101000
0xf0, //B1111000
};

//蛇
void element(int x, int y) {
u8g.drawBitmapP(x,y, 1,4, ele);
}
■ ■ ■ ■ □ □ □ □B111100000xF0
■ □ ■ ■ □ □ □ □B101100000xB0
■ ■ □ ■ □ □ □ □B110100000xD0
■ ■ ■ ■ □ □ □ □B111100000xF0


这样一个4*4的方块为组成蛇的一个单位。

4.游戏的主界面void UI() {
u8g.drawFrame(0,1, 102,62);   //内边界
u8g.drawFrame(0,0, 102,64);   //外边界
u8g.setFont(u8g_font_5x7);    //设置字体
u8g.drawStr(104,12, "LEVEL"); //等级提示
u8g.drawStr(104,40, "SCORE"); //分数提示
}


5.按键的获取void setup() {
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
}

//按键判断
void key() {
if(LOW == digitalRead(2)) {
    snake.dir = DOWN;
}
if(LOW == digitalRead(3)) {
    snake.dir = RIGHT;
}
if(LOW == digitalRead(4)) {
    snake.dir = LEFT;
}
if(LOW == digitalRead(5)) {
    snake.dir = UP;
}
}

6.蛇的移动switch(snake.dir) {
    case RIGHT:
          snake.x += 4;
          if(snake.x>=101) {
            snake.x = 1;
          } break;
    case UP:
          snake.y -= 4;
          if(snake.y<=1) {
            snake.y = 58;
          } break;
    case LEFT:
          snake.x -= 4;
          if(snake.x<=0) {
            snake.x = 97;
          } break;
    case DOWN:
          snake.y += 4;
          if(snake.y>=62) {
            snake.y = 2;
          } break;
}

for(i=snake.node-1;i>0;i--) {
    snake.x = snake.x;
    snake.y = snake.y;
}

7.吃到食物
    蛇头坐标与食物坐标相同,说明蛇吃到了食物。if((snake.x == food.x) && (snake.y == food.y)) {
    snake.x = food.x;
    snake.y = food.y;
   
    snake.node++;
    food.yes = 1;
    score += 2;
    level = score/10+1;
}

8.画出图像
    在do-while循环中写入代码,画出整个界面u8g.firstPage();
do {
    UI(); //画主界面

    //画蛇
    for(i=0; i<snake.node;i++) {
      element(snake.x, snake.y);
    }

    //画食物
    element(food.x, food.y);

    //写分数   
    printScore(109, 22, level);
    printScore(109, 50, score);
}while(u8g.nextPage());

    本人能力有限,如有错误,还望看官海涵轻喷指正。本教程抛砖引玉希望大家DIY出更好的作品。

源文件:

努力微笑 发表于 2014-8-4 07:30:17

很详细的教程,我喜欢

韋編弎絕 发表于 2014-8-4 22:04:07

努力微笑 发表于 2014-8-4 07:30 static/image/common/back.gif
很详细的教程,我喜欢

:handshake谢谢~

迷你强 发表于 2014-8-5 11:20:12

高阶U8GLIB库教程啊。

sharpen 发表于 2014-8-5 13:38:49

赞!赞!赞!赞!

dingshidong 发表于 2015-5-26 14:35:59

附件 u8glib_arduino_v1.17.zip 最新的V1.17版本的库

夜静晚流觞 发表于 2016-10-18 16:32:05

6脚的oled没有cs接口能用这个程序吗?

asd4864815 发表于 2017-4-7 23:02:02

請問有哪些要自己打的? 我執行程式有錯誤

theworld 发表于 2017-10-7 00:33:58

很好,就喜欢详细的,

crjjj 发表于 2018-1-25 20:51:58

最近研究oled 中,貌似新的ug8lib库会编译错误

zxyhp 发表于 2020-1-11 09:10:14

请教一下IIC的屏程序怎么改

tigerzq 发表于 2020-1-13 20:40:09

详细的教程

rui_live 发表于 2020-12-19 14:09:12

非常详尽的教程!
页: [1]
查看完整版本: Arduino+OLED 简易贪吃蛇教程