当前位置:首页  <  产品评测  <  【产品测评】LCD12864液晶摇杆扩展板之贪吃蛇游戏...
【产品测评】LCD12864 液晶摇杆扩展板之贪吃蛇游戏
编辑:neil 2016-09-28 浏览次数:873

LCD 12864液晶摇杆扩展板采用全新12864G-0088液晶屏为主体显示器件。此扩展板采用Arduino叠层板设计理念,可直接插接到Arduino UNO、Carduino UNO R3、Arduino mega2560、Arduino ADK控制器上使用,可以清晰显示中文、英文、字符、图片等;板上添加五向微型摇杆,方便实现人机互动;同时本板还具有5个模拟扩展接口和8个字扩展接口;其中各数字接口均分别用黑色、红色、黄色排针来区别电源地、电源正极和信号IO管脚;即方便操作又具有防呆的作用;扩展接口可连接各种传感器模块,如温度湿度传感器、光线传感器、LED发光模块等,是制作显示互动作品不可获缺的显示器。

简单的产品介绍之后,就该开始我们今天的贪吃蛇游戏制作了,相信应该很多人都玩儿过这个游戏吧?

* 准备硬件

(1)PS2 游戏摇杆模块 * 1个

(2)LCD12864 液晶扩展板 * 1个

(3)Carduino UNO R3 控制器 * 1个

(4)杜邦线 * 若干

(5)USB 数据线 * 1 条

* 硬件连接

如下图所示将硬件连接在一起


接线说明:1、PS2 游戏摇杆模块X连接A1(黄色针,Y连接A2(黄色针,B连接A3(黄色针,+ 连接到控制器模拟口电源正(红色针),- 连接到控制器模拟口电源地(黑色针

2、LCD12864 液晶扩展板直接可以插接到 Carduino UNO R3 控制器上,只要将引脚对应好,就像下图中所示,然后插进去就可以啦!插好之后扩展板和UNO之间没有缝隙

    * 示例代码

 

#include "U8glib.h"
U8GLIB_MINI12864 u8g(5, 6, 2, 4, 3);

#define UP    A1
#define LEFT  A2
#define key A3

int box_x = 0;
int box_y = 0;
int box_x_length = 98;//x方向32  0-31
int box_y_length = 62;//y方向20  0-19
int snake_max_length = 100; //蛇身体最大长度
int snake_x[100];//蛇身x坐标
int snake_y[100];//蛇身y坐标
int snake_body_width = 3; //蛇身方块宽度(正方形)
int food_x;//食物位置坐标x
int food_y;//食物位置坐标y
int snake_length = 3; //当前蛇身长度
unsigned int game_speed;//游戏速度 单位MS
void setup(void)
{
  welcom();//欢迎界面
  delay(2000);
  chose_game();
}
//欢迎界面
void welcom()
{
  u8g.firstPage();
  do
  {
    u8g.setFont(u8g_font_gdr14r);
    u8g.setPrintPos(0, 20);
    u8g.print("Arduino");
    u8g.setPrintPos(0, 35);
    u8g.print("             GAME");
    u8g.setFont(u8g_font_9x18);
    u8g.setPrintPos(0, 55);
    u8g.print("By:ALS ROBOT");
  } while (u8g.nextPage());
}
//开始游戏
int chose_game()
{
  int flag = 1;
  int temp = 1;
  Serial.println(analogRead(3));
  while (flag)
  {
    int key = read_key();
      u8g.firstPage();
      do
      {
        u8g.setFont(u8g_font_9x18);
        u8g.setPrintPos(5, 20);
        u8g.print("Snake  <");
      } while (u8g.nextPage());
      temp = 1;
    if (analogRead(3) > 500)
    {
      return temp;
    }
  }
}
//读取摇杆值
int read_key()
{
  int key_temp;
  if(analogRead(2) < 200) {
    key_temp = 5;//UP;
    return key_temp;
  }
  if(analogRead(2)> 800) {
    key_temp = 6;//DOWN;
    return key_temp;
  }
  if(analogRead(1) < 200) {
    key_temp = 7;//LEFT;
    return key_temp;
  }
  if(analogRead(1) > 800) {
    key_temp = 8;//RIGHT;
    return key_temp;
  }
  if (analogRead(3) == HIGH) {
    key_temp = 9;//A;
    return key_temp;
  }
  return 0;
}

void game_over()//游戏结束
{
  snake_length=3;
  snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
  snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
  snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
}
//贪吃蛇主函数
void snake()
{
  int flag = 1; //标志
  snake_x[0] = 15; snake_y[0] = 15;//snake起始坐标
  snake_x[1] = snake_x[0]  - 1; snake_y[1] = snake_y[0];//snake起始坐标
  snake_x[2] = snake_x[1]  - 1; snake_y[2] = snake_y[1];//snake起始坐标
  int snake_dir=8;//初始方向 right
  game_speed=30;
  int food_flag=1;
  Serial.println("snake!");
  food();
  while (flag)
  {
    snake_frame(500);
    delay(game_speed);
    switch(read_key())
    {
      case 5:
        if(snake_dir!=6)
        {
          snake_dir=5;
          break;
        }
      case 6:
        if(snake_dir!=5)
        {
          snake_dir=6;
          break;
        }
        case 7:
        if(snake_dir!=8)
        {
          snake_dir=7;
          break;
        }
        case 8:
        if(snake_dir!=7)
        {
          snake_dir=8;
          break;
        }
        default:break;
    }
    if(snake_eat_food(snake_dir)==1)
    {
      food();
      if(snake_length<10){game_speed=150;}
      if(snake_length<30&&snake_length>=10){game_speed=180;}
      if(snake_length<50&&snake_length>=30){game_speed=200;}
      if(snake_length>=50){game_speed=0;}
    }
    else
    {
      if(snake_knock_wall(snake_dir==1))
      {
        game_over();
        flag=0;
      }
      else
      {
        if(snake_eat_body(snake_dir)==1)
        {
          game_over();
          flag=0;
        }
        else
        {
          change_con(snake_dir);
        }
      }
    }
  }
}
//游戏主界面
void snake_frame(int s)
{
  u8g.firstPage();
  do
  {
    u8g.drawFrame(box_x, box_y, box_x_length, box_y_length);
    u8g.setFont(u8g_font_5x8);
    u8g.setPrintPos(box_x_length + 1, 12);
    u8g.print("Score");
    u8g.setPrintPos(box_x_length + 1, 22);
    u8g.print((snake_length - 3) * 5);
    u8g.setPrintPos(box_x_length + 1, 46);
    u8g.print("Speed");
    u8g.setPrintPos(box_x_length + 1, 56);
    u8g.print(30-s);
    u8g.drawFrame(food_x*snake_body_width+1, food_y*snake_body_width+1, snake_body_width, snake_body_width);//显示食物
    for (int i = 0; i < snake_length; i++)//显示snake
    {
      if(i==0)
      {
        u8g.drawBox(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
      }
      else
      {
        u8g.drawFrame(snake_x[i]*snake_body_width+1, snake_y[i]*snake_body_width+1, snake_body_width, snake_body_width);
      }
    }
  } while (u8g.nextPage());
}
//食物随机坐标生成函数
void food()
{
  int flag = 1;
  while (flag)
  {
    food_x = random(0,(box_x_length-2)/3);
    food_y = random(0,(box_y_length-2)/3);
    for (int i = 0; i < snake_length; i++)
    {
        if((food_x==snake_x[i])&&(food_y==snake_y[i]))
        {
          break;
        }
        flag=0;
    }
  }
}
//移动后坐标变换函数
void change_con(int DIR)
{
  int temp_x[snake_length+2];
  int temp_y[snake_length+2];
  for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
  {
    temp_x[i]=snake_x[i];
    temp_y[i]=snake_y[i];
  }
  switch(DIR)
  {
    case 8: {snake_x[0]+=1;break;}
    case 7: {snake_x[0]-=1;break;}
    case 5: {snake_y[0]-=1;break;}
    case 6: {snake_y[0]+=1;break;}
  }
  for(int i=1;i<snake_length;i++)
  {
    snake_x[i]=temp_x[i-1];
    snake_y[i]=temp_y[i-1];
  }
}
//吃到食物后坐标变换
void change_pos()
{
  int temp_x[snake_length+2];
  int temp_y[snake_length+2];
  for(int i=0;i<snake_length-1;i++)//将旧坐标数据存放到temp数组  最后一位数据无效
  {
    temp_x[i]=snake_x[i];
    temp_y[i]=snake_y[i];
  }
  snake_x[0]=food_x;
  snake_y[0]=food_y;
  for(int i=1;i<snake_length;i++)
  {
    snake_x[i]=temp_x[i-1];
    snake_y[i]=temp_y[i-1];
  }
}
//判断是否吃到食物 0-没有吃到 1-吃到 2-无效
int snake_eat_food(int dir)
{
  int x_temp=snake_x[0];
  int y_temp=snake_y[0];
  switch(dir)
  {
    case 5 :y_temp-=1;break;
    case 6 :y_temp+=1;break;
    case 7 :x_temp-=1;break;
    case 8 :x_temp+=1;break;
  }
  if((x_temp==food_x)&&(y_temp==food_y))
  {
      snake_length+=1;
      change_pos();
      return 1;
  }
  else
  {
    return 0;
  }
}
//判断是否撞墙 0-没有撞到 1-撞到 2-无效
int snake_knock_wall(int dir)
{
  int x_temp=snake_x[0];
  int y_temp=snake_y[0];
  switch(dir)
  {
    case 5 :y_temp-=1;break;
    case 6 :y_temp+=1;break;
    case 7 :x_temp-=1;break;
    case 8 :x_temp+=1;break;
  }
  if(x_temp<0||x_temp>31||y_temp<0||y_temp>19)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}
//判断是否吃到自己 0-没有吃到 1-吃到 2-无效
int snake_eat_body(int dir)
{
  int x_temp=snake_x[0];
  int y_temp=snake_y[0];
  switch(dir)
  {
    case 5 :y_temp-=1;break;
    case 6 :y_temp+=1;break;
    case 7 :x_temp-=1;break;
    case 8 :x_temp+=1;break;
  }
  for(int i=1;i<snake_length;i++)
  {
    if((snake_x[0]==snake_x[i])&&(snake_y[0]==snake_y[i]))
    {
      return 1;
    }
  }
  return 0;
}
   
void loop(void)//主循环函数
{
  while (1)
  {
    switch (chose_game())
    {
      case 1: snake(); break;
      default:break;
    }
  }
}

注意此程序需要使用到库文件,大家可以点击此处,进入奥松机器人官方技术论坛,下载示例程序及库文件。

    * 程序效果

如图所示,为程序上传后 LCD12864 液晶扩展板显示效果

开机画面会停留 2 秒,然后按下 PS2 摇杆模块的按钮,就会进入贪吃蛇游戏,界面如下图所示,快来体验一下吧。

 

----------------------------------------------------------------------------------------------------------------

奥松机器人官网:www.robotbase.cn

微信号:搜索公众号“奥松机器人”

QQ群: 271230889(讨论,解惑)

微博:@奥松机器人基地

----------------------------------------------------------------------------------------------------------------

温馨提示:予人玫瑰,手留余香;如果你喜欢这篇文章,不妨转发推荐给你身边的朋友!