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 + -
显示快捷键?