/* * Draw or erase the coordinate string of the current pointer position. * Both of these are the same operation because of the XOR operation. */ static void showcoords(GR_BOOL show) { long curlong; long curlat; FLOAT ptrlat; FLOAT ptrlong; if (((show == 0) == (coordvisible == 0)) || !coordenabled) return; if (show) { ptrlat = FIDIV(FIMUL(viewlat, ptry), mapheight - 1); ptrlong = FIDIV(FIMUL(viewlong, ptrx), mapwidth - 1); curlat = FTOI(Latitude + latradius - ptrlat); curlong = FTOI(Longitude - longradius + ptrlong); if (curlong > 180*60) curlong -= 360*60; if (curlong < -180*60) curlong += 360*60; mintostr(coordstring, curlong); strcat(coordstring, " "); mintostr(coordstring + strlen(coordstring), curlat); } GrText(mapwid, xorgc, coordx, coordy, coordstring, -1, GR_TFBOTTOM); coordvisible = show; }
/** * Draw current frame scaled. * * @param x X-coordinate at which to draw * @param y Y-coordinate at which to draw * @param scale Scaling factor */ void Anim::drawScaled (fixed x, fixed y, fixed scale) { // Used to draw bonus level player, so no offset sprites[frame]->drawScaled(FTOI(x), FTOI(y), scale); return; }
/** * Draw the layer. * * @param tileSet The tile set to use for non-flipped tiles * @param flippedTileSet The tile set to use for flipped tiles */ void JJ2Layer::draw (SDL_Surface* tileSet, SDL_Surface* flippedTileSet) { SDL_Rect src, dst; int vX, vY; int x, y; // Set tile drawing dimensions src.w = TTOI(1); src.h = TTOI(1); src.x = 0; // Calculate the layer view vX = FTOI(FTOI(viewX) * xSpeed); vY = FTOI(FTOI(viewY) * ySpeed); if (limit) { if (!tileX) { if (vX + canvasW > TTOI(width)) vX = TTOI(width) - canvasW; } if (!tileY) { vY -= canvasH - SH; if (vY + canvasH > TTOI(height)) vY = TTOI(height) - canvasH; } } for (y = 0; y <= ITOT(canvasH - 1) + 1; y++) { for (x = 0; x <= ITOT(canvasW - 1) + 1; x++) { dst.x = TTOI(x) - (vX & 31); dst.y = TTOI(y) - (vY & 31); src.y = TTOI(getTile(x + ITOT(vX), y + ITOT(vY))); if (src.y) SDL_BlitSurface(getFlipped(x + ITOT(vX), y + ITOT(vY))? flippedTileSet: tileSet, &src, canvas, &dst); } } return; }
/** * Draw placeholder event. * * @param ticks Time * @param change Time since last iteration */ void OtherJJ2Event::draw (unsigned int ticks, int change) { Anim* an; int drawX, drawY; if (prepareDraw(ticks, change)) return; drawX = getDrawX(change); drawY = getDrawY(change); switch (type) { default: if ((type <= 221) && pickupAnims[type]) { an = jj2Level->getAnim(animSet, pickupAnims[type], flipped); an->setFrame((int)ticks / 60, true); an->draw(drawX + F16, drawY + F16 + F32); } else if (!endTime) { drawRect(FTOI(drawX) + 8, FTOI(drawY) + 8, 16, 16, type); } panelBigFont->showNumber(type, FTOI(drawX) + 24, FTOI(drawY) + 12); return; } an->draw(drawX + F16, drawY + F16); return; }
/** * Draw current frame. * * @param x X-coordinate at which to draw * @param y Y-coordinate at which to draw */ void Anim::draw (fixed x, fixed y, int accessories) { Anim* anim; sprites[frame]->draw( FTOI(x) + (xOffsets[frame] << 2), FTOI(y) + yOffsets[frame] - yOffset); if (accessories && accessory) { anim = level->getAnim(accessory); anim->setFrame(frame, true); anim->draw( x + ITOF(accessoryX << 2), y + ITOF(accessoryY - yOffset) - anim->getOffset(), accessories - 1); } return; }
/** * Functionality required by all event types on each iteration * * @param ticks Time * @param msps Ticks per step * * @return Animation */ EventType* Event::prepareStep (unsigned int ticks, int msps) { // Process the next event if (next) next = next->step(ticks, msps); // Get the event properties set = level->getEvent(gridX, gridY); // If the event has been removed from the grid, destroy it if (!set) return NULL; // If the event and its origin are off-screen, the event is not in the // process of self-destruction, remove it if (((animType & ~1) != E_LFINISHANIM) && ((x < viewX - F192) || (x > viewX + ITOF(viewW) + F192) || (y < viewY - F160) || (y > viewY + ITOF(viewH) + F160)) && ((gridX < FTOT(viewX) - 1) || (gridX > ITOT(FTOI(viewX) + viewW) + 1) || (gridY < FTOT(viewY) - 1) || (gridY > ITOT(FTOI(viewY) + viewH) + 1))) return NULL; return set; }
/** * Draw the JJ2 level. */ void JJ2Level::draw () { int width, height; int x, y; unsigned int change; width = layer->getWidth(); height = layer->getHeight(); // Calculate change since last step change = getTimeChange(); // Calculate viewport if (game && (stage == LS_END)) game->view(paused? 0: ((ticks - prevTicks) * 160)); else localPlayer->getJJ2LevelPlayer()->view(ticks, paused? 0: (ticks - prevTicks), change); // Ensure the new viewport is within the level if (FTOI(viewX) + canvasW >= TTOI(width)) viewX = ITOF(TTOI(width) - canvasW); if (viewX < 0) viewX = 0; if (FTOI(viewY) + canvasH >= TTOI(height)) viewY = ITOF(TTOI(height) - canvasH); if (viewY < 0) viewY = 0; // Show background layers for (x = 7; x >= 3; x--) layers[x]->draw(tileSet, flippedTileSet); // Show the events if (events) events->draw(ticks, change); // Show the players for (x = 0; x < nPlayers; x++) players[x].getJJ2LevelPlayer()->draw(ticks, change); // Show foreground layers for (x = 2; x >= 0; x--) layers[x]->draw(tileSet, flippedTileSet); // Temporary lines showing the water level drawRect(0, FTOI(waterLevel - viewY), canvasW, 2, 72); drawRect(0, FTOI(waterLevel - viewY) + 3, canvasW, 1, 72); drawRect(0, FTOI(waterLevel - viewY) + 6, canvasW, 1, 72); drawRect(0, FTOI(waterLevel - viewY) + 10, canvasW, 1, 72); // Black-out areas outside the level (for high resolutions) if (TTOI(layers[3]->getWidth()) - FTOI(viewX) < canvasW) drawRect(TTOI(layers[3]->getWidth()) - FTOI(viewX), 0, canvasW, canvasH, JJ2_BLACK); if (TTOI(layers[3]->getHeight()) - FTOI(viewY) < canvasH) drawRect(0, TTOI(layers[3]->getHeight()) - FTOI(viewY), TTOI(layers[3]->getWidth()) - FTOI(viewX), canvasH, JJ2_BLACK); // Show "panel" data // Show score if (multiplayer) game->getMode()->drawScore(font); else panelSmallFont->showNumber(localPlayer->getScore(), 64, 8); // Draw hearts x = localPlayer->getJJ2LevelPlayer()->getEnergy(); for (y = 1; y <= x; y++) { drawRect(canvasW - (y * 12), 4, 8, 8, 48); } // Show lives panelSmallFont->showNumber(localPlayer->getLives(), 16, canvasH - 16); // Show ammo if (localPlayer->getAmmoType() == -1) { panelSmallFont->showString(":", canvasW - 24, canvasH - 16); panelSmallFont->showString(";", canvasW - 16, canvasH - 16); } else panelSmallFont->showNumber(localPlayer->getAmmo(), canvasW - 8, canvasH - 16); return; }
/* * Read the database file and draw the world. */ static void load(char *fn) { register DBPOINT *pp; DBPOINT *pend; FLOAT x, y, LonPrv, LatPrv; long oldlong = 0L; GR_COORD xnew, ynew; GR_COORD xold = 0, yold = 0; GR_BOOL is_out; GR_BOOL was_out; GR_BOOL newseg = GR_FALSE; GR_COLOR oldcolor; GR_COLOR newcolor; int n; int fh; DBPOINT p[PCount]; LonPrv = ITOF(0); LatPrv = ITOF(0); oldcolor = -1; is_out = GR_FALSE; was_out = GR_FALSE; fh = open(fn, O_BINARY | O_RDONLY); if (fh < 0) { GrClose(); fprintf(stderr, "Cannot open %s\n", fn); exit(1); } while ((n = read(fh, p, PCount * POINTSize)) > 0) { for (pp = p,pend = p + n/POINTSize; pp < pend; pp++) { DBPOINT_CONVERT(pp); /* do displacement */ x = ITOF(pp->Lon) - Longitude; y = ITOF(pp->Lat) - Latitude; /* wrap around for East-West */ if (x < -HSPAN) x += WSPAN; if (x > HSPAN) x -= WSPAN; if (pp->Code > 5) { newcolor = code_colors[pp->Code / 1000]; if (newcolor != oldcolor) { oldcolor = newcolor; GrSetGCForeground(mapgc, oldcolor); } newseg = GR_TRUE; } if (oldcolor == BLACK) goto go_on; /* ignore points outside magnified area */ if ((x < -longradius || x > longradius || y < -latradius || y > latradius)) { is_out = 1; if (was_out) { /* out to out */ LonPrv = x; LatPrv = y; goto go_on; } /* in to out */ xold = mapxorig + FTOI(FFMUL(LonPrv, X_Scale)) / 60; yold = mapyorig - FTOI(FFMUL(LatPrv, Y_Scale)) / 60; } else { /* out to in */ is_out = 0; if (was_out) { xold = mapxorig + FTOI(FFMUL(LonPrv, X_Scale)) / 60; yold = mapyorig - FTOI(FFMUL(LatPrv, Y_Scale)) / 60; } /* in to in */ } LonPrv = x; LatPrv = y; /* scale points w/in area to interlace screen */ xnew = mapxorig + FTOI(FFMUL(x, X_Scale)) / 60; ynew = mapyorig - FTOI(FFMUL(y, Y_Scale)) / 60; /* if new segment, move to place */ if (newseg || ABS(oldlong - pp->Lon) > 180*60) { xold = xnew; yold = ynew; } oldlong = pp->Lon; GrLine(mapwid, mapgc, xold, yold, xnew, ynew); xold = xnew; yold = ynew; go_on: was_out = is_out; newseg = GR_FALSE; } } close(fh); }
/** * Episode 1 guardian iteration. * * @param ticks Time * * @return Remaining event */ JJ1Event* MedGuardian::step(unsigned int ticks) { fixed sin = fSin(ticks / 2); fixed cos = fCos(ticks / 2); set = prepareStep(ticks); if (!set) return remove(false); if (level->getEventHits(gridX, gridY) >= set->strength / 2) stage = 1; if (level->getEventHits(gridX, gridY) >= set->strength) stage = 2; // Stage 0: Move in an eight shape and fire the occasional shot if (stage == 0) { if (direction == 1) { // Lower right part of the eight setAnimType(E_LEFTANIM); dx = TTOF(gridX) + (sin * 96) - x + ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos > 0) direction = 2; } if (direction == 2) { // Upper left part of the eight setAnimType(E_LEFTANIM); dx = TTOF(gridX) - (sin * 96) - x - ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos < 0) direction = 3; } if (direction == 3) { // Lower left part of the eight setAnimType(E_RIGHTANIM); dx = TTOF(gridX) - (sin * 96) - x - ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos > 0) direction = 4; } if (direction == 4) { // Upper right part of the eight setAnimType(E_RIGHTANIM); dx = TTOF(gridX) + (sin * 96) - x + ITOF(96); dy = TTOF(gridY) - (cos * 64) - y; if (cos < 0) direction = 1; } // Decide if there should be a shot if ((ticks % (set->bulletPeriod * 25) > (unsigned int)(set->bulletPeriod * 25) - 300)) { level->setEventTime(gridX, gridY, ticks + 300); shoot = true; } // Shoot if there is a shot if (level->getEventTime(gridX, gridY) && (ticks > level->getEventTime(gridX, gridY)) && shoot) { if (set->bullet < 32) level->createBullet(NULL, gridX, gridY, x + anim->getAccessoryShootX(), y + anim->getAccessoryShootY(), set->bullet, (animType != E_LEFTANIM), ticks); shoot = false; } } // Stage 1: Hop back and forth destroying the bottom row of tiles if (stage == 1) { fixed startPos = TTOF(gridY) + ITOF(40); if (direction < 5) { // Move up or down towards the starting position for hopping direction = (y > startPos) ? 5 : 6; } // Move up to the correct height if (direction == 5) { if (y > startPos) { dx = 0; dy = ITOF(-2); } else direction = 7; } // Move down to the correct height if (direction == 6) { if (y < startPos) { dx = 0; dy = ITOF(2); } else direction = 7; } // Cosinus should be near zero before we start hopping. if (direction == 7) { dx = 0; dy = 0; if (cos > -100 && cos < 100) direction = 8; } // Start hopping if (direction == 8) { if (level->checkMaskUp(x, y) || level->checkMaskUp(x + width, y)) setAnimType((animType == E_LEFTANIM) ? E_RIGHTANIM : E_LEFTANIM); dy = startPos - abs(cos * 96) - y; dx = abs(cos * 6); if (animType == E_LEFTANIM) dx *= -1; if (cos < 0 && level->checkMaskDown(x + ITOF(anim->getWidth() / 2), y + TTOF(1))) direction = 9; } // Destroy the block underneath if (direction == 9) { // Shake a bit dx = (FTOI(x) % 2) ? ITOF(1) : ITOF(-1); dy = 0; // Remove the tile if (cos > 0 && cos < 100) { level->setTile( FTOT(x + ITOF((anim->getWidth() / 2))), FTOT(y) + 1, set->magnitude); direction = 8; } } } // Stage 2: End of behavior if (stage == 2) { dx = 0; dy = ITOF(4); } x += dx; y += dy; dx = dx << 6; dy = dy << 6; return this; }