mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-06 02:10:28 +00:00
STARTREK: Implement drawAllSprites properly.
Still need to do the part which calculates sprite priorities.
This commit is contained in:
parent
7c62092367
commit
a69f025818
35
engines/startrek/common.cpp
Normal file
35
engines/startrek/common.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "startrek/common.h"
|
||||
|
||||
namespace StarTrek {
|
||||
|
||||
Common::Rect getRectEncompassing(Common::Rect r1, Common::Rect r2) {
|
||||
uint16 l = min(r1.left, r2.left);
|
||||
uint16 t = min(r1.top, r2.top);
|
||||
uint16 r = max(r1.right, r2.right);
|
||||
uint16 b = max(r1.bottom, r2.bottom);
|
||||
|
||||
return Common::Rect(l,t,r,b);
|
||||
}
|
||||
|
||||
}
|
39
engines/startrek/common.h
Normal file
39
engines/startrek/common.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef STARTREK_COMMON_H
|
||||
#define STARTREK_COMMON_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace StarTrek {
|
||||
|
||||
template<class T>
|
||||
T min(T a, T b) { return a < b ? a : b; }
|
||||
|
||||
template<class T>
|
||||
T max(T a, T b) { return a > b ? a : b; }
|
||||
|
||||
Common::Rect getRectEncompassing(Common::Rect r1, Common::Rect r2);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -19,11 +19,13 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "startrek/common.h"
|
||||
#include "startrek/graphics.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/rendermode.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace StarTrek {
|
||||
|
||||
@ -34,7 +36,7 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
|
||||
_priData = nullptr;
|
||||
_lutData = nullptr;
|
||||
|
||||
_screenRect = Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_screenRect = Common::Rect(SCREEN_WIDTH-1, SCREEN_HEIGHT-1);
|
||||
|
||||
if (ConfMan.hasKey("render_mode"))
|
||||
_egaMode = (Common::parseRenderMode(ConfMan.get("render_mode").c_str()) == Common::kRenderEGA) && (_vm->getGameType() != GType_STJR) && !(_vm->getFeatures() & GF_DEMO);
|
||||
@ -43,7 +45,6 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
|
||||
_font = new Font(_vm);
|
||||
|
||||
_backgroundImage = new Bitmap(_vm->openFile("DEMON0.BMP").get());
|
||||
_canvas = new Bitmap(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
_numSprites = 0;
|
||||
}
|
||||
@ -55,7 +56,6 @@ Graphics::~Graphics() {
|
||||
|
||||
delete _font;
|
||||
delete _backgroundImage;
|
||||
delete _canvas;
|
||||
}
|
||||
|
||||
|
||||
@ -137,12 +137,8 @@ SharedPtr<Bitmap> Graphics::loadBitmap(Common::String basename) {
|
||||
}
|
||||
|
||||
void Graphics::redrawScreen() {
|
||||
// TODO: get rid of _canvas for efficiency
|
||||
memcpy(_canvas->pixels, _backgroundImage->pixels, SCREEN_WIDTH*SCREEN_HEIGHT);
|
||||
|
||||
_vm->_system->copyRectToScreen(_backgroundImage->pixels, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
drawAllSprites();
|
||||
|
||||
drawBitmapToScreen(_canvas);
|
||||
}
|
||||
|
||||
void Graphics::drawSprite(const Sprite &sprite) {
|
||||
@ -158,7 +154,9 @@ void Graphics::drawSprite(const Sprite &sprite, const Common::Rect &rect) {
|
||||
assert(_screenRect.contains(rect));
|
||||
assert(spriteRect.contains(rect));
|
||||
|
||||
byte *dest = _canvas->pixels + rect.top*SCREEN_WIDTH + rect.left;
|
||||
::Graphics::Surface *surface = _vm->_system->lockScreen();
|
||||
|
||||
byte *dest = (byte*)surface->getPixels() + rect.top*SCREEN_WIDTH + rect.left;
|
||||
|
||||
switch(sprite.drawMode) {
|
||||
case 0: { // Normal sprite
|
||||
@ -233,7 +231,7 @@ void Graphics::drawSprite(const Sprite &sprite, const Common::Rect &rect) {
|
||||
int drawWidth = rectangle1.width() + 1;
|
||||
int drawHeight = rectangle1.height() + 1;
|
||||
|
||||
dest =_canvas->pixels + sprite.drawY*SCREEN_WIDTH + sprite.drawX
|
||||
dest = (byte*)surface->getPixels() + sprite.drawY*SCREEN_WIDTH + sprite.drawX
|
||||
+ rectangle1.top*8*SCREEN_WIDTH + rectangle1.left*8;
|
||||
|
||||
byte *src = sprite.bitmap->pixels + rectangle1.top*sprite.bitmap->width/8 + rectangle1.left;
|
||||
@ -283,16 +281,120 @@ void Graphics::drawSprite(const Sprite &sprite, const Common::Rect &rect) {
|
||||
error("drawSprite: draw mode %d invalid", sprite.drawMode);
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_system->unlockScreen();
|
||||
}
|
||||
|
||||
void Graphics::drawAllSprites() {
|
||||
// TODO: implement properly
|
||||
if (_numSprites == 0)
|
||||
return;
|
||||
|
||||
// TODO: calculateSpriteDrawPriority()
|
||||
|
||||
// Update sprite rectangles
|
||||
for (int i=0; i<_numSprites; i++) {
|
||||
Sprite *spr = _sprites[i];
|
||||
spr->drawX = spr->pos.x;
|
||||
spr->drawY = spr->pos.y;
|
||||
drawSprite(*spr);
|
||||
spr->bitmapChanged = true; // FIXME (delete this later)
|
||||
Common::Rect rect;
|
||||
|
||||
rect.left = spr->pos.x - spr->bitmap->xoffset;
|
||||
rect.top = spr->pos.y - spr->bitmap->yoffset;
|
||||
rect.right = rect.left + spr->bitmap->width - 1;
|
||||
rect.bottom = rect.top + spr->bitmap->height - 1;
|
||||
|
||||
spr->drawX = rect.left;
|
||||
spr->drawY = rect.top;
|
||||
|
||||
spr->drawRect = rect.findIntersectingRect(_screenRect);
|
||||
|
||||
if (!spr->drawRect.isEmpty()) { // At least partly on-screen
|
||||
if (spr->lastDrawRect.left <= spr->lastDrawRect.right) {
|
||||
// If the sprite's position is close to where it was last time it was
|
||||
// drawn, combine the two rectangles and redraw that whole section.
|
||||
// Otherwise, redraw the old position and current position separately.
|
||||
rect = spr->drawRect.findIntersectingRect(spr->lastDrawRect);
|
||||
|
||||
if (rect.isEmpty())
|
||||
spr->rect2Valid = 0;
|
||||
else {
|
||||
spr->rectangle2 = getRectEncompassing(spr->drawRect, spr->lastDrawRect);
|
||||
spr->rect2Valid = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
spr->rectangle2 = spr->drawRect;
|
||||
spr->rect2Valid = 1;
|
||||
}
|
||||
|
||||
spr->isOnScreen = 1;
|
||||
}
|
||||
else { // Off-screen
|
||||
spr->rect2Valid = 0;
|
||||
spr->isOnScreen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine what portions of the screen need to be updated
|
||||
Common::Rect dirtyRects[MAX_SPRITES*2];
|
||||
int numDirtyRects = 0;
|
||||
|
||||
for (int i=0; i<_numSprites; i++) {
|
||||
Sprite *spr = _sprites[i];
|
||||
|
||||
if (spr->bitmapChanged) {
|
||||
if (spr->isOnScreen) {
|
||||
if (spr->rect2Valid) {
|
||||
dirtyRects[numDirtyRects++] = spr->rectangle2;
|
||||
}
|
||||
else {
|
||||
dirtyRects[numDirtyRects++] = spr->drawRect;
|
||||
dirtyRects[numDirtyRects++] = spr->lastDrawRect;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dirtyRects[numDirtyRects++] = spr->lastDrawRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redraw the background on every dirty rectangle
|
||||
for (int i=0; i<numDirtyRects; i++) {
|
||||
Common::Rect &r = dirtyRects[i];
|
||||
|
||||
int offset = r.top*SCREEN_WIDTH + r.left;
|
||||
_vm->_system->copyRectToScreen(_backgroundImage->pixels+offset, SCREEN_WIDTH, r.left, r.top, r.width(), r.height());
|
||||
}
|
||||
|
||||
// For each sprite, merge the rectangles that overlap with it and redraw the sprite.
|
||||
for (int i=0; i<_numSprites; i++) {
|
||||
Sprite *spr = _sprites[i];
|
||||
|
||||
if (spr->field16 == 0 && spr->isOnScreen) {
|
||||
bool mustRedrawSprite = false;
|
||||
Common::Rect rect2;
|
||||
|
||||
for (int j=0; j<numDirtyRects; j++) {
|
||||
Common::Rect rect1 = spr->drawRect.findIntersectingRect(dirtyRects[j]);
|
||||
|
||||
if (!rect1.isEmpty()) {
|
||||
if (mustRedrawSprite)
|
||||
rect2 = getRectEncompassing(rect1, rect2);
|
||||
else
|
||||
rect2 = rect1;
|
||||
mustRedrawSprite = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mustRedrawSprite)
|
||||
drawSprite(*spr, rect2);
|
||||
}
|
||||
|
||||
spr->field16 = 0;
|
||||
spr->bitmapChanged = 0;
|
||||
spr->lastDrawRect = spr->drawRect;
|
||||
}
|
||||
|
||||
_vm->_system->updateScreen();
|
||||
}
|
||||
|
||||
void Graphics::addSprite(Sprite *sprite) {
|
||||
@ -304,10 +406,10 @@ void Graphics::addSprite(Sprite *sprite) {
|
||||
sprite->field8 = 0;
|
||||
sprite->field16 = 0;
|
||||
|
||||
sprite->rectangle1.top = -1;
|
||||
sprite->rectangle1.left = -1;
|
||||
sprite->rectangle1.bottom = -2;
|
||||
sprite->rectangle1.right = -2;
|
||||
sprite->lastDrawRect.top = -1;
|
||||
sprite->lastDrawRect.left = -1;
|
||||
sprite->lastDrawRect.bottom = -2;
|
||||
sprite->lastDrawRect.right = -2;
|
||||
|
||||
_sprites[_numSprites++] = sprite;
|
||||
}
|
||||
|
@ -105,7 +105,6 @@ private:
|
||||
|
||||
Common::Rect _screenRect;
|
||||
Bitmap *_backgroundImage;
|
||||
Bitmap *_canvas;
|
||||
|
||||
Sprite *_sprites[MAX_SPRITES];
|
||||
int _numSprites;
|
||||
|
@ -2,6 +2,7 @@ MODULE := engines/startrek
|
||||
|
||||
MODULE_OBJS = \
|
||||
bitmap.o \
|
||||
common.o \
|
||||
detection.o \
|
||||
filestream.o \
|
||||
font.o \
|
||||
|
@ -37,6 +37,12 @@ using Common::SharedPtr;
|
||||
namespace StarTrek {
|
||||
|
||||
|
||||
// Note: Rects in Star Trek are probably considered to have their bottom-right pixel
|
||||
// contained in the rectangle, but ScummVM is the opposite... (Trek might be inconsistent)
|
||||
// Be careful when using some of Rect's functions, including:
|
||||
// * The width/height constructor
|
||||
// * width/height methods
|
||||
// * "contains" method for points (it should work for other rects)
|
||||
struct Sprite {
|
||||
Common::Point pos;
|
||||
uint16 drawPriority;
|
||||
@ -45,16 +51,16 @@ struct Sprite {
|
||||
SharedPtr<Bitmap> bitmap;
|
||||
uint16 drawMode;
|
||||
uint16 textColor;
|
||||
uint16 bitmapChanged;
|
||||
uint16 redrawCondition2;
|
||||
uint16 redrawCondition3;
|
||||
uint16 field16;
|
||||
Common::Rect rectangle1;
|
||||
Common::Rect clickRectangle;
|
||||
bool bitmapChanged;
|
||||
bool rect2Valid;
|
||||
bool isOnScreen;
|
||||
uint16 field16; // When set, sprite isn't drawn next refresh? (Gets reset to 0 after)
|
||||
Common::Rect lastDrawRect; // Rect encompassing the sprite last time it was drawn
|
||||
Common::Rect drawRect; // Rect encompassing the sprite currently
|
||||
Common::Rect rectangle2;
|
||||
uint16 drawX,drawY;
|
||||
|
||||
int16 drawX,drawY;
|
||||
|
||||
Sprite() { memset(this, 0, sizeof(Sprite)); }
|
||||
void setBitmap(SharedPtr<Bitmap> b);
|
||||
};
|
||||
|
||||
|
@ -101,7 +101,6 @@ Common::Error StarTrekEngine::run() {
|
||||
_gfx->drawBackgroundImage("BRIDGE.BGD");
|
||||
}
|
||||
|
||||
|
||||
// Sprite tests
|
||||
|
||||
// Draw mode 0
|
||||
@ -110,7 +109,7 @@ Common::Error StarTrekEngine::run() {
|
||||
spr->bitmap = _gfx->loadBitmap("MWALKE00");
|
||||
spr->drawPriority = 1;
|
||||
spr->pos.x = 150;
|
||||
spr->pos.y = 30;
|
||||
spr->pos.y = 100;
|
||||
spr->drawMode = 0;
|
||||
|
||||
// Draw mode 2 (translucent background)
|
||||
@ -119,9 +118,10 @@ Common::Error StarTrekEngine::run() {
|
||||
spr->bitmap = _gfx->loadBitmap("KWALKS00");
|
||||
spr->drawPriority = 1;
|
||||
spr->pos.x = 200;
|
||||
spr->pos.y = 40;
|
||||
spr->pos.y = 140;
|
||||
spr->drawMode = 2;
|
||||
|
||||
/*
|
||||
// Draw mode 3 (text)
|
||||
spr = new Sprite;
|
||||
_gfx->addSprite(spr);
|
||||
@ -134,15 +134,14 @@ Common::Error StarTrekEngine::run() {
|
||||
spr->drawMode = 3;
|
||||
|
||||
// initTextSprite function
|
||||
/*
|
||||
spr = new Sprite;
|
||||
int x=0,y=0;
|
||||
_gfx->initTextSprite(&x, &y, 0xb3, 3, false, spr);
|
||||
spr->pos.y = 150;
|
||||
|
||||
|
||||
_gfx->showText(&Graphics::tmpFunction, 0, 50, 50, 0xb3, 0, 10, 0);
|
||||
*/
|
||||
|
||||
|
||||
_gfx->showText(&Graphics::tmpFunction, 0, 150, 50, 0xb3, 0, 10, 0);
|
||||
|
||||
while (!shouldQuit()) {
|
||||
pollEvents();
|
||||
@ -164,7 +163,7 @@ void StarTrekEngine::pollEvents() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_gfx->redrawScreen();
|
||||
_gfx->drawAllSprites();
|
||||
|
||||
_system->delayMillis(1000/60);
|
||||
}
|
||||
|
@ -64,8 +64,6 @@ int Graphics::showText(TextGetterFunc textGetter, int var, int xoffset, int yoff
|
||||
Sprite textboxSprite;
|
||||
SharedPtr<TextBitmap> textBitmap = initTextSprite(&xoffset, &yoffset, textColor, numTextboxLines, numChoicesWithNames, &textboxSprite);
|
||||
|
||||
debug("X: %d, Y: %d\n", xoffset, yoffset);
|
||||
|
||||
int choiceIndex = 0;
|
||||
int var28 = 0;
|
||||
if (tmpTextboxVar1 != 0 && tmpTextboxVar1 != 1 && numChoices == 1
|
||||
@ -178,25 +176,17 @@ SharedPtr<TextBitmap> Graphics::initTextSprite(int *xoffsetPtr, int *yoffsetPtr,
|
||||
if (varC < 0)
|
||||
xoffset += varC;
|
||||
|
||||
debug("xoffset A: %d", xoffset);
|
||||
|
||||
varC = xoffset - (bitmap->width+0x1d)/2;
|
||||
if (varC < 1)
|
||||
xoffset += varC-1;
|
||||
|
||||
debug("xoffset B: %d", xoffset);
|
||||
|
||||
varC = yoffset - (bitmap->height+0x11) - 20;
|
||||
if (varC < 0)
|
||||
yoffset -= varC;
|
||||
|
||||
debug("Mid xoffset: %d", xoffset);
|
||||
|
||||
xoffset -= (bitmap->width+0x1d)/2;
|
||||
yoffset -= bitmap->height;
|
||||
|
||||
debug("Final xoffset: %d", xoffset);
|
||||
|
||||
bitmap->pixels[0] = 0x10;
|
||||
memset(&bitmap->pixels[1], 0x11, TEXTBOX_WIDTH-2);
|
||||
bitmap->pixels[TEXTBOX_WIDTH-1] = 0x12;
|
||||
|
Loading…
x
Reference in New Issue
Block a user