复古像素游戏《雷电》前传(红外遥控&16*16 LED点阵)
我看论坛上基本没有教1616LED点阵模块的....
这是之前为我们课程的作业写的,现在贴出来与大家分享~
因为这学期才开始接触Arduino和汇编语言,编的不能保证简练..
而且有不完善的地方,但我们作业的时间有限,实现功能就行了~
现在还在苦逼苦逼的做最终的大作业.....
有兴趣的童鞋可以下下来自己玩一玩~~
红外遥控器4,6控制飞机左右,2发射炮弹,0是reset
哭泣的表情需要摁reset来继续
视频地址:
http://v.youku.com/v_show/id_XNTM1NzcxNTgw.html
ARDUINO 代码复制打印#include <IRremote.h>// 使用IRRemote函数库#define RowA 3 //行信号,驱动138#define RowB 4#define RowC 5#define RowD 6int hc138en=7; //138 使能//使用了硬件SPI,以下脚不能更改#define R1 11 //数据出 MOSI#define CLK 13 //时钟 SCK#define STB 10 //刷新显示 SS#define DATAIN 12 //数据入,读FLASH时有用 MISObyte dots[] ={//子弹0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01};byte plane2[] ={//飞机0xE0,0x00,0x40,0x00,0x70,0x00,0x20,0x00,0x38,0x00,0x10,0x00,0x1C,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x07,0x00,0x02,0x00,0x03,0x80,0x01,0x00,0x01,0xC0,0x00,0x80,0x00,0xE0,0x00,0x40,0x00,0x70,0x00,0x20,0x00,0x38,0x00,0x10,0x00,0x1C,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x07,0x00,0x02};byte cry[]={ //哭泣表情0x00,0x00,0x00,0x00,0xFC,0x3F,0xFC,0x3F,0x21,0x84,0x21,0x84,0x23,0xC4,0x26,0x64,0x24,0x24,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x00,0x00,0x00,0x00};//红外const int irReceiverPin = 2;// 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口decode_results results; // 定义results变量为红外结果存放位置long IRright=0x00FF5AA5; //right 6long IRleft= 0x00FF10EF; //left 4long IRfire= 0x00FF18E7; //fire 2long IRreset=0x00FF6897; //reset 0void spi_transfer(volatile char data){SPDR = data; // Start the transmissionwhile (!(SPSR & (1<<SPIF))) // Wait the end of the transmission //SPSR:程序状态保存寄存器{ ;}}//输出行void hc138sacn(byte r){ digitalWrite(RowA,!(r & 0x01));digitalWrite(RowB,!(r & 0x02));digitalWrite(RowC,!(r & 0x04));digitalWrite(RowD,!(r & 0x08));}void setup () {pinMode(RowA, OUTPUT);pinMode(RowB, OUTPUT);pinMode(RowC, OUTPUT);pinMode(RowD, OUTPUT); //138片选pinMode(hc138en, OUTPUT); //138 使能pinMode(R1, OUTPUT);//DIpinMode(CLK, OUTPUT); //时钟pinMode(STB, OUTPUT); //Latch锁存pinMode(DATAIN, INPUT); //无用,但SPI必须写Serial.begin(19200);//SPI硬件设置//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,//sample on leading edge of clk,system clock/4 rate (fastest)SPCR = (1<<SPE)|(1<<MSTR);delay(10);irrecv.enableIRIn(); // 启动红外解码}byte row;int count;//子弹部分byte rowb[6];//子弹所在行数int time[6];//计时int post[6];//position(column)int number;//计数int temp;//交换用//洞穴部分int timec; //计时int numberc;//计数byte cave[34]={ //洞穴初始化数据0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07};int fail=1; void loop () {if(fail==1){ //哭泣表情 for(int i=15;i>=0;i--) { spi_transfer(~(cry[i
2])); spi_transfer(~(cry[i2+1])); digitalWrite(hc138en, 1); //关闭显示 hc138sacn(15-i); //换行 digitalWrite(STB, 0); //595刷新 digitalWrite(STB, 1); delayMicroseconds(500) ; //节电用, digitalWrite(hc138en, 0); //开启显示 delayMicroseconds(500) ; //刷新频率调 } if (irrecv.decode(&results)) { // 解码成功,把数据放入results变量中 // 把数据输入到串口 if (results.value ==IRreset ) //reset { fail=0; //飞机部分 count=8; //子弹部分 byte rowb[6]={ 2,2,2,2,2,2 };//子弹所在行数 int time[6]={ 0,0,0,0,0,0 };//计时 int post[6]={ 0,0,0,0,0,0 };//position(column) number=0;//计数 temp=0;//交换用 //洞穴部分 timec=0; //计时 numberc=0;//计数 byte cave[34]={ //洞穴初始化数据 0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07, 0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07, 0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07, 0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07 }; } irrecv.resume(); // 继续等待接收下一组信号 }}else{ int fire=0; if (irrecv.decode(&results)) { // 解碼成功,收到一組紅外線訊號 if (results.value ==IRright ) //right { count=count-1; } else if (results.value ==IRleft ) //left { count=count+1; } if (results.value ==IRfire ) //fire { fire=1; } if(count>14) count=14; if(count<1) count=1; irrecv.resume(); // 继续等待接收下一组信号 } //飞机部分 for(row=1;row<3;row++) { if(row==1) { spi_transfer(~(plane2[count4-4])); spi_transfer(~(plane2[count4-3])); } if(row==2) { spi_transfer(~(plane2[count4-2])); spi_transfer(~(plane2[count4-1])); } digitalWrite(hc138en, 1); //关闭显示 hc138sacn(row); //换行 digitalWrite(STB, 0); //595刷新 digitalWrite(STB, 1); delayMicroseconds(350) ; //节电用, digitalWrite(hc138en, 0); //开启显示 delayMicroseconds(350) ; // } //多发炮弹部分 if(fire==1) { number=temp; rowb[number]=3; post[number]=count; temp=number+1; if(temp==6) temp=0; } for(int i=0;i<=5;i++) { if(rowb[i]>=3) { spi_transfer(~(dots[post[i]2])); spi_transfer(~(dots[post[i]2+1])); time[i]++; digitalWrite(hc138en, 1); //关闭显示 hc138sacn(rowb[i]); //换行 digitalWrite(STB, 0); //595刷新 digitalWrite(STB, 1); delayMicroseconds(250) ; //节电用, digitalWrite(hc138en, 0); //开启显示 delayMicroseconds(250) ; //刷新频率调,差不多120HZ,1/32间隔 if(time[i]==30) { rowb[i]=rowb[i]+1; time[i]=0; } if(rowb[i]>15) rowb[i]=2; } } //洞穴部分 for(int i=0;i<=15;i++) { spi_transfer(~(cave[i2])); spi_transfer(~(cave[i2+1])); digitalWrite(hc138en, 1); //关闭显示 hc138sacn(i); //换行 digitalWrite(STB, 0); //595刷新 digitalWrite(STB, 1); delayMicroseconds(100) ; //节电用, digitalWrite(hc138en, 0); //开启显示 delayMicroseconds(100) ; //刷新频率调 if(i==0) { timec=(timec+1)%100; if(numberc<200){ cave[32]=(random(0,3)<<random(0,5)|0x80); cave[33]=(random(0,3)<<random(1,6)|0x01); } else if(numberc<500){ cave[32]=(random(0,4)<<random(0,5)|0x80); cave[33]=(random(0,4)<<random(1,6)|0x01); } else if(numberc<=900){ cave[32]=(random(0,8)<<random(0,4)|0x80); cave[33]=(random(0,8)<<random(1,5)|0x01); } else{ numberc=900; cave[32]=(random(0,8)<<random(0,4)|0x80); cave[33]=(random(0,8)<<random(1,5)|0x01); } } if(timec==0) { cave[i2]=cave[i2+2]; cave[i2+1]=cave[i2+3]; numberc++; } } for(int j=0;j<=15;j++) { for(int k=0;k<=5;k++) { if(rowb[k]==j) { //用于判断子弹打下哪个B是子弹,C是目标 B^C 异或 if((dots[post[k]2]&cave[j2])||(dots[post[k]2+1]&cave[j2+1])) { cave[j2]=dots[post[k]2]^cave[j2]; cave[j2+1]=dots[post[k]2+1]^cave[j2+1]; rowb[k]=2; } } } //判断飞机是否接触洞穴 if(j==1) if((plane2[count4-4]&cave[j2])||(plane2[count4-3]&cave[j2+1])) fail=1; if(j==2) if((plane2[count4-2]&cave[j2])||(plane2[count4-1]&cave[j2+1])) fail=1; }}}#include <IRremote.h>// 使用IRRemote函数库
2]));
#define RowA 3 //行信号,驱动138
#define RowB 4
#define RowC 5
#define RowD 6
int hc138en=7; //138 使能
//使用了硬件SPI,以下脚不能更改
#define R1 11 //数据出 MOSI
#define CLK 13 //时钟 SCK
#define STB 10 //刷新显示 SS
#define DATAIN 12 //数据入,读FLASH时有用 MISO
byte dots[] ={//子弹
0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,
0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,
0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x10,
0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01
};
byte plane2[] ={//飞机
0xE0,0x00,0x40,0x00,
0x70,0x00,0x20,0x00,
0x38,0x00,0x10,0x00,
0x1C,0x00,0x08,0x00,
0x0E,0x00,0x04,0x00,
0x07,0x00,0x02,0x00,
0x03,0x80,0x01,0x00,
0x01,0xC0,0x00,0x80,
0x00,0xE0,0x00,0x40,
0x00,0x70,0x00,0x20,
0x00,0x38,0x00,0x10,
0x00,0x1C,0x00,0x08,
0x00,0x0E,0x00,0x04,
0x00,0x07,0x00,0x02
};
byte cry[]={ //哭泣表情
0x00,0x00,0x00,0x00,0xFC,0x3F,0xFC,0x3F,
0x21,0x84,0x21,0x84,0x23,0xC4,0x26,0x64,
0x24,0x24,0x20,0x04,0x20,0x04,0x20,0x04,
0x20,0x04,0x20,0x04,0x00,0x00,0x00,0x00};
//红外
const int irReceiverPin = 2;// 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口
IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口
decode_results results; // 定义results变量为红外结果存放位置
long IRright=0x00FF5AA5; //right 6
long IRleft= 0x00FF10EF; //left 4
long IRfire= 0x00FF18E7; //fire 2
long IRreset=0x00FF6897; //reset 0
void spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
//SPSR:程序状态保存寄存器
{
;
}
}
//输出行
void hc138sacn(byte r){
digitalWrite(RowA,!(r & 0x01));
digitalWrite(RowB,!(r & 0x02));
digitalWrite(RowC,!(r & 0x04));
digitalWrite(RowD,!(r & 0x08));
}
void setup () {
pinMode(RowA, OUTPUT);
pinMode(RowB, OUTPUT);
pinMode(RowC, OUTPUT);
pinMode(RowD, OUTPUT); //138片选
pinMode(hc138en, OUTPUT); //138 使能
pinMode(R1, OUTPUT);//DI
pinMode(CLK, OUTPUT); //时钟
pinMode(STB, OUTPUT); //Latch锁存
pinMode(DATAIN, INPUT); //无用,但SPI必须写
Serial.begin(19200);
//SPI硬件设置
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 rate (fastest)
SPCR = (1<<SPE)|(1<<MSTR);
delay(10);
irrecv.enableIRIn(); // 启动红外解码
}
byte row;
int count;
//子弹部分
byte rowb[6];//子弹所在行数
int time[6];//计时
int post[6];//position(column)
int number;//计数
int temp;//交换用
//洞穴部分
int timec; //计时
int numberc;//计数
byte cave[34]={ //洞穴初始化数据
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07};
int fail=1;
void loop () {
if(fail==1)
{ //哭泣表情
for(int i=15;i>=0;i--)
{
spi_transfer(~(cry[i
spi_transfer(~(cry[i2+1]));
digitalWrite(hc138en, 1); //关闭显示
hc138sacn(15-i); //换行
digitalWrite(STB, 0); //595刷新
digitalWrite(STB, 1);
delayMicroseconds(500) ; //节电用,
digitalWrite(hc138en, 0); //开启显示
delayMicroseconds(500) ; //刷新频率调
}
if (irrecv.decode(&results)) { // 解码成功,把数据放入results变量中
// 把数据输入到串口
if (results.value ==IRreset ) //reset
{
fail=0;
//飞机部分
count=8;
//子弹部分
byte rowb[6]={
2,2,2,2,2,2 };//子弹所在行数
int time[6]={
0,0,0,0,0,0 };//计时
int post[6]={
0,0,0,0,0,0 };//position(column)
number=0;//计数
temp=0;//交换用
//洞穴部分
timec=0; //计时
numberc=0;//计数
byte cave[34]={ //洞穴初始化数据
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xFC,0x3F,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,
0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07 };
}
irrecv.resume(); // 继续等待接收下一组信号
}
}
else
{
int fire=0;
if (irrecv.decode(&results))
{
// 解碼成功,收到一組紅外線訊號
if (results.value ==IRright ) //right
{
count=count-1;
}
else if (results.value ==IRleft ) //left
{
count=count+1;
}
if (results.value ==IRfire ) //fire
{
fire=1;
}
if(count>14)
count=14;
if(count<1)
count=1;
irrecv.resume(); // 继续等待接收下一组信号
}
//飞机部分
for(row=1;row<3;row++)
{
if(row==1)
{
spi_transfer(~(plane2[count4-4]));
spi_transfer(~(plane2[count4-3]));
}
if(row==2)
{
spi_transfer(~(plane2[count4-2]));
spi_transfer(~(plane2[count4-1]));
}
digitalWrite(hc138en, 1); //关闭显示
hc138sacn(row); //换行
digitalWrite(STB, 0); //595刷新
digitalWrite(STB, 1);
delayMicroseconds(350) ; //节电用,
digitalWrite(hc138en, 0); //开启显示
delayMicroseconds(350) ; //
}
//多发炮弹部分
if(fire==1)
{
number=temp;
rowb[number]=3;
post[number]=count;
temp=number+1;
if(temp==6)
temp=0;
}
for(int i=0;i<=5;i++)
{
if(rowb[i]>=3)
{
spi_transfer(~(dots[post[i]2]));
spi_transfer(~(dots[post[i]2+1]));
time[i]++;
digitalWrite(hc138en, 1); //关闭显示
hc138sacn(rowb[i]); //换行
digitalWrite(STB, 0); //595刷新
digitalWrite(STB, 1);
delayMicroseconds(250) ; //节电用,
digitalWrite(hc138en, 0); //开启显示
delayMicroseconds(250) ; //刷新频率调,差不多120HZ,1/32间隔
if(time[i]==30)
{
rowb[i]=rowb[i]+1;
time[i]=0;
}
if(rowb[i]>15)
rowb[i]=2;
}
}
//洞穴部分
for(int i=0;i<=15;i++)
{
spi_transfer(~(cave[i2]));
spi_transfer(~(cave[i2+1]));
digitalWrite(hc138en, 1); //关闭显示
hc138sacn(i); //换行
digitalWrite(STB, 0); //595刷新
digitalWrite(STB, 1);
delayMicroseconds(100) ; //节电用,
digitalWrite(hc138en, 0); //开启显示
delayMicroseconds(100) ; //刷新频率调
if(i==0) {
timec=(timec+1)%100;
if(numberc<200){
cave[32]=(random(0,3)<<random(0,5)|0x80);
cave[33]=(random(0,3)<<random(1,6)|0x01);
}
else if(numberc<500){
cave[32]=(random(0,4)<<random(0,5)|0x80);
cave[33]=(random(0,4)<<random(1,6)|0x01);
}
else if(numberc<=900){
cave[32]=(random(0,8)<<random(0,4)|0x80);
cave[33]=(random(0,8)<<random(1,5)|0x01);
}
else{
numberc=900;
cave[32]=(random(0,8)<<random(0,4)|0x80);
cave[33]=(random(0,8)<<random(1,5)|0x01);
}
}
if(timec==0)
{
cave[i2]=cave[i2+2];
cave[i2+1]=cave[i2+3];
numberc++;
}
}
for(int j=0;j<=15;j++)
{
for(int k=0;k<=5;k++)
{
if(rowb[k]==j)
{
//用于判断子弹打下哪个B是子弹,C是目标 B^C 异或
if((dots[post[k]2]&cave[j2])||(dots[post[k]2+1]&cave[j2+1]))
{
cave[j2]=dots[post[k]2]^cave[j2];
cave[j2+1]=dots[post[k]2+1]^cave[j2+1];
rowb[k]=2;
}
}
}
//判断飞机是否接触洞穴
if(j==1)
if((plane2[count4-4]&cave[j2])||(plane2[count4-3]&cave[j2+1]))
fail=1;
if(j==2)
if((plane2[count4-2]&cave[j2])||(plane2[count4-1]&cave[j*2+1]))
fail=1;
}
}
}
via - 极客工坊