极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 267681|回复: 71

复古像素游戏《雷电》前传(红外遥控&16*16 LED点阵)

  [复制链接]
发表于 2013-4-24 19:18:13 | 显示全部楼层 |阅读模式
我看论坛上基本没有教16*16LED点阵模块的....

这是之前为我们课程的作业写的,现在贴出来与大家分享~

因为这学期才开始接触Arduino和汇编语言,编的不能保证简练..
而且有不完善的地方,但我们作业的时间有限,实现功能就行了~
现在还在苦逼苦逼的做最终的大作业.....

有兴趣的童鞋可以下下来自己玩一玩~~
红外遥控器4,6控制飞机左右,2发射炮弹,0是reset
哭泣的表情需要摁reset来继续

视频地址:
http://v.youku.com/v_show/id_XNTM1NzcxNTgw.html


  1. #include <IRremote.h>  // 使用IRRemote函数库

  2. #define RowA 3 //行信号,驱动138
  3. #define RowB 4
  4. #define RowC 5
  5. #define RowD 6
  6. int hc138en=7; //138 使能
  7. //使用了硬件SPI,以下脚不能更改
  8. #define R1 11 //数据出 MOSI
  9. #define CLK 13 //时钟 SCK
  10. #define STB 10 //刷新显示 SS
  11. #define DATAIN 12 //数据入,读FLASH时有用 MISO

  12. byte dots[] ={//子弹
  13.   0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,
  14.   0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,
  15.   0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x10,
  16.   0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01
  17. };
  18. byte plane2[] ={//飞机
  19.   0xE0,0x00,0x40,0x00,
  20.   0x70,0x00,0x20,0x00,
  21.   0x38,0x00,0x10,0x00,
  22.   0x1C,0x00,0x08,0x00,
  23.   0x0E,0x00,0x04,0x00,
  24.   0x07,0x00,0x02,0x00,
  25.   0x03,0x80,0x01,0x00,
  26.   0x01,0xC0,0x00,0x80,
  27.   0x00,0xE0,0x00,0x40,
  28.   0x00,0x70,0x00,0x20,
  29.   0x00,0x38,0x00,0x10,
  30.   0x00,0x1C,0x00,0x08,
  31.   0x00,0x0E,0x00,0x04,
  32.   0x00,0x07,0x00,0x02
  33. };

  34. byte cry[]={ //哭泣表情
  35.   0x00,0x00,0x00,0x00,0xFC,0x3F,0xFC,0x3F,
  36.   0x21,0x84,0x21,0x84,0x23,0xC4,0x26,0x64,
  37.   0x24,0x24,0x20,0x04,0x20,0x04,0x20,0x04,
  38.   0x20,0x04,0x20,0x04,0x00,0x00,0x00,0x00};



  39. //红外
  40. const int irReceiverPin = 2;  // 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
  41. IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
  42. decode_results results;    // 定义results变量为红外结果存放位置

  43. long IRright=0x00FF5AA5;    //right 6
  44. long IRleft= 0x00FF10EF;     //left 4
  45. long IRfire= 0x00FF18E7;         //fire 2
  46. long IRreset=0x00FF6897;        //reset 0  

  47. void spi_transfer(volatile char data)
  48. {
  49.   SPDR = data; // Start the transmission
  50.   while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
  51.     //SPSR:程序状态保存寄存器
  52.   {
  53.     ;
  54.   }
  55. }

  56. //输出行
  57. void hc138sacn(byte r){
  58.   digitalWrite(RowA,!(r & 0x01));
  59.   digitalWrite(RowB,!(r & 0x02));
  60.   digitalWrite(RowC,!(r & 0x04));
  61.   digitalWrite(RowD,!(r & 0x08));
  62. }

  63. void setup () {
  64.   pinMode(RowA, OUTPUT);
  65.   pinMode(RowB, OUTPUT);
  66.   pinMode(RowC, OUTPUT);
  67.   pinMode(RowD, OUTPUT); //138片选
  68.   pinMode(hc138en, OUTPUT); //138 使能
  69.   pinMode(R1, OUTPUT);//DI
  70.   pinMode(CLK, OUTPUT); //时钟
  71.   pinMode(STB, OUTPUT); //Latch锁存
  72.   pinMode(DATAIN, INPUT); //无用,但SPI必须写
  73.   Serial.begin(19200);
  74.   //SPI硬件设置
  75.   //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  76.   //sample on leading edge of clk,system clock/4 rate (fastest)
  77.   SPCR = (1<<SPE)|(1<<MSTR);
  78.   delay(10);

  79.   irrecv.enableIRIn();   // 启动红外解码
  80. }

  81. byte row;
  82. int count;
  83. //子弹部分
  84. byte rowb[6];  //子弹所在行数
  85. int time[6];  //计时
  86. int post[6];//position(column)
  87. int number;//计数
  88. int temp;//交换用
  89. //洞穴部分
  90. int timec; //计时
  91. int numberc;//计数
  92. byte cave[34]={ //洞穴初始化数据
  93.   0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
  94.   0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07,
  95.   0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
  96.   0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07};

  97. int fail=1;      
  98. void loop () {
  99.   if(fail==1)
  100.   {      //哭泣表情
  101.     for(int i=15;i>=0;i--)
  102.     {
  103.       spi_transfer(~(cry[i*2]));
  104.       spi_transfer(~(cry[i*2+1]));

  105.       digitalWrite(hc138en, 1); //关闭显示
  106.       hc138sacn(15-i); //换行
  107.       digitalWrite(STB, 0); //595刷新
  108.       digitalWrite(STB, 1);
  109.       delayMicroseconds(500) ; //节电用,
  110.       digitalWrite(hc138en, 0); //开启显示
  111.       delayMicroseconds(500) ; //刷新频率调
  112.     }
  113.     if (irrecv.decode(&results)) {   // 解码成功,把数据放入results变量中
  114.       // 把数据输入到串口
  115.       if (results.value ==IRreset ) //reset
  116.       {   
  117.         fail=0;
  118.         //飞机部分
  119.         count=8;
  120.         //子弹部分
  121.         byte rowb[6]={
  122.           2,2,2,2,2,2        };  //子弹所在行数
  123.         int time[6]={
  124.           0,0,0,0,0,0        };  //计时
  125.         int post[6]={
  126.           0,0,0,0,0,0        };//position(column)
  127.         number=0;//计数
  128.         temp=0;//交换用
  129.         //洞穴部分
  130.         timec=0; //计时
  131.         numberc=0;//计数
  132.         byte cave[34]={ //洞穴初始化数据
  133.           0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
  134.           0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07,
  135.           0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
  136.           0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07        };

  137.       }
  138.       irrecv.resume();    // 继续等待接收下一组信号
  139.     }
  140.   }
  141.   else
  142.   {
  143.     int fire=0;
  144.     if (irrecv.decode(&results))
  145.     {         
  146.       // 解碼成功,收到一組紅外線訊號
  147.       if (results.value ==IRright ) //right
  148.       {        
  149.         count=count-1;      
  150.       }
  151.       else if (results.value ==IRleft ) //left
  152.       {        
  153.         count=count+1;      
  154.       }
  155.       if (results.value ==IRfire ) //fire
  156.       {        
  157.         fire=1;              
  158.       }

  159.       if(count>14)
  160.         count=14;
  161.       if(count<1)
  162.         count=1;
  163.       irrecv.resume();    // 继续等待接收下一组信号
  164.     }
  165.     //飞机部分
  166.     for(row=1;row<3;row++)
  167.     {
  168.       if(row==1)   
  169.       {
  170.         spi_transfer(~(plane2[count*4-4]));
  171.         spi_transfer(~(plane2[count*4-3]));
  172.       }
  173.       if(row==2)
  174.       {
  175.         spi_transfer(~(plane2[count*4-2]));
  176.         spi_transfer(~(plane2[count*4-1]));
  177.       }            

  178.       digitalWrite(hc138en, 1); //关闭显示
  179.       hc138sacn(row); //换行
  180.       digitalWrite(STB, 0); //595刷新
  181.       digitalWrite(STB, 1);
  182.       delayMicroseconds(350) ; //节电用,
  183.       digitalWrite(hc138en, 0); //开启显示
  184.       delayMicroseconds(350) ; //
  185.     }

  186.     //多发炮弹部分
  187.     if(fire==1)
  188.     {
  189.       number=temp;
  190.       rowb[number]=3;  
  191.       post[number]=count;
  192.       temp=number+1;
  193.       if(temp==6)
  194.         temp=0;
  195.     }
  196.     for(int i=0;i<=5;i++)
  197.     {
  198.       if(rowb[i]>=3)
  199.       {
  200.         spi_transfer(~(dots[post[i]*2]));
  201.         spi_transfer(~(dots[post[i]*2+1]));
  202.         time[i]++;
  203.         digitalWrite(hc138en, 1); //关闭显示
  204.         hc138sacn(rowb[i]); //换行
  205.         digitalWrite(STB, 0); //595刷新
  206.         digitalWrite(STB, 1);
  207.         delayMicroseconds(250) ; //节电用,
  208.         digitalWrite(hc138en, 0); //开启显示
  209.         delayMicroseconds(250) ; //刷新频率调,差不多120HZ,1/32间隔

  210.         if(time[i]==30)
  211.         {
  212.           rowb[i]=rowb[i]+1;
  213.           time[i]=0;
  214.         }
  215.         if(rowb[i]>15)
  216.           rowb[i]=2;
  217.       }
  218.     }

  219.     //洞穴部分

  220.     for(int i=0;i<=15;i++)
  221.     {
  222.       spi_transfer(~(cave[i*2]));
  223.       spi_transfer(~(cave[i*2+1]));

  224.       digitalWrite(hc138en, 1); //关闭显示
  225.       hc138sacn(i); //换行
  226.       digitalWrite(STB, 0); //595刷新
  227.       digitalWrite(STB, 1);
  228.       delayMicroseconds(100) ; //节电用,
  229.       digitalWrite(hc138en, 0); //开启显示
  230.       delayMicroseconds(100) ; //刷新频率调

  231.       if(i==0) {
  232.         timec=(timec+1)%100;
  233.         if(numberc<200){
  234.           cave[32]=(random(0,3)<<random(0,5)|0x80);
  235.           cave[33]=(random(0,3)<<random(1,6)|0x01);
  236.         }
  237.         else if(numberc<500){
  238.           cave[32]=(random(0,4)<<random(0,5)|0x80);
  239.           cave[33]=(random(0,4)<<random(1,6)|0x01);
  240.         }
  241.         else if(numberc<=900){
  242.           cave[32]=(random(0,8)<<random(0,4)|0x80);
  243.           cave[33]=(random(0,8)<<random(1,5)|0x01);
  244.         }
  245.         else{
  246.           numberc=900;
  247.           cave[32]=(random(0,8)<<random(0,4)|0x80);
  248.           cave[33]=(random(0,8)<<random(1,5)|0x01);
  249.         }         
  250.       }

  251.       if(timec==0)
  252.       {   
  253.         cave[i*2]=cave[i*2+2];
  254.         cave[i*2+1]=cave[i*2+3];
  255.         numberc++;
  256.       }

  257.     }

  258.     for(int j=0;j<=15;j++)
  259.     {
  260.       for(int k=0;k<=5;k++)
  261.       {
  262.         if(rowb[k]==j)
  263.         {
  264.           //用于判断子弹打下哪个  B是子弹,C是目标 B^C 异或   
  265.           if((dots[post[k]*2]&cave[j*2])||(dots[post[k]*2+1]&cave[j*2+1]))
  266.           {
  267.             cave[j*2]=dots[post[k]*2]^cave[j*2];
  268.             cave[j*2+1]=dots[post[k]*2+1]^cave[j*2+1];
  269.             rowb[k]=2;
  270.           }
  271.         }     
  272.       }
  273.       //判断飞机是否接触洞穴   
  274.       if(j==1)
  275.         if((plane2[count*4-4]&cave[j*2])||(plane2[count*4-3]&cave[j*2+1]))
  276.           fail=1;
  277.       if(j==2)
  278.         if((plane2[count*4-2]&cave[j*2])||(plane2[count*4-1]&cave[j*2+1]))     
  279.           fail=1;
  280.     }
  281.   }
  282. }
复制代码

评分

参与人数 1 +1 收起 理由
幻生幻灭 + 1 MM声音真好听!

查看全部评分

回复

使用道具 举报

发表于 2013-4-24 21:43:47 | 显示全部楼层
我不过是看个视频,结果沙发就丢了、
回复 支持 1 反对 0

使用道具 举报

发表于 2013-4-24 21:15:43 | 显示全部楼层
哇,妹子做的给力呀~ 16×16点阵板上的是595吧?
回复 支持 反对

使用道具 举报

发表于 2013-4-24 21:23:46 | 显示全部楼层
妹子威武。。。。。
回复 支持 反对

使用道具 举报

发表于 2013-4-24 21:40:50 | 显示全部楼层
妹子好威武。。。你们啥专业。。。居然布置这种作业。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:11:46 | 显示全部楼层
lyili 发表于 2013-4-24 21:15
哇,妹子做的给力呀~ 16×16点阵板上的是595吧?

这是两个妹子的工作成果~~
我们专业叫工业设计......悄悄的说,其实老师要求的没有这么难

LED点阵是网上直接买的,用的595和138
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:15:10 | 显示全部楼层
弘毅 发表于 2013-4-24 21:40
妹子好威武。。。你们啥专业。。。居然布置这种作业。。

对各位大神敬仰已久!老师推荐的初学的教程就是这个论坛上面的,还有Cookbook

应该说,这个论坛对我们的帮助很大~~
回复 支持 反对

使用道具 举报

发表于 2013-4-24 22:16:04 | 显示全部楼层
JasmineL 发表于 2013-4-24 22:15
对各位大神敬仰已久!老师推荐的初学的教程就是这个论坛上面的,还有Cookbook

应该说,这个论坛对我们 ...

弱弱的问问。。是不是浙大的妹纸。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:17:18 | 显示全部楼层
弘毅 发表于 2013-4-24 22:16
弱弱的问问。。是不是浙大的妹纸。。。

被发现了么......
回复 支持 反对

使用道具 举报

发表于 2013-4-24 22:18:29 | 显示全部楼层
JasmineL 发表于 2013-4-24 22:17
被发现了么......

{:soso_e104:} 看来我第六感还是很准的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:20:16 | 显示全部楼层
弘毅 发表于 2013-4-24 22:18
看来我第六感还是很准的

有机会欢迎来看我们课程的大作业展览~在紫金港
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:22:17 | 显示全部楼层
突然发现加精了...好开心~~
回复 支持 反对

使用道具 举报

发表于 2013-4-24 22:22:24 | 显示全部楼层
JasmineL 发表于 2013-4-24 22:20
有机会欢迎来看我们课程的大作业展览~在紫金港

{:soso_e103:} 居然有展览。。。几号开始呀在紫金港啥地方。。。偶们走绕城过去也不远。。。这要去看的。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 22:26:32 | 显示全部楼层
弘毅 发表于 2013-4-24 22:22
居然有展览。。。几号开始呀在紫金港啥地方。。。偶们走绕城过去也不远。。。这要去看的。 ...

应该是定在5月9号,与上一届的毕设一起展览。应该是在月牙楼1层

我们都是初学,软硬件基础基本为零...大神期待不要太高嘛...会有压力的~~
回复 支持 反对

使用道具 举报

发表于 2013-4-24 22:27:00 | 显示全部楼层
{:soso_e183:}学姐威武!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 22:39 , Processed in 0.042652 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表