#include
#include
#include
#include
#include
#include
#include "bmp.h"
#include "ts.h"
#include "wuziqi.h"
extern int wu_point[17][17];
void Go_point(int *XP,int *YP,int *mark_who) //落棋函数
{
int x2=(int)((*XP)*800.0/1024.0+0.5);//计算 触摸屏 坐标(1034*600) 改为(800*480)
int y2=(int)((*YP)*480.0/600.0+0.5);
//int x2=*XP;
//int y2=*YP;
int x2_p=(x2-60)/30+1;//坐标对于棋盘的X
if((x2-60)%30>15)
{
x2_p=x2_p+1;
}
int y2_p=(y2-30)/30+1;//坐标对于棋盘的Y
if((y2-30)%30>15)
{
x2_p=x2_p+1;
}
if(wu_point[x2_p][y2_p]==0 && *mark_who==1 && x2_p<17 && y2_p<17)//若([x2_p],[y2_p])没有棋子,则下棋
{
wu_point[x2_p][y2_p]=1;
yuan((x2_p-1)*30+60,(y2_p-1)*30+30,10,0x000000);//黑棋下棋结束
printf("black_X: %d balck_Y: %d\n",x2_p,y2_p);
*mark_who=2;
}
else if(wu_point[x2_p][y2_p]==0 && *mark_who==2 && x2_p<17 && y2_p<17)//若([x2_p],[y2_p])没有棋子,则下棋
{
wu_point[x2_p][y2_p]=2;
yuan((x2_p-1)*30+60,(y2_p-1)*30+30,10,0xFFFFFF);//白棋下棋结束
printf("white_X: %d white_Y: %d\n",x2_p,y2_p);
*mark_who=1;
}
*XP=x2_p;//把棋子在数组中对应的位置给XP,YP传出去
*YP=y2_p;
}
int panduan(int x,int y) //判断是否胜利
{
int temp;//保存下棋方的颜色
int count=1;//统计个数,针对的同一线
int i=1;//走一格
int j=1;//和i同时用来代表走斜的
int whoWin=0;//1代表黑方,2代表白方
temp=wu_point[x][y];
//水平的左边
while(temp==wu_point[x-i][y]&&x>=5&&x<17&&y>=1&&y<17&&count<5)
{
i++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//水平的右边
i=1;
count=1;//清理掉之前的数据
while(temp==wu_point[x+i][y]&&x>0&&x<13&&y>0&&y<17&&count<5)
{
i++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//解决垂直的方向
//垂直上方
i=1;
count=1;//清理掉之前的数据
while(temp==wu_point[x][y-i]&&x>0&&x<17&&y>4&&y<17&&count<5)
{
i++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//垂直下方
i=1;
while(temp==wu_point[x][y+i]&&x>0&&x<17&&y>0&&y<13&&count<5)
{
i++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//解决左上的斜线
i=1;
j=1;
count=1;
while(temp==wu_point[x-i][y-j]&&x>4&&x<17&&y>4&&y<17&&count<5)
{
i++;
j++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//解决右下的斜线
i=1;
j=1;
count=1;
while(temp==wu_point[x+i][y+j]&&x>0&&x<13&&y>0&&y<13&&count<5)
{
i++;
j++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//解决右上的斜线
i=1;
j=1;
count=1;
while(temp==wu_point[x+i][y-j]&&x>0&&x<13&&y>4&&y<17&&count<5)
{
i++;
j++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
//解决左下的斜线
i=1;
j=1;
count=1;
while(temp==wu_point[x-i][y+j]&&x>4&&x<17&&y>0&&y<13&&count<5)
{
i++;
j++;
count++;
if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
{
if(temp==1)
whoWin=1;
else
whoWin=2;
}
}
return whoWin;
}
void star_game(int fd_s,int *XP,int *YP) //开始游戏
{
chessboard();//画棋盘
int mark_who=1;//谁的回合,1——黑 2——白
int win_who=0;//谁赢 1-黑胜 2-白胜
//int wu_point[15][15];//构建棋盘点,0-无 1-黑 2-白
for(int i=0;i<17;i++)
{
for(int j=0;j<17;j++)
{
if(i==0 ||i==16 ||j==0 ||j==16)
{
wu_point[i][j]=3;
}
else
{
wu_point[i][j]=0;
}
}
}
while(1)
{
int a1=get_touch(fd_s,XP,YP);
Go_point(XP,YP,&mark_who);
win_who= panduan(*XP,*YP);//接受判断结果
if(win_who==1)
{
printf("BLACK WIN!!!\n");
sleep(3);
break;
return;
}
if(win_who==2)
{
printf("WHITE WIN!!!\n");
break;
return;
}
}
}
#include "yueqian.h"
//小游戏:2048
//硬件:粤嵌ARM开发板
//arm-linux-gcc 2048.c yueqian.c -std=gnu99
short map[4][4]={0};
//游戏函数
void refresh_screen();//刷新整个屏幕
void join_numbers(char direction);//数字整合
void add_number();//产生随机数字
void show_pic(int number,int x,int y);//将单个图片放到目标位置
int touch_x;int touch_y;
int main(){
init_board();
add_number();add_number();
refresh_screen();
while(1){
char direction=get_coordinates_and_direction(&touch_x,&touch_y);
if(direction!=NOT_MOVED) join_numbers(direction);
else if(touch_x>=COLUMN-100 && touch_y>=ROW-50) {
system("./ui");
pthread_exit(NULL);
}
}
uninit_board();
}
void join_numbers(char direction){
char is_moved=0;//如果画面无改变,就不产生新的数字
switch(direction){
case UP:
for(int i=0;i<4;i++){//列,从左到右判断
//数字排序
int zero_point=99;//寻找空块,压缩空间
for(int j=0;j<4;j++){//行
//printf("行=%d,zero_point=%d\n",j,zero_point);
if(map[j][i]==0 && zero_point>j){
zero_point=j;
//printf("!!行=%d,zero_point=%d\n",j,zero_point);
}else{
if(zero_point!=99 && map[j][i]!=0){
map[zero_point][i]=map[j][i];
map[j][i]=0;
zero_point++;
is_moved=1;
}
}
}
//数字相加
for(int j=0;j<3;j++){
if(map[j][i]==map[j+1][i] && map[j][i]!=0){
map[j][i]*=2;
map[j+1][i]=0;
j++;
is_moved=1;
}
}
//数字排序(第二次,代码同第一次)
zero_point=99;
for(int j=0;j<4;j++){
if(map[j][i]==0 && zero_point>j){
zero_point=j;
}else{
if(zero_point!=99 && map[j][i]!=0){
map[zero_point][i]=map[j][i];
map[j][i]=0;
zero_point++;
is_moved=1;
}
}
}
}
break;
case DOWN:
for(int i=0;i<4;i++){//列,从左到右判断
//数字排序
int zero_point=-99;
for(int j=3;j>=0;j--){
if(map[j][i]==0 && zero_point<j){
zero_point=j;
}else{
if(zero_point!=-99 && map[j][i]!=0){
map[zero_point][i]=map[j][i];
map[j][i]=0;
zero_point--;
is_moved=1;
}
}
}
//数字相加
for(int j=3;j>0;j--){
if(map[j][i]==map[j-1][i] && map[j][i]!=0){
map[j][i]*=2;
map[j-1][i]=0;
j++;
is_moved=1;
}
}
//数字排序(第二次,代码同第一次)
zero_point=-99;
for(int j=3;j>=0;j--){
if(map[j][i]==0 && zero_point<j){
zero_point=j;
}else{
if(zero_point!=-99 && map[j][i]!=0){
map[zero_point][i]=map[j][i];
map[j][i]=0;
zero_point--;
is_moved=1;
}
}
}
}
break;
case LEFT:
for(int j=0;j<4;j++){//行,从上到下判断
//数字排序
int zero_point=99;
for(int i=0;i<4;i++){
if(map[j][i]==0 && zero_point>i){
zero_point=i;
}else{
if(zero_point!=99 && map[j][i]!=0){
map[j][zero_point]=map[j][i];
map[j][i]=0;
zero_point++;
is_moved=1;
}
}
}
//数字相加
for(int i=0;i<3;i++){
if(map[j][i]==map[j][i+1] && map[j][i]!=0){
map[j][i]*=2;
map[j][i+1]=0;
i++;
is_moved=1;
}
}
//数字排序(第二次,代码同第一次)
zero_point=99;
for(int i=0;i<4;i++){
if(map[j][i]==0 && zero_point>i){
zero_point=i;
}else{
if(zero_point!=99 && map[j][i]!=0){
map[j][zero_point]=map[j][i];
map[j][i]=0;
zero_point++;
is_moved=1;
}
}
}
}
break;
case RIGHT:
for(int j=0;j<4;j++){//行,从上到下判断
//数字排序
int zero_point=-99;
for(int i=3;i>=0;i--){
if(map[j][i]==0 && zero_point<i){
zero_point=i;
}else{
if(zero_point!=-99 && map[j][i]!=0){
map[j][zero_point]=map[j][i];
map[j][i]=0;
zero_point--;
is_moved=1;
}
}
}
//数字相加
for(int i=3;i>0;i--){
if(map[j][i]==map[j][i-1] && map[j][i]!=0){
map[j][i]*=2;
map[j][i-1]=0;
i++;
is_moved=1;
}
}
//数字排序(第二次,代码同第一次)
zero_point=-99;
for(int i=3;i>=0;i--){
if(map[j][i]==0 && zero_point<i){
zero_point=i;
}else{
if(zero_point!=-99 && map[j][i]!=0){
map[j][zero_point]=map[j][i];
map[j][i]=0;
zero_point--;
is_moved=1;
}
}
}
}
break;
}
//判断有没有2048出现,如果有,赢了
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(map[i][j]==2048){
printf("赢了赢了赢了赢了赢了赢了赢了赢了\n");
//放图,结束游戏
refresh_screen();
show_pic_generic("./2048_res/win.bmp",160,0);
sleep(3);
system("./ui");
pthread_exit(NULL);
}
}
}
//如果画面有变化
if(is_moved==1){
//产生随机数字
add_number();
//刷新屏幕
refresh_screen();
}else{//判断是不是输了
char is_lost=1;
for(int i=0;i<4;i++){//判断行能否相加
for(int j=0;j<3;j++){
if(map[i][j]==map[i][j+1]){
is_lost=0;
break;
}
}
if(is_lost==0) break;
}
if(is_lost==1){
for(int j=0;j<4;j++){//判断列能否相加
for(int i=0;i<3;i++){
if(map[i][j]==map[i+1][j]){
is_lost=0;
break;
}
}
if(is_lost==0) break;
}
}
if(is_lost==1){//输了
printf("输了输了输了输了输了输了输了输了\n");
//放图,结束游戏
refresh_screen();
show_pic_generic("./2048_res/lost.bmp",213,0);
sleep(3);
system("./ui");
pthread_exit(NULL);
}
}
}
void add_number(){
char not_ok=1;
while(not_ok){
int x=rand()%4;
int y=rand()%4;
if(map[y][x]==0){//此方法当棋盘很大时效率会很低,但4x4效果还行
map[y][x]=(rand()%2+1)*2;
not_ok=0;
}
}
}
void refresh_screen(){
for(int i=0;i<4;i++){//行
for(int j=0;j<4;j++){//列
show_pic(map[j][i],i*COLUMN/4,j*ROW/4);//显示出来的行列与打印出来的相反,故这里把数组里的i与j对调
printf("%d\t",map[i][j]);
}
printf("\n");
}
show_pic_generic("./2048_res/exit.bmp",COLUMN-100,ROW-50);
}
void show_pic(int number,int offset_x,int offset_y){
char img_path[20];
sprintf(img_path, "./2048_res/%d.bmp", number);//数字转字符串
show_pic_generic(img_path,offset_x,offset_y);
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"lcd.h"
#include"mine.h"
#include"bmp.h"
char* path_arrow = "../res/return.bmp";
int mine_num = 10;
int clicked_num = 0;
int margin_UD = 40;
int margin_LR = 200;
int m[mine_height + 2][mine_width + 2]; // 0未打开,1地雷,2已打开
// 颜色
int c_bg = 0xFFFFFF;
int c_number[8] = {0XFFFFFF,0X00FF00,0X0000FF,0XFFA500,0XFF69B4,0XFFFF00,0XFF0000,0X800080};
int c_unopen = 0xC0C0C0;
int c_open = 0xFFF5EE;
int c_win_bg = 0XFF0000;
int c_win_font = 0X00FF00;
int c_failed_bg = 0X0000F0;
int c_failed_font = 0X000000;
//数值1-8
int num_width = 16;
int num_height = 21;
int padding_UD = 6;
int padding_LR = 4;
unsigned char mine_number[8][16*21/8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1E,0x00,0x7E,0x00,0x7E,0x00,
0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,
0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x7F,0x80,0x7B,0xC0,0xE1,0xC0,0x41,0xC0,
0x03,0xC0,0x03,0x80,0x07,0x80,0x0F,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x78,0x00,
0xFF,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x3F,0x80,0x73,0xC0,0xF1,0xC0,0x61,0xC0,
0x03,0x80,0x0F,0x80,0x1F,0x80,0x03,0xC0,0x01,0xC0,0x41,0xC0,0xE1,0xC0,0x73,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x07,0x80,0x07,0x80,0x0F,0x80,0x1F,0x80,
0x1F,0x80,0x3B,0x80,0x73,0x80,0x73,0x80,0xE3,0x80,0xFF,0xE0,0xFF,0xE0,0x03,0x80,
0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x7F,0xC0,0x7F,0x80,0x70,0x00,0x70,0x00,
0x7F,0x00,0xFF,0x80,0xE3,0xC0,0x01,0xC0,0x01,0xC0,0x41,0xC0,0xE3,0xC0,0xF7,0x80,
0x7F,0x80,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x00,0x0E,0x00,0x1C,0x00,0x3C,0x00,
0x3F,0x00,0x7F,0x80,0x7B,0xC0,0xF1,0xE0,0xE1,0xE0,0xE1,0xE0,0xF1,0xE0,0x73,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0xFF,0xC0,0x7F,0xC0,0x03,0xC0,0x03,0x80,
0x07,0x00,0x07,0x00,0x0F,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,
0x3C,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x7F,0x80,0x73,0xC0,0xE1,0xC0,0xE1,0xC0,
0x73,0x80,0x7F,0x80,0x7F,0x80,0xF3,0xC0,0xE1,0xC0,0xE1,0xC0,0xE1,0xC0,0xF3,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
unsigned char mine_win_fonts[4][40*35/8] = {
/*-- 文字: 你 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x82,0x00,0x00,0x00,0x03,
0x87,0x00,0x00,0x00,0x03,0x87,0x00,0x00,0x00,0x03,0x8F,0x00,0x00,0x00,0x03,0x8E,
0x00,0x00,0x00,0x07,0x8F,0xFF,0xFF,0x80,0x07,0x1F,0xFF,0xFF,0x80,0x07,0x1C,0x0E,
0x03,0xC0,0x07,0x1C,0x0E,0x03,0xC0,0x0F,0x3C,0x0E,0x03,0x80,0x0F,0x38,0x0E,0x03,
0x80,0x0F,0x70,0x0E,0x07,0x80,0x1F,0xF0,0x0E,0x07,0x00,0x1F,0x60,0x0E,0x00,0x00,
0x3F,0x03,0x8E,0x3C,0x00,0x3F,0x03,0x8E,0x1C,0x00,0x7F,0x07,0x0E,0x1C,0x00,0xFF,
0x07,0x0E,0x1E,0x00,0x6F,0x07,0x0E,0x0E,0x00,0x0F,0x0F,0x0E,0x0E,0x00,0x0F,0x0E,
0x0E,0x0F,0x00,0x0F,0x1E,0x0E,0x07,0x00,0x0F,0x1C,0x0E,0x07,0x00,0x0F,0x1C,0x0E,
0x07,0x80,0x0F,0x38,0x0E,0x03,0x80,0x0F,0x38,0x0E,0x03,0x80,0x0F,0x70,0x0E,0x03,
0x80,0x0F,0xF0,0x0E,0x03,0x80,0x0F,0xE0,0x0E,0x03,0xC0,0x0F,0x00,0x0E,0x01,0x80,
0x0F,0x03,0xFE,0x00,0x00,0x0F,0x01,0xFC,0x00,0x00,0x06,0x00,0x78,0x00,0x00},
/*-- 文字: 赢 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,
0x01,0xC0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,
0xFF,0xFF,0x80,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,
0xFE,0x00,0x03,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFC,
0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,
0x0F,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xC7,0xF1,0xFC,0x00,0x3F,0xEF,0xFB,0xFE,0x00,0x38,0xFE,0x3F,0x9E,0x00,0x38,0xFD,
0xBF,0x8E,0x00,0x3F,0xFD,0xFF,0xEE,0x00,0x3F,0xFD,0xFF,0xFE,0x00,0x38,0xFD,0xFF,
0xFE,0x00,0x38,0xFD,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xBF,0xFF,
0xC0,0x38,0xEF,0xF3,0xFF,0xC0,0x38,0xE7,0xF3,0xFF,0xC0,0x78,0xE7,0x7F,0xBF,0xC0,
0x70,0xEF,0x3F,0x0F,0xC0,0x77,0xFE,0x3F,0x0F,0xC0,0xF7,0xDC,0x0E,0x07,0x80},
/*-- 文字: 了 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x1E,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x03,
0xE0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x7E,0x00,
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,
0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,
0x00,0x1C,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,
0x0F,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x78,0x3E,0x00,0x00,
0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00},
/*-- 文字: ! --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,
0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,
0x00,0x01,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,
0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xE0,
0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,
0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};
unsigned char mine_failed_fonts[4][40*35/8] = {
/*-- 文字: 点 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,
0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,
0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0x00,0x00,0x03,0x80,
0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x07,0xFF,0xFF,0xF8,
0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0E,0x00,0x00,0x1C,0x00,
0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,
0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,
0x00,0x1C,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x07,0x1C,0x0E,0x1C,0x00,0x07,0x1E,0x0E,0x1E,0x00,0x0E,0x0E,0x0E,0x0F,
0x00,0x0E,0x0E,0x0F,0x07,0x00,0x1E,0x0E,0x07,0x07,0x80,0x1C,0x0E,0x07,0x03,0x80,
0x38,0x0E,0x07,0x03,0xC0,0x78,0x0E,0x07,0x01,0xC0,0x70,0x0E,0x03,0x01,0xC0},
/*-- 文字: 到 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x3F,
0xFF,0xFC,0x03,0x80,0x7F,0xFF,0xFE,0x83,0x80,0x3F,0xFF,0xFF,0xC3,0x80,0x00,0xE0,
0x03,0xC3,0x80,0x01,0xE3,0x83,0xC3,0x80,0x01,0xC3,0x83,0xC3,0x80,0x03,0xC3,0xC3,
0xC3,0x80,0x03,0x81,0xC3,0xC3,0x80,0x07,0x81,0xE3,0xC3,0x80,0x07,0x00,0xE3,0xC3,
0x80,0x0E,0x1F,0xF3,0xC3,0x80,0x1F,0xFF,0xF3,0xC3,0x80,0x1F,0xFF,0x7B,0xC3,0x80,
0x00,0x38,0x3B,0xC3,0x80,0x00,0x38,0x3B,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,
0x38,0x03,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x3F,0xFF,
0xFB,0xC3,0x80,0x3F,0xFF,0xFB,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x03,
0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x01,0xC3,0x80,0x00,0x38,0x00,0x03,
0x80,0x00,0x38,0x00,0x03,0x80,0x00,0x38,0x1C,0x03,0x80,0x00,0x3F,0xFE,0x03,0x80,
0x3F,0xFF,0xFC,0xF7,0x80,0xFF,0xFC,0x00,0xFF,0x80,0x78,0x00,0x00,0x7F,0x00},
/*-- 文字: 雷 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,
0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xC0,0x70,0x00,0xE0,
0x01,0xC0,0x70,0x00,0xE0,0x01,0xC0,0x7F,0xFE,0xFF,0xFD,0xC0,0x7F,0xFE,0xFF,0xFF,
0xC0,0x70,0x00,0xE0,0x03,0x80,0x70,0x00,0xE0,0x07,0x80,0x70,0x00,0xE0,0x03,0x00,
0x0F,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,
0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1C,0x00,
0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1F,0xFF,0xFF,
0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1C,0x00,0xE0,0x0E,
0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,
0x1F,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x06,0x00,0x00,0x10,0x00},
/*-- 文字: 了 --*/
/*-- 幼圆26; 此字体下对应的点阵为:宽x高=36x35 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=40x35 --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x1E,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x03,
0xE0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x7E,0x00,
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,
0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,
0x00,0x1C,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,
0x0F,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x78,0x3E,0x00,0x00,
0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00}
};
void mine_draw_gezi(int mx, int my, int color)
{
printf("gezi1\n");
printf("mx: %d my: %d\n", mx, my);
int x = (mx-1)*per_len + margin_LR;
int y = (my-1)*per_len + margin_UD;
printf("x: %d y: %d\n", x, y);
lcd_draw_clear(x, y, x + per_len - 2, y + per_len - 2, color);
}
void mine_draw_font(int mx, int my, int number)
{
int x = (mx-1)*per_len + margin_LR + padding_LR;
int y = (my-1)*per_len + margin_UD + padding_UD;
printf("%d %d\n", x, y);
lcd_draw_one_word(x, y, c_number[number - 1], num_width, num_height, mine_number[number - 1]);
}
// 初始化扫雷区域
void mine_init()
{
clicked_num = 0;
lcd_draw_clear(0, 0, 800, 480, c_bg);
srand((unsigned) time(NULL)); // 根据当前时间设置随机数种子
int i, j;
int count = 0; // 已放置的地雷数量
// 先将所有位置初始化为0
for (i = 0; i < mine_height + 2; ++i)
{
for (j = 0; j < mine_width + 2; ++j)
{
m[i][j] = 0;
if(i!=0 && j!=0 && i!=mine_height+1 && j!=mine_width+1)
{
mine_draw_gezi(i, j, c_unopen);
}
else
{
m[i][j] = 2;
}
}
}
// 随机放置地雷
while (count < mine_num) {
i = rand() % mine_height + 1;
j = rand() % mine_width + 1;
if (m[i][j] == 0)
{
m[i][j] = 1; // 标记该位置为地雷
count++; // 已放置的地雷数量加1
}
}
}
// 计算指定位置周围地雷数量
int mine_count_around(int mx, int my)
{
int count = 0;
int i, j;
for (i = mx - 1; i <= mx + 1; ++i) {
for (j = my - 1; j <= my + 1; ++j) {
if (m[i][j] == 1)
{
count++;
}
}
}
return count;
}
// 翻开指定位置
void mine_click(int mx, int my)
{
printf("mine1\n");
if (m[mx][my] == 1) { // 如果该位置是地雷,则游戏结束
mine_failed();
return;
}
printf("mine2\n");
if (m[mx][my] == 2) { // 如果该位置已经翻开,则直接返回
return;
}
printf("mine3\n");
m[mx][my] = 2; // 标记该位置为已翻开
clicked_num ++;
mine_draw_gezi(mx, my, c_open); // 绘制已经翻开的方块
printf("mine4\n");
int n = mine_count_around(mx, my);
if (n == 0) { // 如果周围没有地雷,则递归翻开周围的位置
int i, j;
for (i = mx - 1; i <= mx + 1; ++i) {
for (j = my - 1; j <= my + 1; ++j) {
printf("i: %d, j: %d", i, j);
mine_click(i, j);
}
}
}
else
{
printf("mine5\n");
mine_draw_font(mx, my, n);
}
}
// 处理玩家点击事件
void player_click(int x, int y)
{
int mx = (x - margin_LR) / per_len + 1;
int my = (y - margin_UD) / per_len + 1;
if ((mx < 1) || (mx > 8) || (my < 1) || (my > 8)) { // 如果输入的位置不合法
return;
}
if (m[mx][my] == 2) { // 如果选择了已经翻开的位置
return;
}
mine_click(mx, my); // 翻开该位置5
if (clicked_num == mine_width * mine_height - mine_num) { // 如果所有非地雷位置都已翻开,则游戏胜利
mine_win();
}
}
// 游戏成功
void mine_win()
{
lcd_draw_clear(610, 50, 790, 250, c_win_bg);
lcd_draw_word(620, 137, c_win_font, 4, 40, 35, mine_win_fonts);
printf("游戏成功!\n");
}
// 游戏失败
void mine_failed()
{
lcd_draw_clear(610, 50, 790, 250, c_failed_bg);
lcd_draw_word(620, 137, c_failed_font, 4, 40, 35, mine_failed_fonts);
printf("游戏失败!\n");
}
void mine_start()
{
mine_init();
/*图片的信息*/
unsigned char* data;
int width;
int height;
int pix_bit;
int bmpfd = bmp_open_file(path_arrow);
bmp_get_pic_message(bmpfd, &data, &width, &height, &pix_bit);
bmp_colse_file(bmpfd);
// 绘制箭头
showPic_append(data, height, width, pix_bit);
int event_fd = 0;
ssize_t rsize = 0;
struct input_event ev;//用来保存从输入设备中获取到的的输入事件
event_fd =open("/dev/input/event0",O_RDWR);
if (-1 == event_fd)
{
perror("open event0 error");
}
int xi = 0, x_down = 0;
int yi = 0, y_down = 0;
while(1)
{
rsize = read(event_fd, &ev, sizeof(ev));
if (rsize == sizeof(ev)) //读到了输入事件
{
//printf("0x%2x 0x%2x %d\n", ev.type, ev.code, ev.value);
if (ev.type == 0X03)
{
// 1022*600
if (ev.code == 0X00)
{
//printf("x: %d %d\n", ev.value, ev.value*8/12);
xi = ev.value * 800 / 1020;
}
else if (ev.code == 0X01)
{
//printf("y: %d %d\n", ev.value, ev.value*8/12);
yi = ev.value * 480 / 600;
}
}
if (ev.code == 0x14a)
{
if (ev.value == 1)
{
x_down = xi;
y_down = yi;
}
else if (ev.value == 0)
{
printf("xi: %d x_down: %d yi: %d y_down: %d\n", xi, x_down, yi, y_down);
if (xi < 80 && yi < 60)
{
break;
}
if ((xi > x_down - 5) && (xi < x_down + 5) && (yi > y_down - 5) && (yi < y_down +5))
{
player_click(xi, yi);
}
}
}
}
}
free(data);
}
关键代码:
#include "planemove.h"
#include "event.h"
#include "bmp.h"
int indexs = 0;
char *score[4]={"./1.bmp","./2.bmp","./3.bmp","./4.bmp"};
extern int x_read;
extern int y_read;
void* enemyplane()//敌机在一固定区域随机出现
{
int i;
//extern int index;
int num = 0;
int x;
srandom(time(NULL));
for(num = 0; num < 4; num++)
{
enemyplane_Y = random() % 301;
enemyplane_X = random() % 257;
for(i = 0; i< 200; i++)
{
x=enemyplane_X + 5*i;
show_bmp("./gamePage_800x480_bg.bmp",0,0);
close_bmp();
show_bmp("./plane_60x60_enemy.bmp",enemyplane_X + 5*i,enemyplane_Y);
close_bmp();
show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光炮
close_bmp();
show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
close_bmp();
show_bmp(score[indexs],0,410);
close_bmp();
if(enemyplane_Y>=plane_y-10 && enemyplane_Y<=plane_y+10)//当我方飞机击中敌机,敌机就消失
{
show_bmp("./gamePage_800x480_bg.bmp",0,0);
close_bmp();
show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光
close_bmp();
show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
close_bmp();
indexs++;
sleep(0.5);
break;
}
if(x>730)//敌机超过我方飞机区域就游戏结束
{
show_bmp("./gameover.bmp",160,0);
close_bmp();
return 0;
}
}
sleep(1);
}
}
void planemove()//我方飞机
{
plane_x=730;
//pthread_t th;
pthread_t th1;
int i=0;
//pthread_create(&th,NULL,bullet,NULL);
pthread_create(&th1,NULL,enemyplane,NULL);
while (1)
{
open_event();
plane_y=y_read*480/600;
show_bmp("./gamePage_800x480_bg.bmp",0,0);
close_bmp();
show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光
close_bmp();
show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
close_bmp();
close_event();
}
}
关键代码:
#include "ts.h"
#include "bmp.h"
#include
#include
#include "audio.h"
#include "scorenum.h"
#define ON 1
#define OFF 0
char keyON[][50] = {KEY1ON, KEY2ON, KEY3ON, KEY4ON, KEY5ON, KEY6ON, KEY7ON};
char keyOFF[][50] = {KEY1OFF, KEY2OFF, KEY3OFF, KEY4OFF, KEY5OFF, KEY6OFF, KEY7OFF};
int white[2][12], black[2][11], line[12], key[7]; //1.按键范围,2.按键是否被按
char *FB;
int lcd;
struct fb_var_screeninfo vinfo;
pthread_t tid;
pthread_t touchid; //触摸多线程
pthread_t gameid; //游戏多线程
pthread_t playid; //游戏内单个键多线程
struct coordinate coor, oldcoor; //按键x,y
bool released = false;
char *init_lcd(struct fb_var_screeninfo *vinfo)
{
lcd = open("/dev/fb0", O_RDWR);
bzero(vinfo, sizeof(struct fb_var_screeninfo));
ioctl(lcd, FBIOGET_VSCREENINFO, vinfo);
FB = mmap(NULL, vinfo->xres * vinfo->yres * 4,
PROT_READ | PROT_WRITE,
MAP_SHARED, lcd, 0);
return FB;
}
void init_frame()
{
// 显示背景
bmp2lcd(BACKGROUND, FB, &vinfo, 0, 0);
// 显示标题栏
bmp2lcd(BAR, FB, &vinfo, 0, 0);
// 显示琴键
int i, j;
for (i = 0; i < 12; i++)
{
line[i] = 65 * i + 42;
bmp2lcd(GAMELINE, FB, &vinfo, line[i], 0);
white[0][i] = 65 * i + 10;
white[1][i] = OFF;
bmp2lcd(KEYOFF, FB, &vinfo, white[0][i], 47);
if (i > 0)
{
j = i - 1;
if (j == 2 || j == 5 || j == 9)
{
continue;
}
black[0][j] = 65 * j + 53;
black[1][j] = OFF;
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][i - 1], 47);
}
}
// 显示音乐按键
// bmp2lcd(KEY1, FB, &vinfo, 10, 430);
// bmp2lcd(KEY2, FB, &vinfo, 100, 430);
// bmp2lcd(KEY3, FB, &vinfo, 190, 430);
// bmp2lcd(KEY4, FB, &vinfo, 280, 430);
int len = sizeof(keyOFF) / sizeof(keyOFF[0]);
printf("keynum==%d\n", len);
for (i = 0; i < len; i++)
{
key[i] = 10 + i * 85;
bmp2lcd(keyOFF[i], FB, &vinfo, key[i], 430);
}
// 显示停止按键
bmp2lcd(KEYSTOP, FB, &vinfo, 720, 430);
}
void delay(float time)
{
usleep(time * 1000);
}
// 点击了在琴键之外区域
bool out_of_range(struct coordinate *coor, struct coordinate *oldcoor)
{
if (oldcoor->x == coor->x && oldcoor->y == coor->y && released == false)
{
// coor->x = 0;
// coor->y = 0;
return true;
}
if (coor->x < 10 || coor->x > 790)
{
return true;
}
return false;
}
bool in_of_range(int x1, int x2, int y1, int y2)
{
if (coor.y > y1 && coor.y < y2 && coor.x > x1 && coor.x < x2)
{
return true;
}
return false;
}
void usage(const char *prog)
{
printf("\nwelcome you you you\nUsage: %s volume[0-3]\n", prog);
}
//白色单个按键处理
void key_white(bool key, int pos)
{
printf("key is %d\n pos is %d \n", key, pos);
if (pos == 0 || pos == 3 || pos == 6 || pos == 10)
{
if (key)
{
bmp2lcd(KEYON, FB, &vinfo, white[0][pos], 47);
}
else
{
bmp2lcd(KEYOFF, FB, &vinfo, white[0][pos], 47);
}
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
}
else if (pos == 2 || pos == 5 || pos == 9 || pos == 11)
{
if (key)
{
bmp2lcd(KEYON, FB, &vinfo, white[0][pos], 47);
}
else
{
bmp2lcd(KEYOFF, FB, &vinfo, white[0][pos], 47);
}
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos - 1], 47);
}
else
{
if (key)
{
bmp2lcd(KEYONC, FB, &vinfo, white[0][pos], 47);
}
else
{
bmp2lcd(KEYOFFC, FB, &vinfo, white[0][pos], 47);
}
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
}
}
//选择黑或白键
void key_white_black(bool keyon, bool is_white, int pos)
{
printf("keyon is %d\n is_white is %d\n pos is %d \n", keyon, is_white, pos);
if (is_white)
{
key_white(keyon, pos);
}
else
{
if (keyon)
{
if (pos == 2 || pos == 5 || pos == 9)
{
return;
}
bmp2lcd(KEYBLACKON, FB, &vinfo, black[0][pos], 47);
}
else
{
if (pos == 2 || pos == 5 || pos == 9)
{
return;
}
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
}
}
}
//黑白键处理
bool piano_change(bool is_white, int new_pos, int old_pos, bool touch)
{
int num = 0;
printf("is_white is %d\tnew_pos is %d\told_pos is %d \treleased is %d\t touch is %d\n", is_white, new_pos, old_pos, released, touch);
if (released)
{
key_white_black(false, is_white, new_pos);
touch = true;
released = false;
return touch;
}
if (new_pos != old_pos || touch)
{
//更新琴键状态
key_white_black(true, is_white, new_pos);
if (!touch)
key_white_black(false, is_white, old_pos);
else
touch = false;
// 使用madplay播放琴音
if (is_white)
{
pthread_create(&tid, NULL, play_note, (void *)(new_pos));
}
else
{
if (new_pos == 2 || new_pos == 5 || new_pos == 9)
{
return touch;
}
if (new_pos > 2)
num++;
if (new_pos > 5)
num++;
if (new_pos > 9)
num++;
printf("playnotes is %d\n", new_pos - num + 12);
pthread_create(&tid, NULL, play_note, (void *)(new_pos - num + 20));
}
}
return touch;
}
//歌曲播放
void music_score(int m[])
{
int i;
int len = m[0]; //歌曲长度
printf("len is %d\n", len);
for (i = 1; i < len; i += 2)
{ //歌曲结尾退出
if (m[i] == 0)
{
break;
}
//歌曲分段
if (m[i] <= 0)
{
delay(m[i + 1]);
continue;
}
printf("music is %d\n", m[i]);
key_white(true, m[i] - 1);
pthread_create(&tid, NULL, play_note, (void *)(m[i] - 1));
delay(m[i + 1] * 0.9);
key_white(false, m[i] - 1);
delay(m[i + 1] * 0.1);
if (in_of_range(720, 800, 430, 480))
{
printf("exit\n");
break;
}
}
}
void *get_touch_xy(void *n)
{
while (1)
{
// 等待手指触碰琴键
wait4touch(&coor, &released);
}
}
int main(int argc, char **argv)
{
usage(argv[0]);
if (argc == 2)
{
switch (atoi(argv[1]))
{
case 0:
vol = -105;
break;
case 1:
vol = -45;
break;
case 2:
vol = -15;
break;
case 3:
vol = 10;
break;
}
}
else
{
vol = -45;
}
// 准备LCD
FB = init_lcd(&vinfo);
bzero(FB, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
//初始化界面
init_frame();
// 准备触摸屏
Init_Ts();
//设置线程分离属性
// pthread_attr_init(NULL);
// pthread_attr_setdetachstate(NULL, PTHREAD_CREATE_DETACHED);
int wnew_pos = 0, wold_pos = 0, bnew_pos = 0, bold_pos = 0;
bool w_touch = true, b_touch = true;
int len;
bool use_touch = false;
pthread_create(&touchid, NULL, get_touch_xy, NULL);
while (1)
{
delay(10); //防止太快导致coor没写入就读取
// printf("x=%d y=%d \n", coor.x, coor.y);
if (out_of_range(&coor, &oldcoor))
continue;
oldcoor.x = coor.x;
oldcoor.y = coor.y;
//黑色键部分
if (coor.y > 47 && coor.y < 47)
{
bold_pos = bnew_pos;
bnew_pos = (coor.x - 50) / 65;
printf("black x=%d y=%d wnew_pos=%d\n", coor.x, coor.y, bnew_pos);
if (bnew_pos > 10)
{
continue;
}
b_touch = piano_change(false, bnew_pos, bold_pos, b_touch);
use_touch = true;
continue;
}
//白色键部分
if (coor.y > 47 && coor.y < 280)
{
wold_pos = wnew_pos;
wnew_pos = (coor.x - 10) / 65;
printf("white x=%d y=%d wnew_pos=%d\n", coor.x, coor.y, wnew_pos);
if (wnew_pos > 11)
{
wnew_pos = 11;
}
w_touch = piano_change(true, wnew_pos, wold_pos, w_touch);
use_touch = true;
continue;
}
//歌曲部分
if (coor.y > 430 && coor.y < 480)
{
printf("music x=%d y=%d \n", coor.x, coor.y);
//歌曲选择
int i;
for (i = 0; i < 7; i++)
{
if (coor.x > 10 + i * 90 && coor.x < 90 + i * 90)
{
len = sizeof(musicnum[i]) / sizeof(musicnum[i][0]);
musicnum[i][0] = len;
bmp2lcd(keyON[i], FB, &vinfo, key[i], 430);
music_score(musicnum[i]);
bmp2lcd(keyOFF[i], FB, &vinfo, key[i], 430);
break;
}
}
coor.x = 0;
coor.y = 0;
released = false;
continue;
}
//黑白键超出范围重置按键
if (coor.y > 0 && coor.y < 47 && use_touch)
bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][bold_pos], 47);
if (coor.y > 320 && coor.y < 430 && use_touch)
key_white(false, wold_pos);
use_touch = false;
if (in_of_range(0, 50, 0, 50))
{
printf("exit piano\n");
break;
}
}
//结束和卸载程序
UnInit_Ts();
//撤销映射
munmap(FB, //映射后的地址,通过mmap返回的值
800 * 480 * 4); //映射的大小
close(lcd);
pthread_exit(NULL);
pthread_join(tid, NULL);
pthread_join(gameid, NULL);
pthread_join(playid, NULL);
exit(0);
return 0;
}
源代码:
#include
#include
#include
#include
#include
#include
#include
#define FBDEV "/dev/fb0" // Framebuffer设备文件路径
#define EVENT_DEV "/dev/input/event0"// 输入设备文件路径
#define IMAGE_PATH "/path/to/image.bmp"// 图片路径
#define SCREEN_WIDTH 800 // 屏幕宽度
#define SCREEN_HEIGHT 480 // 屏幕高度
#define SCRATCH_PERCENTAGE 0.5 // 刮开比例
struct fb_var_screeninfo vinfo; // 变量屏幕信息
struct fb_fix_screeninfo finfo; // 固定屏幕信息
char *fbp = 0; // Framebuffer指针
int fbfd = 0; // Framebuffer设备文件描述符
bool running = true; // 游戏运行状态
// 判断两个像素是否相同
bool pixel_equal(char *p1, char *p2) {
return p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2];
}
// 判断两个像素是否相邻
bool pixel_nearby(char *p1, char *p2, int dist) {
int dr = p1[0] - p2[0];
int dg = p1[1] - p2[1];
int db = p1[2] - p2[2];
return dr * dr + dg * dg + db * db < dist * dist;
}
// 判断一个像素是否在刮开的区域内
bool pixel_inside_scratch(char *p, char *p_scratch, int scratch_size) {
return pixel_nearby(p, p_scratch, scratch_size) || pixel_nearby(p, p_scratch + 3, scratch_size) ||
pixel_nearby(p, p_scratch + 3 * scratch_size, scratch_size) || pixel_nearby(p, p_scratch + 3 * scratch_size + 3, scratch_size);
}
// 判断一个像素是否在屏幕上
bool pixel_inside_screen(int x, int y) {
return x >= 0 && x < vinfo.xres && y >= 0 && y < vinfo.yres;
}
// 判断一个像素是否已经被刮开了
bool pixel_scratched(char *p, char *p_scratch) {
return pixel_equal(p, p_scratch) || pixel_equal(p, p_scratch + 3) || pixel_equal(p, p_scratch + 3 * SCREEN_WIDTH) ||
pixel_equal(p, p_scratch + 3 * SCREEN_WIDTH + 3);
}
// 更新刮开的比例
void update_scratch_percentage(char *p_scratch, int scratch_size, float *percentage) {
int num_scratched = 0;
for (int y = 0; y < SCREEN_HEIGHT; y += 10) {
for (int x = 0; x < SCREEN_WIDTH; x += 10) {
char *p = fbp + (y * vinfo.xres + x) * 4;
if (pixel_inside_scratch(p, p_scratch, scratch_size) && !pixel_scratched(p, p_scratch)) {
num_scratched++;
}
}
}
*percentage = (float)num_scratched / ((float)SCREEN_WIDTH * SCREEN_HEIGHT / 100.0 * SCRATCH_PERCENTAGE);
}
// 绘制刮开的区域
void draw_scratch(char *p_scratch, int scratch_size) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
char *p = fbp + (y * vinfo.xres + x) * 4;
if (pixel_inside_scratch(p, p_scratch, scratch_size)) {
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
}
}
}
}
// 加载bmp图片
void load_image(char *image_path, char **image_data, int *image_width, int *image_height) {
int image_fd = open(image_path, O_RDONLY);
if (image_fd < 0){
perror("Failed to open image file");
exit(EXIT_FAILURE);
}
// 读取bmp文件头
unsigned char bmp_header[54];
ssize_t n_read = read(image_fd, bmp_header, 54);
if (n_read < 0) {
perror("Failed to read BMP header");
close(image_fd);
exit(EXIT_FAILURE);
}
// 判断是否为bmp文件
if (bmp_header[0] != 'B' || bmp_header[1] != 'M') {
fprintf(stderr, "File %s is not a BMP file", image_path);
close(image_fd);
exit(EXIT_FAILURE);
}
// 读取图片宽度和高度
*image_width = *(int*)&bmp_header[0x12];
*image_height = *(int*)&bmp_header[0x16];
// 计算像素数据大小
int pixel_data_size = (*image_width) * (*image_height) * 3;
// 分配像素数据内存
*image_data = (char*)malloc(pixel_data_size);
if (*image_data == NULL) {
perror("Failed to allocate memory for image data");
close(image_fd);
exit(EXIT_FAILURE);
}
// 读取像素数据
n_read = read(image_fd, *image_data, pixel_data_size);
if (n_read < 0) {
perror("Failed to read pixel data");
close(image_fd);
free(*image_data);
exit(EXIT_FAILURE);
}
close(image_fd);
}
// 初始化Framebuffer
void init_fb() {
fbfd = open(FBDEV, O_RDWR);
if (fbfd == -1) {
perror("Error: cannot open framebuffer device");
exit(EXIT_FAILURE);
}
// 获取固定屏幕信息
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Error reading fixed information");
exit(EXIT_FAILURE);
}
// 获取变量屏幕信息
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Error reading variable information");
exit(EXIT_FAILURE);
}
// 计算Framebuffer的大小
int screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
// 映射Framebuffer到内存
fbp = (char*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1) {
perror("Error: failed to map framebuffer device to memory");
exit(EXIT_FAILURE);
}
}
// 处理输入事件
void handle_input_event(struct input_event ev, char *p_scratch, int scratch_size, float *scratch_percentage) {
// 判断是否为触摸屏事件
if (ev.type == EV_ABS && ev.code == ABS_X) {
int x = ev.value;
ev = (struct input_event){0};
read_event(EVENT_DEV, &ev);
int y = ev.value;
// 判断是否在屏幕范围内
if (pixel_inside_screen(x, y)) {
// 判断是否在刮开的区域内
char *p = fbp + (y * vinfo.xres + x) * 4;
if (pixel_inside_scratch(p, p_scratch, scratch_size)) {
// 判断是否已经刮开
if (!pixel_scratched(p, p_scratch)) {
// 刮开像素
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
// 更新刮开的比例
update_scratch_percentage(p_scratch, scratch_size, scratch_percentage);
}
}
}
}
}
int main() {
// 初始化Framebuffer
init_fb();
// 加载图片
char *image_data = NULL;
int image_width, image_height;
load_image(IMAGE_PATH, &image_data, &image_width, &image_height);
// 计算刮开的区域大小
int scratch_size = SCREEN_WIDTH * SCREEN_HEIGHT * SCRATCH_PERCENTAGE;
// 随机生成刮开的区域
char *p_scratch = image_data + (rand() % (image_width - SCREEN_WIDTH)) * 3 + (rand() % (image_height - SCREEN_HEIGHT)) * image_width * 3;
//接下来是代码的后半部分,包括主循环和一些辅助函数:
// 初始化刮开的比例为0
float scratch_percentage = 0.0f;
// 主循环
struct input_event ev;
while (1) {
// 读取输入事件
read_event(EVENT_DEV, &ev);
// 处理输入事件
handle_input_event(ev, p_scratch, scratch_size, &scratch_percentage);
// 判断是否已经刮开足够的比例
if (scratch_percentage >= SCRATCH_PERCENTAGE) {
// 显示完整图片
memcpy(fbp, image_data, vinfo.xres * vinfo.yres * 3);
break;
}
}
// 等待用户按下回车键退出
printf("Press enter to exit\n");
getchar();
// 释放资源
munmap(fbp, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
close(fbfd);
free(image_data);
return 0;
}
// 判断像素是否在屏幕范围内
int pixel_inside_screen(int x, int y) {
return x >= 0 && x < vinfo.xres && y >= 0 && y < vinfo.yres;
}
// 判断像素是否在刮开的区域内
int pixel_inside_scratch(char *p, char *p_scratch, int scratch_size) {
return p >= p_scratch && p < p_scratch + scratch_size;
}
// 判断像素是否已经刮开
int pixel_scratched(char *p, char *p_scratch) {
return p[3] == 0 || p < p_scratch;
}
// 更新刮开的比例
void update_scratch_percentage(char *p_scratch, int scratch_size, float *scratch_percentage) {
int scratched_count = 0;
for (char *p = p_scratch; p < p_scratch + scratch_size; p += 4) {
if (pixel_scratched(p, p_scratch)) {
scratched_count++;
}
}
*scratch_percentage = (float)scratched_count / (float)(scratch_size / 4);
}
// 读取输入事件
void read_event(const char *dev_path, struct input_event *ev) {
static int fd = -1;
if (fd == -1) {
fd = open(dev_path, O_RDONLY);
if (fd == -1) {
perror("Error: cannot open input device");
exit(EXIT_FAILURE);
}
}
ssize_t n_read = read(fd, ev, sizeof(struct input_event));
if (n_read < 0) {
perror("Error: failed to read input event");
exit(EXIT_FAILURE);
}
}
源代码:
#include
#include
#include
#include
#include
#include
#include
#include
// 游戏参数
#define SCREEN_WIDTH 800 // 屏幕宽度
#define SCREEN_HEIGHT 480 // 屏幕高度
#define HOLE_WIDTH 100 // 地鼠洞宽度
#define HOLE_HEIGHT 100 // 地鼠洞高度
#define HOLE_COUNT 9 // 地鼠洞数量
#define HOLE_INTERVAL 50 // 地鼠洞之间的间距
#define HOLE_HIT_SCORE 10 // 击中地鼠得分
#define HOLE_MISS_SCORE -5 // 错过地鼠扣分
#define GAME_TIME 60 // 游戏时间,单位秒
// 输入设备文件路径
#define EVENT_DEV "/dev/input/event0"
// Framebuffer设备文件路径
#define FBDEV "/dev/fb0"
// 红色地鼠图片路径
#define MOLE_RED_PATH "mole_red.bmp"
// 绿色地鼠图片路径
#define MOLE_GREEN_PATH "mole_green.bmp"
// 游戏状态
enum GameState {
GAME_STATE_INIT,
GAME_STATE_PLAYING,
GAME_STATE_GAME_OVER
};
// 地鼠洞
struct Hole {
int x; // 地鼠洞左上角x坐标
int y; // 地鼠洞左上角y坐标
int state; // 地鼠状态,0表示没有地鼠,1表示有红色地鼠,2表示有绿色地鼠
};
// Framebuffer设备信息
int fbfd = -1;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char *fbp = NULL;
// 红色地鼠图片数据
char *mole_red_data = NULL;
int mole_red_width, mole_red_height;
// 绿色地鼠图片数据
char *mole_green_data = NULL;
int mole_green_width, mole_green_height;
// 游戏状态
enum GameState game_state = GAME_STATE_INIT;
// 游戏时间
int game_time = 0;
// 游戏得分
int game_score = 0;
// 地鼠洞数组
struct Hole holes[HOLE_COUNT];
// 初始化地鼠洞
void init_holes() {
int hole_x = (SCREEN_WIDTH - HOLE_WIDTH * 3 - HOLE_INTERVAL * 2) / 2;
int hole_y = (SCREEN_HEIGHT - HOLE_HEIGHT * 3 - HOLE_INTERVAL * 2) / 2;
for (int i = 0; i < HOLE_COUNT; i++) {
holes[i].x = hole_x + (i % 3) * (HOLE_WIDTH + HOLE_INTERVAL);
holes[i].y = hole_y + (i / 3) * (HOLE_HEIGHT + HOLE_INTERVAL);
holes[i].state = 0;
}
}
// 初始化红色地鼠
void init_mole_red() {
// 加载红色地鼠图片
load_image(MOLE_RED_PATH, &mole_red_data, &mole_red_width, &mole_red_height);
// 缩放红色地鼠图片
char *mole_red_data_resized = (char*)malloc(HOLE_WIDTH * HOLE_HEIGHT * 3);
if (mole_red_data_resized == NULL) {
perror("Failed to allocate memory for mole red data");
exit(EXIT_FAILURE);
}
resize_image(mole_red_data, mole_red_width, mole_red_height, mole_red_data_resized, HOLE_WIDTH, HOLE_HEIGHT);
free(mole_red_data);
mole_red_data = mole_red_data_resized;
}
// 初始化绿色地鼠
void init_mole_green() {
// 加载绿色地鼠图片
load_image(MOLE_GREEN_PATH, &mole_green_data, &mole_green_width, &mole_green_height);
// 缩放绿色地鼠图片
char *mole_green_data_resized = (char*)malloc(HOLE_WIDTH * HOLE_HEIGHT * 3);
if (mole_green_data_resized == NULL) {
perror("Failed to allocate memory for mole green data");
exit(EXIT_FAILURE);
}
resize_image(mole_green_data, mole_green_width, mole_green_height, mole_green_data_resized, HOLE_WIDTH, HOLE_HEIGHT);
free(mole_green_data);
mole_green_data = mole_green_data_resized;
}
// 初始化游戏
void init_game() {
// 打开输入设备文件
int evfd = open(EVENT_DEV, O_RDONLY);
if (evfd == -1) {
perror("Failed to open input device");
exit(EXIT_FAILURE);
}
// 获取FrameBuffer设备信息
fbfd = open(FBDEV, O_RDWR);
if (fbfd == -1) {
perror("Failed to open framebuffer device");
exit(EXIT_FAILURE);
}
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Failed to get framebuffer device info");
exit(EXIT_FAILURE);
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Failed to get framebuffer device info");
exit(EXIT_FAILURE);
}
// 映射FrameBuffer内存
fbp = (char*)mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1) {
perror("Failed to mmap framebuffer");
exit(EXIT_FAILURE);
}
// 初始化地鼠洞
init_holes();
// 初始化红色地鼠
init_mole_red();
// 初始化绿色地鼠
init_mole_green();
// 初始化游戏时间
game_time = GAME_TIME;
// 初始化游戏得分
game_score = 0;
// 初始化游戏状态
game_state = GAME_STATE_PLAYING;
}
// 绘制游戏界面
void draw_game() {
// 清空屏幕
clear_screen();
// 绘制地鼠洞
for (int i = 0; i < HOLE_COUNT; i++) {
struct Hole hole = holes[i];
if (hole.state == 1) {
draw_image(mole_red_data, HOLE_WIDTH, HOLE_HEIGHT, hole.x, hole.y);
} else if (hole.state == 2) {
draw_image(mole_green_data, HOLE_WIDTH, HOLE_HEIGHT, hole.x, hole.y);
}
}
// 绘制得分和游戏时间
draw_text("Score: %d", game_score, 10, 10);
draw_text("Time: %d", game_time, SCREEN_WIDTH - 100, 10);
}
// 游戏主循环
void game_loop() {
// 获取输入事件
struct input_event ev;
while (read_input_event(&ev) > 0) {
if (ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 1) {
// 点击屏幕
for (int i = 0; i < HOLE_COUNT; i++) {
struct Hole hole = holes[i];
if (ev.x >= hole.x && ev.x < hole.x + HOLE_WIDTH && ev.y >= hole.y && ev.y < hole.y + HOLE_HEIGHT) {
// 点击到地鼠洞
if (hole.state == 1) {
// 击中红色地鼠
game_score += HOLE_HIT_SCORE;
hole.state = 0;
} else if (hole.state == 2) {
// 击中绿色地鼠
game_score += HOLE_HIT_SCORE;
hole.state = 1;
} else {
// 错过地鼠
game_score += HOLE_MISS_SCORE;
}
break;
}
}
}
}
// 更新游戏时间
game_time--;
for (int i = 0; i < NUM_HOLES; i++) {
struct hole_t hole = holes[i];
// 地鼠洞为空,有一定概率出现地鼠
if (hole.state == 0) {
if (rand() % 100 < 2) {
hole.state = 1;
hole.time_left = HOLE_SHOW_TIME;
}
}
// 地鼠洞有红色地鼠,减少显示时间
else if (hole.state == 1) {
hole.time_left--;
if (hole.time_left <= 0) {
// 地鼠逃走了
hole.state = 0;
}
// 地鼠被击中
if (hole.hit) {
hole.state = 2;
hole.time_left = HOLE_SHOW_TIME;
game_score += 10;
}
}
// 地鼠洞有绿色地鼠,减少显示时间
else if (hole.state == 2) {
hole.time_left--;
if (hole.time_left <= 0) {
// 地鼠逃走了
hole.state = 0;
}
}
hole.hit = false; // 重置击中标志位
holes[i] = hole;
}
// 更新屏幕
draw_game();
// 判断游戏是否结束
if (game_time <= 0) {
game_state = GAME_STATE_GAME_OVER;
}
}
// 游戏结束
void game_over() {
// 显示游戏结束界面
clear_screen();
draw_text("Game Over", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
draw_text("Score: %d", game_score, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 50);
// 等待点击屏幕重新开始游戏
struct input_event ev;
while (read_input_event(&ev) > 0) {
if (ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 1) {
// 点击屏幕,重新开始游戏
game_state = GAME_STATE_INIT;
break;
}
}
}
// 主函数
int main() {
// 初始化游戏
init_game();
// 游戏循环
while (1) {
if (game_state == GAME_STATE_INIT) {
// 初始化游戏
init_game();
} else if (game_state == GAME_STATE_PLAYING) {
// 游戏进行中
game_loop();
} else if (game_state == GAME_STATE_GAME_OVER) {
// 游戏结束
game_over();
}
}
return 0;
}