xuanyu an / Mbed 2 deprecated tankworld

Dependencies:   mbed N5110

main1.cpp

Committer:
YPA_YPA
Date:
2021-05-04
Revision:
2:ce24c50fc0a6
Parent:
1:47967167a3a6
Child:
3:4bc4e762a906

File content as of revision 2:ce24c50fc0a6:

#include "mbed.h"
#include "N5110.h"
#include "main.h"
#ifndef bullet_v
#define bullet_v 3//炮弹的速度为坦克三倍
#endif
#ifndef tank_num
#define tank_num 4//坦克数量
#endif

DigitalIn button_A2(p29);
DigitalIn button_B2(p28);
DigitalIn button_C2(p27);
DigitalIn button_D2(p26);

AnalogIn  joy_v2(p20);
AnalogIn  joy_h2(p19);
AnalogIn joy_button2(p17); // could be DigitalIn, but use AnalogIn so pot can also be used

// JP1 must be in 2/3 position
N5110 lcd2(p8,p9,p10,p11,p13,p21);
const int map[9][11] =   {
    { 0,0,0,0,0,0,0,0,0,0,0},
    { 0,1,0,2,1,1,1,2,0,1,0},
    { 0,1,0,2,0,1,0,2,0,1,0},
    { 0,0,0,0,0,0,0,0,0,0,0},
    { 2,2,0,1,2,2,2,1,0,2,2},
    { 0,0,0,0,0,0,0,0,0,0,0},
    { 0,1,0,2,0,1,0,2,0,1,0},
    { 0,1,0,2,1,1,1,2,0,1,0},
    { 0,0,0,0,0,0,0,0,0,0,0},
};//9*11大小的地图,1是墙,2是灌木
const int wall[5][7] =   {
    { 1,1,1,1,1,1,1},
    { 1,1,0,0,0,1,1},
    { 1,1,0,0,0,1,1},
    { 1,1,0,0,0,1,1},
    { 1,1,1,1,1,1,1},
};//5*7的墙,不可破坏
const int bush[5][7] =   {
    { 1,0,1,0,1,0,1},
    { 0,1,0,1,0,1,0},
    { 1,0,1,0,1,0,1},
    { 0,1,0,1,0,1,0},
    { 1,0,1,0,1,0,1},

};//5*7的g灌木,可破坏
const int destroyed_bush[5][7] =   {
    { 1,0,0,1,0,0,1},
    { 0,0,1,0,0,1,0},
    { 0,1,0,0,1,0,0},
    { 1,0,0,1,0,0,1},
    { 0,0,1,0,0,1,0},

};//被击中的灌木
const int tank[tank_num][4][5][7] = {
    {
        {
            { 0,1,0,1,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,1,0,1,1,0},
            { 0,1,1,0,1,1,0},
            { 0,1,0,0,0,1,0}
        },
        {
            { 0,1,0,0,0,1,0},
            { 0,1,1,0,1,1,0},
            { 0,1,1,0,1,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,1,0,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,1,1,1,0,0},
            { 0,1,1,0,0,0,0},
            { 0,0,1,1,1,0,0},
            { 0,1,1,1,1,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,1,1,1,0,0},
            { 0,0,0,0,1,1,0},
            { 0,0,1,1,1,0,0},
            { 0,1,1,1,1,1,0}
        }
    },//tank1
    {
        {
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,1,0,0,1,0},
            { 0,1,0,0,0,1,0}

        },
        {
            { 0,1,0,0,0,1,0},
            { 0,1,0,0,1,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,0,0,0},
            { 0,0,0,1,1,0,0},
            { 0,1,1,1,1,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,1,1,0,0,0},
            { 0,0,0,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,1,1,0}
        }
    },//tank2
    {
        {
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,0,0,0,1,0}

        },
        {
            { 0,1,0,0,0,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,1,0,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,1,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,0,1,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,1,1,0}
        }
    }, //tank3
    {
        {
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,0,1,1,0},
            { 0,1,0,0,0,1,0}

        },
        {
            { 0,1,0,0,0,1,0},
            { 0,1,1,0,0,1,0},
            { 0,1,1,1,1,1,0},
            { 0,1,0,1,0,1,0},
            { 0,1,0,1,0,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,0,1,1,0,0},
            { 0,1,1,1,0,0,0},
            { 0,0,0,1,0,0,0},
            { 0,1,1,1,1,1,0}
        },
        {
            { 0,1,1,1,1,1,0},
            { 0,0,0,1,0,0,0},
            { 0,0,0,1,1,1,0},
            { 0,0,1,1,0,0,0},
            { 0,1,1,1,1,1,0}
        }
    }//tank4
};
const int tank_exp[5][7] =   {
    { 0,1,0,1,0,1,0},
    { 0,0,1,0,1,0,0},
    { 1,1,0,0,0,1,1},
    { 0,0,1,0,1,0,0},
    { 0,1,0,1,0,1,0},
};//击毁的坦克
const int bullet[5][7] =   {
    { 0,0,0,0,0,0,0},
    { 0,0,1,1,0,0,0},
    { 0,0,1,1,0,0,0},
    { 0,0,0,0,0,0,0},
    { 0,0,0,0,0,0,0},
};//炮弹
const int hp_ai[2][5][7] =   {{
        { 0,1,1,0,0,0,0},
        { 1,1,1,1,0,0,0},
        { 0,1,1,1,0,0,0},
        { 1,0,1,1,0,0,1},
        { 1,1,0,1,0,1,1},
    },{
        { 0,1,1,0,1,1,0},
        { 1,1,1,1,1,1,1},
        { 0,1,1,1,1,1,0},
        { 1,0,1,1,1,0,1},
        { 1,1,0,1,0,1,1},
    }
};//炮弹
const int t_start[tank_num][2] = {{0,5},{8,1},{8,5},{8,9}}; //坦克初始坐标
const int ai_mod[3]= {0,1,0};
const int ai_changetime[3]= {6,8,5};
void map_scan2(int map_adj[9][11]) //扫描地图函数
{
    int x = 0;
    int y = 0; //地图扫描坐标
    lcd2.drawRect(0,0,84,1,FILL_BLACK);
    lcd2.drawRect(0,46,84,2,FILL_BLACK);
    lcd2.drawRect(0,0,3,48,FILL_BLACK);
    lcd2.drawRect(80,0,4,48,FILL_BLACK);//边框

    for (x=0; x<11; x++) {
        for (y=0; y<9; y++) {
            if(map_adj[y][x]==1) {
                lcd2.drawSprite(x*7+3,y*5+1,5,7,(int *)wall);
            } else if(map_adj[y][x]==2) {
                lcd2.drawSprite(x*7+3,y*5+1,5,7,(int *)bush);
            }
        }
    }
}

void hp_show2(int hp[4],int level)  //显示血量函数
{
    int heart_num;
    int i;
    for  (heart_num=0; heart_num<3; heart_num++) {
        if(heart_num<hp[0]) {
            lcd2.drawSprite(4*7+heart_num*7+3,5*1+1,5,7,(int *)hp_ai[0]);
            for(i=1; i<tank_num-level; i++) {
                if(heart_num<hp[i]) {
                    lcd2.drawSprite(4*7+(i-1)*7+3,7*5+1,5,7,(int *)hp_ai[hp[i]-1]);
                }
            }
        }

    }
}

void tank_show2(int tank_state[4],int t[4][2],int hp[4],int level) //显示坦克函数
{
    int i;
    for(i=0; i<tank_num-level; i++) {
        if(hp[i]!=0) {
            lcd2.drawSprite(t[i][1]*7+3,t[i][0]*5+1,5,7,(int *)tank[i][tank_state[i]]);
        }
    }
}
int body(int level)
{
    // need to initialise the lcd2 first, do this once outside of the loop
    lcd2.init();
    //int command[2][4]={{0,0,0,0},{0,0,0,0}};//处理后的指令
    int command[4]= {0,0,0,0};
    int turn=0;
    int a;
    int stop;//stop command for ai
    int i;
    int j; //地图复制计数
    int ii;
    int k;
    int l;
    int n; //炮弹刷新计数
    int shoot;//开火计数
    int t[tank_num][2]; //坦克坐标
    int t_pre[tank_num][2]; //坦克预测坐标(npc)
    int b[tank_num][3][2]; //炮弹坐标
    int bullet_cont=0;//发射炮弹计数
    int bullet_direct[tank_num][3];//炮弹的方向
    int bullet_val[tank_num][3];//炮弹是否被阻挡
    int tank_state[tank_num]; //坦克的f方向
    int hp_set[tank_num]= {3,1,1,1}; //坦克血量预设
    int hp[tank_num]= {0,0,0,0}; //坦克血量
    int tank_count;//坦克单位的计数
    int trace[tank_num-1][3]= {{0,0,0},{0,0,0},{0,0,0}};
    int map_adj[9][11];
    int tank_des;//serial number of destoried tank destroy
    int hit;
    int obj_kind;
    for (k=0; k<tank_num-level; k++) {
        hp[k]=hp_set[k];
        tank_state[k]=0;
        map_adj[t_start[k][0]][t_start[k][1]]=k+3;
        for (l=0; l<bullet_v; l++) {
            bullet_val[k][l]=0;
        }
        for (ii=0; ii<2; ii++) {
            t[k][ii]=t_start[k][ii];
        } //复制坦克坐标
    }

    for (i=0; i<11; i++) {
        for (j=0; j<9; j++) {
            map_adj[j][i]=map[j][i];
        }
    }//复制地图
    shoot=0;
    tank_count=0;
    while(1) {
        lcd2.clear();
        map_scan2(map_adj);//地图显示
        hp_show2(hp,level);//血量显示
        tank_show2(tank_state,t,hp,level);//坦克显示

        if(shoot==0) {
            command[3] = button_A2.read();
            command[0] = button_B2.read();
            command[2] = button_C2.read();
            command[1] = button_D2.read(); //复制指令
            turn=turn+1;
            if(turn==15) {
                turn=0;
            }//各种计数
            bullet_cont++;
            if(bullet_cont==3) {
                bullet_cont=0;
            }

            for(tank_count=0; tank_count<tank_num-level; tank_count++) {
                if(tank_count!=0&&hp[tank_count]!=0) {
                    stop=0;
                    t_pre[tank_count][0]=t[tank_count][0];
                    t_pre[tank_count][1]=t[tank_count][1];
                    trace[tank_count][0]=(ai_changetime[tank_count-1]<turn)^ai_mod[tank_count-1]^(t[tank_count][0]>t[0][0]);//1代表坦克1在坦克2的下方
                    trace[tank_count][1]=(ai_changetime[tank_count-1]<turn)^ai_mod[tank_count-1]^(t[tank_count][1]>t[0][1]);//1代表坦克1在坦克2的右
                    trace[tank_count][2]=(abs(t[0][0]-t[tank_count][0]))>(abs(t[0][1]-t[tank_count][1]));//1代表坦克竖直距离大于水平距离
                    for(a=0; a<4; a++) {
                        tank_state[tank_count]=2*(!((a%2)^trace[tank_count][2]))+(!((a>>1)^trace[tank_count][0]))*((a%2)^trace[tank_count][2])+(!((a>>1)^trace[tank_count][1]))*(!((a%2)^trace[tank_count][2]));
                        t_pre[tank_count][0]=t[tank_count][0]+(!(tank_state[tank_count]>>1))*(2*(tank_state[tank_count]%2)-1);
                        t_pre[tank_count][1]=t[tank_count][1]+(tank_state[tank_count]>>1)*(2*(tank_state[tank_count]%2)-1);
                        if((map_adj[t_pre[tank_count][0]][t_pre[tank_count][1]]==0)&&(t_pre[tank_count][1]>=0)&&(t_pre[tank_count][1]<=10)&&(t_pre[tank_count][0]>=0)&&(t_pre[tank_count][0]<=8)) {
                            break;
                        }
                        if(a==3) stop=1;
                    }
                    map_adj[t[tank_count][0]][t[tank_count][1]]=0;
                    if(stop==0) {
                        t[tank_count][tank_state[tank_count]>>1]=t[tank_count][tank_state[tank_count]>>1]+2*(tank_state[tank_count]%2)-1;
                    }
                    map_adj[t[tank_count][0]][t[tank_count][1]]=tank_count+3;
                    bullet_val[tank_count][bullet_cont]=1; //坦克发射炮弹技炮弹坐标方向计算
                    bullet_direct[tank_count][bullet_cont]=tank_state[tank_count];
                    b[tank_count][bullet_cont][0]=t[tank_count][0];
                    b[tank_count][bullet_cont][1]=t[tank_count][1];
                } else if(hp[tank_count]!=0&&tank_count==0) {
                    command[3]=(~command[0])&(~command[1])&(~command[2])&command[3];
                    command[2]=(~command[0])&(~command[1])&command[2];
                    command[1]=(~command[0])&command[1];
                    command[0]=command[0];

                    map_adj[t[tank_count][0]][t[tank_count][1]]=0;
                    t[tank_count][0]=t[tank_count][0]-command[0]+command[1];
                    t[tank_count][1]=t[tank_count][1]-command[2]+command[3];//指令控制坦克

                    if(map_adj[t[tank_count][0]][t[tank_count][1]]!=0||t[tank_count][1]<0||t[tank_count][1]>10||t[tank_count][0]<0||t[tank_count][0]>8) {
                        t[tank_count][0]=t[tank_count][0]+command[0]-command[1];
                        t[tank_count][1]=t[tank_count][1]+command[2]-command[3];
                    }//障碍物判断,前方有障碍物时指令无效
                    map_adj[t[tank_count][0]][t[tank_count][1]]=tank_count+3;
                    if(command[0]||command[1]||command[2]||command[3]) {
                        tank_state[tank_count]=command[1]*1+command[2]*2+command[3]*3;
                    } //坦克方向计算
                    if (joy_button2.read()==0) {
                        bullet_val[tank_count][bullet_cont]=1; //坦克发射炮弹技炮弹坐标方向计算
                        bullet_direct[tank_count][bullet_cont]=tank_state[tank_count];
                        b[tank_count][bullet_cont][0]=t[tank_count][0];
                        b[tank_count][bullet_cont][1]=t[tank_count][1];
                    }
                }

            }

        }
        for(tank_count=0; tank_count<tank_num-level; tank_count++) { //游戏里坦克依次进行运算
            if(hp[tank_count]!=0) {
                for(n=0; n<bullet_v; n++) { //炮弹比坦克快三倍运算也快三倍
                    b[tank_count][n][0]=b[tank_count][n][0]+(!(bullet_direct[tank_count][n]>>1))*(-1+2*(bullet_direct[tank_count][n]%2));
                    b[tank_count][n][1]=b[tank_count][n][1]+(bullet_direct[tank_count][n]>>1)*(-1+2*(bullet_direct[tank_count][n]%2));//炮弹坐标刷新
                    if(b[tank_count][n][1]>=0&&b[tank_count][n][1]<=10&&b[tank_count][n][0]>=0&&b[tank_count][n][0]<=8&&bullet_val[tank_count][n]==1) {
                        //炮弹有效且未出界
                        obj_kind=map_adj[b[tank_count][n][0]][b[tank_count][n][1]];
                        hit=(((tank_count==0)+(obj_kind<4))%2)&&(obj_kind>=3);
                        if(obj_kind==0) { //炮弹无障碍飞行的情况
                            lcd2.drawSprite(b[tank_count][n][1]*7+3,b[tank_count][n][0]*5+1,5,7,(int *)bullet);
                        } else if (obj_kind==2) { //炮弹打到灌木的情况
                            lcd2.drawSprite(b[tank_count][n][1]*7+3,b[tank_count][n][0]*5+1,5,7,(int *)destroyed_bush);
                            map_adj[b[tank_count][n][0]][b[tank_count][n][1]]=0;
                            bullet_val[tank_count][n]=0;
                        } else if (obj_kind==1) { //炮弹打墙的情况
                            bullet_val[tank_count][n]=0;
                        } else if(obj_kind>=3&&hit) { //炮弹击杀坦克的情况
                            tank_des=map_adj[b[tank_count][n][0]][b[tank_count][n][1]]-3;
                            map_adj[b[tank_count][n][0]][b[tank_count][n][1]]=0;
                            lcd2.drawSprite(t[tank_des][1]*7+3,t[tank_des][0]*5+1,5,7,(int *)tank_exp);
                            t[tank_des][0]=t_start[tank_des][0];
                            t[tank_des][1]=t_start[tank_des][1];//坦克回出生点
                            hp[tank_des]=hp[tank_des]-1;//血量减一
                            bullet_val[tank_count][n]=0;//炮弹失效
                            if(hp[0]==0) {
                                return 0;
                            } else if((hp[1]+hp[2]+hp[3])==0) {
                                return 1;
                            }
                        }
                    }
                }
            }
        }
        shoot=shoot+1;
        if(shoot==bullet_v) {
            shoot=0;
        }
        lcd2.refresh(); // refresh the lcd2 so the pixels appear
        wait_ms(600/bullet_v); // 画面按炮弹移动s时间刷新,600为坦克移动时间
    }
}
void init_buttons2()
{
    // PCB has external pull-down resistors so turn the internal ones off
    // (default for DigitalIn)
    button_A2.mode(PullNone);
    button_B2.mode(PullNone);
    button_C2.mode(PullNone);
    button_D2.mode(PullNone);
}
void main1()
{
    int result;
    result=body(1);
    if (result==0) {
        lcd2.clear();
        lcd2.printString("Game Over", 15, 1);
        lcd2.printString("You lose:", 17, 3);
        lcd2.refresh();
        wait(1);
        while(1) {
            if (button_A2.read() == 1) {
                main();
            }
        }
    } else if (result==1) {
        lcd2.clear();
        lcd2.printString("Level 1: win", 10, 1);
        lcd2.printString("A:Next level", 10, 3);
        lcd2.refresh();
        wait(1);
        while(1) {
            if (button_A2.read() == 1) {
                result=body(0);
                if(result==0) {
                    lcd2.clear();
                    lcd2.printString("Game Over", 15, 1);
                    lcd2.printString("You lose:", 17, 3);
                    lcd2.refresh();
                } else if (result==1) {
                    lcd2.clear();
                    lcd2.printString("You win", 20, 1);
                    lcd2.printString("A:Menu", 25, 3);
                    lcd2.refresh();

                }
                wait(1);
                while(1) {
                    if (button_A2.read() == 1) {
                        main();
                    }
                }
            }
        }
    }
}