DRAGOMS: Work on actor draw priorities

This commit is contained in:
Eric Fry 2019-01-15 07:19:54 +11:00 committed by Eugene Sandulenko
parent df0298f8f4
commit c0f1d70393
11 changed files with 184 additions and 67 deletions

View File

@ -20,6 +20,7 @@
*
*/
#include <common/debug.h>
#include "dragons.h"
#include "actorresource.h"
#include "actor.h"
@ -32,10 +33,10 @@ ActorManager::ActorManager(ActorResourceLoader *actorResourceLoader) : _actorRes
}
Actor *ActorManager::loadActor(uint32 resourceId, uint32 sequenceId, int16 x, int16 y, uint16 field16) {
Actor *ActorManager::loadActor(uint32 resourceId, uint32 sequenceId, int16 x, int16 y, uint16 priorityLayer) {
Actor *actor = loadActor(resourceId, sequenceId, x, y);
if(actor) {
actor->field16 = field16;
actor->priorityLayer = priorityLayer;
}
return actor;
}
@ -79,12 +80,18 @@ void ActorManager::clearActorFlags(uint16 startingActorId) {
}
}
Actor *ActorManager::loadActor(uint32 resourceId, uint16 actorId) {
Actor *actor = getActor(actorId);
actor->_actorResource = _actorResourceLoader->load(resourceId);
return actor;
}
Actor::Actor(uint16 id) : _actorID(id) {
_actorResource = NULL;
resourceID = -1;
_seqCodeIp = 0;
frame_pointer_maybe = NULL;
field16 = 3;
priorityLayer = 3;
x_pos = 160;
y_pos = 110;
target_x_pos = 0;
@ -100,13 +107,14 @@ Actor::Actor(uint16 id) : _actorID(id) {
}
void Actor::init(ActorResource *resource, int16 x, int16 y, uint32 sequenceID) {
debug(3, "actor %d Init", _actorID);
_actorResource = resource;
x_pos = x;
y_pos = y;
sequenceTimer = 0;
target_x_pos = x;
target_y_pos = y;
var_e = 0x100;
field_e = 0x100;
_sequenceID2 = 0;
flags = (Dragons::ACTOR_FLAG_40 | Dragons::ACTOR_FLAG_4);
frame_width = 0;
@ -117,12 +125,6 @@ void Actor::init(ActorResource *resource, int16 x, int16 y, uint32 sequenceID) {
updateSequence((uint16)sequenceID);
}
Graphics::Surface *Actor::getCurrentFrame() {
frame_vram_x = _actorResource->getFrameHeader(sequenceTimer)->xOffset;
frame_vram_y = _actorResource->getFrameHeader(sequenceTimer)->yOffset;
return _actorResource->loadFrame(sequenceTimer);
}
void Actor::updateSequence(uint16 newSequenceID) {
_sequenceID = newSequenceID;
flags &= 0xfbf1;
@ -142,9 +144,18 @@ void Actor::loadFrame(uint16 frameOffset) {
}
frame = _actorResource->loadFrameHeader(frameOffset);
surface = _actorResource->loadFrame(*frame);
uint16 paletteId = 0;
if (flags & Dragons::ACTOR_FLAG_4000) {
paletteId = 0xf7;
} else if (flags & Dragons::ACTOR_FLAG_8000) {
paletteId = 0xf1;
} else {
paletteId = 0;
}
debug(3, "load frame header: (%d,%d)", frame->width, frame->height);
surface = _actorResource->loadFrame(*frame, NULL); // TODO paletteId == 0xf1 ? getEngine()->getBackgroundPalette() : NULL);
debug(3, "ActorId: %d load frame header: (%d,%d) palette: %X", _actorID, frame->width, frame->height, paletteId);
}

View File

@ -64,7 +64,8 @@ public:
public:
Actor *loadActor(uint32 resourceId, uint32 sequenceId, int16 x, int16 y);
Actor *loadActor(uint32 resourceId, uint32 sequenceId, int16 x, int16 y, uint16 field16);
Actor *loadActor(uint32 resourceId, uint32 sequenceId, int16 x, int16 y, uint16 priorityLayer);
Actor *loadActor(uint32 resourceId, uint16 actorId);
Actor *getActor(uint16 actorId);
void clearActorFlags(uint16 startingActorId);
@ -83,11 +84,11 @@ public:
ActorFrame *frame;
Graphics::Surface *surface;
uint16 field_c;
int16 var_e;
int16 field_e;
uint16 sequenceTimer;
uint16 _sequenceID;
uint16 _sequenceID2;
int16 field16;
int16 priorityLayer;
uint16 flags;
int16 x_pos;
int16 y_pos;
@ -114,7 +115,6 @@ public:
Actor(uint16 id);
void init(ActorResource *resource, int16 x, int16 y, uint32 sequenceID);
Graphics::Surface *getCurrentFrame();
void updateSequence(uint16 newSequenceID);
void resetSequenceIP();
byte *getSeqIpAtOffset(uint32 offset);

View File

@ -79,30 +79,28 @@ bool ActorResource::load(uint32 id, byte *dataStart, Common::SeekableReadStream
_frames[i].frameDataOffset = &dataStart[frameDataOffset];
_frames[i].flags = stream.readUint16LE();
_frames[i].field_c = stream.readUint16LE();
// debug("Frame[%d] field_0: %d field_2: %d (%d, %d) offset: %X, flags: %X field_c: %d",
// i, _frames[i].field_0, _frames[i].field_2, _frames[i].width, _frames[i].height, frameDataOffset, _frames[i].flags, _frames[i].field_c);
debug("Frame[%d] @%X, xOffset: %d field_2: %d (%d, %d) offset: %X, flags: %X field_c: %d",
i, offset, _frames[i].xOffset, _frames[i].yOffset, _frames[i].width, _frames[i].height, frameDataOffset, _frames[i].flags, _frames[i].field_c);
}
return false;
}
void ActorResource::writePixelBlock(byte *pixels, byte *data) {
pixels[0] = _palette[data[0] * 2];
pixels[1] = _palette[data[0] * 2 + 1];
pixels[2] = _palette[data[1] * 2];
pixels[3] = _palette[data[1] * 2 + 1];
pixels[4] = _palette[data[2] * 2];
pixels[5] = _palette[data[2] * 2 + 1];
pixels[6] = _palette[data[3] * 2];
pixels[7] = _palette[data[3] *2 + 1];
void ActorResource::writePixelBlock(byte *pixels, byte *data, byte *palette) {
pixels[0] = palette[data[0] * 2];
pixels[1] = palette[data[0] * 2 + 1];
pixels[2] = palette[data[1] * 2];
pixels[3] = palette[data[1] * 2 + 1];
pixels[4] = palette[data[2] * 2];
pixels[5] = palette[data[2] * 2 + 1];
pixels[6] = palette[data[3] * 2];
pixels[7] = palette[data[3] * 2 + 1];
}
Graphics::Surface *ActorResource::loadFrame(uint16 frameNumber) {
assert (frameNumber < _framesCount);
return loadFrame(_frames[frameNumber]);
}
Graphics::Surface *ActorResource::loadFrame(ActorFrame &actorFrame) {
Graphics::Surface *ActorResource::loadFrame(ActorFrame &actorFrame, byte *palette) {
if (!palette) {
palette = _palette;
}
Graphics::Surface *surface = new Graphics::Surface();
Graphics::PixelFormat pixelFormat16(2, 5, 5, 5, 1, 10, 5, 0, 15); //TODO move this to a better location.
@ -128,7 +126,7 @@ Graphics::Surface *ActorResource::loadFrame(ActorFrame &actorFrame) {
if (size != 0) {
for(int32 i = size; i != 0; i--) {
//TODO clean up this copy.
writePixelBlock(pixels, data);
writePixelBlock(pixels, data, palette);
data += 4;
pixels += 8;
@ -143,11 +141,11 @@ Graphics::Surface *ActorResource::loadFrame(ActorFrame &actorFrame) {
if (size != 0) {
for(int32 i = size; i != 0; i--) {
//TODO write bytes to pixel data.
writePixelBlock(pixels, data);
writePixelBlock(pixels, data, palette);
pixels += 8;
}
data += 4;
}
data += 4;
}
}

View File

@ -32,8 +32,8 @@ class ActorResource;
struct ActorFrame {
int16 xOffset;
int16 yOffset;
uint8 width;
uint8 height;
uint16 width;
uint16 height;
byte *frameDataOffset;
uint16 flags;
uint16 field_c;
@ -61,8 +61,7 @@ private:
public:
bool load(uint32 id, byte *dataStart, Common::SeekableReadStream &stream);
Graphics::Surface *loadFrame(uint16 frameNumber);
Graphics::Surface *loadFrame(ActorFrame &frameNumber);
Graphics::Surface *loadFrame(ActorFrame &frameNumber, byte *palette);
ActorFrame *loadFrameHeader(uint16 frameOffset);
ActorFrame *getFrameHeader(uint16 frameNumber);
@ -71,7 +70,7 @@ public:
const char *getFilename();
private:
void writePixelBlock(byte *pixels, byte *data);
void writePixelBlock(byte *pixels, byte *data, byte *palette);
};
} // End of namespace Dragons

View File

@ -54,10 +54,10 @@ void Dragons::PriorityLayer::load(TileMap &tileMap, byte *tiles) {
int16 PriorityLayer::getPriority(Common::Point pos) {
pos.x = CLIP<int16>(pos.x, 0, _width - 1);
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
const int16 tx = pos.x / 32, sx = pos.x % 32;
const int16 ty = pos.y / 8, sy = pos.y % 8;
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
return _values[mapIndex * 32 * 8 + sx + sy * 32];
const int16 tx = pos.x / TILE_WIDTH, sx = pos.x % TILE_WIDTH;
const int16 ty = pos.y / TILE_HEIGHT, sy = pos.y % TILE_HEIGHT;
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth));
return _values[mapIndex * 32 * 8 + sx + sy * 32] + 1;
}
@ -73,7 +73,7 @@ bool Background::load(byte *dataStart, Common::SeekableReadStream &stream) {
stream.seek(0x308);
uint32 tilemapOffset = 0x324;
TileMap tileMap[3];
TileMap tileMap[4];
for(int i=0;i< 3;i++) {
tileMap[i].w = stream.readUint16LE();
tileMap[i].h = stream.readUint16LE();
@ -87,10 +87,17 @@ bool Background::load(byte *dataStart, Common::SeekableReadStream &stream) {
uint32 finalSize = stream.readUint32LE();
_priorityLayer = new PriorityLayer();
_priorityLayer->load(tileMap[0], dataStart + tilemapOffset);
tileMap[3].w = tileMap[0].w;
tileMap[3].h = tileMap[0].h;
tileMap[3].size = tileMap[0].size;
tileMap[3].map = dataStart + tilemapOffset;
tileMap[3].tileIndexOffset = tileindexOffset;
uint32 tilesOffset = tilemapOffset + finalSize;
_priorityLayer = new PriorityLayer();
_priorityLayer->load(tileMap[3], dataStart + tilesOffset);
debug("Tiles: %X", tilesOffset);
debug("tileIndexOffset: %d", tileMap[0].tileIndexOffset);
_bgLayer = loadGfxLayer(tileMap[0], dataStart + tilesOffset);

View File

@ -25,6 +25,7 @@
#include "common/error.h"
#include "actor.h"
#include "actorresource.h"
#include "background.h"
#include "bigfile.h"
#include "dragonrms.h"
#include "dragonini.h"
@ -37,6 +38,12 @@ namespace Dragons {
#define DRAGONS_TICK_INTERVAL 17
static DragonsEngine *_engine = nullptr;
DragonsEngine *getEngine() {
return _engine;
}
DragonsEngine::DragonsEngine(OSystem *syst) : Engine(syst) {
_bigfileArchive = NULL;
_dragonRMS = NULL;
@ -46,6 +53,8 @@ DragonsEngine::DragonsEngine(OSystem *syst) : Engine(syst) {
_flags = 0;
_unkFlags1 = 0;
_sequenceOpcodes = new SequenceOpcodes(this);
_engine = this;
_cursorPosition = Common::Point();
}
DragonsEngine::~DragonsEngine() {
@ -75,6 +84,25 @@ Common::Error DragonsEngine::run() {
_scene = new Scene(this, _screen, _bigfileArchive, _actorManager, _dragonRMS, _dragonINIResource);
_flags = 0x1046;
Actor *cursor = _actorManager->loadActor(0, 0); //Load cursor
cursor->x_pos = _cursorPosition.x = 160;
cursor->y_pos = _cursorPosition.y = 100;
cursor->priorityLayer = 6;
cursor->flags = 0;
cursor->field_e = 0x100;
cursor->updateSequence(0);
cursor->flags |= (Dragons::ACTOR_FLAG_40 | Dragons::ACTOR_FLAG_80 | Dragons::ACTOR_FLAG_100 | Dragons::ACTOR_FLAG_200);
Actor *inventory = _actorManager->loadActor(1, 1); //Load inventory
inventory->x_pos = 2;
inventory->y_pos = 0;
inventory->priorityLayer = 6;
inventory->flags = 0;
inventory->field_e = 0x100;
inventory->updateSequence(0);
inventory->flags |= (Dragons::ACTOR_FLAG_40 | Dragons::ACTOR_FLAG_80 | Dragons::ACTOR_FLAG_100 | Dragons::ACTOR_FLAG_200);
_scene->loadScene(0x12, 0x1e);
_scene->draw();
@ -115,20 +143,20 @@ void DragonsEngine::updateHandler() {
DragonINI *flicker = _dragonINIResource->getFlickerRecord();
if (flicker && _scene->contains(flicker) && flicker->actor->_actorID == i) {
if (priority < 8 || priority == 0x10) {
actor->field16 = priority;
actor->priorityLayer = priority;
}
} else {
if (priority != -1) {
actor->field16 = priority;
actor->priorityLayer = priority;
}
}
if (actor->field16 >= 0x11) {
actor->field16 = 0;
if (actor->priorityLayer >= 0x11) {
actor->priorityLayer = 0;
}
if (actor->field16 >= 9) {
actor->field16 -= 8;
if (actor->priorityLayer >= 9) {
actor->priorityLayer -= 8;
}
}
@ -260,4 +288,9 @@ void DragonsEngine::clearUnkFlags(uint32 flags) {
_unkFlags1 &= ~flags;
}
byte *DragonsEngine::getBackgroundPalette() {
assert(_scene);
return _scene->getPalette();
}
} // End of namespace Dragons

View File

@ -97,6 +97,7 @@ private:
uint32 _nextUpdatetime;
uint32 _flags;
uint32 _unkFlags1;
Common::Point _cursorPosition;
public:
DragonsEngine(OSystem *syst);
@ -116,6 +117,8 @@ public:
void setUnkFlags(uint32 flags);
void clearUnkFlags(uint32 flags);
byte *getBackgroundPalette();
private:
void gameLoop();
void updateHandler();
@ -123,6 +126,8 @@ private:
void wait();
};
DragonsEngine *getEngine();
} // End of namespace Dragons
#endif //SCUMMVM_DRAGONS_H

View File

@ -145,27 +145,36 @@ void Scene::loadScene(uint32 sceneId, uint32 cameraPointId) {
void Scene::draw() {
Common::Rect rect(_camera.x, _camera.y, 320, 200);
_screen->copyRectToSurface(*_stage->getBgLayer(), 0, 0, rect);
_screen->copyRectToSurface(*_stage->getMgLayer(), 0, 0, rect);
_screen->copyRectToSurface(*_stage->getFgLayer(), 0, 0, rect);
for(int i=0;i < _dragonINIResource->totalRecords(); i++) {
DragonINI *ini = _dragonINIResource->getRecord(i);
if (ini->sceneId == _currentSceneId && (ini->field_1a_flags_maybe & 1)) {
Actor *actor = ini->actor;
for(uint16 priority = 1; priority < 16; priority++) {
if (priority == 1) {
_screen->copyRectToSurface(*_stage->getBgLayer(), 0, 0, rect);
} else if (priority == 2) {
_screen->copyRectToSurface(*_stage->getMgLayer(), 0, 0, rect);
} else if (priority == 3) {
_screen->copyRectToSurface(*_stage->getFgLayer(), 0, 0, rect);
}
for (uint16 i = 0; i < DRAGONS_ENGINE_NUM_ACTORS; i++) {
Actor *actor = _actorManager->getActor(i);
if (actor &&
actor->flags & Dragons::ACTOR_FLAG_40 &&
actor->surface) {
Graphics::Surface *s = actor->surface;
//TODO fix for scenes that are larger than a screen.
int x = actor->x_pos - actor->frame->xOffset;
int y = actor->y_pos - actor->frame->yOffset;
//int x = ini->x;// - actor->frame_vram_x;
//int y = ini->y;// - actor->frame_vram_y;
if (x >= 0 && y >= 0 && x + s->w < 320 && y + s->h < 200) {
debug(4, "Actor %d %s (%d, %d) w:%d h:%d", actor->_actorID, actor->_actorResource->getFilename(), x, y, s->w, s->h);
if (actor->priorityLayer == priority) { //} && x + s->w < 320 && y + s->h < 200) {
debug(4, "Actor %d %s (%d, %d) w:%d h:%d Priority: %d", actor->_actorID, actor->_actorResource->getFilename(), x,
y,
s->w, s->h, actor->priorityLayer);
_screen->copyRectToSurface(*s, x, y, Common::Rect(s->w, s->h));
} else {
debug(4, "Actor (not displayed) %d %s (%d, %d)", actor->_actorID, actor->_actorResource->getFilename(), x, y);
// _stage->getFgLayer()->copyRectToSurface(*s, 0, 0, Common::Rect(s->w, s->h));
debug(4, "Actor (not displayed) %d %s (%d, %d) Priority: %d", actor->_actorID,
actor->_actorResource->getFilename(),
x, y, actor->priorityLayer);
}
}
}
@ -181,4 +190,9 @@ bool Scene::contains(DragonINI *ini) {
return ini->sceneId == _currentSceneId;
}
byte *Scene::getPalette() {
assert(_stage);
return _stage->getPalette();
}
} // End of namespace Dragons

View File

@ -35,7 +35,7 @@ class BackgroundResourceLoader;
class DragonINIResource;
class BigfileArchive;
class Screen;
class DragonINI;
struct DragonINI;
class Scene {
private:
@ -58,6 +58,7 @@ public:
int16 getPriorityAtPosition(Common::Point pos);
void draw();
bool contains(DragonINI *ini);
byte *getPalette();
};
} // End of namespace Dragons

View File

@ -48,7 +48,19 @@ void Screen::copyRectToSurface(const Graphics::Surface &srcSurface, int destX, i
}
void Screen::copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect srcRect) {
copyRectToSurface(srcSurface.getBasePtr(srcRect.left, srcRect.top), srcSurface.pitch, destX, destY, srcRect.width(), srcRect.height());
Common::Rect clipRect = clipRectToScreen( destX, destY, srcRect);
if (clipRect.width() == 0 || clipRect.height() == 0) {
return;
}
if (destX < 0) {
destX = 0;
}
if (destY < 0) {
destY = 0;
}
copyRectToSurface(srcSurface.getBasePtr(clipRect.left, clipRect.top), srcSurface.pitch, destX, destY, clipRect.width(), clipRect.height());
}
void Screen::copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
@ -75,4 +87,39 @@ void Screen::copyRectToSurface(const void *buffer, int srcPitch, int destX, int
}
}
Common::Rect Screen::clipRectToScreen(int destX, int destY, const Common::Rect rect) {
int16 x, y, w, h;
x = rect.left;
y = rect.top;
w = rect.width();
h = rect.height();
if (destX >= 320) {
w = 0;
}
if (destY >= 200) {
h = 0;
}
if (destX < 0) {
w += destX;
x += destX;
}
if (destY < 0) {
h += destY;
y += destY;
}
if (destX + w >= 320) {
w -= (destX + w) - 320;
}
if (destY + h >= 200) {
h -= (destY + h) - 200;
}
return Common::Rect(x, y, x + w, y + h);
}
} // End of namespace Dragons

View File

@ -41,6 +41,8 @@ public:
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect srcRect);
void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height);
void updateScreen();
private:
Common::Rect clipRectToScreen(int destX, int destY, const Common::Rect rect);
};
} // End of namespace Dragons