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(讨论,解惑)
微博:@奥松机器人基地
----------------------------------------------------------------------------------------------------------------
温馨提示:予人玫瑰,手留余香;如果你喜欢这篇文章,不妨转发推荐给你身边的朋友!
近期新闻
热门新闻
奥松智能微信