zzz 发表于 2013-7-21 20:59:28

【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); //根据得分加快蛇的速度
}

迷你强 发表于 2013-7-21 21:03:10

:funk:好像很牛x的样子

code-AR 发表于 2013-7-21 21:22:30

霸气那,不知道有没有更多的细节。

幻生幻灭 发表于 2013-7-21 21:28:53

好高级

s2z0g0 发表于 2013-7-22 20:21:25

好厉害呀呀呀呀!

小猪会轮滑 发表于 2013-7-22 20:26:33

:lol:lol:lol:lol:lol:lol:lol很好玩的样子

Bingo 发表于 2013-7-22 21:28:43

大神啊!果断顶!收藏了

chqiyi 发表于 2013-7-23 00:31:44

好多高手啊,这个也佩服啊

宜昌城老张 发表于 2013-7-23 14:35:33

太牛,高手出少年。

mostro 发表于 2013-7-23 16:44:58

厉害啊~~~~{:soso_e179:}

小小弧 发表于 2013-8-18 00:27:30

强帖必须留名

hmjack2008 发表于 2013-10-6 00:33:59

参照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);
}

蓝胖子1 发表于 2013-10-6 22:59:50

o(≧ o ≦)o

wininw 发表于 2014-9-10 18:08:13

不错,就是这个模块有点贵啊。

suoma 发表于 2015-4-20 17:49:58

谢谢分享学习一下
页: [1] 2
查看完整版本: 【Z也来玩点阵】Arduino I2C 8*8点阵玩贪吃蛇游戏~附程序讲解~