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();
当游戏结束后重新开始执行:
game_start();
在游戏的主循环里:
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、摩尔斯电码输入错误时重新计算长度
实际上并不需要判断对错。因为这里用的是超过一定时间就算输入,一旦输入,判断对错是用于游戏计分的。因此,对于重新计算输入的电码长度,就可以忽略了,也就是,对于输入后,只需要把输入清空就可以了。
if(nopress_time>30){
// 判断是否击中代码区域开始
...
// 判断是否击中代码区域结束
strcpy(input,""); //强制把输入的摩尔斯电码情况
lv_label_set_text(text_input,"");//输入效果清空
}
11、优化代码:
开机进入一个画面,之后通过按钮进入另外的画面。
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);
}
}
可以发现,新增了一个用于自由输入练习的子task:
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);
}
}
最后游戏部分全部代码:
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);
}
}