⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wormlet.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * Returns the index of the food that is closest to the point * specified by x, y. This index may be used in the foodx and  * foody arrays. * @param int x The x coordinate of the point * @param int y The y coordinate of the point * @return int A value usable as index in foodx and foody. */static int get_nearest_food(int x, int y){    int nearestfood = 0;    int olddistance = FIELD_RECT_WIDTH + FIELD_RECT_HEIGHT;    int deltax = 0;    int deltay = 0;    int foodindex;    for (foodindex = 0; foodindex < MAX_FOOD; foodindex++) {        int distance;        deltax = foodx[foodindex] - x;        deltay = foody[foodindex] - y;        deltax = deltax > 0 ? deltax : deltax * (-1);        deltay = deltay > 0 ? deltay : deltay * (-1);        distance = deltax + deltay;        if (distance < olddistance) {            olddistance = distance;            nearestfood = foodindex;        }    }    return nearestfood;}/**  * Returns wether the specified position is next to the worm * and in the direction the worm looks. Use this method to  * test wether this position would be hit with the next move of  * the worm unless the worm changes its direction. * @param struct worm *w - The worm to be investigated * @param int x - The x coordinate of the position to test. * @param int y - The y coordinate of the position to test. * @return Returns true if the worm will hit the position unless * it change its direction before the next move. */static bool is_in_front_of_worm(struct worm *w, int x, int y) {    bool infront = false;    int deltax = x - w->x[w->head];    int deltay = y - w->y[w->head];    if (w->dirx == 0) {        infront = (w->diry * deltay) > 0;    } else {        infront = (w->dirx * deltax) > 0;    }    return infront;}/** * Returns true if the worm will collide with the next move unless * it changes its direction. * @param struct worm *w - The worm to be investigated. * @return Returns true if the worm will collide with the next move * unless it changes its direction. */static bool will_worm_collide(struct worm *w) {    int x = w->x[w->head] + w->dirx;    int y = w->y[w->head] + w->diry;    bool retVal = !is_in_field_rect(x, y);    if (!retVal) {        retVal = (argh_collision(x, y) != -1);    }        if (!retVal) {        retVal = (worm_collision(w, x, y) != NULL);    }    return retVal;}/**  * This function * may be used to be stored in worm.fetch_worm_direction for * worms that are not controlled by humans but by artificial stupidity.  * A direction is searched that doesn't lead to collision but to the nearest * food - but not very intelligent. The direction is written to the specified * worm. * @param struct worm *w - The worm of which the direction  * is altered. */static void virtual_player(struct worm *w) {    bool isright;    int plana, planb, planc;    /* find the next lunch */    int nearestfood = get_nearest_food(w->x[w->head], w->y[w->head]);    /* determine in which direction it is */    /* in front of me? */    bool infront = is_in_front_of_worm(w, foodx[nearestfood], foody[nearestfood]);    /* left right of me? */    int olddir = get_worm_dir(w);    set_worm_dir(w, (olddir + 1) % 4);    isright = is_in_front_of_worm(w, foodx[nearestfood], foody[nearestfood]);    set_worm_dir(w, olddir);    /* detect situation, set strategy */    if (infront) {        if (isright) {            plana = olddir;            planb = (olddir + 1) % 4;            planc = (olddir + 3) % 4;        } else {            plana = olddir;            planb = (olddir + 3) % 4;            planc = (olddir + 1) % 4;        }    } else {        if (isright) {            plana = (olddir + 1) % 4;            planb = olddir;            planc = (olddir + 3) % 4;        } else {            plana = (olddir + 3) % 4;            planb = olddir;            planc = (olddir + 1) % 4;        }    }    /* test for collision */    set_worm_dir(w, plana);    if (will_worm_collide(w)){        /* plan b */        set_worm_dir(w, planb);        /* test for collision */        if (will_worm_collide(w)) {            /* plan c */            set_worm_dir(w, planc);        }    }}/** * prints out the score board with all the status information * about the game. */static void score_board(void){    char buf[15];    char* buf2 = NULL;    int i;    int y = 0;    rb->lcd_clearrect(FIELD_RECT_WIDTH + 2, 0, LCD_WIDTH - FIELD_RECT_WIDTH - 2, LCD_HEIGHT);    for (i = 0; i < worm_count; i++) {        int score = get_score(&worms[i]);            /* high score */        if (worms[i].fetch_worm_direction != virtual_player){            if (highscore < score) {                highscore = score;            }        }        /* length */        rb->snprintf(buf, sizeof (buf),"Len:%d", score);        /* worm state */        switch (check_collision(&worms[i])) {            case COLLISION_NONE:                  if (worms[i].growing > 0)                    buf2 = "Growing";                else {                    if (worms[i].alive)                        buf2 = "Hungry";                    else                        buf2 = "Wormed";                }                break;            case COLLISION_WORM:                  buf2 = "Wormed";                break;            case COLLISION_FOOD:                  buf2 = "Growing";                break;            case COLLISION_ARGH:                  buf2 = "Argh";                break;            case COLLISION_FIELD:                 buf2 = "Crashed";                break;        }        rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, y  , buf);        rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, y+8, buf2);        if (!worms[i].alive){            rb->lcd_invertrect(FIELD_RECT_WIDTH + 2, y,                                LCD_WIDTH - FIELD_RECT_WIDTH - 2, 17);        }        y += 19;    }    rb->snprintf(buf , sizeof(buf), "Hs: %d", highscore);#ifndef DEBUG_WORMLET    rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, buf);#else    rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, debugout);#endif}/** * Checks for collisions of the worm and its environment and * takes appropriate actions like growing the worm or killing it. * @return bool Returns true if the worm is dead. Returns * false if the worm is healthy, up and creeping. */static bool process_collisions(struct worm *w){    int index = -1;    w->alive &= !field_collision(w);    if (w->alive) {        /* check if food was eaten */        index = food_collision(w->x[w->head], w->y[w->head]);        if (index != -1){            int i;                        clear_food(index);            make_food(index);            draw_food(index);                        for (i = 0; i < ARGHS_PER_FOOD; i++) {                argh_count++;                if (argh_count > MAX_ARGH)                    argh_count = MAX_ARGH;                make_argh(argh_count - 1);                draw_argh(argh_count - 1);            }            add_growing(w, WORM_PER_FOOD);            draw_worm(w);        }        /* check if argh was eaten */        else {            index = argh_collision(w->x[w->head], w->y[w->head]);            if (index != -1) {                w->alive = false;        }            else {                if (worm_collision(w, w->x[w->head], w->y[w->head]) != NULL) {                    w->alive = false;    }            }        }    }    return !w->alive;}/** * The main loop of the game. * @return bool Returns true if the game ended * with a dead worm. Returns false if the user * aborted the game manually. */ static bool run(void){    int button = 0;    int wormDead = false;    /* ticks are counted to compensate speed variations */    long cycle_start = 0, cycle_end = 0;#ifdef DEBUG_WORMLET    int ticks_to_max_cycle_reset = 20;    long max_cycle = 0;    char buf[20];#endif    /* initialize the board and so on */    init_wormlet();    cycle_start = *rb->current_tick;    /* change the direction of the worm */    while (button != BUTTON_OFF && ! wormDead)    {        int i;        long cycle_duration ;        switch (button) {            case BUTTON_UP:                if (players == 1 && !use_remote) {                    player1_dir = NORTH;                }                break;            case BUTTON_DOWN:                if (players == 1 && !use_remote) {                    player1_dir = SOUTH;                }                break;            case BUTTON_LEFT:                if (players != 1 || use_remote) {                    player1_dir = (player1_dir + 3) % 4;                } else {                    player1_dir = WEST;                }                break;            case BUTTON_RIGHT:                if (players != 1 || use_remote) {                    player1_dir = (player1_dir + 1) % 4;                } else {                    player1_dir = EAST;                }                break;            case BUTTON_F2:                player2_dir = (player2_dir + 3) % 4;                break;            case BUTTON_F3:                player2_dir = (player2_dir + 1) % 4;                break;            case BUTTON_RC_VOL_UP:                player3_dir = (player3_dir + 1) % 4;                break;            case BUTTON_RC_VOL_DOWN:                player3_dir = (player3_dir + 3) % 4;                break;            case BUTTON_PLAY:                do {                    button = rb->button_get(true);                } while (button != BUTTON_PLAY &&                         button != BUTTON_OFF  &&                         button != BUTTON_ON);                break;        }        for (i = 0; i < worm_count; i++) {            worms[i].fetch_worm_direction(&worms[i]);        }        wormDead = true;        for (i = 0; i < worm_count; i++){            struct worm *w = &worms[i];            move_worm(w);            wormDead &= process_collisions(w);            draw_worm(w);        }        score_board();        rb->lcd_update();        if (button == BUTTON_ON) {            wormDead = true;        }        /* here the wormlet game cycle ends           thus the current tick is stored           as end time */        cycle_end = *rb->current_tick;        /* The duration of the game cycle */        cycle_duration = cycle_end - cycle_start;        cycle_duration = MAX(0, cycle_duration);        cycle_duration = MIN(SPEED -1, cycle_duration);#ifdef DEBUG_WORMLET        ticks_to_max_cycle_reset--;        if (ticks_to_max_cycle_reset <= 0) {            max_cycle = 0;        }        if (max_cycle < cycle_duration) {            max_cycle = cycle_duration;            ticks_to_max_cycle_reset = 20;        }        rb->snprintf(buf, sizeof buf, "ticks %d", max_cycle);        set_debug_out(buf);#endif        /* adjust the number of ticks to wait for a button.           This ensures that a complete game cycle including           user input runs in constant time */        button = rb->button_get_w_tmo(SPEED - cycle_duration);        cycle_start = *rb->current_tick;    }    return wormDead;}#ifdef DEBUG_WORMLET/** * Just a test routine that checks that worm_food_collision works * in some typical situations. */static void test_worm_food_collision(void) {    int collision_count = 0;    int i;    rb->lcd_clear_display();    init_worm(&worms[0], 10, 10);    add_growing(&worms[0], 10);    set_worm_dir(&worms[0], EAST);    for (i = 0; i < 10; i++) {        move_worm(&worms[0]);        draw_worm(&worms[0]);    }    set_worm_dir(&worms[0], SOUTH);    for (i = 0; i < 10; i++) {        move_worm(&worms[0]);        draw_worm(&worms[0]);    }    foodx[0] = 15;    foody[0] = 12;    for (foody[0] = 20; foody[0] > 0; foody[0] --) {        char buf[20];        bool collision;        draw_worm(&worms[0]);        draw_food(0);        collision = worm_food_collision(&worms[0], 0);        if (collision) {            collision_count++;        }        rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);        rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);        rb->lcd_update();    }    if (collision_count != FOOD_SIZE) {        rb->button_get(true);    }    foody[0] = 15;    for (foodx[0] = 30; foodx[0] > 0; foodx[0] --) {        char buf[20];        bool collision;        draw_worm(&worms[0]);        draw_food(0);        collision = worm_food_collision(&worms[0], 0);        if (collision) {            collision_count ++;        }        rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);        rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);        rb->lcd_update();    }    if (collision_count != FOOD_SIZE * 2) {        rb->button_get(true);    }}static bool expensive_worm_in_rect(struct worm *w, int rx, int ry, int rw, int rh){    int x, y;    bool retVal = false;    for (x = rx; x < rx + rw; x++){        for (y = ry; y < ry + rh; y++) {            if (specific_worm_collision(w, x, y) != -1) {                retVal = true;            }        }    }    return retVal;}static void test_worm_argh_collision(void) {    int i;    int dir;    int collision_count = 0;    rb->lcd_clear_display();    init_worm(&worms[0], 10, 10);    add_growing(&worms[0], 40);    for (dir = 0; dir < 4; dir++) {        set_worm_dir(&worms[0], (EAST + dir) % 4);        for (i = 0; i < 10; i++) {            move_worm(&worms[0]);            draw_worm(&worms[0]);        }    }    arghx[0] = 12;    for (arghy[0] = 0; arghy[0] < FIELD_RECT_HEIGHT - ARGH_SIZE; arghy[0]++){        char buf[20];        bool collision;        draw_argh(0);        collision = worm_argh_collision(&worms[0], 0);        if (collision) {            collision_count ++;        }        rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);        rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);        rb->lcd_update();    }    if (collision_count != ARGH_SIZE * 2) {        rb->button_get(true);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -