ASYLUM: Pipes puzzle: add spiders

This commit is contained in:
Alexander
2021-05-17 15:37:04 +02:00
committed by Eugene Sandulenko
parent 7828f300fa
commit 80583b079b
2 changed files with 141 additions and 19 deletions
+106 -17
View File
@@ -103,19 +103,13 @@ const Common::Point peepholePoints[] = {
const uint32 peepholeResources[] = {15, 15, 15, 15, 32, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 32, 32, 15,
15, 32, 32, 15, 15, 15, 15,15, 15, 15, 15, 32, 15, 15, 15, 15, 15, 15, 15};
const double LOG2 = 0.6931471;
//////////////////////////////////////////////////////////////////////////
// Peephole
//////////////////////////////////////////////////////////////////////////
bool Peephole::marks[peepholesCount];
void Peephole::connect(Connector *connector) {
_connectors.push_back(connector);
}
void Peephole::disconnect(Connector *connector) {
_connectors.remove(connector);
}
void Peephole::startUpWater(bool flag) {
if (flag)
memset(marks, false, sizeof(marks));
@@ -183,8 +177,8 @@ void Connector::turn() {
oldIndex[1] = 2;
}
} else {
newIndex[0] = log((double)(newState & delta)) / log((double)2);
oldIndex[0] = log((double)(_state & delta)) / log((double)2);
newIndex[0] = log((double)(newState & delta)) / LOG2;
oldIndex[0] = log((double)(_state & delta)) / LOG2;
}
for (uint32 i = 0; i < (uint32)(delta == kBinNum1111 ? 2 : 1); ++i) {
@@ -259,6 +253,49 @@ void Connector::disconnect(Connector *connector) {
_isConnected = connector->_isConnected = false;
}
//////////////////////////////////////////////////////////////////////////
// Spider
//////////////////////////////////////////////////////////////////////////
Spider::Spider(Common::Rect rect, Common::String id) {
_boundingBox = rect;
_rnd = new Common::RandomSource(Common::String("pipes_spider") + id);
_isAlive = true;
_location.x = _rnd->getRandomNumber(_boundingBox.right - _boundingBox.left) + _boundingBox.left;
_location.y = _rnd->getRandomNumber(_boundingBox.bottom - _boundingBox.top) + _boundingBox.top;
_direction = Direction(1 << _rnd->getRandomNumber(3));
randomize();
}
void Spider::randomize(Direction excluded) {
if (_rnd->getRandomNumber(5) == 5)
_delta = Common::Point(0, 0);
else {
while (_direction == excluded)
_direction = Direction(1 << _rnd->getRandomNumber(3));
_delta = Common::Point((_direction & kBinNum0010 ? 1 : 0) - (_direction & kBinNum1000 ? 1 : 0), (_direction & kBinNum0100 ? 1 : 0) - (_direction & kBinNum0001 ? 1 : 0));
}
_stepsNumber = _rnd->getRandomNumber(maxStepsNumber - minStepsNumber) + minStepsNumber;
_steps = 0;
}
Common::Point Spider::move() {
Common::Point previousLocation(_location);
if (_isAlive) {
if (_steps++ > _stepsNumber)
randomize();
if (!_boundingBox.contains(_location + _delta))
randomize(_direction);
else
_location += _delta;
}
return previousLocation;
}
//////////////////////////////////////////////////////////////////////////
// PuzzlePipes
//////////////////////////////////////////////////////////////////////////
@@ -272,6 +309,9 @@ PuzzlePipes::PuzzlePipes(AsylumEngine *engine) : Puzzle(engine) {
}
PuzzlePipes::~PuzzlePipes() {
for (uint32 i = 0; i < _spiders.size(); ++i)
delete _spiders[i];
delete [] _frameIndexSpider;
}
void PuzzlePipes::reset() {
@@ -324,8 +364,10 @@ bool PuzzlePipes::update(const AsylumEvent &evt) {
_isLeverReady = false;
if (_frameIndexLever) {
_frameIndexLever = (_frameIndexLever + 1) % GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[2]);
if (!_frameIndexLever)
if (!_frameIndexLever) {
_isLeverReady = true;
getCursor()->show();
}
}
// TODO: turn the fountain on
@@ -340,6 +382,32 @@ bool PuzzlePipes::update(const AsylumEvent &evt) {
if (!_levelFlags[4])
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[45], 0, Common::Point(518, 108), kDrawFlagNone, 0, 2);
for (uint32 i = 0; i < _spiders.size(); ++i) {
uint32 spiderResourceId;
switch (_spiders[i]->getDirection()) {
case kDirectionNh:
spiderResourceId = _spiders[i]->isAlive() ? 34 : 37;
break;
case kDirectionEt:
spiderResourceId = _spiders[i]->isAlive() ? 35 : 38; // FIXME
break;
case kDirectionSh:
spiderResourceId = _spiders[i]->isAlive() ? 36 : 39;
break;
case kDirectionWt:
spiderResourceId = _spiders[i]->isAlive() ? 35 : 38;
break;
default: ;
}
if (_spiders[i]->isVisible(Common::Rect(-10, -10, 650, 490))) {
uint32 frameCountSpider = GraphicResource::getFrameCount(_vm, getWorld()->graphicResourceIds[spiderResourceId]);
_frameIndexSpider[i] = _spiders[i]->isActive() ? (_frameIndexSpider[i] + 1) % frameCountSpider : 0;
getScreen()->addGraphicToQueue(getWorld()->graphicResourceIds[spiderResourceId], _frameIndexSpider[i], _spiders[i]->move(), kDrawFlagNone, 0, 1);
}
}
getScreen()->drawGraphicsInQueue();
getScreen()->copyBackBufferToScreen();
updateCursor();
@@ -361,16 +429,22 @@ bool PuzzlePipes::mouseLeftDown(const AsylumEvent &evt) {
if (Common::Rect(540, 90, 590, 250).contains(mousePos)) {
if (!_frameIndexLever)
++_frameIndexLever;
getCursor()->hide();
getSound()->playSound(getWorld()->graphicResourceIds[43], false, Config.sfxVolume - 10);
} else {
if (_rectIndex != -1) {
getSound()->playSound(getWorld()->graphicResourceIds[42], false, Config.sfxVolume - 10);
if (_rectIndex < ARRAYSIZE(connectorPoints)) {
getSound()->playSound(getWorld()->graphicResourceIds[42], false, Config.sfxVolume - 10);
_connectors[_rectIndex].turn();
startUpWater();
memset(_levelFlags, false, sizeof(_levelFlags));
_levelFlags[checkFlags()] = true;
_connectors[_rectIndex].turn();
startUpWater();
memset(_levelFlags, false, sizeof(_levelFlags));
_levelFlags[checkFlags()] = true;
} else {
getSound()->playSound(getWorld()->graphicResourceIds[44], false, Config.sfxVolume - 10);
_spiders[_rectIndex - ARRAYSIZE(connectorPoints)]->smash();
_frameIndexSpider[_rectIndex - ARRAYSIZE(connectorPoints)] = 0;
}
}
}
@@ -447,6 +521,17 @@ void PuzzlePipes::setup() {
_connectors[10].initGroup();
_connectors[11].initGroup();
uint32 i = rnd(7);
if (i & kBinNum0001)
_spiders.push_back(new Spider(Common::Rect(-10, 45, 92, 315), "1"));
if (i & kBinNum0010)
_spiders.push_back(new Spider(Common::Rect(-10, 389, 149, 476), "2"));
if (i & kBinNum0100)
_spiders.push_back(new Spider(Common::Rect(544, 225, 650, 490), "3"));
_frameIndexSpider = new uint32[_spiders.size()];
memset(_frameIndexSpider, 0, sizeof(_frameIndexSpider));
startUpWater();
}
@@ -469,6 +554,10 @@ int32 PuzzlePipes::findRect() {
if (Common::Rect(connectorPoints[i].x - 5, connectorPoints[i].y - 5, connectorPoints[i].x + 30, connectorPoints[i].y + 30).contains(getCursor()->position()))
return i;
for (uint32 i = 0; i < _spiders.size(); ++i)
if (_spiders[i]->getPolygon(Common::Rect(10, 10, 30, 30)).contains(getCursor()->position()))
return ARRAYSIZE(connectorPoints) + i;
return -1;
}
+35 -2
View File
@@ -27,6 +27,9 @@
#include "common/list.h"
#include "common/hashmap.h"
#include "common/array.h"
#include "common/random.h"
#include "common/str.h"
namespace Asylum {
@@ -76,8 +79,8 @@ public:
uint32 getLevel1() { return _flowValues[0] + _flowValues[1] + _flowValues[2] + _flowValues[3]; }
bool isConnected() { return isConnected(0) || isConnected(1) || isConnected(2) || isConnected(3); }
void connect(Connector *connector);
void disconnect(Connector *connector);
void connect(Connector *connector) { _connectors.push_back(connector); }
void disconnect(Connector *connector) { _connectors.remove(connector); }
void startUpWater(bool flag = false);
private:
@@ -118,6 +121,34 @@ private:
friend void Peephole::startUpWater(bool);
};
class Spider {
public:
Spider(Common::Rect rect, Common::String id);
~Spider() { delete _rnd; }
bool isAlive() const { return _isAlive; }
bool isActive() const { return _delta != Common::Point(0, 0); }
bool isVisible(Common::Rect rect) const { return rect.contains(_location); }
Direction getDirection() const { return _direction; }
Common::Rect getPolygon(Common::Rect frame) const { return Common::Rect(_location.x - frame.left, _location.y - frame.top, _location.x + frame.right, _location.y + frame.bottom); }
Common::Point move();
void smash() { _isAlive = false; }
private:
static const uint32 minStepsNumber = 20, maxStepsNumber = 200;
Common::RandomSource *_rnd;
bool _isAlive;
Common::Point _location;
Common::Point _delta;
Common::Rect _boundingBox;
Direction _direction;
uint32 _stepsNumber;
uint32 _steps;
void randomize(Direction excluded = kDirectionNowhere);
};
class PuzzlePipes : public Puzzle {
public:
PuzzlePipes(AsylumEngine *engine);
@@ -136,6 +167,8 @@ private:
Connector _connectors[connectorsCount];
Peephole _peepholes[peepholesCount];
Peephole *_sinks[4], *_sources[4];
Common::Array<Spider *> _spiders;
uint32 *_frameIndexSpider;
//////////////////////////////////////////////////////////////////////////
// Event Handling