/* 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 "common/str.h" #include "gob/gob.h" #include "gob/surface.h" #include "gob/anifile.h" #include "gob/video.h" #include "gob/pregob/onceupon/stork.h" enum Animation { kAnimFlyNearWithBundle = 9, kAnimFlyFarWithBundle = 12, kAnimFlyNearWithoutBundle = 10, kAnimFlyFarWithoutBundle = 13, kAnimBundleNear = 11, kAnimBundleFar = 14 }; namespace Gob { namespace OnceUpon { Stork::Stork(GobEngine *vm, const ANIFile &ani) : ANIObject(ani), _shouldDrop(false) { _frame = new Surface(320, 200, 1); vm->_video->drawPackedSprite("cadre.cmp", *_frame); _bundle = new ANIObject(ani); _bundle->setVisible(false); _bundle->setPause(true); setState(kStateFlyNearWithBundle, kAnimFlyNearWithBundle, -80); } Stork::~Stork() { delete _frame; delete _bundle; } bool Stork::hasBundleLanded() const { if (!_shouldDrop || !_bundle->isVisible() || _bundle->isPaused()) return false; int16 x, y, width, height; _bundle->getFramePosition(x, y); _bundle->getFrameSize(width, height); return (y + height) >= _bundleDrop.landY; } void Stork::dropBundle(const BundleDrop &drop) { if (_shouldDrop) return; _shouldDrop = true; _bundleDrop = drop; } bool Stork::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { left = 0x7FFF; top = 0x7FFF; right = 0x0000; bottom = 0x0000; bool drawn = ANIObject::draw(dest, left, top, right, bottom); if (drawn) { // Left frame edge if (left <= 15) dest.blit(*_frame, left, top, MIN(15, right), bottom, left, top); // Right frame edge if (right >= 304) dest.blit(*_frame, MAX(304, left), top, right, bottom, MAX(304, left), top); } int16 bLeft, bTop, bRight, bBottom; if (_bundle->draw(dest, bLeft, bTop, bRight, bBottom)) { // Bottom frame edge if (bBottom >= 188) dest.blit(*_frame, bLeft, MAX(188, bTop), bRight, bBottom, bLeft, MAX(188, bTop)); left = MIN(left , bLeft ); top = MIN(top , bTop ); right = MAX(right , bRight ); bottom = MAX(bottom, bBottom); drawn = true; } return drawn; } bool Stork::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { left = 0x7FFF; top = 0x7FFF; right = 0x0000; bottom = 0x0000; bool cleared = _bundle->clear(dest, left, top, right, bottom); int16 sLeft, sTop, sRight, sBottom; if (ANIObject::clear(dest, sLeft, sTop, sRight, sBottom)) { left = MIN(left , sLeft ); top = MIN(top , sTop ); right = MAX(right , sRight ); bottom = MAX(bottom, sBottom); cleared = true; } return cleared; } void Stork::advance() { _bundle->advance(); ANIObject::advance(); int16 curX, curY, curWidth, curHeight; getFramePosition(curX, curY, 0); getFrameSize(curWidth, curHeight, 0); const int16 curRight = curX + curWidth - 1; int16 nextX, nextY, nextWidth, nextHeight; getFramePosition(nextX, nextY, 1); getFrameSize(nextWidth, nextHeight, 1); const int16 nextRight = nextX + nextWidth - 1; switch (_state) { case kStateFlyNearWithBundle: if (curX >= 330) setState(kStateFlyFarWithBundle, kAnimFlyFarWithBundle, 330); if ((curRight <= _bundleDrop.dropX) && (nextRight >= _bundleDrop.dropX) && _shouldDrop && !_bundleDrop.dropWhileFar) dropBundle(kStateFlyNearWithoutBundle, kAnimFlyNearWithoutBundle); break; case kStateFlyFarWithBundle: if (curX <= -80) setState(kStateFlyNearWithBundle, kAnimFlyNearWithBundle, -80); if ((curX >= _bundleDrop.dropX) && (nextX <= _bundleDrop.dropX) && _shouldDrop && _bundleDrop.dropWhileFar) dropBundle(kStateFlyFarWithoutBundle, kAnimFlyFarWithoutBundle); break; case kStateFlyNearWithoutBundle: if (curX >= 330) setState(kStateFlyFarWithoutBundle, kAnimFlyFarWithoutBundle, 330); break; case kStateFlyFarWithoutBundle: if (curX <= -80) setState(kStateFlyNearWithoutBundle, kAnimFlyNearWithoutBundle, -80); break; default: break; } } void Stork::dropBundle(State state, uint16 anim) { setState(state, anim); int16 x, y, width, height; getFramePosition(x, y); getFrameSize(width, height); _bundle->setAnimation(_bundleDrop.anim); _bundle->setPause(false); _bundle->setVisible(true); int16 bWidth, bHeight; _bundle->getFrameSize(bWidth, bHeight); // Drop position x = _bundleDrop.dropX; y = y + height - bHeight; // If the stork is flying near (from left to right), drop the bundle at the right edge if (!_bundleDrop.dropWhileFar) x = x - bWidth; _bundle->setPosition(x, y); } void Stork::setState(State state, uint16 anim) { setAnimation(anim); setVisible(true); setPause(false); _state = state; } void Stork::setState(State state, uint16 anim, int16 x) { setState(state, anim); setPosition(); int16 pX, pY; getPosition(pX, pY); setPosition( x, pY); } } // End of namespace OnceUpon } // End of namespace Gob