From c884eb7528ac847976d8ebd053e89c4be9a2d7c0 Mon Sep 17 00:00:00 2001 From: ghaushe Date: Sat, 8 Mar 2003 00:27:26 +0000 Subject: [PATCH] rotating planet should now be smoother than before. planet zoom while entering orbit decelerates (ala 3DO) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@867 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/planets/pl_stuff.c | 93 +++++++++++++++--------------- sc2/src/sc2code/planets/plangen.c | 73 ++++++++++++++++++++--- 2 files changed, 111 insertions(+), 55 deletions(-) diff --git a/sc2/src/sc2code/planets/pl_stuff.c b/sc2/src/sc2code/planets/pl_stuff.c index 3f16b15cc..b8ef5d7f5 100644 --- a/sc2/src/sc2code/planets/pl_stuff.c +++ b/sc2/src/sc2code/planets/pl_stuff.c @@ -20,6 +20,7 @@ #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawable.h" +#include // define USE_ADDITIVE_SCAN_BLIT to use additive blittting // instead of transparency for the planet scans. // It still doesn't look right though (it is too bright) @@ -45,76 +46,70 @@ void RepairBackRect (PRECT pRect); // This will take care of zooming into a planet on orbit, generating the planet frames // And applying the shield. -// The initial size of the planet when zooming. MUST BE ODD -#define PLANET_INIT_ZOOM_SIZE 9 // The speed to zoom in. #define PLANET_ZOOM_SPEED 2 -int -RotatePlanet (int x, int da, int dx, int dy, int zoom) +void +PlanetZoomOrbit (int x, COUNT zoom_amt, UBYTE zoom_from) { - STAMP s; FRAME pFrame[2]; COUNT i, num_frames; - static COUNT scale_amt = PLANET_INIT_ZOOM_SIZE; - static UBYTE zoom_from = 0; - RECT r, *rp = NULL; - CONTEXT OldContext; + COUNT scale_amt; - (void)da; // ignored - - // If this frame hasn't been generted, generate it - if (! pSolarSysState->isPFADefined[x]) { - RenderLevelMasks (x); - pSolarSysState->isPFADefined[x] = 1; - } num_frames = (pSolarSysState->ShieldFrame == 0) ? 1 : 2; pFrame[0] = SetAbsFrameIndex (pSolarSysState->PlanetFrameArray, (COUNT)(x + 1)); if (num_frames == 2) pFrame[1] = pSolarSysState->ShieldFrame; - if (zoom) + // we're zooming in, take care of scaling the frames + for (i=0; i < num_frames; i++) + { + COUNT frameh, this_scale; + if (pSolarSysState->ScaleFrame[i]) + { + DestroyDrawable (ReleaseDrawable (pSolarSysState->ScaleFrame[i])); + pSolarSysState->ScaleFrame[i] = 0; + } + frameh = GetFrameHeight (pFrame[i]); + this_scale = frameh * zoom_amt / MAP_HEIGHT; + if (! (this_scale & 0x01)) + this_scale++; + pSolarSysState->ScaleFrame[i] = stretch_frame ( + pFrame[i], this_scale, this_scale, 0 + ); + SetFrameHot ( + pSolarSysState->ScaleFrame[i], + MAKE_HOT_SPOT ((COORD)((this_scale >> 1) + 1), + (COORD)((this_scale >> 1) + 1))); + pFrame[i] = pSolarSysState->ScaleFrame[i]; + } +} + +int +RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from) +{ + STAMP s; + FRAME pFrame[2]; + COUNT i, num_frames; + RECT r, *rp = NULL; + CONTEXT OldContext; + + num_frames = (pSolarSysState->ShieldFrame == 0) ? 1 : 2; + pFrame[0] = SetAbsFrameIndex (pSolarSysState->PlanetFrameArray, (COUNT)(x + 1)); + if (num_frames == 2) + pFrame[1] = pSolarSysState->ShieldFrame; + if (scale_amt) { r.corner.x = 0; r.corner.y = 0; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT - MAP_HEIGHT; rp = &r; - if (scale_amt == PLANET_INIT_ZOOM_SIZE) - zoom_from |= TFB_Random () & 0x03; // we're zooming in, take care of scaling the frames for (i=0; i < num_frames; i++) - { - COUNT frameh, this_scale; - if (pSolarSysState->ScaleFrame[i]) - { - DestroyDrawable (ReleaseDrawable (pSolarSysState->ScaleFrame[i])); - pSolarSysState->ScaleFrame[i] = 0; - } - frameh = GetFrameHeight (pFrame[i]); - this_scale = frameh * scale_amt / MAP_HEIGHT; - if (! (this_scale & 0x01)) - this_scale++; - pSolarSysState->ScaleFrame[i] = stretch_frame ( - pFrame[i], this_scale, this_scale, 0 - ); - SetFrameHot ( - pSolarSysState->ScaleFrame[i], - MAKE_HOT_SPOT ((this_scale >> 1) + 1, (this_scale >> 1) + 1) - ); pFrame[i] = pSolarSysState->ScaleFrame[i]; - } - scale_amt += PLANET_ZOOM_SPEED; //Translate the planet so it comes from the bottom right corner - if (scale_amt > MAP_HEIGHT) - scale_amt=MAP_HEIGHT; dx += ((zoom_from & 0x01) ? 1 : -1) * dx * (MAP_HEIGHT - scale_amt) / MAP_HEIGHT; dy += ((zoom_from & 0x02) ? 1 : -1) * dy * (MAP_HEIGHT - scale_amt) / MAP_HEIGHT; - if (scale_amt == MAP_HEIGHT) - { - scale_amt = PLANET_INIT_ZOOM_SIZE; - zoom = 0; - zoom_from = 0; - } } //SetSemaphore (GraphicsSem); @@ -144,7 +139,9 @@ RotatePlanet (int x, int da, int dx, int dy, int zoom) SetContext (OldContext); } //ClearSemaphore (GraphicsSem); - return (zoom); + if (scale_amt && scale_amt != MAP_HEIGHT) + return 1; + return 0; } void diff --git a/sc2/src/sc2code/planets/plangen.c b/sc2/src/sc2code/planets/plangen.c index c5b645ab6..8fde42aa0 100644 --- a/sc2/src/sc2code/planets/plangen.c +++ b/sc2/src/sc2code/planets/plangen.c @@ -24,6 +24,9 @@ #define PROFILE 1 #define ROTATION_TIME 12 +// The initial size of the planet when zooming. MUST BE ODD +#define PLANET_INIT_ZOOM_SIZE 3 + // define USE_ALPHA_SHIELD to use an aloha overlay instead of // an additive overlay for the shield effect #undef USE_ALPHA_SHIELD @@ -37,7 +40,7 @@ void SetPlanetTilt (int da); void RepairBackRect (PRECT pRect); -int RotatePlanet (int x, int angle, int dx, int dy,int zoom); +int RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from); DWORD frame_mapRGBA (FRAME FramePtr,UBYTE r, UBYTE g, UBYTE b, UBYTE a); @@ -51,6 +54,9 @@ void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame, RECT *rdst, i FRAME scale16xRandomizeFrame(FRAME FramePtr); +COUNT PlanetZoomOrbit (int x, COUNT zoom_amt, UBYTE zoom_from); + + DWORD **getpixelarray(FRAME FramePtr,int width, int height); #define NUM_BATCH_POINTS 64 @@ -464,6 +470,30 @@ SetPlanetTilt (int angle) } } +//init_zoom_array +// evaluate the function 5/6*(1-e^(-x/14)) to get a decelerating zoom +// on entering planet orbit. This gives is nearly equivalent to what +// the 3DO does. +#define ZOOM_TIME (1.13) +#define ZOOM_FACT1 (6.0 / 5) +#define ZOOM_FACT2 (14.0 / 25) +COUNT +init_zoom_array (COUNT *zoom_arr) +{ + float frames_per_sec; + int num_frames, i; + + frames_per_sec = (float)MAP_WIDTH / ROTATION_TIME; + num_frames = (int)((frames_per_sec * ZOOM_TIME) + 0.5); + for (i = 0; i < num_frames; i++) + { + zoom_arr[i] = (COUNT) (MAP_HEIGHT * ZOOM_FACT1 * + (1 - exp (-(i + 1) / (ZOOM_FACT2 * num_frames)))); + } + zoom_arr[i] = MAP_HEIGHT; + return i; +} + //CreateShieldMask // The shield is created in two parts. This routine creates the Halo. // The red tint of the planet is currently applied in RenderLevelMasks @@ -1335,9 +1365,13 @@ int rotate_planet_task (void *data) { SIZE i; + COORD init_x; DWORD TimeIn; PSOLARSYS_STATE pSS; BOOLEAN repair, zooming; + UBYTE zoom_from; + COUNT zoom_arr[50]; + COUNT zoom_amt, frame_num = 0, zoom_frames; int angle=0; Task task = (Task) data; @@ -1354,16 +1388,23 @@ rotate_planet_task (void *data) // angle=pSS->SysInfo.PlanetInfo.AxialTilt; i = 1 - ((pSS->SysInfo.PlanetInfo.AxialTilt & 1) << 1); + init_x = (i == 1) ? (0) : (MAP_WIDTH - 1); + // Render the first planet frame + RenderLevelMasks (init_x); + pSolarSysState->isPFADefined[init_x] = 1; + + zoom_from = (UBYTE)TFB_Random () & 0x03; + zoom_frames = init_zoom_array (zoom_arr); + PlanetZoomOrbit (init_x, zoom_arr[frame_num++], zoom_from); + zoom_amt = zoom_arr[frame_num]; + TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { BYTE view_index; COORD x; - if (i > 0) - x = 0; - else - x = MAP_WIDTH - 1; + x = init_x; view_index = MAP_WIDTH; do { @@ -1383,18 +1424,36 @@ rotate_planet_task (void *data) if (((PSOLARSYS_STATE volatile)pSS)->PauseRotate == 2) pSS->PauseRotate = 1; - repair = RotatePlanet (x, angle, SIS_SCREEN_WIDTH >> 1, - (148 - SIS_ORG_Y) >> 1, zooming + repair = RotatePlanet (x, SIS_SCREEN_WIDTH >> 1, + (148 - SIS_ORG_Y) >> 1, zoom_amt, zoom_from ); if (!repair && zooming) { zooming = FALSE; + zoom_amt = 0; ++pSS->MenuState.Initialized; } x += i; } ClearSemaphore (GraphicsSem); + // If this frame hasn't been generted, generate it + if (! pSolarSysState->isPFADefined[x]) { + RenderLevelMasks (x); + pSolarSysState->isPFADefined[x] = 1; + } + if (zooming) + { + PlanetZoomOrbit (x, zoom_arr[frame_num++], zoom_from); + if (frame_num > zoom_frames) + { + fprintf (stderr, "rotate_planet_task() : zoom frame out of bounds!\n"); + frame_num = zoom_frames; + } + zoom_amt = zoom_arr[frame_num]; + } + + SleepThreadUntil (TimeIn + (ONE_SECOND * ROTATION_TIME) / (MAP_WIDTH)); // SleepThreadUntil (TimeIn + (ONE_SECOND * 5 / (MAP_WIDTH-32))); TimeIn = GetTimeCounter ();