defender.c
来自「开发linux应用-用gtk+和gdk开发linux图形用户界面应用--的实例」· C语言 代码 · 共 1,642 行 · 第 1/3 页
C
1,642 行
/* * File: defender.c * Auth: Eric Harlow * * Sort of like the 1980's game defender, but not a * complete version. * */#include <gtk/gtk.h>#include "defender.h"#include "defproto.h"#include "mutant.h"#include "math.h"/* * How many people and aliens should the game start * out with? */#define START_ALIENS 10#define START_PEOPLE 10/* * These are for the acceleration, of the player/hero, the * effect of friction to slow him down, and the maximum * velocity that can be attained. */#define FRICTION .5#define MAX_SPEED 16#define ACCELERATION 3.5 /* * Of course, the laser has to be configurable too. The * laser beam has a speed (how fast it travels out) and * a length (primarily for show). */#define LASER_LENGTH 60#define LASER_SPEED 60/* * Range of the game. */#define X_RANGE 2000/* * How high the mountain peaks are. */#define MAX_PEAK 150/* * The number of mountain peaks generated. */#define NUM_PEAKS 10 /* * --- Trigger happiness * * The mutants are much more trigger happy than the landers * are. */#define LANDER_TRIGGER_PCT 3#define MUTANT_TRIGGER_PCT 6/* * During an explosion, we use eight sprites spiraling away * from where the item exploded. These are the eight * directions. */int x_exp[] = {1, 1, 0, -1, -1, -1, 0, 1};int y_exp[] = {0, 1, 1, 1, 0, -1, -1, -1}; /* * How big is the radar screen. */#define RADAR_WIDTH 200#define RADAR_HEIGHT 50/* * How big are other things in the screen */#define GAME_HEIGHT 220#define BOTTOM_HEIGHT 30#define PERSON_HEIGHT (RADAR_HEIGHT+GAME_HEIGHT+7)/* * Colors used for drawing */GdkGC *penGreen = NULL;GdkGC *penWhite = NULL;GdkGC *penPurple = NULL;GdkGC *penRed = NULL;/* * variables used in calculations */int nShipAdjustment;int nRelativeAdjustment;int nScreenWidth;/* * Define the sprites for the cast of characters. */typSprite sprite_man[1] = { { xpm_man, NULL, NULL, 0, 0 } };typSprite sprite_ship1[1] = { { xpm_ship1, NULL, NULL, 0, 0 } };typSprite sprite_ship2[1] = { { xpm_ship2, NULL, NULL, 0, 0 } };typSprite sprite_lander[1] = { { xpm_lander, NULL, NULL, 0, 0 } };typSprite sprite_mutant[1] = { { xpm_mutant, NULL, NULL, 0, 0 } };typSprite sprite_missile[1] = { { xpm_missile, NULL, NULL, 0, 0 } };/* * The ship could be pointing left or right (sprite_ship1, * sprite_ship2) - however, sprite_ship is what's used to * draw it. If the ship changes direction, then this * should also be adjusted. */typSprite *sprite_ship = sprite_ship1;/* * List of mountain peaks. */GList *terrainList = NULL;/* * All the units in the game */GList *unitList = NULL;/* * The hero. */typUnit *hero = NULL;/* * Prototypes. */GdkColor *NewColor (long red, long green, long blue);GdkGC *GetPen (GdkColor *c);void GetWidthHeight (gchar **xpm, int *width, int *height);void DisplaySprite (GtkWidget *drawing_area, typSprite *sprite, int x, int y);/* * UnitScreenX * * Convert the unit's X coordinates to screen coordinates * relative to the hero's coordinates. */int UnitScreenX (typUnit *unit){ int xPos; /* --- Adjust -x- if out of range --- */ if (unit->x < 0) { unit->x += X_RANGE; } else if (unit->x > X_RANGE) { unit->x -= X_RANGE; } /* --- Make it relative --- */ xPos = (int) (unit->x - nRelativeAdjustment); /* --- Readjust -x- if out of range --- */ if (xPos < 0) xPos += X_RANGE; if (xPos > X_RANGE) xPos -= X_RANGE; return (xPos);}/* * ScreenX * * Take the game -x- value and convert it to the screen * -x- value. */int ScreenX (int x){ int xPos; /* --- Adjust if out of range --- */ if (x < 0) { x += X_RANGE; } else if (x > X_RANGE) { x -= X_RANGE; } /* --- Make it absolute --- */ xPos = (int) (x - nRelativeAdjustment); /* --- Readajust if out of range --- */ if (xPos < (-(X_RANGE - nScreenWidth) / 2)) { xPos += X_RANGE; } else if (xPos > ((X_RANGE - nScreenWidth) / 2)) { xPos -= X_RANGE; } return (xPos);}/* * GameX * * Take a screen -x- value and convert it to the * game coordinate -x- value. */int GameX (int x){ int xPos; /* --- Relative to the hero --- */ xPos = (int) (x + nRelativeAdjustment); /* --- Make sure it's not out of range --- */ if (xPos < 0) xPos += X_RANGE; if (xPos > X_RANGE) xPos -= X_RANGE; return (xPos);}/* * Move * * Move a unit in the X direction by vx (velocity in x) and * in the Y direction by vy. */void Move (typUnit *unit){ /* --- Move the unit --- */ unit->y += unit->vy; unit->x += unit->vx; /* --- But keep it within the world --- */ if (unit->x < 0) unit->x += X_RANGE; if (unit->x > X_RANGE) unit->x -= X_RANGE;}/* * LoadPixmaps * * Load the image into the sprite. */void LoadPixmaps (GtkWidget *widget, typSprite *sprites){ /* --- Create a pixmap from the xpm data --- */ sprites->pixmap = gdk_pixmap_create_from_xpm_d ( widget->window, &sprites->mask, NULL, sprites->xpm_data); /* --- Get the width and height --- */ GetWidthHeight (sprites->xpm_data, &sprites->width, &sprites->height);}/* * LoadImages * * Load up the images so that we can display them in the * game and configure the colors. */void LoadImages (GtkWidget *window){ /* --- Load up the images --- */ LoadPixmaps (window, sprite_man); LoadPixmaps (window, sprite_ship1); LoadPixmaps (window, sprite_ship2); LoadPixmaps (window, sprite_lander); LoadPixmaps (window, sprite_mutant); LoadPixmaps (window, sprite_missile); /* --- Get the colors defined --- */ penRed = GetPen (NewColor (0xffff, 0x8888, 0x8888)); penGreen = GetPen (NewColor (0, 0xffff, 0)); penPurple = GetPen (NewColor (0xffff, 0, 0xffff)); penWhite = GetPen (NewColor (0xffff, 0xffff, 0xffff));}/* * CreateHero * * Create the typUnit for the player and initialize * it with the player settings. */typUnit *CreateHero (){ /* --- Allocate the memory --- */ hero = g_malloc (sizeof (typUnit)); /* --- Initialize player information --- */ hero->bDestroy = FALSE; hero->direction = 1; hero->type = HERO; hero->x = 0; hero->y = 150; hero->vx = 0; hero->vy = 0; hero->lockunit = NULL; /* --- Return object. --- */ return (hero);}/* * HeroFile * * Our hero is opening fire! Create a laser shot * and add it to the global list of units. */void HeroFire (){ typUnit *laser; /* --- Create the laser --- */ laser = (typUnit *) g_malloc (sizeof (typUnit)); /* --- The direction is the same as the spaceship --- */ laser->direction = hero->direction; laser->type = LASER; /* * Move the starting point of the laser in front of the * spaceship. */ if (laser->direction > 0) { laser->x = hero->x + (sprite_ship->width / 2); } else { laser->x = hero->x - (sprite_ship->width / 2); } laser->y = hero->y + 4; laser->vx = LASER_SPEED * hero->direction; laser->vy = 0; laser->lockunit = NULL; laser->bDestroy = 0; /* --- Laser bolt lasts through two movements. --- */ laser->life = 2; /* --- Add the laser to the list of units --- */ unitList = g_list_append (unitList, laser);}/* * HeroMove * * Move the player in the direction specified. */void HeroMove (int direction){ switch (direction) { case MOVE_UP: hero->y -= 3; break; case MOVE_DOWN: hero->y += 3; break; case MOVE_LEFT: /* * Make sure the ship is pointing in the * correct direction. */ sprite_ship = sprite_ship2; hero->direction = -1; /* --- Speed up the ship --- */ hero->vx -= ACCELERATION; break; case MOVE_RIGHT: /* * Make sure the ship is pointing in the * correct direction. */ sprite_ship = sprite_ship1; hero->direction = 1; /* --- Speed up the ship --- */ hero->vx += ACCELERATION; break; }}/* * ApplyFriction * * Slow down gradually and make sure the player cannot go * into warp speed by holding down the acceleration. */void ApplyFriction (){ /* --- Slow ship down --- */ if (hero->vx > FRICTION) { hero->vx -= FRICTION; } else if (hero->vx < -FRICTION) { hero->vx += FRICTION; } else { /* --- Speed less than friction, we stop --- */ hero->vx = 0; } /* --- Don't let the maximum speed be exceeded --- */ if (hero->vx > MAX_SPEED) hero->vx = MAX_SPEED; if (hero->vx < -MAX_SPEED) hero->vx = -MAX_SPEED;}/* * CreatePerson * * Create the little people on the planet. */typUnit *CreatePerson (){ typUnit *person; /* --- Allocate the memory --- */ person = g_malloc (sizeof (typUnit)); /* --- Initialize the person --- */ person->bDestroy = FALSE; person->direction = 0; person->type = PERSON; person->x = rand () % X_RANGE; person->y = PERSON_HEIGHT; person->vx = 0; person->vy = 0; person->lockunit = NULL; return (person);}/* * PlacePeople * * Create people randomly and place them on the screen */void PlacePeople (){ int i; typUnit *person; /* --- Create all the little people --- */ for (i = 0; i < START_PEOPLE; i++) { /* --- Create a person --- */ person = CreatePerson (); /* --- Add it to the list of units --- */ unitList = g_list_append (unitList, person); }}/* * CreateAlien * * Create an alien lander */typUnit *CreateAlien (){ typUnit *alien; /* --- Get the memory --- */ alien = g_malloc (sizeof (typUnit)); /* --- Initialize the structure --- */ alien->bDestroy = FALSE; alien->pctFiring = LANDER_TRIGGER_PCT; alien->type = LANDER; alien->x = rand () % X_RANGE; alien->y = rand () % 50 + RADAR_HEIGHT ; alien->vx = 0; alien->vy = 0; alien->lockunit = NULL; return (alien);}/* * CreateMissile * * Missiles are what the aliens fire. They are given * a fixed direction and last a limited amount of time * before they disappear. */typUnit *CreateMissile (typUnit *alien, typUnit *hero){ float flength; typUnit *missile; /* --- Allocate the memory --- */ missile = (typUnit *) g_malloc (sizeof (typUnit)); /* --- Inialize the structure --- */ missile->bDestroy = FALSE; missile->pctFiring = 0; missile->type = MISSILE; missile->x = alien->x; missile->y = alien->y; /* --- Calculate missile velocity --- */ missile->vx = (float) DistanceBetween (missile, hero) * Direction (missile, hero); missile->vy = (float) (hero->y - alien->y); /* * Adjust missile velocity */ flength = sqrt (missile->vx * missile->vx + missile->vy * missile->vy); if (flength < .1) flength = .1; flength /= 3; missile->vx /= flength; missile->vy /= flength; missile->lockunit = NULL; /*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?