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

📄 wormlet.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 4 页
字号:
/*************************************************************************** *             __________               __   ___. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  / *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ *                     \/            \/     \/    \/            \/ * $Id: wormlet.c,v 1.1 2003/06/29 16:33:04 zagor Exp $ * * Copyright (C) 2002 Philipp Pertermann * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include "plugin.h"#ifdef HAVE_LCD_BITMAP/* size of the field the worm lives in */#define FIELD_RECT_X 1#define FIELD_RECT_Y 1#define FIELD_RECT_WIDTH  (LCD_WIDTH - 45)#define FIELD_RECT_HEIGHT (LCD_HEIGHT - 2)/* size of the ring of the worm    choos a value that is a power of 2 to help    the compiler optimize modul operations*/#define MAX_WORM_SEGMENTS 64   /* when the game starts */#define INITIAL_WORM_LENGTH 10 /* num of pixel the worm grows per eaten food */#define WORM_PER_FOOD 7        /* num of worms creeping in the FIELD */#define MAX_WORMS 3            /* minimal distance between a worm and an argh    when a new argh is made */#define MIN_ARGH_DIST 5/** * All the properties that a worm has. */static struct worm {    /* The worm is stored in a ring of xy coordinates */    char x[MAX_WORM_SEGMENTS];    char y[MAX_WORM_SEGMENTS];    int head;      /* index of the head within the buffer */    int tail;      /* index of the tail within the buffer */    int growing;   /* number of cyles the worm still keeps growing */    bool alive;    /* the worms living state */    /* direction vector in which the worm moves */    int dirx; /* only values -1 0 1 allowed */    int diry; /* only values -1 0 1 allowed */    /* this method is used to fetch the direction the user       has selected. It can be one of the values       human_player1, human_player2, remote_player, virtual_player.        All these values are fuctions, that can change the direction        of the worm */    void (*fetch_worm_direction)(struct worm *w);} worms[MAX_WORMS];/* stores the highscore - besides it was scored by a virtual player */static int highscore;#define MAX_FOOD  5 /* maximal number of food items */#define FOOD_SIZE 3 /* the width and height of a food *//* The arrays store the food coordinates  */static char foodx[MAX_FOOD];static char foody[MAX_FOOD];#define MAX_ARGH  100    /* maximal number of argh items */#define ARGH_SIZE 4      /* the width and height of a argh */#define ARGHS_PER_FOOD 2 /* number of arghs produced per eaten food *//* The arrays store the argh coordinates */static char arghx[MAX_ARGH];static char arghy[MAX_ARGH];/* the number of arghs that are currently in use */ static int argh_count;#ifdef DEBUG_WORMLET/* just a buffer used for debug output */static char debugout[15];#endif/* the number of ticks each game cycle should take */ #define SPEED 14/* the number of active worms (dead or alive) */static int worm_count = MAX_WORMS;/* in multiplayer mode: en- / disables the remote worm control   in singleplayer mode: toggles 4 / 2 button worm control */static bool use_remote = false;/* return values of check_collision */#define COLLISION_NONE 0#define COLLISION_WORM 1#define COLLISION_FOOD 2#define COLLISION_ARGH 3#define COLLISION_FIELD 4/* constants for use as directions.   Note that the values are ordered clockwise.   Thus increasing / decreasing the values   is equivalent to right / left turns. */#define WEST  0#define NORTH 1#define EAST  2#define SOUTH 3/* direction of human player 1 */static int player1_dir = EAST; /* direction of human player 2 */static int player2_dir = EAST; /* direction of human player 3 */static int player3_dir = EAST;/* the number of (human) players that currently   control a worm */static int players = 1;/* the rockbox plugin api */static struct plugin_api* rb;#ifdef DEBUG_WORMLETstatic void set_debug_out(char *str){    strcpy(debugout, str);}#endif/** * Returns the direction id in which the worm * currently is creeping. * @param struct worm *w The worm that is to be investigated.  *        w Must not be null. * @return int A value 0 <= value < 4 *         Note the predefined constants NORTH, SOUTH, EAST, WEST */static int get_worm_dir(struct worm *w) {    int retVal ;    if (w->dirx == 0) {        if (w->diry == 1) {            retVal = SOUTH;        } else {            retVal = NORTH;        }    } else {        if (w->dirx == 1) {            retVal = EAST;        } else {            retVal = WEST;        }    }    return retVal;}/** * Set the direction of the specified worm with a direction id. * Increasing the value by 1 means to turn the worm direction * to right by 90 degree. * @param struct worm *w The worm that is to be altered. w Must not be null. * @param int dir The new direction in which the worm is to creep. *        dir must be  0 <= dir < 4. Use predefined constants  *        NORTH, SOUTH, EAST, WEST */static void set_worm_dir(struct worm *w, int dir) {    switch (dir) {        case WEST:            w->dirx = -1;            w->diry = 0;            break;         case NORTH:            w->dirx = 0;            w->diry = - 1;            break;        case EAST:            w->dirx = 1;            w->diry = 0;            break;        case SOUTH:            w->dirx = 0;            w->diry = 1;            break;   }}/** * Returns the current length of the worm array. This * is also a value for the number of bends that are in the worm. * @return int a positive value with 0 <= value < MAX_WORM_SEGMENTS */static int get_worm_array_length(struct worm *w) {    /* initial simple calculation will be overwritten if wrong. */    int retVal = w->head - w->tail;    /* if the worm 'crosses' the boundaries of the ringbuffer */    if (retVal < 0) {        retVal = w->head + MAX_WORM_SEGMENTS - w->tail;    }    return retVal;}/** * Returns the score the specified worm. The score is the length * of the worm. * @param struct worm *w The worm that is to be investigated. *        w must not be null. * @return int The length of the worm (>= 0). */static int get_score(struct worm *w) {    int retval = 0;    int length = get_worm_array_length(w);    int i;    for (i = 0; i < length; i++) {        /* The iteration iterates the length of the worm.           Here's the conversion to the true indices within the worm arrays. */        int linestart = (w->tail + i  ) % MAX_WORM_SEGMENTS;        int lineend   = (linestart + 1) % MAX_WORM_SEGMENTS;        int startx = w->x[linestart];        int starty = w->y[linestart];        int endx = w->x[lineend];        int endy = w->y[lineend];        int minimum, maximum;        if (startx == endx) {            minimum = MIN(starty, endy);            maximum = MAX(starty, endy);        } else {            minimum = MIN(startx, endx);            maximum = MAX(startx, endx);        }            retval += abs(maximum - minimum);    }    return retval;}/** * Determines wether the line specified by startx, starty, endx, endy intersects * the rectangle specified by x, y, width, height. Note that the line must be exactly * horizontal or vertical (startx == endx or starty == endy).  * @param int startx The x coordinate of the start point of the line. * @param int starty The y coordinate of the start point of the line. * @param int endx The x coordinate of the end point of the line. * @param int endy The y coordinate of the end point of the line. * @param int x The x coordinate of the top left corner of the rectangle. * @param int y The y coordinate of the top left corner of the rectangle. * @param int width The width of the rectangle. * @param int height The height of the rectangle. * @return bool Returns true if the specified line intersects with the recangle. */static bool line_in_rect(int startx, int starty, int endx, int endy, int x, int y, int width, int height) {    bool retval = false;    int simple, simplemin, simplemax;    int compa, compb, compmin, compmax;    int temp;    if (startx == endx) {        simple = startx;        simplemin = x;        simplemax = x + width;        compa = starty;        compb = endy;        compmin = y;        compmax = y + height;    } else {        simple = starty;        simplemin = y;        simplemax = y + height;        compa = startx;        compb = endx;        compmin = x;        compmax = x + width;    };    temp = compa;    compa = MIN(compa, compb);    compb = MAX(temp, compb);    if (simplemin <= simple && simple <= simplemax) {        if ((compmin <= compa && compa <= compmax) ||            (compmin <= compb && compb <= compmax) ||            (compa <= compmin && compb >= compmax)) {            retval = true;        }    }    return retval;}/**  * Tests wether the specified worm intersects with the rect. * @param struct worm *w The worm to be investigated * @param int x The x coordinate of the top left corner of the rect * @param int y The y coordinate of the top left corner of the rect * @param int widht The width of the rect * @param int height The height of the rect * @return bool Returns true if the worm intersects with the rect */static bool worm_in_rect(struct worm *w, int x, int y, int width, int height) {    bool retval = false;    /* get_worm_array_length is expensive -> buffer the value */    int wormLength = get_worm_array_length(w);    int i;    /* test each entry that is part of the worm */    for (i = 0; i < wormLength && retval == false; i++) {        /* The iteration iterates the length of the worm.           Here's the conversion to the true indices within the worm arrays. */        int linestart = (w->tail + i  ) % MAX_WORM_SEGMENTS;        int lineend   = (linestart + 1) % MAX_WORM_SEGMENTS;        int startx = w->x[linestart];        int starty = w->y[linestart];        int endx = w->x[lineend];        int endy = w->y[lineend];        retval = line_in_rect(startx, starty, endx, endy, x, y, width, height);    }    return retval;}/** * Checks wether a specific food in the food arrays is at the * specified coordinates. * @param int foodIndex The index of the food in the food arrays * @param int x the x coordinate. * @param int y the y coordinate. * @return Returns true if the coordinate hits the food specified by * foodIndex. */static bool specific_food_collision(int foodIndex, int x, int y) {    bool retVal = false;    if (x >= foodx[foodIndex]             &&        x <  foodx[foodIndex] + FOOD_SIZE &&        y >= foody[foodIndex]             &&        y <  foody[foodIndex] + FOOD_SIZE) {        retVal = true;    }    return retVal;}/** * Returns the index of the food that is at the * given coordinates. If no food is at the coordinates * -1 is returned. * @return int  -1 <= value < MAX_FOOD */static int food_collision(int x, int y) {    int i = 0;    int retVal = -1;    for (i = 0; i < MAX_FOOD; i++) {        if (specific_food_collision(i, x, y)) {            retVal = i;            break;        }    }    return retVal;}/** * Checks wether a specific argh in the argh arrays is at the * specified coordinates. * @param int arghIndex The index of the argh in the argh arrays * @param int x the x coordinate. * @param int y the y coordinate. * @return Returns true if the coordinate hits the argh specified by * arghIndex. */static bool specific_argh_collision(int arghIndex, int x, int y) {    if ( x >= arghx[arghIndex] &&         y >= arghy[arghIndex] &&         x <  arghx[arghIndex] + ARGH_SIZE &&         y <  arghy[arghIndex] + ARGH_SIZE )    {        return true;    }    return false;}/** * Returns the index of the argh that is at the * given coordinates. If no argh is at the coordinates * -1 is returned. * @param int x The x coordinate. * @param int y The y coordinate. * @return int  -1 <= value < argh_count <= MAX_ARGH */static int argh_collision(int x, int y) {    int i = 0;    int retVal = -1;    /* search for the argh that has the specified coords */    for (i = 0; i < argh_count; i++) {        if (specific_argh_collision(i, x, y)) {            retVal = i;            break;        }    }    return retVal;}/** * Checks wether the worm collides with the food at the specfied food-arrays. * @param int foodIndex The index of the food in the arrays. Ensure the value is * 0 <= foodIndex <= MAX_FOOD * @return Returns true if the worm collides with the specified food. */static bool worm_food_collision(struct worm *w, int foodIndex){    bool retVal = false;    retVal = worm_in_rect(w, foodx[foodIndex], foody[foodIndex],                           FOOD_SIZE - 1, FOOD_SIZE - 1);    return retVal;}/** * Returns true if the worm hits the argh within the next moves (unless * the worm changes it's direction). * @param struct worm *w - The worm to investigate * @param int argh_idx - The index of the argh  * @param int moves - The number of moves that are considered. * @return Returns false if the specified argh is not hit within the next *         moves. */static bool worm_argh_collision_in_moves(struct worm *w, int argh_idx, int moves){    bool retVal = false;    int x1, y1, x2, y2;    x1 = w->x[w->head];    y1 = w->y[w->head];    x2 = w->x[w->head] + moves * w->dirx;    y2 = w->y[w->head] + moves * w->diry;    retVal = line_in_rect(x1, y1, x2, y2, arghx[argh_idx], arghy[argh_idx],                          ARGH_SIZE, ARGH_SIZE);    return retVal;}/** * Checks wether the worm collides with the argh at the specfied argh-arrays. * @param int arghIndex The index of the argh in the arrays. * Ensure the value is 0 <= arghIndex < argh_count <= MAX_ARGH * @return Returns true if the worm collides with the specified argh. */static bool worm_argh_collision(struct worm *w, int arghIndex){    bool retVal = false;    retVal = worm_in_rect(w, arghx[arghIndex], arghy[arghIndex],                           ARGH_SIZE - 1, ARGH_SIZE - 1);    return retVal;}/** * Find new coordinates for the food stored in foodx[index], foody[index] * that don't collide with any other food or argh * @param int index  * Ensure that 0 <= index < MAX_FOOD. */static int make_food(int index) {    int x = 0;    int y = 0;    bool collisionDetected = false;    int tries = 0;    int i;    do {        /* make coordinates for a new food so that           the entire food lies within the FIELD */        x = rb->rand() % (FIELD_RECT_WIDTH  - FOOD_SIZE);        y = rb->rand() % (FIELD_RECT_HEIGHT - FOOD_SIZE);        tries ++;        /* Ensure that the new food doesn't collide with any           existing foods or arghs.           If one or more corners of the new food hit any existing           argh or food a collision is detected.

⌨️ 快捷键说明

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