Initial commit
This commit is contained in:
293
engines/illusions/bbdou/bbdou_bubble.cpp
Normal file
293
engines/illusions/bbdou/bbdou_bubble.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_bubble.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
BbdouBubble::BbdouBubble(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou)
|
||||
: _vm(vm), _bbdou(bbdou) {
|
||||
}
|
||||
|
||||
BbdouBubble::~BbdouBubble() {
|
||||
}
|
||||
|
||||
void BbdouBubble::init() {
|
||||
|
||||
static const uint32 kTrailObjectIds[] = {
|
||||
0x0004003B, 0x0004003C, 0x0004003D, 0x0004003E,
|
||||
0x0004003F, 0x00040040, 0x00040041, 0x00040042,
|
||||
0x00040043, 0x00040044, 0x00040045, 0x00040046,
|
||||
0x00040047, 0x00040048, 0x00040049, 0x0004004A,
|
||||
0x0004004B, 0x0004004C, 0x0004004D, 0x0004004E,
|
||||
0x0004004F, 0x00040050, 0x00040051, 0x00040052,
|
||||
0x00040053, 0x00040054, 0x00040055, 0x00040056,
|
||||
0x00040057, 0x00040058, 0x00040059, 0x0004005A
|
||||
};
|
||||
|
||||
static const uint32 kIconObjectIds[] = {
|
||||
0x0004001B, 0x0004001C, 0x0004001D, 0x0004001E,
|
||||
0x0004001F, 0x00040020, 0x00040021, 0x00040022,
|
||||
0x00040023, 0x00040024, 0x00040025, 0x00040026,
|
||||
0x00040027, 0x00040028, 0x00040029, 0x0004002A,
|
||||
0x0004002B, 0x0004002C, 0x0004002D, 0x0004002E,
|
||||
0x0004002F, 0x00040030, 0x00040031, 0x00040032,
|
||||
0x00040033, 0x00040034, 0x00040035, 0x00040036,
|
||||
0x00040037, 0x00040038, 0x00040039, 0x0004003A
|
||||
};
|
||||
|
||||
_bubbleObjectId1 = 0x4005B;
|
||||
_bubbleObjectId2 = 0x4005C;
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_trailObjectIds[i] = kTrailObjectIds[i];
|
||||
}
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_icons[i]._objectId = kIconObjectIds[i];
|
||||
_icons[i]._enabled = false;
|
||||
_icons[i]._position.x = 0;
|
||||
_icons[i]._position.y = 0;
|
||||
_icons[i]._sequenceId = 0;
|
||||
}
|
||||
|
||||
_currBubbleStyle = nullptr;
|
||||
_showingBubbleStyle = nullptr;
|
||||
_hidingBubbleStyle = nullptr;
|
||||
_sourcePt.x = 0;
|
||||
_sourcePt.y = 0;
|
||||
_destPt.x = 0;
|
||||
_destPt.y = 0;
|
||||
|
||||
}
|
||||
|
||||
void BbdouBubble::addBubbleStyle(uint32 showSequenceId, uint32 hideSequenceId, uint32 progResKeywordId,
|
||||
uint32 namedPointId, int16 count, uint32 *namedPointIds) {
|
||||
BubbleStyle style;
|
||||
style._showSequenceId = showSequenceId;
|
||||
style._hideSequenceId = hideSequenceId;
|
||||
style._progResKeywordId = progResKeywordId;
|
||||
style._baseNamedPointId = namedPointId;
|
||||
style._count = count;
|
||||
for (int16 i = 0; i < count; ++i) {
|
||||
style._namedPointIds[i] = FROM_LE_32(namedPointIds[i]);
|
||||
}
|
||||
style._objectId = 0;
|
||||
style._position.x = 0;
|
||||
style._position.y = 0;
|
||||
_bubbleStyles.push_back(style);
|
||||
}
|
||||
|
||||
void BbdouBubble::show() {
|
||||
|
||||
if (_showingBubbleStyle) {
|
||||
hide();
|
||||
}
|
||||
|
||||
_showingBubbleStyle = _currBubbleStyle;
|
||||
_currBubbleStyle = nullptr;
|
||||
|
||||
calcBubbleTrail(_sourcePt, _destPt);
|
||||
|
||||
Control *bubbleControl = _vm->_dict->getObjectControl(_showingBubbleStyle->_objectId);
|
||||
bubbleControl->setActorPosition(_destPt);
|
||||
bubbleControl->startSequenceActor(0x60057, 2, 0);
|
||||
bubbleControl->startSequenceActor(_showingBubbleStyle->_showSequenceId, 2, 0);
|
||||
bubbleControl->appearActor();
|
||||
bubbleControl->deactivateObject();
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
if (_icons[i]._enabled) {
|
||||
Control *iconControl = _vm->_dict->getObjectControl(_icons[i]._objectId);
|
||||
iconControl->setActorPosition(_icons[i]._position);
|
||||
iconControl->startSequenceActor(_icons[i]._sequenceId, 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BbdouBubble::hide() {
|
||||
_hidingBubbleStyle = _showingBubbleStyle;
|
||||
_showingBubbleStyle = nullptr;
|
||||
if (_hidingBubbleStyle) {
|
||||
Control *bubbleControl = _vm->_dict->getObjectControl(_hidingBubbleStyle->_objectId);
|
||||
bubbleControl->startSequenceActor(_hidingBubbleStyle->_hideSequenceId, 2, 0);
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
Control *trailControl = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
trailControl->stopActor();
|
||||
trailControl->disappearActor();
|
||||
}
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
Control *iconControl = _vm->_dict->getObjectControl(_icons[i]._objectId);
|
||||
iconControl->stopActor();
|
||||
iconControl->disappearActor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouBubble::selectBubbleStyle(int16 minCount, Common::Point sourcePt, Common::Point destPt, uint32 progResKeywordId) {
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_icons[i]._enabled = false;
|
||||
}
|
||||
int16 maxCount = 32;
|
||||
for (uint i = 0; i < _bubbleStyles.size(); ++i) {
|
||||
BubbleStyle *style = &_bubbleStyles[i];
|
||||
if (style->_count < maxCount && style->_count >= minCount &&
|
||||
(progResKeywordId == 0 || progResKeywordId == style->_progResKeywordId)) {
|
||||
maxCount = style->_count;
|
||||
_currBubbleStyle = style;
|
||||
}
|
||||
}
|
||||
_sourcePt = sourcePt;
|
||||
_destPt = destPt;
|
||||
_currBubbleStyle->_position = destPt;
|
||||
_currBubbleStyle->_objectId = _bubbleObjectId1;
|
||||
if (_showingBubbleStyle && _showingBubbleStyle->_objectId == _currBubbleStyle->_objectId)
|
||||
_currBubbleStyle->_objectId = _bubbleObjectId2;
|
||||
}
|
||||
|
||||
uint32 BbdouBubble::addBubbleIcon(uint positionIndex, uint32 sequenceId) {
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
BubbleIcon *icon = &_icons[i];
|
||||
if (!icon->_enabled) {
|
||||
Common::Point itemPos = _vm->getNamedPointPosition(_currBubbleStyle->_namedPointIds[positionIndex]);
|
||||
Common::Point basePos = _vm->getNamedPointPosition(_currBubbleStyle->_baseNamedPointId);
|
||||
icon->_enabled = true;
|
||||
icon->_sequenceId = sequenceId;
|
||||
icon->_position.x = itemPos.x + _currBubbleStyle->_position.x - basePos.x;
|
||||
icon->_position.y = itemPos.y + _currBubbleStyle->_position.y - basePos.y;
|
||||
return icon->_objectId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BbdouBubble::calcBubbleTrail(Common::Point &sourcePt, Common::Point &destPt) {
|
||||
const int kSequenceIdsCount = 10;
|
||||
const float kDistanceBetweenPoints = 30.0;
|
||||
static const uint32 kBubbleTrailSequenceIds[] = {
|
||||
0x00060042, 0x00060043, 0x00060044, 0x00060045, 0x00060046,
|
||||
0x00060047, 0x00060048, 0x00060049, 0x0006004A, 0x0006004B
|
||||
};
|
||||
static const int kIndexTbl[kSequenceIdsCount] = {4, 0, 8, 2, 6, 5, 1, 9, 3, 7};
|
||||
|
||||
int sequenceCounters[kSequenceIdsCount];
|
||||
bool swapY;
|
||||
int centerX, centerY;
|
||||
float currentAngle, radius;
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
Control *control = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
control->startSequenceActor(0x00060056, 2, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSequenceIdsCount; ++i) {
|
||||
sequenceCounters[i] = 0;
|
||||
}
|
||||
|
||||
if (destPt.y >= sourcePt.y) {
|
||||
swapY = true;
|
||||
if (sourcePt.x == destPt.x)
|
||||
destPt.x = destPt.x + 20;
|
||||
} else {
|
||||
swapY = false;
|
||||
if (sourcePt.y == destPt.y)
|
||||
destPt.y = destPt.y + 20;
|
||||
}
|
||||
|
||||
if (swapY) {
|
||||
centerX = (destPt.x * destPt.x - (destPt.y - sourcePt.y) * (destPt.y - sourcePt.y) - sourcePt.x * sourcePt.x) / (2 * (destPt.x - sourcePt.x));
|
||||
centerY = destPt.y;
|
||||
radius = ABS(destPt.x - centerX);
|
||||
} else {
|
||||
centerX = destPt.x;
|
||||
centerY = (destPt.y * destPt.y - (destPt.x - sourcePt.x) * (destPt.x - sourcePt.x) - sourcePt.y * sourcePt.y) / (2 * (destPt.y - sourcePt.y));
|
||||
radius = ABS(destPt.y - centerY);
|
||||
}
|
||||
|
||||
const float fullDistance = sqrt((destPt.y - sourcePt.y) * (destPt.y - sourcePt.y) + (destPt.x - sourcePt.x) * (destPt.x - sourcePt.x));
|
||||
const float arcAngle = 2 * asin(CLIP(0.5 * fullDistance / radius, -1.0, 1.0));
|
||||
const float arcLength = arcAngle * radius;
|
||||
int pointsCount = (int)(arcLength / kDistanceBetweenPoints);
|
||||
float partAngle = ABS(kDistanceBetweenPoints / radius);
|
||||
|
||||
for (int i = 0; i < pointsCount; ++i) {
|
||||
++sequenceCounters[kIndexTbl[i % kSequenceIdsCount]];
|
||||
}
|
||||
|
||||
if (!swapY) {
|
||||
if (destPt.y < sourcePt.y) {
|
||||
currentAngle = (float)M_PI * 0.5F;
|
||||
} else {
|
||||
currentAngle = (float)M_PI * 1.5F;
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
if (destPt.x < sourcePt.x)
|
||||
partAngle = -partAngle;
|
||||
} else {
|
||||
if (destPt.x <= sourcePt.x) {
|
||||
currentAngle = (float)M_PI;
|
||||
} else {
|
||||
currentAngle = 0.0;
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
if (destPt.y > sourcePt.y)
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
|
||||
float angleStep = partAngle / (float)pointsCount * 0.5;
|
||||
float angleIncr = (float)(pointsCount / 2) * angleStep + partAngle;
|
||||
|
||||
if (pointsCount > 32)
|
||||
pointsCount = 32;
|
||||
|
||||
for (int i = 0; i < pointsCount; ++i) {
|
||||
|
||||
currentAngle += angleIncr;
|
||||
angleIncr -= angleStep;
|
||||
|
||||
Common::Point newPoint(
|
||||
centerX + _vm->getRandom(8) - 2 + (int)(cos(currentAngle) * radius),
|
||||
centerY + _vm->getRandom(8) - 2 - (int)(sin(currentAngle) * radius));
|
||||
|
||||
Control *trailControl = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
|
||||
for (int index = kSequenceIdsCount - 1; index >= 0; --index) {
|
||||
if (sequenceCounters[index] > 0) {
|
||||
--sequenceCounters[index];
|
||||
trailControl->setActorPosition(newPoint);
|
||||
trailControl->startSequenceActor(kBubbleTrailSequenceIds[index], 2, 0);
|
||||
trailControl->appearActor();
|
||||
trailControl->deactivateObject();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
Reference in New Issue
Block a user