这是第一次写博客,保存最近做的一次项目,代码有点长。(可能会有bug,不喜勿喷,纯粹用于个人纪录)。
时间:2020年7月31日
内容:Linux,6818开发板,触摸屏,花样展示图片(轮播,百叶窗,缩放等),视频,音频,2048小游戏
解释都在代码里
//新增音乐相册(可以在相册里点击进入)
//将相册目录改成了缩略图,可点击跳转对应图片。
头文件
#ifndef MYIOHEAD_H_
#define MYIOHEAD_H_
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <dirent.h>
#include <linux/input.h>
#include <termio.h>
#include <bits/signum.h>
#include <signal.h>
#include <semaphore.h>
#endif
头文件不长,是常用的几个。
主代码
#include "myiohead.h"
//花样展示图片
int special_showbmp(char *bmppath)
{
int bmpfd;
int lcdfd;
int i;
int x,y;
int w,h;
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//读取图片的宽和高
lseek(bmpfd,18,SEEK_SET);
read(bmpfd,&w,4);//读取宽
read(bmpfd,&h,4);//读取高
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
// //把转换后的数据写入lcd中
// for(int i = 0;i < h;i++)
// {
// usleep(4000);
// write(lcdfd,&tempbuf[w*i],w*4);
// // *(lcdmem+(j*800)+i)=tempbuf[j*w+i];
// lseek(lcdfd,(800-w)*4,SEEK_CUR);
// }
//把转换后的数据写入lcd中
for (int j = 0; j < h; j++)
{
usleep(4000);
for(int i = 0,n = 0;i < w;i++)
{
*(lcdmem+(j*800)+i)=tempbuf[j*w+i];
//n++;
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//缩放图片
int zoom_showbmp(char *bmppath)
{
int bmpfd;
int lcdfd;
int i;
int x,y;
int w,h;
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//读取图片的宽和高
lseek(bmpfd,18,SEEK_SET);
read(bmpfd,&w,4);//读取宽
read(bmpfd,&h,4);//读取高
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
// //把转换后的数据写入lcd中
for (int j = 0,m = 0; j < (h/2); j++,m = m+2)
{
for(int i = 0,n = 0;i < (w/2);i++,n = n+2)
{
*(lcdmem+(j*800)+i)=tempbuf[m*w+n];
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//普通展示图片
int showbmp(char *bmppath)
{
int bmpfd;
int lcdfd;
int i;
int x,y;
int w,h;
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//读取图片的宽和高
lseek(bmpfd,18,SEEK_SET);
read(bmpfd,&w,4);//读取宽
read(bmpfd,&h,4);//读取高
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
//把转换后的数据写入lcd中
for (int j = 0; j < h; j++)
{
for(int i = 0,n = 0;i < w;i++)
{
*(lcdmem+(j*800)+i)=tempbuf[j*w+i];
//n++;
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
char data[100];
struct doublelist *next;
struct doublelist *fnext;
}dlist;
dlist * init_list()
{
dlist *head = calloc(1,sizeof(dlist));
// head->data = "1.bmp";
//strcpy(head->data, "1.bmp");
head->next = head;
head->fnext = head;
return head;
}
//尾插
int insert_(char * newdata,dlist * head)
{
dlist * p =head;
while(p->next != head)
{
p = p->next;
}
dlist *newnode = calloc(1,sizeof(dlist));
//newnode->data = newdata;
strcpy(newnode->data, newdata);
newnode->next = head;
p->next = newnode;
head->fnext = newnode;
newnode->fnext = p;
}
//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
DIR * dir = opendir(path);
if (NULL == dir)
{
perror("打开目录失败!");
exit(0);
}
struct dirent * rd = NULL;
while((rd = readdir(dir)) != NULL)
{
//printf("d_name : %s\n", rd->d_name);
if (rd->d_type == DT_REG)
{
//printf("这是普通文件!\n");
if (strstr(rd->d_name,".bmp") != 0)
{
insert_(rd->d_name,head);
}
}
// if (rd->d_type == DT_DIR)
// {
// printf("这是目录!\n");
// system("cp *.txt ..");
// system("cp *.txt abs");
// }
}
return 0;
}
//获取触摸屏坐标
int get_x_y(int *touch_x,int *touch_y)
{
int flag = 0;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
flag++;
* touch_x = (myevent.value*800)/1024;
}
if(myevent.code==ABS_Y) //y坐标
{
flag++;
* touch_y = (myevent.value*480)/600;
}
if (2 == flag)
{
flag = 0;
break;
}
}
}
close(to);
}
//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
int flag = 1;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
int count = 1;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
* touch_x1 = (myevent.value*800)/1024;
if (count)
{
* touch_x = (myevent.value*800)/1024;
count = 0;
}
}
if(myevent.code==ABS_Y) //y坐标
{
* touch_y1 = (myevent.value*480)/600;
if (flag)
{
* touch_y = (myevent.value*480)/600;
flag = 0;
}
}
}
if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
{
//count = 0;
//printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
//printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
break;
}
}
close(to);
}
//缩放图片--用于相册缩略图
int zoom1_showbmp(char *bmppath,int num)
{
int bmpfd;
int lcdfd;
int w,h;
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//读取图片的宽和高
lseek(bmpfd,18,SEEK_SET);
read(bmpfd,&w,4);//读取宽
read(bmpfd,&h,4);//读取高
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(int i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(int x=0; x<w; x++)
for(int y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
/*//把转换后的数据写入lcd中,高缩小2倍,宽缩小2倍
for (int j = 0,m = 0; j < (h/2); j++,m = m+2)
{
for(int i = 0,n = 0;i < (w/2);i++,n = n+2)
{
*(lcdmem+(j*800)+i)=tempbuf[m*w+n];
}
}
*/
// //把转换后的数据写入lcd中,高缩小(h/160)倍,宽缩小w/160倍
int a = (num%5)*160;
int b = (num/5)*160;
for (int j = 0,m = 0; j < (h/(h/160)); j = j-b+1,m = m+(h/160))
{
j = j+b;
for(int i = 0,n = 0;i < (w/(w/160));i = i-a+1,n = n+(w/160))
{
i = i + a;
*(lcdmem+(j*800)+i)=tempbuf[m*w+n];
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//登陆和注册
int denglu()
{
char usename[100] = {0};
char newname[100] = {0};
char password[100] = {0};
char newword[100] = {0};
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
//打开保存注册名字的文件
int fd = open("a.txt",O_RDWR);
if (-1 == fd)
{
perror("打开源文件失败");
exit(0);
}
char buf[1000] = {0};
char buff[1000] = {0};
while(1)
{
//注册账号和密码
get_x_y(touch_x,touch_y);
if ((*touch_x>322) &&(*touch_x<361) && (*touch_y>258) && (*touch_y<277) )
{
printf("请输入你想注册的账号!(<=12位)\n");
scanf("%s",newname);
printf("请输入你想注册的密码!(<=12位)\n");
scanf("%s",newword);
lseek(fd,0,SEEK_SET);
write(fd,newname,sizeof(newname));
lseek(fd,12,SEEK_SET);
write(fd,newword,sizeof(newword));
lseek(fd,12,SEEK_SET);
printf("注册成功,请重新登陆\n");
continue;
}
else
{
for (int i = 0; i < 100; ++i)
{
lseek(fd,24*i,SEEK_SET);
read(fd,buf+i,12);//把注册名存到buf中
lseek(fd,24*i+12,SEEK_SET);
read(fd,buff+i,12);//把密码存到buff中
}
printf("请输入用户名!\n");//初始用户名我设置为chenwangxin
scanf("%s",usename);
printf("请输入密码!\n");//初始密码我设置为123456
scanf("%s",password);
if ((strcmp(usename,"chenwangxin") == 0) && (strcmp(password,"123456") == 0))
{
break;
}
int i = 0;
while ((strcmp(usename,buf+i) != 0) || (strcmp(password,buff+i) != 0))
{
i++;
if (i = 99)
{
break;
}
}
if ((strcmp(usename,buf+i) == 0) && (strcmp(password,buff+i) == 0))
{
break;
}
printf("用户名或密码错误,请重新输入!\n");
}
}
}
//我的相册
int myphoto()
{
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
int *touch_x1 = calloc(1,1000);
int *touch_y1 = calloc(1,1000);
dlist *mydlist=init_list();
read_dir("/myphoto/",mydlist);
char a[500] = "/myphoto/";
int page = 0;
int count = 0;
int num = 0;
//计算总共有多少张图片
dlist * p = mydlist;
while(p->next != mydlist)
{
p = p->next;
count++;
}
p = mydlist;
while(p->next != NULL)
{
printf("点击底层中部进入音乐相册,顶层中部进入相册缩略图,点击可跳转对应对应图片。\n");
yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
//上一张
if ((*touch_x<200) &&(*touch_y>360))
{
p = p->fnext;
if (p == mydlist)
{
p = p->fnext;
}
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
//showbmp(a);
printf("a里面的内容%s\n",a );
special_showbmp(a);
}
//下一张
if ((*touch_x>600) && (*touch_y>360))
{
p = p->next;
if (p == mydlist)
{
p = p->next;
}
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
//showbmp(a);
printf("a里面的内容%s\n",a );
special_showbmp(a);
}
//音乐相册
if ((*touch_x>350) && (*touch_x<450) && (*touch_y>360))
{
system("./music_album");
printf("退出音乐后要点击上/下一张回到相册后才能退出哦\n");
bzero(touch_x,1000);
bzero(touch_y,1000);
// continue;
}
//显示目录,加载目录中的照片
if ((*touch_x>300) &&(*touch_x<500) && (*touch_y<66))
{
//开头显示第一页缩略图
int k = 0;
page = 0;
p = mydlist;
while(p->next != mydlist && k<15)
{
k++;
p = p->next;
num++;
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
zoom1_showbmp(a,num-1);
}
num = 0;
p = mydlist;
while(1)
{
//到while循环的顶部了
yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
//向左划,下一页缩略图
if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
{
if (count<=15)
{
printf("所有图片都在这里了噢。\n");
continue;
}
if (page <= count/15)
{
page++;
}
if (page > count/15)
{
if (count%15 == 0)
{
printf("这已经是最后一页了。\n");
if (page > count/15)
{
page--;
}
continue;
}
}
p = mydlist;
for (int i = 0; i < 15*page; i++)
{
p = p->next;
}
k = 0;
while(p->next != mydlist && k<15)
{
k++;
p = p->next;
num++;
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
zoom1_showbmp(a,num-1);
}
}
num = 0;
//向右划,上一页
if( ((*touch_x1-*touch_x) >=80) && (*touch_x1>=*touch_x) )
{
if (page==0)
{
printf("当前已经是第一页了。\n");
continue;
}
page--;
p = mydlist;
for (int i = 0; i < 15*page; i++)
{
p = p->next;
}
k = 0;
while(p->next != mydlist && k<15)
{
k++;
p = p->next;
num++;
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
zoom1_showbmp(a,num-1);
}
}
num = 0;
//跳转点击到的图片
if( ((*touch_x1-*touch_x) <80) && (*touch_x1>=*touch_x) )
{
int h = (*touch_x1/160) + (*touch_y1/160)*5;
p = mydlist->next;
for (int i = 0; i < 15*page; i++)
{
p = p->next;
}
for (int i = 0; i < h; i++)
{
if (p->next != mydlist)
{
p = p->next;
}
else
{
printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
break;
}
}
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
special_showbmp(a);
break;
}
//跳转点击到的图片
if( ((*touch_x-*touch_x1) <80) && (*touch_x>=*touch_x1) )
{
int h = (*touch_x1/160) + (*touch_y1/160)*5;
p = mydlist->next;
for (int i = 0; i < 15*page; i++)
{
p = p->next;
}
for (int i = 0; i < h; i++)
{
if (p->next != mydlist)
{
p = p->next;
}
else
{
printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
break;
}
}
bzero(a,500);
strcpy(a,"/myphoto/");
strcat(a,p->data);
special_showbmp(a);
break;
}
//到while循环的底部了
}
}
//退出相册
if ((*touch_x>742) && (*touch_y<36))
{
break;
}
}
printf("退出了我的相册\n");
}
//我的音乐
int mymusic()
{
printf("左下方为上一首,右下方为上一首\n");
printf("中间为暂停/播放,滑动快进/退\n");
system("./mymusic");
printf("退出了我的音乐\n");
}
//我的视频
int myvideo()
{
printf("左下方为上一集,右下方为上一集\n");
printf("中间为暂停/播放,滑动快进/退\n");
system("./myvideo");
printf("退出了我的视频\n");
}
int main(int argc, char const *argv[])
{
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
showbmp("dl.bmp");
printf("点击登陆或注册后登陆才能进入我的娱乐世界哦\n");
//登陆和注册
denglu();
printf("登陆成功,欢迎进入我的娱乐世界!\n");
showbmp("zjm.bmp");
printf("使用相册和音视频播放器等应用时:左下角为播放上一张/首/个,右下角为播放下一张/首/个,左上角为退出当前应用\n");
while(1)
{
//打开相册
get_x_y(touch_x,touch_y);
if ((*touch_x>22) &&(*touch_x<96) && (*touch_y>144) && (*touch_y<222) )
{
special_showbmp("1.bmp");
sleep(1);
zoom_showbmp("3.bmp");
myphoto();
}
showbmp("zjm.bmp");
//打开音乐播放器
if ((*touch_x>31) &&(*touch_x<102) && (*touch_y>23) && (*touch_y<98) )
{
showbmp("mymp3.bmp");
printf("已经打开音乐播放器,请点击进行播放音乐!\n");
mymusic();
}
showbmp("zjm.bmp");
//打开视频播放器
if ((*touch_x>129) &&(*touch_x<207) && (*touch_y>23) && (*touch_y<108) )
{
printf("已经打开视频播放器,请点击上/下一集进行播放视频!\n");
showbmp("mymp3.bmp");
myvideo();
}
showbmp("zjm.bmp");
if ((*touch_x>119) &&(*touch_x<199) && (*touch_y>140) && (*touch_y<217) )
{
system("./yx1");
}
showbmp("zjm.bmp");
}
return 0;
}
上面的是主代码,2048代码,音频模块,视频模块,新增的音乐相册如下:
(2048还有待改善)
音频模块
//音频模块,下面的视频模块的思路也是一样的
//音频模块
#include "myiohead.h"
//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
int flag = 1;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
int count = 1;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
* touch_x1 = (myevent.value*800)/1024;
if (count)
{
* touch_x = (myevent.value*800)/1024;
count = 0;
}
}
if(myevent.code==ABS_Y) //y坐标
{
* touch_y1 = (myevent.value*480)/600;
if (flag)
{
* touch_y = (myevent.value*480)/600;
flag = 0;
}
}
}
if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
{
//count = 0;
//printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
//printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
break;
}
}
close(to);
}
//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
char data[100];
struct doublelist *next;
struct doublelist *fnext;
}dlist;
dlist * init_list()
{
dlist *head = calloc(1,sizeof(dlist));
// head->data = "1.bmp";
strcpy(head->data, "1.bmp");
head->next = head;
head->fnext = head;
return head;
}
//尾插
int insert_(char * newdata,dlist * head)
{
dlist * p =head;
while(p->next != head)
{
p = p->next;
}
dlist *newnode = calloc(1,sizeof(dlist));
//newnode->data = newdata;
strcpy(newnode->data, newdata);
newnode->next = head;
p->next = newnode;
head->fnext = newnode;
newnode->fnext = p;
}
//读取目录,获得音乐名字
int read_dir(char *path,dlist * head)
{
DIR * dir = opendir(path);
if (NULL == dir)
{
perror("打开目录失败!");
exit(0);
}
struct dirent * rd = NULL;
while((rd = readdir(dir)) != NULL)
{
//printf("d_name : %s\n", rd->d_name);
if (rd->d_type == DT_REG)
{
//printf("这是普通文件!\n");
if (strstr(rd->d_name,".mp3") != 0)
{
insert_(rd->d_name,head);
}
}
// if (rd->d_type == DT_DIR)
// {
// printf("这是目录!\n");
// system("cp *.txt ..");
// system("cp *.txt abs");
// }
}
return 0;
}
void * task(void * n)//播放/暂停/快进/快退/上/下一首音乐
{
int *touch_x1 = calloc(1,1000);
int *touch_y1 = calloc(1,1000);
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
dlist * mydlist = init_list();
read_dir("/myword/2048bmp/",mydlist);
char a[100] = {0};
if (access("/root/myfifo",F_OK) == -1)
{
int ret = mkfifo("/root/myfifo",0777);
if (-1 == ret)
{
perror("创建管道文件失败!");
exit(0);
}
}
int fd = open("/root/myfifo", O_RDWR);
if (-1 == fd)
{
perror("打开管道文件失败!");
exit(0);
}
dlist * p =mydlist;
int count = 0;
int flag = 2;
while(1)
{
yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
if ((*touch_x<200)&&(*touch_y>360))//上一首
{
if (count == 1)
{
system("killall -9 mplayer");
}
p = p->fnext;
if (p == mydlist)
{
p = p->fnext;
}
bzero(a,100);
strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
strcat(a,p->data);
strcat(a," &");
system(a);
count = 1;
flag = 1;
}
if ((*touch_x>600) && (*touch_y>360))//下一首
{
if (count == 1)
{
system("killall -9 mplayer");
}
p = p->next;
if (p == mydlist)
{
p = p->next;
}
bzero(a,100);
strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
strcat(a,p->data);
strcat(a," &");
system(a);
count = 1;
flag = 1;
}
if ((*touch_x>358) && (*touch_x<414) && (*touch_y>203) && (*touch_y<268)) //暂停/播放
{
if (flag == 1)//暂停
{
system("killall -STOP mplayer");
flag = 0;
}
else if (flag == 0)//播放
{
system("killall -CONT mplayer");
flag = 1;
}
}
//快退5秒
if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
{
/// 写入的字节数一定要和实际一模一样,不然会出问题
// 不能快进快退
char msg[] = "seek -5\n";
write (fd,msg,strlen(msg));
}
//快进5s
if((*touch_x1>*touch_x)&&((*touch_x1-*touch_x)>=80))
{
// 写入的字节数一定要和实际一模一样,不然会出问题
// 不能快进快退
char msg[] = "seek 5\n";
write (fd,msg,strlen(msg));
}
if ((*touch_x>742) && (*touch_y<36))
{
system("killall -9 mplayer");
raise(9);
break;
}
}
}
int main(int argc, char const *argv[])
{
pthread_t id;
pthread_create(&id,NULL,task, NULL);
pthread_join(id,NULL);
return 0;
}
视频模块
视频模块(和音频大同小异)
//这里是视频模块
#include "myiohead.h"
//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
int flag = 1;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
int count = 1;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
* touch_x1 = (myevent.value*800)/1024;
if (count)
{
* touch_x = (myevent.value*800)/1024;
count = 0;
}
}
if(myevent.code==ABS_Y) //y坐标
{
* touch_y1 = (myevent.value*480)/600;
if (flag)
{
* touch_y = (myevent.value*480)/600;
flag = 0;
}
}
}
if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
{
//count = 0;
//printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
//printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
break;
}
}
close(to);
}
//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
char data[100];
struct doublelist *next;
struct doublelist *fnext;
}dlist;
dlist * init_list()
{
dlist *head = calloc(1,sizeof(dlist));
// head->data = "1.bmp";
strcpy(head->data, "1.bmp");
head->next = head;
head->fnext = head;
return head;
}
//尾插
int insert_(char * newdata,dlist * head)
{
dlist * p =head;
while(p->next != head)
{
p = p->next;
}
dlist *newnode = calloc(1,sizeof(dlist));
//newnode->data = newdata;
strcpy(newnode->data, newdata);
newnode->next = head;
p->next = newnode;
head->fnext = newnode;
newnode->fnext = p;
}
//读取目录,获得音乐名字
int read_dir(char *path,dlist * head)
{
DIR * dir = opendir(path);
if (NULL == dir)
{
perror("打开目录失败!");
exit(0);
}
struct dirent * rd = NULL;
while((rd = readdir(dir)) != NULL)
{
//printf("d_name : %s\n", rd->d_name);
if (rd->d_type == DT_REG)
{
//printf("这是普通文件!\n");
if (strstr(rd->d_name,".avi") != 0)
{
insert_(rd->d_name,head);
}
}
// if (rd->d_type == DT_DIR)
// {
// printf("这是目录!\n");
// system("cp *.txt ..");
// system("cp *.txt abs");
// }
}
return 0;
}
void * task(void * n)//播放/暂停/快进/快退/上/下一个视频
{
int *touch_x1 = calloc(1,1000);
int *touch_y1 = calloc(1,1000);
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
dlist * mydlist = init_list();
read_dir("/myword/2048bmp/",mydlist);
char a[100] = {0};
if (access("/root/myfifo",F_OK) == -1)
{
int ret = mkfifo("/root/myfifo",0777);
if (-1 == ret)
{
perror("创建管道文件失败!");
exit(0);
}
}
int fd = open("/root/myfifo", O_RDWR);
if (-1 == fd)
{
perror("打开管道文件失败!");
exit(0);
}
dlist * p =mydlist;
int count = 0;
int flag = 2;
while(1)
{
yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
if ((*touch_x<200)&&(*touch_y>360))//上一个
{
if (count == 1)
{
system("killall -9 mplayer");
}
p = p->fnext;
if (p == mydlist)
{
p = p->fnext;
}
bzero(a,100);
strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
strcat(a,p->data);
strcat(a," &");
system(a);
count = 1;
flag = 1;
}
if ((*touch_x>600) && (*touch_y>360))//下一个
{
if (count == 1)
{
system("killall -9 mplayer");
}
p = p->next;
if (p == mydlist)
{
p = p->next;
}
bzero(a,100);
strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
strcat(a,p->data);
strcat(a," &");
system(a);
count = 1;
flag = 1;
}
if ((*touch_x>358) && (*touch_x<414) && (*touch_y>203) && (*touch_y<268)) //暂停/播放
{
if (flag == 1)//暂停
{
system("killall -STOP mplayer");
flag = 0;
}
else if (flag == 0)//播放
{
system("killall -CONT mplayer");
flag = 1;
}
}
//快退5秒
if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
{
/// 写入的字节数一定要和实际一模一样,不然会出问题
// 不能快进快退
char msg[] = "seek -5\n";
write (fd,msg,strlen(msg));
}
//快进5s
if((*touch_x1>*touch_x)&&((*touch_x1-*touch_x)>=80))
{
// 写入的字节数一定要和实际一模一样,不然会出问题
// 不能快进快退
char msg[] = "seek 5\n";
write (fd,msg,strlen(msg));
}
if ((*touch_x>742) && (*touch_y<36))
{
system("killall -9 mplayer");
raise(9);
break;
}
}
}
int main(int argc, char const *argv[])
{
pthread_t id;
pthread_create(&id,NULL,task, NULL);
pthread_join(id,NULL);
return 0;
}
音乐相册
音乐相册
//音乐相册
#include "myiohead.h"
//获取触摸屏坐标
int get_x_y(int *touch_x,int *touch_y)
{
int flag = 0;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
flag++;
* touch_x = (myevent.value*800)/1024;
}
if(myevent.code==ABS_Y) //y坐标
{
flag++;
* touch_y = (myevent.value*480)/600;
}
if (2 == flag)
{
flag = 0;
break;
}
}
}
close(to);
}
//普通展示图片
int showbmp(char *bmppath)
{
int bmpfd;
int lcdfd;
int w,h;
int i;
int x,y;
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//读取图片的宽和高
lseek(bmpfd,18,SEEK_SET);
read(bmpfd,&w,4);//读取宽
read(bmpfd,&h,4);//读取高
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
//把转换后的数据写入lcd中
for (int j = 0; j < h; j++)
{
for(int i = 0,n = 0;i < w;i++)
{
*(lcdmem+(j*800)+i)=tempbuf[j*w+i];
//n++;
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
char data[100];
struct doublelist *next;
struct doublelist *fnext;
}dlist;
dlist * init_list()
{
dlist *head = calloc(1,sizeof(dlist));
// head->data = "1.bmp";
strcpy(head->data, "1.bmp");
head->next = head;
head->fnext = head;
return head;
}
//尾插
int insert_(char * newdata,dlist * head)
{
dlist * p =head;
while(p->next != head)
{
p = p->next;
}
dlist *newnode = calloc(1,sizeof(dlist));
//newnode->data = newdata;
strcpy(newnode->data, newdata);
newnode->next = head;
p->next = newnode;
head->fnext = newnode;
newnode->fnext = p;
}
//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
DIR * dir = opendir(path);
if (NULL == dir)
{
perror("打开目录失败!");
exit(0);
}
struct dirent * rd = NULL;
while((rd = readdir(dir)) != NULL)
{
//printf("d_name : %s\n", rd->d_name);
if (rd->d_type == DT_REG)
{
//printf("这是普通文件!\n");
if (strstr(rd->d_name,".bmp") != 0)
{
insert_(rd->d_name,head);
}
}
// if (rd->d_type == DT_DIR)
// {
// printf("这是目录!\n");
// system("cp *.txt ..");
// system("cp *.txt abs");
// }
}
return 0;
}
void * task(void * n)//循环播放相册
{
dlist * mydlist = init_list();
read_dir("/myphoto",mydlist);
char a[100] = "/myphoto/";
dlist * p =mydlist;
while(p->next != NULL)
{
p = p->next;
if (p == mydlist)
{
p = p->next;
}
bzero(a,100);
strcpy(a,"/myphoto/");
strcat(a,p->data);
showbmp(a);
sleep(1);
}
}
void * task1(void * n)
{
system("mplayer Apologize.mp3 &");
}
int main(int argc, char const *argv[])
{
pthread_t id;
pthread_create(&id,NULL,task, NULL);
pthread_t id1;
pthread_create(&id1,NULL,task1, NULL);
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
while(1)
{
get_x_y(touch_x,touch_y);
if ((*touch_x>742) && (*touch_y<36))
{
pthread_cancel(id);
pthread_cancel(id1);
system("killall -9 mplayer");
raise(9);
break;
}
}
return 0;
}
2048
下面是2048小游戏
#include "myiohead.h"
int showbmp(int w,int h,char *bmppath)
{
int bmpfd;
int lcdfd;
int i;
int x,y;
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
//把转换后的数据写入lcd中
for (int j = 0; j < h; j++)
{
for(int i = 0,n = 0;i < w;i++)
{
*(lcdmem+(j*800)+i)=tempbuf[j*w+i];
//n++;
}
}
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//2048数字图片的映射
int showyxbmp(int w,int h,int r,int s,char *bmppath)
{
int bmpfd;
int lcdfd;
int i;
int x,y;
//定义一个数组,依据图片的大小
char bmpbuf[w*h*3]; //char占1个字节
//定义另外一个数组,存放转换得到的ARGB数据
int lcdbuf[w*h]; //int占4字节
//定义中间变量。临时存放数据
int tempbuf[w*h];
//打开你要显示的w*h大小的bmp
bmpfd=open(bmppath,O_RDWR);
if(bmpfd==-1)
{
perror("打开图片失败!\n");
return -1;
}
//打开lcd驱动
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败!\n");
return -1;
}
//跳过bmp图片头信息54字节,从55字节开始读取
lseek(bmpfd,54,SEEK_SET);
//读取bmp图片的RGB数据
//每三个字节为一组,构成一个像素点的RGB数据
read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
// B G R
//bmpbuf[3] bmpbuf[4] bmpbuf[5]
//把三个字节--》转换成四个字节
/*
细节分析如下:
lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5]
*/
for(i=0; i<w*h; i++)
lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
//把颠倒的图片翻转过来
/*
细节分析如下:
lcdbuf[0] --->lcdbuf[479*800]
*/
for(x=0; x<w; x++)
for(y=0; y<h; y++)
//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
//把转换后的数据写入lcd中
for (int j = 0; j < h; j++)
{
for(int i = 0,n = 0;i < w;i++)
{
//我的背景方格是360*360,也就是每个小格子为90*90
*(lcdmem+((j*800)+(90*s)+(90*800*r))+i)=tempbuf[j*w+i];
//*(lcdmem+(j*800)+i)=tempbuf[j*w+i];
}
}
// //把转换后的数据写入lcd中
// lseek(lcdfd,((90*s)+(r*90*800))*4,SEEK_SET);
// for(int i = 0;i < h;i++)
// {
// write(lcdfd,&tempbuf[w*i],w*4);
// lseek(lcdfd,(800-w)*4,SEEK_CUR);
// }
//关闭
close(bmpfd);
close(lcdfd);
return 0;
}
//获取触摸屏坐标
// int get_x_y(int *touch_x,int *touch_y)
// {
// int flag = 0;
// int to = open ("/dev/input/event0",O_RDWR);
// if (-1 == to)
// {
// perror("打开触摸屏的驱动失败!");
// exit(0);
// }
// struct input_event myevent;
// while(1)
// {
// read(to,&myevent,sizeof(struct input_event));
// if (myevent.type == EV_ABS)
// {
// if(myevent.code==ABS_X) //x坐标
// //由于新开发板的坐标范围跟800*480不一致,按比例修正
// //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
// {
// flag++;
// * touch_x = (myevent.value*800)/1024;
// }
// if(myevent.code==ABS_Y) //y坐标
// {
// flag++;
// * touch_y = (myevent.value*480)/600;
// }
// if (2 == flag)
// {
// flag = 0;
// break;
// }
// }
// }
// close(to);
// }
//获取游戏滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
int flag = 1;
int to = open ("/dev/input/event0",O_RDWR);
if (-1 == to)
{
perror("打开触摸屏的驱动失败!");
exit(0);
}
struct input_event myevent;
int count = 1;
while(1)
{
read(to,&myevent,sizeof(struct input_event));
if (myevent.type == EV_ABS)
{
if(myevent.code==ABS_X) //x坐标
//由于新开发板的坐标范围跟800*480不一致,按比例修正
//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
{
* touch_x1 = (myevent.value*800)/1024;
if (count)
{
* touch_x = (myevent.value*800)/1024;
count = 0;
}
}
if(myevent.code==ABS_Y) //y坐标
{
* touch_y1 = (myevent.value*480)/600;
if (flag)
{
* touch_y = (myevent.value*480)/600;
flag = 0;
}
}
}
if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
{
//count = 0;
//printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
//printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
break;
}
}
close(to);
}
int play_game()
{
int *touch_x1 = calloc(1,1000);
int *touch_y1 = calloc(1,1000);
int *touch_x = calloc(1,1000);
int *touch_y = calloc(1,1000);
int ifmove = 0;
showbmp(360,360,"2048.bmp");
/* 了解到游戏初始化时出现的两个数一定会有个2,所以先随机生成一个2,其他均为0 */
int n;
n = rand() % 16;
int board[4][4] = {0};
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
board[i][j] = (n-- == 0 ? 2 : 0);
}
}
/* 前面已经生成了一个2,这里再生成一个随机的2或者4,概率之比9:1 */
n = 0;
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (board[i][j] == 0)
{
n = n+1;
}
}
}
srand((unsigned int) time(0));
n = rand() % n; /* 确定在何处空位置生成随机数 */
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
/* 定位待生成的位置 */
if (board[i][j] == 0 && n-- == 0)
{
board[i][j] = (rand() % 10 ? 2 : 4); /* 生成数字2或4,生成概率为9:1 */
}
}
}
//展示初始画面
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (board[i][j] == 0)
{
showyxbmp(80,80,i,j,"num0.bmp");
}
if (board[i][j] == 2)
{
showyxbmp(80,80,i,j,"num2.bmp");
}
if (board[i][j] == 4)
{
showyxbmp(80,80,i,j,"num4.bmp");
}
}
}
while(1)
{
yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
//printf("x是%d,x1是%d,y是%d,y1是%d\n", *touch_x,*touch_x1,*touch_y,*touch_y1);
//向左划
if((*touch_y1-*touch_y)<(*touch_x-*touch_x1)&&(*touch_y1-*touch_y)>(*touch_x1-*touch_x))
{
// printf("这里是左\n");
ifmove = 1;
for (int i = 0; i < 4; i++)
{
/* 变量i用来遍历行项的下标,并且在移动时所有行相互独立,互不影响 */
/* 变量j为列下标,变量k为待比较(合并)项的下标,循环进入时k<j */
for (int j = 3; j >= 0; j--)
{
int k = 0;
if (board[i][j] == 0) /* 找出k后面第一个不为空的项,下标为j,之后分三种情况 */
{
continue;
}
if (j != 0)
{
k = j-1;
}
else
k = 0;
while(board[i][k] == 0)
{
board[i][k] = board[i][j];
board[i][j] = 0;
if (k != 0)
{
k--;
}
else
break;
}
if (board[i][j] == 0)
{
continue;
}
if (board[i][j] == board[i][k] && j != 0)
{
board[i][k] = 2*board[i][k];
board[i][j] = 0;
}
if (board[i][j] != board[i][k] && board[i][k] != 0)
{
if ((k+1) !=j)
{
board[i][k+1] = board[i][j];
board[i][j] = 0;
}
}
if (board[i][j] != board[i][k] && board[i][k] == 0)
{
board[i][k] = board[i][j];
board[i][j] = 0;
}
}
}
}
//向右划
else if((*touch_x1-*touch_x)>(*touch_y1-*touch_y)&&(*touch_x1-*touch_x)>(*touch_y-*touch_y1))
{
// printf("这里是右\n");
ifmove = 1;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int k = 0;
if (board[i][j] == 0)
{
continue;
}
if (j != 3)
{
k = j+1;
}
else
k = 3;
while(board[i][k] == 0 )
{
board[i][k] = board[i][j];
board[i][j] = 0;
if (k != 3)
{
k++;
}
else
break;
}
if (board[i][j] == 0)
{
continue;
}
if (board[i][j] == board[i][k] && j !=3)
{
board[i][k] = 2*board[i][k];
board[i][j] = 0;
}
if (board[i][j] != board[i][k] && board[i][k] != 0)
{
if ((k-1)!=j)
{
board[i][k-1] = board[i][j];
board[i][j] = 0;
}
}
if (board[i][j] != board[i][k] && board[i][k] == 0)
{
board[i][k] = board[i][j];
board[i][j] = 0;
}
}
}
}
//向上划
else if((*touch_x1-*touch_x)>(*touch_y1-*touch_y)&&(*touch_x1-*touch_x)<(*touch_y-*touch_y1))
{
// printf("这里是上\n");
ifmove = 1;
/* 仿照左移操作,区别仅仅是行列互换后遍历 */
for (int j = 0; j < 4; j++)
{
for (int i = 3; i >= 0; i--)
{
int k = 0;
if (board[i][j] == 0)
{
continue;
}
if (i != 0)
{
k = i-1;
}
else
k = 0;
while(board[k][j] == 0)
{
board[k][j] = board[i][j];
board[i][j] = 0;
if (k != 0)
{
k--;
}
else
break;
}
if (board[i][j] == 0)
{
continue;
}
if (board[i][j] == board[k][j] && i != 0)
{
board[k][j] = 2*board[i][j];
board[i][j] = 0;
}
if (board[i][j] != board[k][i] && board[k][i] != 0)
{
if ((k+1) !=i)
{
board[k+1][j] = board[i][j];
board[i][j] = 0;
}
}
if (board[i][j] != board[k][i] && board[k][i] == 0)
{
board[k][i] = board[i][j];
board[i][j] = 0;
}
}
}
}
//向下划
else if((*touch_y1-*touch_y)>(*touch_x-*touch_x1)&&(*touch_y1-*touch_y)>(*touch_x1-*touch_x))
{
// printf("这里是下\n");
ifmove = 1;
/* 仿照左移操作,区别仅仅是行列互换后遍历,且j和k都反向遍历 */
for (int j = 0; j < 4; j++)
{
for (int i = 0; i< 4; i++)
{
int k = 0;
if (board[i][j] == 0)
{
continue;
}
if (i != 3)
{
k = i+1;
}
else
k = 3;
while(board[k][j] == 0)
{
board[k][j] = board[i][j];
board[i][j] = 0;
if (k !=3)
{
k++;
}
else
break;
}
if (board[i][j] == 0)
{
continue;
}
if (board[i][j] == board[k][j] && i !=3)
{
board[k][j] = 2*board[i][j];
board[i][j] = 0;
}
if (board[i][j] != board[k][i] && board[k][i] != 0)
{
if ((k-1) !=i)
{
board[k-1][j] = board[i][j];
board[i][j] = 0;
}
}
if (board[i][j] != board[k][i] && board[k][i] == 0)
{
board[k][i] = board[i][j];
board[i][j] = 0;
}
}
}
}
if (ifmove == 1)
{
/* 这里再生成一个随机的2或者4,概率之比9:1 */
n = 0;
for (int l = 0; l < 4; ++l)
{
for (int m = 0; m < 4; ++m)
{
if (board[l][m] == 0)
{
n = n+1;
}
}
}
srand((unsigned int) time(0));
n = rand() % n; /* 确定在何处空位置生成随机数 */
for (int l = 0; l < 4; ++l)
{
for (int m = 0; m < 4; ++m)
{
/* 定位待生成的位置 */
if (board[l][m] == 0 && n-- == 0)
{
board[l][m] = (rand() % 10 ? 2 : 4); /* 生成数字2或4,生成概率为9:1 */
}
}
}
}
//从头开始打印
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (board[i][j] == 0)
{
showyxbmp(80,80,i,j,"num0.bmp");
}
if (board[i][j] == 2)
{
showyxbmp(80,80,i,j,"num2.bmp");
}
if (board[i][j] == 4)
{
showyxbmp(80,80,i,j,"num4.bmp");
}
if (board[i][j] == 8)
{
showyxbmp(80,80,i,j,"num8.bmp");
}
if (board[i][j] == 16)
{
showyxbmp(80,80,i,j,"num16.bmp");
}
if (board[i][j] == 32)
{
showyxbmp(80,80,i,j,"num32.bmp");
}
if (board[i][j] == 64)
{
showyxbmp(80,80,i,j,"num64.bmp");
}
if (board[i][j] == 128)
{
showyxbmp(80,80,i,j,"num128.bmp");
}
if (board[i][j] == 256)
{
showyxbmp(80,80,i,j,"num256.bmp");
}
if (board[i][j] == 512)
{
showyxbmp(80,80,i,j,"num512.bmp");
}
if (board[i][j] == 1024)
{
showyxbmp(80,80,i,j,"num1024.bmp");
}
if (board[i][j] == 2048)
{
showyxbmp(80,80,i,j,"num2048.bmp");
}
if (board[i][j] == 4096)
{
showyxbmp(80,80,i,j,"num4096.bmp");
}
if (board[i][j] == 8192)
{
showyxbmp(80,80,i,j,"num8192.bmp");
}
}
}
int ifgameover = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
/* 横向和纵向比较挨着的两个元素是否相等,若有相等则游戏不结束 */
if (board[i][j] == board[i][j + 1] || board[j][i] == board[j + 1][i])
{
break;
}
else
ifgameover++;
}
}
//printf("ganmeover%d\n", ifgameover);
if (ifgameover == 11)
{
break;
}
if ((*touch_x>742) && (*touch_y<36))
{
break;
}
}
printf("您已退出了游戏。\n");
}
int main(int argc, char const *argv[])
{
// int *touch_x = calloc(1,1000);
// int *touch_x1 = calloc(1,1000);
// int *touch_y = calloc(1,1000);
// int *touch_y1 = calloc(1,1000);
// showbmp(800,480,"zjm.bmp");
// // showyxbmp(80,80,2,3,"num2.bmp");
// while(1)
// {
// //打开2048小游戏
// yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
//get_x_y(touch_x,touch_y);
// if ((*touch_x>119) &&(*touch_x<199) && (*touch_y>140) && (*touch_y<217) )
// {
play_game();
// }
// if ((*touch_x>742) && (*touch_y<36))
// {
// break;
// }
// }
// printf("已回到主界面。\n");
// showbmp(800,480,"zjm.bmp");
// return 0;
}
2048 右移逻辑,先找到第一个不为空格的数a[ i ][ j ],然后用另一个数组,与a[i][j]对比各种情况;
eg:当a[i][j]与a[i][k]相等时,a【i】【k】= a【i】【j】,a【i】【j】= 0;若不相等,则a【i】【k-1】= a【i】【j】;还有各种细节,可以看代码,上下左右都是同一个逻辑。