/* map_sendTileSignal Sends a signal to an active tile. */ void map_sendTileSignal(int z, int x, int y, Signal *s) { extern Map map; if (TILE_AT(z, x, y)->active) sig_push(&TILE_AT(z, x, y)->signals, s); }
/* map_getTileGfx Returns a pointer to an SDL_Surface of the currently displayed graphic of a tile, or NULL if there is no tile. */ SDL_Surface * map_getTileGfx(int z, int x, int y) { extern Tileset tileset; extern Map map; return (TILE_AT(z, x, y) == NULL) ? NULL : tileset.data[TILE_AT(z, x, y)->anim.anim_id].frames[TILE_AT(z, x, y)->anim.curr_frame].image; }
/* map_getTileGfxOffset Gets the offset of the tile's current graphic. */ Point map_getTileGfxOffset(int z, int x, int y) { extern Map map; extern Tileset tileset; Point p; p.x = TILE_AT(z, x, y)->anim.offset.x + tileset.data[TILE_AT(z, x, y)->anim.anim_id].frames[TILE_AT(z, x, y)->anim.curr_frame].offset.x; p.y = TILE_AT(z, x, y)->anim.offset.y + tileset.data[TILE_AT(z, x, y)->anim.anim_id].frames[TILE_AT(z, x, y)->anim.curr_frame].offset.y; return p; }
/* map_freeMap Frees the loaded map. */ void map_freeMap(void) { extern Map map; int i; /* Free it layer by layer */ for (i = 0; i < map.n_layers; i++) { int x, y; /* Free all of the tiles in the layer */ for (x = 0; x < map.layers[i].w; x++) { for (y = 0; y < map.layers[i].h; y++) { /* Is there a tile here? */ if (TILE_AT(i, x, y) != NULL) { freeTile(i, x, y); } } } /* Free the array */ dyn_arrayFree((void **) map.layers[i].data, map.layers[i].w); } /* Free the array of layers */ dyn_1dArrayFree(map.layers); }
/* event: pick one tile and randomize all its stats */ static void randomizeOneTile (struct state *st) { int c = RAND_FLOAT_01 * st->columns; int r = RAND_FLOAT_01 * st->rows; Tile *t = TILE_AT (c, r); t->angle = RAND_ANGLE; t->zoom = RAND_ZOOM; t->vAngle = RAND_VANGLE; t->vZoom = RAND_VZOOM; }
/* map_runTiles Has tiles which are within our specified range run and animate */ void map_runTiles(void) { extern Map map; extern Tileset tileset; int l, x, y; for (l = 0; l < map.n_layers; l++) { /* Get the range of real coordinates on this layer the camera can see */ Rect cam_range = cam_getViewRange(l); /* Loop through all of the onscreen tiles, plus a certain range beyond that */ for (x = (map_realToMapX(cam_range.p1.x) - TILE_X_RANGE) >= 0 ? (map_realToMapX(cam_range.p1.x) - TILE_X_RANGE) : 0; (x <= map_realToMapX(cam_range.p2.x) + TILE_X_RANGE) && (x < map_getLayerWidth(l)); x++) { for (y = (map_realToMapY(cam_range.p1.y) - TILE_Y_RANGE) >= 0 ? (map_realToMapY(cam_range.p1.y) - TILE_Y_RANGE) : 0; (y <= map_realToMapY(cam_range.p2.y) + TILE_Y_RANGE) && (y < map_getLayerHeight(l)); y++) { /* If there is a tile here */ if (TILE_AT(l, x, y) != NULL) { /* Have the tile do its go action if it's active */ if (TILE_AT(l, x, y)->active) TILE_AT(l, x, y)->go(l, x, y); /* Animate */ anim_animate(&TILE_AT(l, x, y)->anim, &tileset.data[TILE_AT(l, x, y)->anim.anim_id]); } } } } }
/* set up the model */ static void setupModel (struct state *st) { int c; int r; int leftX; /* x of the center of the top-left tile */ int topY; /* y of the center of the top-left tile */ if (st->tileSize > (st->windowWidth / 2)) { st->tileSize = st->windowWidth / 2; } if (st->tileSize > (st->windowHeight / 2)) { st->tileSize = st->windowHeight / 2; } st->columns = st->tileSize ? st->windowWidth / st->tileSize : 0; st->rows = st->tileSize ? st->windowHeight / st->tileSize : 0; if ((st->maxColumns != 0) && (st->columns > st->maxColumns)) { st->columns = st->maxColumns; } if ((st->maxRows != 0) && (st->rows > st->maxRows)) { st->rows = st->maxRows; } st->tileCount = st->rows * st->columns; leftX = (st->windowWidth - (st->columns * st->tileSize) + st->tileSize) / 2; topY = (st->windowHeight - (st->rows * st->tileSize) + st->tileSize) / 2; if (st->tileCount < 1) st->tileCount = 1; st->tiles = calloc (st->tileCount, sizeof (Tile)); st->sortedTiles = calloc (st->tileCount, sizeof (Tile *)); for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { Tile *t = TILE_AT (c, r); t->x = leftX + c * st->tileSize; t->y = topY + r * st->tileSize; st->sortedTiles[c + r * st->columns] = t; } } randomizeEverything (st); }
/* event: randomize all the zoomular velocities */ static void randomizeAllZoomularVelocities (struct state *st) { int c; int r; for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { TILE_AT (c, r)->vZoom = RAND_VZOOM; } } }
/* event: randomize all the zoomular orientations */ static void randomizeAllZoomularOrientations (struct state *st) { int c; int r; for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { TILE_AT (c, r)->zoom = RAND_ZOOM; } } }
/* event: randomize all the angular orientations */ static void randomizeAllAngularOrientations (struct state *st) { int c; int r; for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { TILE_AT (c, r)->angle = RAND_ANGLE; } } }
/* event: randomize all the angular velocities */ static void randomizeAllAngularVelocities (struct state *st) { int c; int r; for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { TILE_AT (c, r)->vAngle = RAND_VANGLE; } } }
/* event: pick one column and randomize everything about each of its tiles */ static void randomizeOneColumn (struct state *st) { int c = RAND_FLOAT_01 * st->columns; int r; for (r = 0; r < st->rows; r++) { Tile *t = TILE_AT (c, r); t->angle = RAND_ANGLE; t->zoom = RAND_ZOOM; t->vAngle = RAND_VANGLE; t->vZoom = RAND_VZOOM; } }
/* event: pick one row and randomize everything about each of its tiles */ static void randomizeOneRow (struct state *st) { int c; int r = RAND_FLOAT_01 * st->rows; for (c = 0; c < st->columns; c++) { Tile *t = TILE_AT (c, r); t->angle = RAND_ANGLE; t->zoom = RAND_ZOOM; t->vAngle = RAND_VANGLE; t->vZoom = RAND_VZOOM; } }
/* freeTile Frees a tile. */ void freeTile(int l, int x, int y) { Tile *t = TILE_AT(l, x, y); /* Free its boundaries */ Bound *b = t->bounds; while (b != NULL) { Bound *next_bound = b->next; free(b); b = next_bound; } /* Flush the signal queue */ sig_flush(&t->signals); /* If the object is active, it may have allocated its own type-specific attributes which it will free itself: */ if (t->active) t->free_atts(l, x, y); free(t); TILE_AT(l, x, y) = NULL; }
/* map_getTileBounds Returns a pointer to the boundary list of a tile, or NULL of there is no tile. */ Bound * map_getTileBounds(int z, int x, int y) { extern Map map; return (TILE_AT(z, x, y) == NULL) ? NULL : TILE_AT(z, x, y)->bounds; }
/* map_tileIsSolid Returns true if a tile is solid */ int map_tileIsSolid(int z, int x, int y) { extern Map map; return (TILE_AT(z, x, y)->solid); }
/* update the model for one iteration */ static void updateModel (struct state *st) { int r; int c; /* for each tile, decrease its velocities according to the friction, * and increase them based on its current orientation and the orientations * of its orthogonal neighbors */ for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { Tile *t = TILE_AT (c, r); FLOAT a = t->angle; FLOAT z = t->zoom; FLOAT va = t->vAngle; FLOAT vz = t->vZoom; va -= t->angle * st->springiness; vz -= t->zoom * st->springiness; if (c > 0) { Tile *t2 = TILE_AT (c - 1, r); va += (t2->angle - a) * st->transference; vz += (t2->zoom - z) * st->transference; } if (c < (st->columns - 1)) { Tile *t2 = TILE_AT (c + 1, r); va += (t2->angle - a) * st->transference; vz += (t2->zoom - z) * st->transference; } if (r > 0) { Tile *t2 = TILE_AT (c, r - 1); va += (t2->angle - a) * st->transference; vz += (t2->zoom - z) * st->transference; } if (r < (st->rows - 1)) { Tile *t2 = TILE_AT (c, r + 1); va += (t2->angle - a) * st->transference; vz += (t2->zoom - z) * st->transference; } va *= (1.0 - st->friction); vz *= (1.0 - st->friction); if (va > MAX_VANGLE) va = MAX_VANGLE; else if (va < -MAX_VANGLE) va = -MAX_VANGLE; t->vAngle = va; if (vz > MAX_VZOOM) vz = MAX_VZOOM; else if (vz < -MAX_VZOOM) vz = -MAX_VZOOM; t->vZoom = vz; } } /* for each tile, update its orientation based on its velocities */ for (r = 0; r < st->rows; r++) { for (c = 0; c < st->columns; c++) { Tile *t = TILE_AT (c, r); FLOAT a = t->angle + t->vAngle; FLOAT z = t->zoom + t->vZoom; if (a > M_PI) a = M_PI; else if (a < -M_PI) a = -M_PI; t->angle = a; if (z > 1.0) z = 1.0; else if (z < -1.0) z = -1.0; t->zoom = z; } } }
/* map_getTileType Returns a tile's type. */ int map_getTileType(int z, int x, int y) { extern Map map; return (TILE_AT(z, x, y)->type); }
/* map_loadMap Loads the map for an area. */ void map_loadMap(char *areafile) { extern Map map; extern Tileset tileset; extern struct tile_att_define *tile_defs[]; int i; /* Open the area file */ file_openFile(areafile, 'r'); /* Get the background color */ map.bg_color = file_getAreaBackgroundColor(areafile); /* Get the number of layers */ map.n_layers = file_getAreaNLayers(areafile); /* Allocate the array of layers */ map.layers = (Layer *) dyn_1dArrayAlloc(map.n_layers, sizeof(Layer)); /* Create the layers */ for (i = 0; i < map.n_layers; i++) { int w, h; /* Find the next layer in the area file */ file_nextLayer(areafile); /* Get the layer's dimensions. */ file_getLayerDims(areafile, &w, &h); map.layers[i].w = w; map.layers[i].h = h; /* Allocate the layer data array */ map.layers[i].data = (Tile ***) dyn_arrayAlloc(map.layers[i].w, map.layers[i].h, sizeof(Tile *)); /* Get all the tiles in the layer */ while (file_nextTile(areafile)) { Bound *b; int x, y, type; char *anim_name; /* Get the tile's attributes */ file_getTileAtts(areafile, &x, &y, &type, &anim_name); /* Allocate the tile in the proper place in the array */ MALLOC(TILE_AT(i, x, y), sizeof(Tile)); /* Initialize the signal queue */ sig_initQ(&TILE_AT(i, x, y)->signals); /* Set the tile's type: */ TILE_AT(i, x, y)->type = type; /* Get tile-specific attributes from the definitions included in tiledata.c */ TILE_AT(i, x, y)->elasticity = tile_defs[type]->elasticity; TILE_AT(i, x, y)->solid = tile_defs[type]->solid; TILE_AT(i, x, y)->friction = tile_defs[type]->friction; if (TILE_AT(i, x, y)->active = tile_defs[type]->active) { /* Only assign the tile functions if it is active */ TILE_AT(i, x, y)->atts = tile_defs[type]->init_atts(); TILE_AT(i, x, y)->go = tile_defs[type]->go; TILE_AT(i, x, y)->free_atts = tile_defs[type]->free_atts; } /* Set the tile's animation: */ TILE_AT(i, x, y)->anim.anim_id = animNameToID(anim_name); free(anim_name); TILE_AT(i, x, y)->anim.curr_frame = 0; TILE_AT(i, x, y)->anim.play_dir = 0; TILE_AT(i, x, y)->anim.offset.x = 0; TILE_AT(i, x, y)->anim.offset.y = 0; /* Get the animation speed from the animation's default: */ time_init(&TILE_AT(i, x, y)->anim.timer, tileset.data[TILE_AT(i, x, y)->anim.anim_id].def_delay); /* Get all of the boundaries for this tile */ TILE_AT(i, x, y)->bounds = NULL; while (file_nextTileBound(areafile)) { /* If this is the head of the list: */ if (TILE_AT(i, x, y)->bounds == NULL) { MALLOC(TILE_AT(i, x, y)->bounds, sizeof(Bound)); b = TILE_AT(i, x, y)->bounds; } else { MALLOC(b->next, sizeof(Bound)); b = b->next; } /* Read the boundary in */ file_getTileBound(areafile, b); b->next = NULL; } } /* Found all the tiles in the layer */ } /* Found all the layers */ file_closeFile(areafile); }