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
This commit is contained in:
ghaushe
2003-03-08 00:27:26 +00:00
parent 53b6ea685c
commit c884eb7528
2 changed files with 111 additions and 55 deletions
+35 -38
View File
@@ -20,6 +20,7 @@
#include "libs/graphics/gfx_common.h"
#include "libs/graphics/drawable.h"
#include <math.h>
// 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,42 +46,20 @@ 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)
{
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++)
{
@@ -91,7 +70,7 @@ RotatePlanet (int x, int da, int dx, int dy, int zoom)
pSolarSysState->ScaleFrame[i] = 0;
}
frameh = GetFrameHeight (pFrame[i]);
this_scale = frameh * scale_amt / MAP_HEIGHT;
this_scale = frameh * zoom_amt / MAP_HEIGHT;
if (! (this_scale & 0x01))
this_scale++;
pSolarSysState->ScaleFrame[i] = stretch_frame (
@@ -99,22 +78,38 @@ RotatePlanet (int x, int da, int dx, int dy, int zoom)
);
SetFrameHot (
pSolarSysState->ScaleFrame[i],
MAKE_HOT_SPOT ((this_scale >> 1) + 1, (this_scale >> 1) + 1)
);
MAKE_HOT_SPOT ((COORD)((this_scale >> 1) + 1),
(COORD)((this_scale >> 1) + 1)));
pFrame[i] = pSolarSysState->ScaleFrame[i];
}
scale_amt += PLANET_ZOOM_SPEED;
}
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;
// we're zooming in, take care of scaling the frames
for (i=0; i < num_frames; i++)
pFrame[i] = pSolarSysState->ScaleFrame[i];
//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
+66 -7
View File
@@ -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 ();