MADS: Implementing code for panning screen transitions
This commit is contained in:
parent
cbbd1a9219
commit
5e00b39cae
6 changed files with 183 additions and 3 deletions
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue