aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/gob/aniobject.cpp30
-rw-r--r--engines/gob/aniobject.h5
-rw-r--r--engines/gob/minigames/geisha/diving.cpp54
-rw-r--r--engines/gob/minigames/geisha/diving.h5
-rw-r--r--engines/gob/minigames/geisha/evilfish.cpp17
-rw-r--r--engines/gob/minigames/geisha/evilfish.h6
-rw-r--r--engines/gob/minigames/geisha/oko.cpp10
-rw-r--r--engines/gob/minigames/geisha/oko.h4
8 files changed, 106 insertions, 25 deletions
diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp
index a01fe43672..0ca850d1fb 100644
--- a/engines/gob/aniobject.cpp
+++ b/engines/gob/aniobject.cpp
@@ -111,6 +111,36 @@ void ANIObject::getFrameSize(int16 &width, int16 &height) const {
height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top + 1;
}
+bool ANIObject::isIn(int16 x, int16 y) const {
+ if (!isVisible())
+ return false;
+
+ int16 frameX, frameY, frameWidth, frameHeight;
+ getFramePosition(frameX, frameY);
+ getFrameSize(frameWidth, frameHeight);
+
+ if ((x < frameX) || (y < frameY))
+ return false;
+ if ((x > (frameX + frameWidth)) || (y > (frameY + frameHeight)))
+ return false;
+
+ return true;
+}
+
+bool ANIObject::isIn(const ANIObject &obj) const {
+ if (!isVisible() || !obj.isVisible())
+ return false;
+
+ int16 frameX, frameY, frameWidth, frameHeight;
+ getFramePosition(frameX, frameY);
+ getFrameSize(frameWidth, frameHeight);
+
+ return obj.isIn(frameX , frameY ) ||
+ obj.isIn(frameX + frameWidth - 1, frameY ) ||
+ obj.isIn(frameX , frameY + frameHeight - 1) ||
+ obj.isIn(frameX + frameWidth - 1, frameY + frameHeight - 1);
+}
+
void ANIObject::draw(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
diff --git a/engines/gob/aniobject.h b/engines/gob/aniobject.h
index 28103007a6..e3fe301400 100644
--- a/engines/gob/aniobject.h
+++ b/engines/gob/aniobject.h
@@ -69,6 +69,11 @@ public:
/** Return the current frame size. */
void getFrameSize(int16 &width, int16 &height) const;
+ /** Are there coordinates within the animation sprite? */
+ bool isIn(int16 x, int16 y) const;
+ /** Is this object within the animation sprite? */
+ bool isIn(const ANIObject &obj) const;
+
/** Set the animation number. */
void setAnimation(uint16 animation);
diff --git a/engines/gob/minigames/geisha/diving.cpp b/engines/gob/minigames/geisha/diving.cpp
index 0a43f96be9..fb906ce346 100644
--- a/engines/gob/minigames/geisha/diving.cpp
+++ b/engines/gob/minigames/geisha/diving.cpp
@@ -66,8 +66,8 @@ Diving::Diving(GobEngine *vm) : _vm(vm), _background(0),
_blackPearl = new Surface(11, 8, 1);
- _airMeter = new Meter(4 , 195, 38, 2, 5, 7, 38, Meter::kFillToLeft);
- _healthMeter = new Meter(276, 195, 38, 2, 6, 7, 38, Meter::kFillToLeft);
+ _airMeter = new Meter(3 , 195, 40, 2, 5, 7, 40, Meter::kFillToLeft);
+ _healthMeter = new Meter(275, 195, 40, 2, 6, 7, 4, Meter::kFillToLeft);
for (uint i = 0; i < kEvilFishCount; i++)
_evilFish[i].evilFish = 0;
@@ -108,6 +108,8 @@ bool Diving::play(uint16 playerCount, bool hasPearlLocation) {
while (!_vm->shouldQuit()) {
checkShots();
+ checkOkoHurt();
+
updateAirMeter();
updateEvilFish();
updateDecorFish();
@@ -132,13 +134,7 @@ bool Diving::play(uint16 playerCount, bool hasPearlLocation) {
if (mouseButtons == kMouseButtonsLeft)
shoot(mouseX, mouseY);
- if (key == kKeyDown) {
- _oko->sink();
- if ((_oko->getState() == Oko::kStatePick) && (_oko->getFrame() == 0))
- getPearl();
-
- } else if (key == kKeyUp)
- _oko->raise();
+ handleOko(key);
if ((_whitePearlCount >= 20) || (_blackPearlCount >= 2))
break;
@@ -251,6 +247,7 @@ void Diving::init() {
_healthMeter->setValue(38);
_airCycle = 0;
+ _hurtGracePeriod = 0;
}
void Diving::deinit() {
@@ -682,6 +679,45 @@ void Diving::checkShots() {
}
}
+void Diving::handleOko(int16 key) {
+ if (key == kKeyDown) {
+ _oko->sink();
+
+ if ((_oko->getState() == Oko::kStatePick) && (_oko->getFrame() == 0))
+ getPearl();
+
+ } else if (key == kKeyUp)
+ _oko->raise();
+}
+
+void Diving::checkOkoHurt() {
+ if (_oko->getState() != Oko::kStateSwim)
+ return;
+
+ // Oko dies if the health reaches 0
+ if (_healthMeter->getValue() == 0)
+ _oko->die();
+
+ // Give Oko a grace period after being hurt
+ if (_hurtGracePeriod > 0) {
+ _hurtGracePeriod--;
+ return;
+ }
+
+ // Check for a fish/Oko-collision
+ for (uint i = 0; i < kEvilFishCount; i++) {
+ EvilFish &evilFish = *_evilFish[i].evilFish;
+
+ if (!evilFish.isDead() && evilFish.isIn(*_oko)) {
+ _oko->hurt();
+ _healthMeter->decrease();
+
+ _hurtGracePeriod = 10;
+ break;
+ }
+ }
+}
+
} // End of namespace Geisha
} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/diving.h b/engines/gob/minigames/geisha/diving.h
index 2915e85a93..5db1b8199a 100644
--- a/engines/gob/minigames/geisha/diving.h
+++ b/engines/gob/minigames/geisha/diving.h
@@ -137,6 +137,7 @@ private:
Meter *_healthMeter;
uint8 _airCycle;
+ uint8 _hurtGracePeriod;
uint8 _currentShot;
@@ -174,6 +175,10 @@ private:
void shoot(int16 mouseX, int16 mouseY);
void checkShots();
+
+ void handleOko(int16 key);
+
+ void checkOkoHurt();
};
} // End of namespace Geisha
diff --git a/engines/gob/minigames/geisha/evilfish.cpp b/engines/gob/minigames/geisha/evilfish.cpp
index e9503f4aed..c7ef9d5622 100644
--- a/engines/gob/minigames/geisha/evilfish.cpp
+++ b/engines/gob/minigames/geisha/evilfish.cpp
@@ -39,19 +39,6 @@ EvilFish::EvilFish(const ANIFile &ani, uint16 screenWidth,
EvilFish::~EvilFish() {
}
-bool EvilFish::isIn(int16 x, int16 y) const {
- int16 frameX, frameY, frameWidth, frameHeight;
- getFramePosition(frameX, frameY);
- getFrameSize(frameWidth, frameHeight);
-
- if ((x < frameX) || (y < frameY))
- return false;
- if ((x > (frameX + frameWidth)) || (y > (frameY + frameHeight)))
- return false;
-
- return true;
-}
-
void EvilFish::enter(Direction from, int16 y) {
_shouldLeave = false;
@@ -184,6 +171,10 @@ void EvilFish::mutate(uint16 animSwimLeft, uint16 animSwimRight,
}
}
+bool EvilFish::isDead() {
+ return !isVisible() || (_state == kStateNone) || (_state == kStateDie);
+}
+
} // End of namespace Geisha
} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/evilfish.h b/engines/gob/minigames/geisha/evilfish.h
index 223645f47f..81efb676e2 100644
--- a/engines/gob/minigames/geisha/evilfish.h
+++ b/engines/gob/minigames/geisha/evilfish.h
@@ -42,9 +42,6 @@ public:
uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie);
~EvilFish();
- /** Are there coordinates within the fish's sprite? */
- bool isIn(int16 x, int16 y) const;
-
/** Enter from this direction / screen edge. */
void enter(Direction from, int16 y);
/** Leave the screen in the current direction. */
@@ -60,6 +57,9 @@ public:
void mutate(uint16 animSwimLeft, uint16 animSwimRight,
uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie);
+ /** Is the fish dead? */
+ bool isDead();
+
private:
enum State {
kStateNone,
diff --git a/engines/gob/minigames/geisha/oko.cpp b/engines/gob/minigames/geisha/oko.cpp
index c9d4d1f43f..1e90b1f8bf 100644
--- a/engines/gob/minigames/geisha/oko.cpp
+++ b/engines/gob/minigames/geisha/oko.cpp
@@ -35,6 +35,7 @@ enum kOkoAnimation {
kOkoAnimationRaise = 7,
kOkoAnimationBreathe = 2,
kOkoAnimationPick = 3,
+ kOkoAnimationHurt = 4,
kOkoAnimationDie0 = 17,
kOkoAnimationDie1 = 18,
kOkoAnimationDie2 = 19
@@ -80,6 +81,7 @@ void Oko::advance() {
_sound->blasterPlay(_breathe, 1, 0);
case kStateSink:
case kStateRaise:
+ case kStateHurt:
if (wasLastFrame) {
setAnimation(kOkoAnimationSwim);
setPosition(kOkoPositionX, kLevelPositionX[_level]);
@@ -135,6 +137,14 @@ void Oko::raise() {
_level--;
}
+void Oko::hurt() {
+ if (_state != kStateSwim)
+ return;
+
+ setAnimation(kOkoAnimationHurt);
+ _state = kStateHurt;
+}
+
void Oko::die() {
if (_state != kStateSwim)
return;
diff --git a/engines/gob/minigames/geisha/oko.h b/engines/gob/minigames/geisha/oko.h
index d5d18c16b3..7fe0001393 100644
--- a/engines/gob/minigames/geisha/oko.h
+++ b/engines/gob/minigames/geisha/oko.h
@@ -42,6 +42,7 @@ public:
kStateRaise,
kStateBreathe,
kStatePick,
+ kStateHurt,
kStateDead
};
@@ -56,6 +57,9 @@ public:
/** Oko should raise a level. */
void raise();
+ /** Oko should get hurt. */
+ void hurt();
+
/** Oko should die. */
void die();