defender.c

来自「开发linux应用-用gtk+和gdk开发linux图形用户界面应用--的实例」· C语言 代码 · 共 1,642 行 · 第 1/3 页

C
1,642
字号
     * --- This missile has a life, when it goes to zero,      *     it gets destroyed.     */    missile->life = 60;    return (missile);}/* * AddExplosion * * A unit was destroyed - we create an explosion at the  * unit's location */void AddExplosion (typUnit *unit){    typUnit *frag;    int i;    /* --- Creating eight fragments --- */    for (i = 0; i < 8; i++) {        /* --- Create a fragment of the explosion --- */        frag = (typUnit *) g_malloc (sizeof (typUnit));        /* --- Initialize the fragment --- */        frag->bDestroy = FALSE;        frag->pctFiring = 0;        frag->type = EXPLOSION;        frag->x = unit->x;        frag->y = unit->y;          /* --- Moves quite fast --- */        frag->vx = x_exp[i] * 5;        frag->vy = y_exp[i] * 5;        frag->lockunit = NULL;        /* --- Short life --- */        frag->life = 20;        /* --- Add it to the list of units --- */        unitList = g_list_append (unitList, frag);    }}/* * PlaceAliens * * Create the aliens.   */void PlaceAliens (){    int i;    typUnit *alien;    /* --- Create each of the aliens --- */    for (i = 0; i < START_ALIENS; i++) {        /* --- Create one alien --- */        alien = CreateAlien ();        /* --- Add it to the units list --- */        unitList = g_list_append (unitList, alien);    }}/* * DistanceBetween * * Calculate the distance between two units - but * only use the X direction to calculate the distance. * The distance is not just the difference between * the units X coordinates, but since the world  * wraps around, we have to consider the fact that * the distance between 1 and X_RANGE - 1 is not  * (X_RANGE-1) - 1 */int DistanceBetween (typUnit *u1, typUnit *u2){    int nDistance;    int nDistance2;    /* --- Figure out which is greater --- */    if (u1->x < u2->x) {          /* --- Calculate distance both ways --- */        nDistance = u2->x - u1->x;        nDistance2 = X_RANGE + u1->x - u2->x;    } else {        /* --- Calculate distance both ways --- */        nDistance = u1->x - u2->x;        nDistance2 = X_RANGE + u2->x - u1->x;    }     /* --- Pick smaller of the distances --- */    return ((nDistance < nDistance2) ? nDistance : nDistance2);}/* * Direction * * What is the -x- directory between the two units? * It's either going to be -1, 1, or 0.  */int Direction (typUnit *u1, typUnit *u2){    int nDistance;    int nDistance2;    if (u1->x < u2->x) {          /* --- Distance each way --- */        nDistance = u2->x - u1->x;        nDistance2 = X_RANGE + u1->x - u2->x;    } else {        /* --- Distance each way --- */        nDistance2 = u1->x - u2->x;        nDistance = X_RANGE + u2->x - u1->x;    }    /* --- Direction depends on closer distance --- */    return ((nDistance < nDistance2) ? 1 : -1);}/* * AttemptFiring * * Have the alien fire at the hero. */void AttemptFiring (typUnit *unit){    typUnit *missile;    /* --- Close enough to shoot at --- */    if (DistanceBetween (hero, unit) < (nScreenWidth / 2)) {                /* --- Random chance - less than unit's chance --- */        if ((rand () % 100) < unit->pctFiring) {            /* --- Create the missle going after the hero --- */            missile = CreateMissile (unit, hero);            /* --- Add to the list of units --- */            unitList = g_list_append (unitList, missile);        }    }}/* * AIModule * * Contains the logic for each of the units to move.  * Some units like landers are looking for people to * pick up.  Mutuants hunt down the player.  Missiles * just go until they die, etc. */void AIModule (typUnit *unit){    typUnit *tmp;    int bestdist = 50000;    typUnit *closest = NULL;    GList *node;    /*     * Alien lander AI logic     */    if (unit->type == LANDER) {        /* --- if the alien's locked on a person --- */        if (unit->lockunit) {            /* --- Move it up. --- */            closest = unit->lockunit;            unit->y -= .5;            closest->y -= .5;                        /* --- If alien's made it to the top --- */            if (unit->y - (sprite_lander[0].height / 2) < RADAR_HEIGHT) {                /* --- Assimilate human! --- */                unit->y = RADAR_HEIGHT + (sprite_lander[0].height / 2);                unit->type = MUTANT;                unit->pctFiring = MUTANT_TRIGGER_PCT;                unit->lockunit = NULL;                closest->bDestroy = TRUE;            }            return;        }        /* --- Any people nearby to snatch? --- */        for (node = unitList; node; node = node->next) {            tmp = (typUnit *) node->data;                       if (tmp->type == PERSON && tmp->lockunit == NULL) {                    /* --- Look for a closer person --- */                if (DistanceBetween (unit, tmp) < bestdist) {                    closest = tmp;                    bestdist = DistanceBetween (unit, tmp);                }            }        }        /* --- We're locked onto a target --- */        if (bestdist <= 1) {            /* --- Scootch it over a bit --- */            unit->vx = 0;            unit->x = closest->x;            /*              * --- Check for a lock... ---              */            if ((unit->y + (sprite_lander[0].height / 2) + .8) <                 (closest->y - (sprite_man[0].height / 2))) {                /* --- Come down on it. --- */                unit->y += .5;            } else if ((unit->y + (sprite_lander[0].height / 2)) >                 (closest->y - (sprite_man[0].height / 2))) {                            unit->y -= .5;            } else {                /* --- Lock it in --- */                unit->lockunit = closest;                closest->lockunit = unit;                closest->life = 20;            }        /* --- Anything in reasonable range? --- */        } else if (bestdist < 20) {            /* --- Move towards it --- */            unit->vx = Direction (unit, closest);            unit->x += unit->vx;        } else {            /*              * --- Nothing nearby.  Move in a random direction.              */            if (unit->vx == 0) {                if ((rand () % 2) == 0) {                    unit->vx = 1;                } else {                    unit->vx = -1;                }            }            unit->x += unit->vx;        }            /*         * See if there is anything worth shooting at.         */        AttemptFiring (unit);    /*     * Mutant AI logic     */    } else if (unit->type == MUTANT) {        /*          * --- Lets go crazy.  Mutant moves almost randomly yet          *     slowly towards the player.         */        unit->vx = Direction (unit, hero) * ((rand () % 4) + 1);        unit->vy = rand () % 5 - 2;                /*          * If the hero is within smelling distance, move towards         * player in the -y- direction.         */        if (DistanceBetween (unit, hero) < 200) {            if (unit->y < hero->y) unit->vy++;            if (unit->y > hero->y) unit->vy--;        }        /* --- Finally move the unit --- */        Move (unit);        /* --- Let the mutant attempt firing --- */        AttemptFiring (unit);    /*     * --- Missiles and explosions     */    } else if ((unit->type == MISSILE) ||                (unit->type == EXPLOSION)) {        /* --- These have a life.  Decrement it. --- */         unit->life --;        /* --- Move it. --- */        Move (unit);        /* --- When it reaches zero, destroy it --- */        if (unit->life <= 0) {            unit->bDestroy = TRUE;        }    /*     * Person AI.     */    } else if (unit->type == PERSON) {        /*          * Only time person moves by itself is when it's falling         * from the sky after the alien carrying it has been shot.         */        if (unit->lockunit == NULL && unit->y < PERSON_HEIGHT) {            /* --- Move it down --- */            unit->y += 2;        }    }}/* * GetSprite *  * Get the sprite for the unit.  */typSprite *GetSprite (typUnit *unit){    typSprite *sprite;    /* --- Get sprite --- */    switch (unit->type) {        case HERO:            sprite = sprite_ship;            break;         case PERSON:            sprite = sprite_man;            break;        case LANDER:             sprite = sprite_lander;            break;        case MUTANT:             sprite = sprite_mutant;            break;        case MISSILE:        case EXPLOSION:            sprite = sprite_missile;            break;        default:            sprite = NULL;            break;    }    return (sprite);}/* * AnyoneBetween *  * Is any unit between these coordinates?  Used by the  * laser when computing if anything has been hit.  */typUnit *AnyoneBetween (int x1, int y1, int x2, int y2){    GList *node;    typUnit *unit;    typUnit *closestUnit = NULL;    int closestX;    typSprite *sprite;    int screenX;    /* --- Check each unit --- */    for (node = unitList; node; node = node->next) {         unit = (typUnit *) node->data;         /* --- if it's a bad guy --- */         if ((unit->type == LANDER) ||              (unit->type == PERSON) ||             (unit->type == MUTANT)) {             /* --- Get sprite and screen position --- */             screenX = UnitScreenX (unit);             sprite = GetSprite (unit);             /* --- If we have a sprite --- */             if (sprite) {                 /* --- If in range using -x- --- */                 if ((screenX >= x1 && screenX <= x2) ||                      (screenX <= x1 && screenX >= x2)) {                     /* --- And in range using -y- --- */                     if ((unit->y - (sprite->height / 2) < y1) &&                         unit->y + (sprite->height / 2) > y1) {                             /*                            * Haven't found a unit or this one                          * is closer.                          */                         if ((closestUnit == NULL) ||                              (abs (x1 - screenX) < abs (x1 - closestX))) {                             /* --- This is closst so far --- */                             closestUnit = unit;                             closestX = screenX;                         }                     }                 }             }         }     }      return (closestUnit);}/* * UnitTop *  * Calculate the maximum height of the unit based on the  * radar screen and the sprite size. */int UnitTop (typUnit *unit){    typSprite *sprite;    /* --- Get the sprite --- */    sprite = GetSprite (unit);    /* --- Add 1/2 sprite size to radar size. --- */    return (RADAR_HEIGHT + (sprite[0].height / 2));}/* * UnitBottom *  * Calculate how low the unit can appear on the screen.  * It's partially based on the unit's size. */int UnitBottom (typUnit *unit){    typSprite *sprite;    sprite = GetSprite (unit);    return (GetGameHeight () - (sprite[0].height / 2));}/* * */void AdjustSpriteHeight (typUnit *unit){    typSprite *sprite;    int nTop;    int nBottom;    /* --- Get the sprite for the unit --- */    sprite = GetSprite (unit);    if (sprite == NULL) return;    /* --- Calculate the top and bottom range of unit --- */    nTop = UnitTop (unit);    nBottom = UnitBottom (unit);    /* --- Don't let them go too high or too low --- */    if (unit->y < nTop) {        unit->y = nTop;    } else if (unit->y > nBottom) {        unit->y = nBottom;    }}/* * DisplayOtherUnits * * Display all the units on the screen. First, we need  * to move each of the units to their new positions.  * Some of this is done in the AI module.  *  */void DisplayOtherUnits (GdkPixmap *pixmap, GtkWidget *drawing_area){    typUnit *unit;    typUnit *unitHit;    GList *node;    int xPos;    int xPosEnd;    typSprite *sprite;    /* --- Each unit in the list --- */    for (node = unitList; node; node = node->next) {         /* --- Get the unit --- */        unit = (typUnit *) node->data;        /*           * --- Run the AI module on it to move it ---          */        AIModule (unit);        /*          * If the unit was destroyed by the AI,          * don't draw the unit.         */        if (unit->bDestroy) {            continue;        }        /*          * If there's no sprite for the unit,          * we can't draw it now, can we?         */        sprite = GetSprite (unit);        if (sprite == NULL) continue;         /* --- Where on the screen is it going? --- */        xPos = UnitScreenX (unit);        /* --- Make sure unit doesn't go out of bounds --- */        AdjustSpriteHeight (unit);        /* --- Finally draw unit --- */        DisplaySprite (drawing_area, sprite,                    (int) (xPos - sprite[0].width / 2),                    (int) (unit->y - sprite[0].height / 2));    }    /*      * --- once everyone is painted, fire the lasers.     */

⌨️ 快捷键说明

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