9. Game over and restart
If you want to restart the game after it ends, you need to use a variable to represent the game state:
void game_init(){
for(int i=0;i<size;i++){
objs[i].label=lv_label_create(lv_scr_act(), NULL);
lv_obj_set_size(objs[i].label, 20, 20);
lv_obj_add_style(objs[i].label, LV_LABEL_PART_MAIN, &style);
lv_label_set_text(objs[i].label, objs[i].name);
}
}
Extract data initialization into a method so that it can be reused after the game ends, that is, restart:
void game_start(){
for(int i=0;i<size;i++){
objs[i].x=20 + rand() % (128-80);
objs[i].y=-1*(rand() % size)-30;
objs[i].die=0;
lv_obj_set_pos(objs[i].label, objs[i].x, objs[i].y);
}
for (int i = 0; i < size; ++i){
for (int j = i + 1; j < size; ++j){
if (objs[i].y < objs[j].y){
struct Obj temp = objs[i];
objs[i] = objs[j];
objs[j] = temp;
}
}
}
for(int i=0;i<size;i++){
objs[i].y=-1*30*i;
}
lv_label_set_text(text_gameover, "");
score=0;
looptime=0;
enemy_go_home=0;
lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
lv_label_set_text_fmt(enemy_go_home_label,LV_SYMBOL_WARNING " %d", enemy_go_home);
status=1;
}
First execution:
game_init();
game_start();
When the game is finished, restart the execution:
game_start();
In the main game loop:
while (1) {
lv_task_handler();
if(status==1){
// 游戏中的代码
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key1)&&status==3) {
// 重新开始游戏
game_start();
}
aos_msleep(5);
lv_tick_inc(1);
}
10. Recalculate the length when the Morse code is entered incorrectly
In fact, there is no need to judge right or wrong. Because here, input is considered as input after a certain time. Once input, judging right or wrong is used for game scoring. Therefore, the recalculation of the input code length can be ignored, that is, after input, you only need to clear the input.
if(nopress_time>30){
// 判断是否击中代码区域开始
...
// 判断是否击中代码区域结束
strcpy(input,""); //强制把输入的摩尔斯电码情况
lv_label_set_text(text_input,"");//输入效果清空
}
11. Optimize code:
Turn on the computer to enter one screen, and then press the button to enter another screen.
static void gui_welcome_task(void *arg){
lv_obj_t *title;
lv_obj_t * btn_left;
lv_obj_t * btn_right;
void init_title(void){
title = lv_label_create(lv_scr_act(), NULL);
// lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);不知道这个为什么不好使
lv_obj_set_pos(title, 22, 10);
lv_label_set_text(title,"Morse Code");
}
void buttonInput(void){
lv_obj_t * label;
btn_left = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_pos(btn_left, 0, 30);
lv_obj_set_size(btn_left, 70, 30);
label = lv_label_create(btn_left, NULL);
lv_label_set_text(label,LV_SYMBOL_EDIT " Test");
}
void buttonGame(void){
lv_obj_t * label;
btn_right = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_pos(btn_right, 60, 30);
lv_obj_set_size(btn_right, 70, 30);
label = lv_label_create(btn_right, NULL);
lv_label_set_text(label,LV_SYMBOL_PLAY " Play");
}
void destroy (void){
lv_obj_del(title);
lv_obj_del(btn_left);
lv_obj_del(btn_right);
aos_task_exit(0);
}
init_title();
buttonInput();
buttonGame();
while(1){
lv_task_handler();
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key1)) {
aos_task_new("gui", gui_game_task, NULL, 10 * 1024);
destroy();
break;
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key2)) {
aos_task_new("gui", gui_test_task, NULL, 10 * 1024);
destroy();
break;
}
aos_msleep(5);
lv_tick_inc(1);
}
}
It can be found that a new subtask for free input practice has been added:
static void gui_test_task(void *arg){
lv_obj_t *text;
void textarea_create(void)
{
text = lv_textarea_create(lv_scr_act(), NULL);
lv_obj_set_size(text, 128, 60);
lv_obj_align(text, NULL, LV_ALIGN_CENTER, 0, 0);
lv_textarea_set_text(text, "");
lv_textarea_set_placeholder_text(text, "Morse Code");
}
void text_append(char* c){
int len = strlen(input);
for(int i=0;i<len;i++){
lv_textarea_del_char(text);
}
lv_textarea_add_text(text, c);
strcpy(input,"");
}
void check_input(void)
{
if(strcmp(input,".-")==0){
text_append("A");
}
if(strcmp(input,"-...")==0){
text_append("B");
}
if(strcmp(input,"-.-.")==0){
text_append("C");
}
if(strcmp(input,"-..")==0){
text_append("D");
}
if(strcmp(input,".")==0){
text_append("E");
}
if(strcmp(input,"..-.")==0){
text_append("F");
}
if(strcmp(input,"--.")==0){
text_append("G");
}
if(strcmp(input,"....")==0){
text_append("H");
}
if(strcmp(input,"..")==0){
text_append("I");
}
if(strcmp(input,".---")==0){
text_append("J");
}
if(strcmp(input,"-.-")==0){
text_append("K");
}
if(strcmp(input,".-..")==0){
text_append("L");
}
if(strcmp(input,"--")==0){
text_append("M");
}
if(strcmp(input,"-.")==0){
text_append("N");
}
if(strcmp(input,"---")==0){
text_append("O");
}
if(strcmp(input,".--.")==0){
text_append("P");
}
if(strcmp(input,"--.-")==0){
text_append("Q");
}
if(strcmp(input,".-.")==0){
text_append("R");
}
if(strcmp(input,"...")==0){
text_append("S");
}
if(strcmp(input,"-")==0){
text_append("T");
}
if(strcmp(input,"..-")==0){
text_append("U");
}
if(strcmp(input,"...-")==0){
text_append("V");
}
if(strcmp(input,".--")==0){
text_append("W");
}
if(strcmp(input,"-..-")==0){
text_append("X");
}
if(strcmp(input,"-.--")==0){
text_append("Y");
}
if(strcmp(input,"--..")==0){
text_append("Z");
}
if(strcmp(input,"-----")==0){
text_append("0");
}
if(strcmp(input,".----")==0){
text_append("1");
}
if(strcmp(input,"..---")==0){
text_append("2");
}
if(strcmp(input,"...--")==0){
text_append("3");
}
if(strcmp(input,"....-")==0){
text_append("4");
}
if(strcmp(input,".....")==0){
text_append("5");
}
if(strcmp(input,"-....")==0){
text_append("6");
}
if(strcmp(input,"--...")==0){
text_append("7");
}
if(strcmp(input,"---..")==0){
text_append("8");
}
if(strcmp(input,"----.")==0){
text_append("9");
}
}
textarea_create();
while (1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key1)) {
//当低电平(按下时)
if(button1_pressed==0){
// 如果button1的状态没有被按下,则设为按下
button1_pressed = 1;
}
if(button1_pressed==1){
//如果button1的状态是按下,则计时
time_for_pressed++;
}
}
if(GPIO_PIN_HIGH == csi_gpio_pin_read(&key1)) {
if(button1_pressed==0){
nopress_time++;
if(nopress_time>30){
check_input();
}
}
if(button1_pressed==1){
nopress_time=0;
printf("%d",time_for_pressed);
//通过判断time_for_pressed的大小,得出是长按还是短按
if(time_for_pressed>20){
//长按
printf("-");
strcat(input,"-");
lv_textarea_add_text(text,"-");
}else{
//短按
printf(".");
strcat(input,".");
lv_textarea_add_text(text,".");
}
time_for_pressed=0;//恢复计数
button1_pressed = 0;
}
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key2)) {
if(button2_pressed==0){
button2_pressed=1;
}
}
if(GPIO_PIN_HIGH == csi_gpio_pin_read(&key2)) {
if(button2_pressed==1){
printf("\n");
button2_pressed=0;
strcpy(input,"");
lv_textarea_del_char(text);
}
}
aos_msleep(5);
lv_tick_inc(1);
}
}
The final game code:
static void gui_game_task(void *arg){
static lv_style_t style;
lv_style_init(&style);
static int pad_width = 2;
time_t t;
srand((unsigned) time(&t));
int looptime = 0;
int score=0;//分数初始为0
int status=0;//初始状态为 0 游戏中 1 胜利 2 失败 3
lv_obj_t *text_gameover = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_pos(text_gameover, 28, 30);
lv_obj_set_size(text_gameover, 128, 60);
lv_label_set_text(text_gameover, "");
//输入的标签
lv_obj_t *text_input = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_pos(text_input, 100, 50);
lv_obj_set_size(text_input, 80, 20);
lv_label_set_text(text_input, "");
lv_obj_t *score_label = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_pos(score_label, 2, 0);
lv_obj_set_size(score_label, 128, 30);
lv_style_set_bg_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLUE);
lv_style_set_text_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
// set padding
lv_style_set_pad_left(&style,LV_STATE_DEFAULT,pad_width);
lv_style_set_pad_right(&style,LV_STATE_DEFAULT,pad_width);
lv_style_set_pad_top(&style,LV_STATE_DEFAULT,pad_width-1);
lv_style_set_pad_bottom(&style,LV_STATE_DEFAULT,pad_width-1);
lv_style_set_value_font(&style,LV_STATE_DEFAULT,LV_FONT_MONTSERRAT_12);
// lv_style_set_text_font(&style, LV_STATE_DEFAULT,LV_FONT_MONTSERRAT_22 );
lv_style_set_border_width(&style, LV_STATE_DEFAULT, 1);
lv_style_set_radius(&style, LV_STATE_DEFAULT, 5);
lv_style_set_border_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_label_set_text_fmt(score_label,"%d" LV_SYMBOL_OK, score);
int enemy_go_home=0;//没有被击落的字母就是敌人,这是敌人落下(家门口)的数量
// enemy go home count
lv_obj_t *enemy_go_home_label = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_pos(enemy_go_home_label, 95, 0);
lv_obj_set_size(enemy_go_home_label, 30, 30);
lv_label_set_text_fmt(enemy_go_home_label, LV_SYMBOL_WARNING " %d", enemy_go_home);
int size = 36;
struct Obj{
char name[20];
char code[20];
lv_obj_t *label;
int x;
int y;
int die;
}objs[36]={
{"A",".-"},
{"B","-..."},
{"C","-.-."},
{"D","-.."},
{"E","."},
{"F","..-."},
{"G","--."},
{"H","...."},
{"I",".."},
{"J",".---"},
{"K","-.-"},
{"L",".-.."},
{"M","--"},
{"N","-."},
{"O","---"},
{"P",".--."},
{"Q","--.-"},
{"R",".-."},
{"S","..."},
{"T","-"},
{"U","..-"},
{"V","...-"},
{"W",".--"},
{"X","-..-"},
{"Y","-.--"},
{"Z","--.."},
{"0","-----"},
{"1",".----"},
{"2","..---"},
{"3","...--"},
{"4","....-"},
{"5","....."},
{"6","-...."},
{"7","--..."},
{"8","---.."},
{"9","----."},
};
void game_init(){
for(int i=0;i<size;i++){
objs[i].label=lv_label_create(lv_scr_act(), NULL);
lv_obj_set_size(objs[i].label, 20, 20);
lv_obj_add_style(objs[i].label, LV_LABEL_PART_MAIN, &style);
lv_label_set_text(objs[i].label, objs[i].name);
}
}
void game_start(){
for(int i=0;i<size;i++){
objs[i].x=20 + rand() % (128-80);
objs[i].y=-1*(rand() % size)-30;
objs[i].die=0;
lv_obj_set_pos(objs[i].label, objs[i].x, objs[i].y);
}
for (int i = 0; i < size; ++i){
for (int j = i + 1; j < size; ++j){
if (objs[i].y < objs[j].y){
struct Obj temp = objs[i];
objs[i] = objs[j];
objs[j] = temp;
}
}
}
for(int i=0;i<size;i++){
objs[i].y=-1*30*i;
}
lv_label_set_text(text_gameover, "");
score=0;
looptime=0;
enemy_go_home=0;
lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
lv_label_set_text_fmt(enemy_go_home_label,LV_SYMBOL_WARNING " %d", enemy_go_home);
status=1;
}
game_init();
game_start();
while (1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
if(status==1){
looptime+=1;
if(looptime % 10 ==0){
for(int i=0;i<size;i++){
if(objs[i].die==0){
objs[i].y+=1;
lv_obj_set_pos(objs[i].label, objs[i].x, objs[i].y);
//如果没有被击中,而且落下去了
if(objs[i].y>64){
enemy_go_home+=1;
lv_label_set_text_fmt(enemy_go_home_label, LV_SYMBOL_WARNING " %d", enemy_go_home);
objs[i].die=1;
}
}
}
if(enemy_go_home>=5){
// for(int i=0;i<size;i++){
// lv_label_set_text(objs[i].label, "");
// }
lv_label_set_text(text_gameover, "GameOver");
status = 3; //game over
}
}
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key1)&&status==3) {
//restart
game_start();
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key1)&&status==1) {
//当低电平(按下时)
if(button1_pressed==0){
// 如果button1的状态没有被按下,则设为按下
button1_pressed = 1;
}
if(button1_pressed==1){
//如果button1的状态是按下,则计时
time_for_pressed++;
}
}
if(GPIO_PIN_HIGH == csi_gpio_pin_read(&key1)&&status==1) {
if(button1_pressed==0){
nopress_time++;
if(nopress_time>30){
//check_input();
for(int i=0;i<size;i++){
//如果没有被击中
if(objs[i].die==0){
if(objs[i].y>0 && objs[i].y<64){
//在可视区间
if(strcmp(input,objs[i].code)==0){
objs[i].die = 1;//标记被击中
objs[i].y = 128;
lv_obj_set_pos(objs[i].label, objs[i].x, objs[i].y);
score++;
lv_label_set_text_fmt(score_label,"%d " LV_SYMBOL_OK, score);
}
}
}
}
strcpy(input,"");
lv_label_set_text(text_input,"");//输入效果清空
//check win
//if status == playing
if(score==size){
//status == "win"
}
}
}
if(button1_pressed==1){
nopress_time=0;
printf("%d",time_for_pressed);
//通过判断time_for_pressed的大小,得出是长按还是短按
if(time_for_pressed>20){
//长按
printf("-");
strcat(input,"-");
}else{
//短按
printf(".");
strcat(input,".");
}
lv_label_set_text(text_input,input);//输入效果
time_for_pressed=0;//恢复计数
button1_pressed = 0;
}
}
if(GPIO_PIN_LOW == csi_gpio_pin_read(&key2)&&status==1) {
if(button2_pressed==0){
button2_pressed=1;
}
}
if(GPIO_PIN_HIGH == csi_gpio_pin_read(&key2)&&status==1) {
if(button2_pressed==1){
printf("\n");
button2_pressed=0;
strcpy(input,"");
lv_label_set_text(text_input,"");//输入效果清空
}
}
aos_msleep(5);
lv_tick_inc(1);
}
}