【Z也来玩点阵】Arduino I2C 8*8点阵玩贪吃蛇游戏~附程序讲解~
本帖最后由 zzz 于 2019-5-17 09:25 编辑今天中午Z收到了迷你强这两天一直在玩的I2C点阵,这种小8*8点阵最大的特点是内置恒流驱动,而且是IIC控制,支持arduino最新的GFX图形库,所以做起交互来可谓是相当的简单,下午随手写了一个贪吃蛇游戏,用的是大家都能看懂的算法~没有用C上常用的贪吃蛇算法来做,因为那样初学者理解起来可能会很困难,所以就特地用最简单的方式来写~先上一段测试视频~
http://v.youku.com/v_show/id_XNTg1NzY2MzUy.html
代码详解
#include <Wire.h> //I2C链接库
#include "Adafruit_LEDBackpack.h" //点阵驱动库
#include "Adafruit_GFX.h" //Arduino图形库
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix(); //设置I2C点阵型号
static uint8_t __attribute__ ((progmem)) z[]={B01111110,B00000010,B00000100,B00001000,B00010000,B00100000,B01000000,B01111110}; //小Z的logo代码,其实就是一个一个点的量灭组成的,可以自己写~
int speedS=8; //贪吃蛇的初始速度
int socre=0; //游戏起始得分
int FX,FY; //事物的坐标
int SX,SY; //蛇头的坐标
int KEY,K; //串口取得按键码和比对后的按键码,这里后面有说明
char s; //蛇身体坐标集合,一共3个点,6个元素
void setup() {
Serial.begin(9600);
RANDOM(); //获取一个随机食物坐标
s=0;s=2;s=1;s=2;s=2;s=2; //初始化蛇的身体坐标
KEY=4; //初始化按键码,实际上就是行进方向,用1、2、3、4来代替4个正交方向
matrix.begin(0x70); //设定IIC屏幕地址
matrix.clear();//屏幕清屏
matrix.writeDisplay();//屏幕显示
matrix.setRotation(3);//设置屏幕显示方向
matrix.clear();
Logo(); //绘制开机Logo,哈哈其实就是小Z的logo,视频里看不清,自己玩下就懂了~
matrix.writeDisplay();
delay(1000);
matrix.setTextWrap(false);//设置字体平滑模式
matrix.setTextSize(1); //设置字体大小
matrix.setTextColor(2); //设定LED颜色,这里说明下,除了双色点阵,其他都用2表示点亮LED,0表示熄灭~
for (int8_t x=7; x>=-59; x--) {
matrix.clear();
matrix.setCursor(x,0);
matrix.print("READY!!! GO");
matrix.writeDisplay();
delay(70);
}
//循环绘制文字,获得滚动效果
matrix.clear();
for(int i=1;i<=6;i+=2)
{
matrix.drawPixel(s, s, 2);
}
matrix.writeDisplay();
delay(400);
}
//循环绘制蛇的身体,实际上就是3个点咯~
void RANDOM()
{
FX=random(0, 7);
FY=random(0, 7);
}
//随机食物获取函数
void Delay(int timeF)
{
for(int t=1;t<=timeF;t++)
{
matrix.drawPixel(FX, FY, 2);
matrix.writeDisplay();
delay(50);
matrix.drawPixel(FX, FY, 0);
matrix.writeDisplay();
delay(50);
}
}
//重点说一下,这个是演示函数,实际上通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动,来让大家不断的看到~
void Logo()
{
for (int x=1;x<=6;x++) {
matrix.drawPixel(x, 0, 2);
matrix.writeDisplay();
delay(35);
}
for (int x=1;x<=6;x++) {
matrix.drawPixel(7-x, x, 2);
matrix.writeDisplay();
delay(35);
}
for (int x=1;x<=6;x++) {
matrix.drawPixel(x, 7, 2);
matrix.writeDisplay();
delay(35);
}
for (int x=1;x<=45;x++) {
matrix.clear();
matrix.writeDisplay();
delay(x);
matrix.drawBitmap(0,0,z,8,8,2);
matrix.writeDisplay();
delay(x);
}
}
//Z Logo绘制函数,看不懂可以跳过~~~不过还是蛮简单的,仔细看下就明白了~
void gameover()
{
for (int8_t x=7; x>=-125; x--) {
matrix.clear();
matrix.setCursor(x,0);
matrix.print("GAME OVER YOUR SOCRE:");
matrix.writeDisplay();
delay(70);
}
//GameOver函数,显示游戏结束和得分
for (int8_t x=7; x>=-39; x--) {
matrix.clear();
matrix.setCursor(x,0);
matrix.print(socre);
matrix.writeDisplay();
delay(70);
}
s=0;s=2;s=1;s=2;s=2;s=2;//重置蛇的坐标
}
void loop() {
if (Serial.available()){
K=Serial.read()-48;//获得串口发送的按键信息
if (K==1&&KEY!=2 ){
KEY=K;
}
if (K==2&&KEY!=1 ){
KEY=K;
}
if (K==3&&KEY!=4 ){
KEY=K;
}
if (K==4&&KEY!=3 ){
KEY=K;
}
}
//重点,这里是在比对是否方向和目前蛇的行进方向相反,相反就放弃按键
while(Serial.read()>=0); //清空串口缓冲区
matrix.clear();
if(KEY==1){
s=s;s=s;s=s;s=s;s=s-1;
}
if(KEY==2){
s=s;s=s;s=s;s=s;s=s+1;
}
if(KEY==3){
s=s;s=s;s=s;s=s;s=s-1;
}
if(KEY==4){
s=s;s=s;s=s;s=s;s=s+1;
}
//根据按键来移动蛇的身体
for(int i=1;i<=6;i+=2)
{
matrix.drawPixel(s, s, 2);
}
matrix.writeDisplay();
Delay(speedS);
SX=s;SY=s; //获取蛇头的坐标
if(SY<0 or SY>7 or SX<0 or SX>7){
gameover();
}
//判断是否超出边框,超出就跳转到GameOver
if(SY==FY&&SX==FX){
socre=socre+1;
RANDOM();
}
//判断是否吃到了食物~吃到了就会加分和重新随机生成食物~
speedS=speedS-int(socre/3); //根据得分加快蛇的速度
}
:funk:好像很牛x的样子 霸气那,不知道有没有更多的细节。 好高级 好厉害呀呀呀呀! :lol:lol:lol:lol:lol:lol:lol很好玩的样子 大神啊!果断顶!收藏了 好多高手啊,这个也佩服啊 太牛,高手出少年。 厉害啊~~~~{:soso_e179:} 强帖必须留名 参照LZ的原理, 也写了一个 “MAX7219 8x8 LED" 贪吃蛇游戏...
#include "LedControl.h"
/*
MAX7219 8x8 LED
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD (CS)
*/
LedControl lc=LedControl(12,11,10,1);
int xValue; // JoyStick-Y
int yValue; // JoyStick-X
int SkValue; // JokStick-Click
int Sxy= {{2,4},{1,4},{0,4}}; //蛇身体坐标集合,一共3个点
int speedS=8; //贪吃蛇的初始速度
int FX,FY; //食物的坐标
int SX,SY; //蛇头的坐标
char KEY ='d'; // up, down, left, right
int Speed =8;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,2);
/* and clear the display */
lc.clearDisplay(0);
Serial.begin(9600);
delay(5000);
pinMode(9,INPUT);
//循环绘制蛇的身体,3个点
resetSnake();
}
void loop() {
//获得 按键信息
xValue = analogRead(A0); // JoyStick-Y
yValue = analogRead(A1); // JoyStick-X
SkValue = digitalRead(9); // JokStick-Click
//获得的按键信息 发送串口
Serial.print("Y : ");
Serial.println(yValue);
Serial.print("X : ");
Serial.println(xValue);
Serial.print("Sk : ");
Serial.println(SkValue);
//获得 按键信息
if(yValue>700)
{
KEY='r';
}
if(yValue<300) {
KEY='l';
}
if(xValue>700)
{
KEY='d';
}
if(xValue<300) {
KEY='u';
}
if(SkValue ==0)
{
lc.clearDisplay(0);
resetSnake();
}
drawSnake(LOW);
if(KEY =='u') {
SX =Sxy-1; // up
SY =Sxy;
/* 根据按键来移动蛇的身体
Sxy = Sxy;
Sxy = Sxy;
Sxy = Sxy;
Sxy = Sxy;
*/
for (int i=2; i>0; i--) {
Sxy = Sxy;
Sxy = Sxy;
}
Sxy =SX;
Sxy =SY;
}
if(KEY =='d') {
SX =Sxy+1; // down
SY =Sxy;
for (int i=2; i>0; i--) {
Sxy = Sxy;
Sxy = Sxy;
}
Sxy =SX;
Sxy =SY;
}
if(KEY =='r') {
SX =Sxy;
SY =Sxy+1; // right
for (int i=2; i>0; i--) {
Sxy = Sxy;
Sxy = Sxy;
}
Sxy =SX;
Sxy =SY;
}
if(KEY =='l') {
SX =Sxy;
SY =Sxy-1; // left
for (int i=2; i>0; i--) {
Sxy = Sxy;
Sxy = Sxy;
}
Sxy =SX;
Sxy =SY;
}
//判断是否超出边框,超出就跳转到GameOver
if(SY<0 || SY>7 || SX<0 || SX>7) {
gameover();
resetSnake();
}
//判断是否吃到了食物~吃到就会加分和重新随机生成食物~
if(Sxy==FX && Sxy==FY) {
RANDOM();
Speed --;
if (Speed<0) {
Speed = 0;
}
}
drawSnake(HIGH);
WAIT(Speed);
}
// 重置蛇的坐标
void resetSnake() {
int k=millis()%10 + 1;
for(int i=0; i<k; i++) {
RANDOM(); //获取一个随机食物坐标
}
for (int i=0; i<3; i++) {
// Sxy= {{2,4},{1,4},{0,4}};
Sxy =2-i;
Sxy =4;
}
KEY ='d';
Speed = 8;
WAIT(5);
}
// 绘制蛇的函数
void drawSnake(boolean OnOff) {
for (int i=0; i<3; i++) {
lc.setLed(0,Sxy,Sxy,OnOff);
}
}
//随机食物获取函数
void RANDOM()
{
FX=random(0, 7);
FY=random(0, 7);
}
//通过不断闪现食物来完成延迟,这样既可以做到精确延时,也可以让食物不断闪动
void WAIT(int timeF)
{
for(int t=1;t<=timeF;t++) {
lc.setLed(0,FX,FY,HIGH);
delay(50);
lc.setLed(0,FX,FY,LOW);
delay(50);
}
}
//GameOver函数,游戏结束
void gameover()
{
for (int j=0; j<10; j++) {
drawSnake(HIGH);
delay(250);
drawSnake(LOW);
delay(150);
}
delay(5000);
}
o(≧ o ≦)o 不错,就是这个模块有点贵啊。 谢谢分享学习一下
页:
[1]
2