defender.c

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

C
1,642
字号
    for (node = unitList; node; node = node->next) {        unit = (typUnit *) node->data;        /* --- If this is a laser --- */        if (unit->type == LASER) {             /* --- Get starting and ending positions --- */            xPos = ScreenX ((int) unit->x);            xPosEnd = xPos + LASER_LENGTH * unit->direction;            /* --- See if anything was hit --- */            unitHit = AnyoneBetween ((int) xPos, (int) unit->y,                                      (int) xPosEnd, (int) unit->y);            if (unitHit) {                /* --- Something was hit --- */                /* --- Laser shot only goes this far --- */                xPosEnd = UnitScreenX (unitHit);                /* --- Destroy the unit --- */                unitHit->bDestroy = TRUE;                unit->bDestroy = TRUE;                /* --- Special effects of destruction --- */                AddExplosion (unitHit);            }            /* --- Draw the laser --- */            gdk_draw_line (pixmap, penWhite,                           xPos, unit->y,                            xPosEnd,                           unit->y);                        /* --- Get real coordinates of laser --- */            unit->x = GameX (xPosEnd);            /* --- If laser has gone too far... --- */            if (DistanceBetween (unit, hero) > nScreenWidth / 2) {                /* --- destroy it --- */                unit->bDestroy = TRUE;            }        }    }}/* * Terrain functions * *//* * MountainCompare *  * Compare function for sorting the mountain peaks. */gint MountainCompare (typMountain *m1, typMountain *m2){    return (m1->start.x - m2->start.x);}/* * AddMountain * * Add a mountain peak to the list we use to keep track * of the mountain peaks. */GList *AddMountain (GList *mountainList, int peakx, int peaky){    typMountain *node;     node = (typMountain *) g_malloc (sizeof (typMountain));    node->start.x = peakx - peaky;    node->start.y = 0;    node->peak.x = peakx;    node->peak.y = peaky;    node->end.x = peakx + peaky;    node->end.y = 0;     return (g_list_insert_sorted (mountainList, node, MountainCompare));}/* * AddPoint * * Add a mountain peak at (x, y) */GList *AddPoint (GList *terrainList, int x, int y){    typPoint *p;    /* --- Allocate the memory --- */    p = (typPoint *) g_malloc (sizeof (typPoint));    /* --- Initialize the point --- */    p->x = x;    p->y = y;    /* --- Add the point to the list --- */    terrainList = g_list_append (terrainList, p);    return (terrainList);}/* * GenerateTerrain * * Create random mountain peaks that are used to generate the * background terrain. */void GenerateTerrain (){    int peakx;    int peaky;    GList *mountainList = NULL;    GList *node;    typMountain *prevMountain;    typMountain *mtn;    int i;    /* --- Compute the peaks --- */    for (i = 0; i < NUM_PEAKS; i++) {        peakx = rand () % X_RANGE;        peaky = rand () % MAX_PEAK;         mountainList = AddMountain (mountainList, peakx, peaky);    }    prevMountain = NULL;    terrainList = AddPoint (terrainList, 0, 0);    /* --- Compute the lines based on the peaks --- */    for (node = mountainList; node; node = node->next) {          mtn = (typMountain *) node->data;        /* --- First mountain --- */        if (prevMountain == NULL) {            terrainList = AddPoint (terrainList, mtn->start.x, mtn->start.y);            terrainList = AddPoint (terrainList, mtn->peak.x, mtn->peak.y);            prevMountain = mtn;        /* --- Don't cross paths --- */        } else if (prevMountain->end.x < mtn->start.x) {             terrainList = AddPoint (terrainList,                                     prevMountain->end.x,                                     prevMountain->end.y);            terrainList = AddPoint (terrainList, mtn->start.x, mtn->start.y);            terrainList = AddPoint (terrainList, mtn->peak.x, mtn->peak.y);            prevMountain = mtn;        /* --- previous mountain eats this one --- */        } else if (prevMountain->end.x > mtn->end.x) {                        /* --- Do nothing yet --- */        } else {            /* --- Mountains intersect --- */            terrainList = AddPoint (terrainList,                                     (prevMountain->end.x + mtn->start.x) / 2,                                    (prevMountain->end.x - mtn->start.x) / 2);            terrainList = AddPoint (terrainList, mtn->peak.x, mtn->peak.y);            prevMountain = mtn;        }    }    terrainList = AddPoint (terrainList,                                     prevMountain->end.x,                                     prevMountain->end.y);    terrainList = AddPoint (terrainList, X_RANGE, 0);}void StartGame (){    unitList = NULL;    /* --- Create our hero's ship --- */    hero = CreateHero ();    /* --- Generate the map --- */    GenerateTerrain ();    /* --- Place the people --- */    PlacePeople ();    /* --- Place aliens --- */    PlaceAliens ();   }/* * DrawMountainSlope * * Draw the mountains in the background of the game. */void DrawMountainSlope (GdkPixmap *pixmap,                         typPoint *lastPt,                         typPoint *pt,                         int nTop,                         int nBottom){    int x1;    int x2;    int nStart;    int nEnd;    int nHeight;    nHeight = nBottom - nTop;    nStart = hero->x - (nScreenWidth / 2);    nEnd = hero->x + (nScreenWidth / 2);    x1 = ScreenX (lastPt->x);    x2 = ScreenX (pt->x);    if ((x2 < 0) ||         (x1 > nScreenWidth)) {        /* ---  Do nothing --- */    } else {        /* --- Draw point --- */        gdk_draw_line (pixmap, penWhite,                   ScreenX (lastPt->x),                   (int) (nBottom - ((lastPt->y * nHeight) / MAX_PEAK)),                   ScreenX (pt->x),                   (int) (nBottom - ((pt->y * nHeight) / MAX_PEAK)));    }}void DrawMountains (GdkPixmap *pixmap,                     GtkWidget *drawing_area,                    int nTop, int nBottom){    typPoint *lastPt;    typPoint *pt;    GList *node;    lastPt = NULL;    /* --- where is the viewpoint from? --- */    for (node = terrainList; node; node = node->next) {        /* --- Get the point. --- */        pt = (typPoint *) node->data;        if (lastPt) {               DrawMountainSlope (pixmap, lastPt, pt, nTop, nBottom);        }        lastPt = pt;    }}void CalculateAdjustments (GtkWidget *drawing_area){    nShipAdjustment = (drawing_area->allocation.width / 2);    nRelativeAdjustment = hero->x - nShipAdjustment;}/* * DrawAllUnits * * Draw all the units */void DrawAllUnits (GdkPixmap *pixmap,                GtkWidget *drawing_area){    /*     * Move and display the hero     */    ApplyFriction ();    Move (hero);    /* --- Keep him in-bounds. --- */    AdjustSpriteHeight (hero);    DisplaySprite (drawing_area, sprite_ship,                    nShipAdjustment - (sprite_ship->width / 2),                    (int) hero->y - (sprite_ship->height / 2));    /*     * Move and display everyone else     */    DisplayOtherUnits (pixmap, drawing_area);}/* * DrawRadar * * Draw all the units on the radar screen.  Of course, the  * radar screen has to be drawn and then the units have to * have their points converted to "radar" coordinates and  * little dots are drawn on the screen in different colors * to refect the type of each of the units in the game. */void DrawRadar (GdkPixmap *pixmap, GtkWidget *drawing_area){    int   nLeft;    GList *node;    typUnit *unit;    int x, y;    int nMin;    int newx, newy;    /* --- Get radar coordinates --- */    nLeft = (drawing_area->allocation.width - RADAR_WIDTH) / 2;    nMin = hero->x - (X_RANGE / 2);    /* --- Clear out the rectangle --- */    gdk_draw_rectangle (pixmap, drawing_area->style->white_gc,                        FALSE,                        nLeft, 0, RADAR_WIDTH, RADAR_HEIGHT);    /*     * --- Display all the units     */    for (node = unitList; node; node = node->next) {            unit = (typUnit *) node->data;        x = unit->x;        y = unit->y;        if (x > hero->x + (X_RANGE / 2)) {                         x -= X_RANGE;        } else if (x < hero->x - (X_RANGE / 2)) {            x += X_RANGE;        }        /* --- Convert -x- to radar coordinates --- */        newx = (x - nMin) * RADAR_WIDTH / X_RANGE;        /* --- Convert -y- to radar coordinates --- */        newy = ((y - RADAR_HEIGHT) * (RADAR_HEIGHT - 6) / GAME_HEIGHT) + 2;        switch (unit->type) {            case PERSON:                gdk_draw_rectangle (pixmap, penPurple,                        TRUE, nLeft + newx-1, newy-1, 2, 2);                break;            case LANDER:                gdk_draw_rectangle (pixmap, penGreen,                        TRUE, nLeft + newx-1, newy-1, 2, 2);                break;            case MUTANT:                gdk_draw_rectangle (pixmap, penRed,                        TRUE, nLeft + newx-1, newy-1, 2, 2);                break;            case MISSILE:            case EXPLOSION:                gdk_draw_rectangle (pixmap, penWhite,                        TRUE, nLeft + newx, newy, 1, 1);                break;        }    }    /*     * --- Put the hero on the screen too.     */    /* --- Convert -x- to radar coordinates --- */    newx = (hero->x - nMin) * RADAR_WIDTH / X_RANGE;    /* --- Convert -y- to radar coordinates --- */    newy = ((hero->y - RADAR_HEIGHT) * (RADAR_HEIGHT - 6) / GAME_HEIGHT) + 2;    gdk_draw_rectangle (pixmap, penWhite, TRUE,                        nLeft + newx-1, newy-1, 2, 2);}/* * DrawScreen * * This does a lot of work.  It draws the background and  * all the units, as well as the radar.  This routine is  * essentially the main loop that gets called by the  * timer every update frequency. */void DrawScreen (GdkPixmap *pixmap, GtkWidget *drawing_area){    /* --- Move player based on keys pressed --- */    HandleKeysPressed ();    /* --- Get the screen width --- */    nScreenWidth = drawing_area->allocation.width;    /* --- Figure out the offset of the player --- */    CalculateAdjustments (drawing_area);    /* --- clear pixmap (background image) --- */    gdk_draw_rectangle (pixmap,              drawing_area->style->black_gc,              TRUE,              0, 0,              drawing_area->allocation.width,              drawing_area->allocation.height);    /* --- Draw top border and radar screen --- */    gdk_draw_line (pixmap, drawing_area->style->white_gc,                    0, RADAR_HEIGHT,                    drawing_area->allocation.width,                    RADAR_HEIGHT);    /* --- Oh those high peaks --- */    DrawMountains (pixmap, drawing_area,                    drawing_area->allocation.height - 65,                   drawing_area->allocation.height - BOTTOM_HEIGHT);     /* --- Draw the characters --- */    DrawAllUnits (pixmap, drawing_area);     /* --- Draw the units on the radar --- */    DrawRadar (pixmap, drawing_area);    /* --- Look for collisions --- */    CollisionCheck ();    /* --- Clean up those that got destroyed --- */    FreeDestroyedUnits ();}/* * CollisionCheck * * Hero suffer a collision?  Check for a collision * but don't really do anything.  This isn't really * a game, but rather a demo on how is could be done. */void CollisionCheck (){    GList *node;    typSprite *sprite;    int hero_x;    int unit_x;    typUnit *unit;    /* --- See if anything collides with the hero. --- */    for (node = unitList; node; node = node->next) {        /* --- Get the unit --- */        unit = (typUnit *) node->data;        /* --- Get the unit's sprite --- */        sprite = GetSprite (unit);        if (sprite == NULL) continue;               /* --- Eliminate non-collisions --- */        if (hero->y + (sprite_ship->height / 2) <             unit->y - (sprite->height / 2)) continue;        if (hero->y - (sprite_ship->height / 2) >             unit->y + (sprite->height / 2)) continue;        hero_x = UnitScreenX (hero);        unit_x = UnitScreenX (unit);                if (hero_x + (sprite_ship->width / 2) <             unit_x - (sprite->width / 2)) continue;        if (hero_x - (sprite_ship->width / 2) >             unit_x + (sprite->width / 2)) continue;        /* --- Hero collides here since everything failed. --- */    }} /* * GetGameHeight * * Get the height of the game. */int GetGameHeight (){    return (RADAR_HEIGHT + GAME_HEIGHT + BOTTOM_HEIGHT);}/* * FreeDestroyedUnits * * The units are just marked as being destroyed.  This * routine goes through the list and removes all the units * that are marked as destroyed and frees up any memory * they're using. */void FreeDestroyedUnits (){    GList *node;    GList *next;    typUnit *unit;    node = unitList;     while (node) {          next = node->next;        unit = (typUnit *) node->data;           /* --- If it's to be destroyed --- */        if (unit->bDestroy) {            /* --- Remove from the list of units --- */            unitList = g_list_remove (unitList, unit);            /* --- if unit was locked to another --- */            if (unit->lockunit) {                /* --- Remove lock to this unit --- */                unit->lockunit->lockunit = NULL;            }            g_free (unit);        }        node = next;    }}

⌨️ 快捷键说明

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