MADS: Implementing code for panning screen transitions

This commit is contained in:
Paul Gilbert 2015-02-08 22:07:42 -05:00
parent cbbd1a9219
commit 5e00b39cae
6 changed files with 183 additions and 3 deletions

View file

@ -485,7 +485,6 @@ void MSurface::scrollY(int yAmount) {
delete[] tempData;
}
void MSurface::translate(Common::Array<RGB6> &palette) {
for (int y = 0; y < this->h; ++y) {
byte *pDest = getBasePtr(0, y);
@ -521,6 +520,20 @@ MSurface *MSurface::flipHorizontal() const {
return dest;
}
void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
const Common::Point &destPos, const Common::Rect &srcRect) {
// Loop through the lines
for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
const byte *srcP = srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
byte *destP = getBasePtr(destPos.x, destPos.y + yCtr);
// Copy the line over
for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
*destP = paletteMap[*srcP];
}
}
}
/*------------------------------------------------------------------------*/
int DepthSurface::getDepth(const Common::Point &pt) {

View file

@ -220,6 +220,13 @@ public:
* Create a new surface which is a flipped horizontal copy of the current one
*/
MSurface *flipHorizontal() const;
/**
* Copy an area from one surface to another, translating it using a palette
* map as it's done
*/
void copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
const Common::Point &destPos, const Common::Rect &srcRect);
};
class DepthSurface : public MSurface {

View file

@ -885,4 +885,30 @@ void Palette::refreshSceneColors() {
setPalette(_mainPalette + (val * 3), val, 256 - val);
}
int Palette::closestColor(const byte *matchColor, const byte *refPalette,
int listWrap, int count) {
int bestColor = 0;
int bestDifference = 0x7fff;
for (int idx = 0; idx < count; ++idx) {
// Figure out hash for color
int hash = 0;
for (int rgbIdx = 0; rgbIdx < 3; ++rgbIdx, ++refPalette) {
byte diff = *refPalette - matchColor[rgbIdx];
hash += (int)diff * (int)diff;
}
// If the given color is a closer match to our color, store the index
if (hash < bestDifference) {
bestDifference = hash;
bestColor = idx;
}
refPalette += listWrap - 3;
}
return bestColor;
}
} // End of namespace MADS

View file

@ -318,6 +318,9 @@ public:
void unlock();
void refreshSceneColors();
static int closestColor(const byte *matchColor, const byte *refPalette,
int listWrap, int count);
};
} // End of namespace MADS

View file

@ -607,6 +607,7 @@ void ScreenSurface::updateScreen() {
void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
Palette &pal = *_vm->_palette;
Scene &scene = _vm->_game->_scene;
byte palData[PALETTE_SIZE];
switch (transitionType) {
@ -639,8 +640,9 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
case kTransitionPanLeftToRight:
case kTransitionPanRightToLeft:
warning("TODO: pan transition");
transition(kTransitionFadeIn, surfaceFlag);
panTransition(scene._backgroundSurface, pal._mainPalette,
transitionType - kTransitionPanLeftToRight,
Common::Point(0, 0), scene._posAdjust, THROUGH_BLACK2, true, 1);
break;
case kTransitionCircleIn1:
@ -674,5 +676,121 @@ void ScreenSurface::resetClipBounds() {
setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
}
void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entrySide,
const Common::Point &srcPos, const Common::Point &destPos,
ThroughBlack throughBlack, bool setPalette, int numTicks) {
EventsManager &events = *_vm->_events;
Palette &palette = *_vm->_palette;
Common::Point size;
int y1, y2;
int startX = 0;
int deltaX;
int sizeY;
int xAt;
int loopStart;
// uint32 baseTicks, currentTicks;
byte paletteMap[256];
size.x = MIN(newScreen.w, (uint16)MADS_SCREEN_WIDTH);
size.y = newScreen.h;
if (newScreen.h >= MADS_SCREEN_HEIGHT)
size.y = MADS_SCENE_HEIGHT;
// Set starting position and direction delta for the transition
if (entrySide == 1)
// Right to left
startX = size.x - 1;
deltaX = startX ? -1 : 1;
if (setPalette & !throughBlack)
palette.setFullPalette(palData);
// TODO: Original uses a different frequency ticks counter. Need to
// confirm frequency and see whether we need to implement it, or
// if the current frame ticks can substitute for it
// baseTicks = events.getFrameCounter();
y1 = 0;
y2 = size.y - 1;
sizeY = y2 - y1 + 1;
if (throughBlack == THROUGH_BLACK2)
swapForeground(palData, &paletteMap[0]);
loopStart = throughBlack == THROUGH_BLACK1 ? 0 : 1;
for (int loop = loopStart; loop < 2; ++loop) {
xAt = startX;
for (int xCtr = 0; xCtr < size.x; ++xCtr, xAt += deltaX) {
if (!loop) {
fillRect(Common::Rect(xAt + destPos.x, y1 + destPos.y,
xAt + destPos.x + 1, y2 + destPos.y), 0);
} else if (throughBlack == THROUGH_BLACK2) {
copyRectTranslate(newScreen, paletteMap,
Common::Point(xAt, destPos.y),
Common::Rect(srcPos.x + xAt, srcPos.y,
srcPos.x + xAt + 1, srcPos.y + size.y));
} else {
newScreen.copyRectToSurface(*this, xAt, destPos.y,
Common::Rect(srcPos.x + xAt, srcPos.y,
srcPos.x + xAt + 1, srcPos.y + size.y));
}
copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y));
// Slight delay
events.delay(1);
}
if ((setPalette && !loop) || throughBlack == THROUGH_BLACK2)
palette.setFullPalette(palData);
}
if (throughBlack == THROUGH_BLACK2) {
Common::Rect r(srcPos.x, srcPos.y, srcPos.x + size.x, srcPos.y + size.y);
copyRectToSurface(newScreen, destPos.x, destPos.y, r);
copyRectToScreen(r);
}
}
void ScreenSurface::swapForeground(byte palData[PALETTE_SIZE], byte *paletteMap) {
Palette &palette = *_vm->_palette;
byte oldPalette[PALETTE_SIZE];
byte oldMap[256];
byte newMap[256];
palette.getFullPalette(oldPalette);
swapPalette(oldPalette, oldMap, true);
swapPalette(palData, newMap, false);
Common::copy(&palData[3], &palData[PALETTE_SIZE], &oldPalette[3]);
copyRectTranslate(*this, oldMap, Common::Point(0, 0),
Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
palette.setFullPalette(oldPalette);
}
void ScreenSurface::swapPalette(byte *palData, byte swapTable[PALETTE_COUNT],
int start) {
byte *dynamicList = &palData[start * 3];
int staticStart = 1 - start;
byte *staticList = &palData[staticStart * 3];
const int PALETTE_START = 1;
const int PALETTE_END = 252;
// Set initial index values
for (int idx = 0; idx < PALETTE_COUNT; ++idx)
swapTable[idx] = idx;
for (int idx = 0; idx < 128; ++idx) {
if (start >= PALETTE_START && start <= PALETTE_END) {
swapTable[start] = Palette::closestColor(dynamicList, staticList,
6, 128) * 2 + staticStart;
}
dynamicList += 6;
start += 2;
}
}
} // End of namespace MADS

View file

@ -56,6 +56,11 @@ enum InputMode {
kInputLimitedSentences = 2 // Use only scene hotspots
};
enum ThroughBlack {
THROUGH_BLACK1 = 1,
THROUGH_BLACK2 = 2
};
class SpriteSlot;
class TextDisplay;
class UISlot;
@ -207,6 +212,14 @@ private:
uint16 _random;
byte *_surfacePixels;
Common::Rect _clipBounds;
void panTransition(MSurface &newScreen, byte *palData, int entrySide,
const Common::Point &srcPos, const Common::Point &destPos,
ThroughBlack throughBlack, bool setPalette, int numTicks);
void swapForeground(byte *palData, byte *paletteMap);
void swapPalette(byte palData[PALETTE_SIZE], byte swapTable[PALETTE_COUNT], int start);
public:
int _shakeCountdown;
public: