diff options
Diffstat (limited to 'engines/bbvs/minigames/bbant.cpp')
-rw-r--r-- | engines/bbvs/minigames/bbant.cpp | 1317 |
1 files changed, 1317 insertions, 0 deletions
diff --git a/engines/bbvs/minigames/bbant.cpp b/engines/bbvs/minigames/bbant.cpp new file mode 100644 index 0000000000..abecf22aff --- /dev/null +++ b/engines/bbvs/minigames/bbant.cpp @@ -0,0 +1,1317 @@ +/* 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 "bbvs/minigames/bbant.h" + +namespace Bbvs { + +static const BBPoint kPosIncrTbl1[] = { + {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, + { 0, 1}, { 1, 1}, { 1, 0}, { 1, -1} +}; + +static const BBPoint kPosIncrTbl2[] = { + {0, -2}, {-2, -2}, {-2, 0}, {-2, 2}, + { 0, 2}, { 2, 2}, { 2, 0}, { 2, -2} +}; + +static const int kScoreTbl[] = { + 0, 1, 1, 3, 2, 4 +}; + +static const char * const kSoundFilenames[] = { + "ant1.aif", "ant2.aif", "ant3.aif", "ant4.aif", "ant5.aif", + "ant6.aif", "ant7.aif", "ant8.aif", "ant9.aif", "ant10.aif", + "ant11.aif", "antmus1.aif", "fryant.aif", "stomp.aif", "bing.aif", + "bvyell.aif" +}; + +static const uint kSoundFilenamesCount = ARRAYSIZE(kSoundFilenames); + +static const uint kSoundTbl1[] = { + 2, 3, 4, 6 +}; + +static const uint kSoundTbl2[] = { + 5, 7, 11 +}; + +static const uint kSoundTbl3[] = { + 8, 10, 11 +}; + +static const uint kSoundTbl4[] = { + 2, 3, 4, 6, 8, 10, 11, 5, 7, 16 +}; + +void MinigameBbAnt::buildDrawList0(DrawList &drawList) { + + if (_titleScreenSpriteIndex) + drawList.add(_titleScreenSpriteIndex, 0, 0, 0); + + for (int i = 0; i < kMaxObjectsCount; ++i) { + Obj *obj = &_objects[i]; + if (obj->kind) + drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, obj->priority); + } + +} + +void MinigameBbAnt::buildDrawList1(DrawList &drawList) { + + if (_backgroundSpriteIndex) + drawList.add(_backgroundSpriteIndex, _stompX, _stompY, 0); + + for (int i = 1; i < kMaxObjectsCount; ++i) { + Obj *obj = &_objects[i]; + if (obj->kind) { + drawList.add(obj->anim->frameIndices[obj->frameIndex], + _stompX + (obj->x >> 16), _stompY + (obj->y >> 16), + obj->priority); + } + } + + drawList.add(getAnimation(164)->frameIndices[0], 5, 2, 2000); + drawNumber(drawList, _score, 68, 16); + drawList.add(getAnimation(166)->frameIndices[0], 230, 2, 2000); + drawNumber(drawList, _levelTimeLeft, 280, 16); + + for (int i = 0; i < _stompCount; ++i) + drawList.add(getAnimation(130)->frameIndices[0], 20 + i * 30, 230, 2000); + +} + +void MinigameBbAnt::buildDrawList2(DrawList &drawList) { + buildDrawList1(drawList); + drawList.add(getAnimation(168)->frameIndices[0], 40, 100, 2000); + drawNumber(drawList, _counter1, 190, 112); + drawNumber(drawList, _countdown5, 258, 112); + drawList.add(getAnimation(169)->frameIndices[0], 120, 120, 2000); + drawNumber(drawList, _counter4, 192, 132); +} + +void MinigameBbAnt::buildDrawList3(DrawList &drawList) { + buildDrawList1(drawList); + drawList.add(getAnimation(163)->frameIndices[0], 120, 70, 2000); + drawList.add(getAnimation(165)->frameIndices[0], 95, 95, 2000); + drawNumber(drawList, _hiScore, 208, 107); +} + +void MinigameBbAnt::drawMagnifyingGlass(DrawList &drawList) { + scale2x(_objects[0].x - 28, _objects[0].y - 27); + drawList.clear(); + drawList.add(_objects[0].anim->frameIndices[0], _objects[0].x, _objects[0].y, _objects[0].priority); + drawList.add(_objects[0].anim->frameIndices[1], _objects[0].x, _objects[0].y, _objects[0].priority); + drawList.add(_objects[0].anim->frameIndices[2], _objects[0].x, _objects[0].y, _objects[0].priority); +} + +void MinigameBbAnt::drawSprites() { + switch (_gameState) { + case 0: + drawSprites0(); + break; + case 1: + drawSprites1(); + break; + case 2: + drawSprites2(); + break; + case 3: + drawSprites3(); + break; + } +} + +void MinigameBbAnt::drawSprites0() { + DrawList drawList; + buildDrawList0(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + _vm->_screen->copyToScreen(); +} + +void MinigameBbAnt::drawSprites1() { + DrawList drawList; + buildDrawList1(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + drawMagnifyingGlass(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + _vm->_screen->copyToScreen(); +} + +void MinigameBbAnt::drawSprites2() { + DrawList drawList; + buildDrawList2(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + drawMagnifyingGlass(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + _vm->_screen->copyToScreen(); +} + +void MinigameBbAnt::drawSprites3() { + DrawList drawList; + buildDrawList3(drawList); + _vm->_screen->drawDrawList(drawList, _spriteModule); + _vm->_screen->copyToScreen(); +} + +MinigameBbAnt::Obj *MinigameBbAnt::getFreeObject() { + for (int i = 12; i < kMaxObjectsCount; ++i) + if (_objects[i].kind == 0) + return &_objects[i]; + return 0; +} + +void MinigameBbAnt::initObjects() { + switch (_gameState) { + case 0: + initObjects0(); + break; + case 1: + initObjects1(); + break; + case 2: + case 3: + // Nothing + break; + } +} + +void MinigameBbAnt::initObjects0() { + _objects[0].anim = getAnimation(172); + _objects[0].frameIndex = 0; + _objects[0].ticks = getAnimation(172)->frameTicks[0]; + _objects[0].x = 160; + _objects[0].y = 120; + _objects[0].priority = 2000; + _objects[0].kind = 1; + _objects[1].anim = getAnimation(170); + _objects[1].frameIndex = 0; + _objects[1].ticks = getAnimation(170)->frameTicks[0]; + _objects[1].x = 40; + _objects[1].y = 240; + _objects[1].priority = 100; + _objects[1].kind = 2; + _objects[2].anim = getAnimation(171); + _objects[2].frameIndex = 0; + _objects[2].ticks = getAnimation(171)->frameTicks[0]; + _objects[2].x = 280; + _objects[2].y = 240; + _objects[2].priority = 100; + _objects[2].kind = 2; +} + +void MinigameBbAnt::initObjects1() { + _objects[0].kind = 0; + _objects[0].x = 160; + _objects[0].y = 120; + _objects[0].xIncr = 0; + _objects[0].yIncr = 0; + _objects[0].anim = getAnimation(159); + _objects[0].frameIndex = 0; + _objects[0].ticks = _objects[0].anim->frameTicks[0]; + _objects[0].priority = 1000; + _objects[1].kind = 8; + _objects[1].x = 0x1E0000; + _objects[1].y = 0x280000; + _objects[1].xIncr = 0; + _objects[1].yIncr = 0; + _objects[1].anim = getAnimation(160); + _objects[1].frameIndex = 0; + _objects[1].ticks = _objects[0].anim->frameTicks[0]; + _objects[1].priority = 900; + _objects[1].smokeCtr = 0; + _objects[1].hasSmoke = false; + _objects[1].status = 0; + _objects[2].kind = 8; + _objects[2].x = 0x280000; + _objects[2].y = 0x4B0000; + _objects[2].xIncr = 0; + _objects[2].yIncr = 0; + _objects[2].anim = getAnimation(161); + _objects[2].frameIndex = 0; + _objects[2].ticks = _objects[0].anim->frameTicks[0]; + _objects[2].priority = 900; + _objects[2].smokeCtr = 0; + _objects[2].hasSmoke = false; + _objects[2].status = 0; + for (int i = 3; i < 12; ++i) { + const ObjInit *objInit = getObjInit(i - 3); + _objects[i].kind = 6; + _objects[i].x = objInit->x << 16; + _objects[i].y = objInit->y << 16; + _objects[i].xIncr = 0; + _objects[i].yIncr = 0; + _objects[i].anim = objInit->anim1; + _objects[i].frameIndex = 0; + _objects[i].ticks = _objects[0].anim->frameTicks[0]; + _objects[i].priority = 600; + _objects[i].status = 9; + _objects[i].damageCtr = 0; + + } +} + +void MinigameBbAnt::initVars() { + switch (_gameState) { + case 0: + // Nothing + break; + case 1: + initVars1(); + break; + case 2: + initVars2(); + break; + case 3: + initVars3(); + break; + } +} + +void MinigameBbAnt::initVars1() { + _stompX = 0; + _stompY = 0; + _stompDelay1 = 0; + _stompCount = 1; + _stompCounter1 = 80; + _stompCounter2 = 80; + _totalBugsCount = 0; + _hasLastStompObj = false; + _counter1 = 9; + _countdown10 = 140; + _score = 0; + _counter4 = 1; + _gameTicks = 0; + _skullBugCtr = 500; + _levelTimeDelay = 58; + _levelTimeLeft = 30; + _bugsChanceByKind[0] = 0; + _bugsChanceByKind[1] = 20; + _bugsChanceByKind[2] = 20; + _bugsChanceByKind[3] = 5; + _bugsChanceByKind[4] = 7; + _bugsCountByKind[0] = 0; + _bugsCountByKind[1] = 0; + _bugsCountByKind[2] = 0; + _bugsCountByKind[3] = 0; + _bugsCountByKind[4] = 0; + _bugsCountByKind[5] = 0; +} + +void MinigameBbAnt::initVars2() { + _countdown4 = 0; + _countdown3 = 0; + _levelTimeDelay = 58; + _countdown6 = 60; + _countdown5 = 50 * _counter1; +} + +void MinigameBbAnt::initVars3() { + if (_score > _hiScore) + _hiScore = _score; + playSound(9); +} + +bool MinigameBbAnt::updateStatus(int mouseX, int mouseY, uint mouseButtons) { + switch (_gameState) { + case 0: + return updateStatus0(mouseX, mouseY, mouseButtons); + case 1: + return updateStatus1(mouseX, mouseY, mouseButtons); + case 2: + return updateStatus2(mouseX, mouseY, mouseButtons); + case 3: + return updateStatus3(mouseX, mouseY, mouseButtons); + } + return false; +} + +bool MinigameBbAnt::updateStatus0(int mouseX, int mouseY, uint mouseButtons) { + + _objects[0].x = mouseX; + _objects[0].y = mouseY; + + if (_objects[0].x >= 320) + _objects[0].x = 320 - 1; + if (_objects[0].y >= 240) + _objects[0].y = 240 - 1; + if (_objects[0].x < 0) + _objects[0].x = 0; + if (_objects[0].y < 0) + _objects[0].y = 0; + + if ((mouseButtons & kLeftButtonDown) || (mouseButtons & kRightButtonDown)) { + _gameState = 1; + initObjects(); + initVars(); + _gameTicks = 0; + playSound(1); + } else { + for (int i = 0; i < kMaxObjectsCount; ++i) { + Obj *obj = &_objects[i]; + if (obj->kind == 2) { + if (--obj->ticks == 0) { + ++obj->frameIndex; + if (obj->frameIndex >= obj->anim->frameCount) + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + } + } + } + } + + return true; +} + +bool MinigameBbAnt::updateStatus1(int mouseX, int mouseY, uint mouseButtons) { + const int kMaxBugsCount = 52; + + --_levelTimeDelay; + if (!_levelTimeDelay) { + _levelTimeDelay = 58; + --_levelTimeLeft; + } + + _objects[0].x = mouseX; + _objects[0].y = mouseY; + + if (_objects[0].x >= 320) + _objects[0].x = 320 - 1; + if (_objects[0].y >= 240) + _objects[0].y = 240 - 1; + if (_objects[0].x < 0) + _objects[0].x = 0; + if (_objects[0].y < 0) + _objects[0].y = 0; + + if (!_levelTimeLeft) { + _gameState = 2; + initVars(); + initObjects(); + _gameTicks = 0; + return true; + } + + if (_counter1 == 0) { + _gameState = 3; + initVars(); + initObjects(); + _gameTicks = 0; + return true; + } + + if ((mouseButtons & kRightButtonClicked) && (_stompCount > 0|| _hasLastStompObj) && !_objects[2].status) { + if (_hasLastStompObj) + removeStompObj(_lastStompObj); + --_stompCount; + _objects[2].status = 1; + } + + if ((mouseButtons & kLeftButtonClicked) && _objects[2].status == 0 && isMagGlassAtBeavisLeg(2)) { + if (_vm->getRandom(10) == 1 && !isAnySoundPlaying(kSoundTbl4, 10)) + playSound(16); + insertSmokeObj(_objects[0].x << 16, _objects[0].y << 16); + } + + if (_skullBugCtr > 0) { + if (--_skullBugCtr == 0) { + _skullBugCtr = _vm->getRandom(150) + 500; + insertRandomBugObj(5); + } + } + + if (_stompCounter2 > 0) + --_stompCounter2; + + if (_totalBugsCount < kMaxBugsCount && _vm->getRandom(_stompCounter2) == 0) { + int testTbl[4]; + int maxKindCount = 0, objKind = 0; + + _stompCounter2 = _stompCounter1; + + for (int i = 0; i < 4; ++i) + testTbl[i] = _vm->getRandom(_bugsChanceByKind[i] - _bugsCountByKind[i]); + + for (int i = 0; i < 4; ++i) { + if (testTbl[i] >= maxKindCount) { + maxKindCount = testTbl[i]; + objKind = i + 1; + } + } + + if (objKind) + insertRandomBugObj(objKind); + + } + + updateObjs(mouseButtons); + updateFootObj(2); + + if (--_countdown10 == 0) { + _countdown10 = 140; + if (_stompCounter1 > 20) + --_stompCounter1; + } + + return true; +} + +bool MinigameBbAnt::updateStatus2(int mouseX, int mouseY, uint mouseButtons) { + + _objects[0].x = mouseX; + _objects[0].y = mouseY; + + if (_objects[0].x >= 320) + _objects[0].x = 320 - 1; + if (_objects[0].y >= 240) + _objects[0].y = 240 - 1; + if (_objects[0].x < 0) + _objects[0].x = 0; + if (_objects[0].y < 0) + _objects[0].y = 0; + + if (_countdown6 > 0) { + if (--_countdown6 == 0) { + _countdown4 = 150; + playSound(15, true); + } + } else if (_countdown4 > 0) { + if (--_countdown4 == 0) { + _countdown3 = 150; + } else if (_countdown5 > 0) { + ++_countdown4; + ++_score; + if (--_countdown5 == 0) { + stopSound(15); + _bugsChanceByKind[5] = 10; + _countdown7 = 40; + _countdown4 = 10 * (13 - _counter1); + return true; + } + } else { + if (--_countdown7 == 0) { + bool flag1 = false; + _countdown7 = _bugsChanceByKind[5]; + for (int i = 3; i < 12 && !flag1; ++i) { + Obj *obj = &_objects[i]; + if (obj->status == 13) { + const ObjInit *objInit = getObjInit(i - 3); + obj->x = objInit->x << 16; + obj->y = objInit->y << 16; + obj->anim = objInit->anim3; + obj->frameIndex = 0; + obj->ticks = _objects[0].anim->frameTicks[0]; + obj->status = 9; + obj->damageCtr = 0; + obj->priority = 600; + ++_counter1; + playSound(15); + flag1 = true; + } + } + } + } + } else if (_countdown3 > 0) { + if ((mouseButtons & kLeftButtonDown) || (mouseButtons & kRightButtonDown) || (--_countdown3 == 0)) { + _levelTimeDelay = 58; + _levelTimeLeft = 30; + _gameState = 1; + _gameTicks = 0; + ++_counter4; + } + } + + return true; +} + +bool MinigameBbAnt::updateStatus3(int mouseX, int mouseY, uint mouseButtons) { + if (!isSoundPlaying(9) && _fromMainGame) { + _vm->_system->delayMillis(1000); + _gameDone = true; + } + return true; +} + +void MinigameBbAnt::getRandomBugObjValues(int &x, int &y, int &animIndexIncr, int &field30) { + field30 = _vm->getRandom(4); + switch (field30) { + case 0: + y = -5; + x = _vm->getRandom(190) + 120; + animIndexIncr = 4; + break; + case 1: + x = 325; + y = _vm->getRandom(220) + 10; + animIndexIncr = 2; + break; + case 2: + y = 245; + x = _vm->getRandom(300) + 10; + animIndexIncr = 0; + break; + case 3: + x = -5; + y = _vm->getRandom(190) + 120; + animIndexIncr = 6; + break; + } +} + +void MinigameBbAnt::insertBugSmokeObj(int x, int y, int bugObjIndex) { + Obj *obj = getFreeObject(); + if (obj) { + Obj *bugObj = &_objects[bugObjIndex]; + bugObj->hasSmoke = true; + obj->kind = 7; + obj->x = x; + obj->y = y; + obj->priority = 950; + if (bugObj->status >= 4 && (bugObj->status <= 6 || bugObj->status == 8)) { + obj->xIncr = 0; + obj->yIncr = (-1 << 16); + } else { + obj->xIncr = bugObj->xIncr / 8; + obj->yIncr = bugObj->yIncr / 8; + } + obj->anim = getAnimation(158); + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + } +} + +void MinigameBbAnt::insertSmokeObj(int x, int y) { + Obj *obj = getFreeObject(); + if (obj) { + obj->kind = 7; + obj->x = x; + obj->y = y; + obj->priority = 950; + obj->xIncr = 0x2000; + obj->yIncr = -0xC000; + obj->anim = getAnimation(158); + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + } +} + +void MinigameBbAnt::resetObj(int objIndex) { + _objects[objIndex].kind = 0; +} + +void MinigameBbAnt::insertStompObj(int x, int y) { + Obj *obj = getFreeObject(); + if (obj) { + obj->kind = 9; + obj->x = x; + obj->y = y; + obj->priority = 2000; + obj->xIncr = (0x1E0000 * _stompCount - x + 0x140000) / 15; + obj->yIncr = (0xE60000 - y) / 15; + obj->anim = getAnimation(130); + obj->frameIndex = 0; + obj->ticks = 15; + _lastStompObj = obj; + _hasLastStompObj = true; + } +} + +void MinigameBbAnt::removeStompObj(Obj *obj) { + ++_stompCount; + _hasLastStompObj = false; + obj->kind = 0; +} + +void MinigameBbAnt::insertBugObj(int kind, int animIndexIncr, int always0, int x, int y, int field30, int always1) { + Obj *obj = getFreeObject(); + if (obj) { + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(kind); + obj->field30 = field30; + obj->animIndexIncr = animIndexIncr; + obj->kind = kind; + obj->x = x << 16; + obj->y = y << 16; + obj->priority = 610; + obj->xIncr = kPosIncrTbl1[0].x << 16; + obj->yIncr = kPosIncrTbl1[0].y << 16; + obj->anim = objKindAnimTable[0]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + obj->animIndex = 0; + obj->status = 1; + obj->damageCtr = 0; + obj->hasSmoke = false; + obj->flag = 0; + ++_bugsCountByKind[kind]; + ++_totalBugsCount; + } +} + +void MinigameBbAnt::removeBugObj(int objIndex) { + Obj *obj = &_objects[objIndex]; + --_totalBugsCount; + --_bugsCountByKind[obj->kind]; + obj->hasSmoke = false; + obj->kind = 0; +} + +void MinigameBbAnt::updateBugObjAnim(int objIndex) { + Obj *obj = &_objects[objIndex]; + + switch (obj->field30) { + case 0: + obj->animIndexIncr = 4; + break; + case 1: + obj->animIndexIncr = 2; + break; + case 2: + obj->animIndexIncr = 0; + break; + case 3: + obj->animIndexIncr = 6; + break; + } + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->xIncr = kPosIncrTbl1[obj->animIndexIncr].x << 16; + obj->yIncr = kPosIncrTbl1[obj->animIndexIncr].y << 16; + obj->anim = objKindAnimTable[obj->animIndexIncr]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; +} + +void MinigameBbAnt::updateObjAnim2(int objIndex) { + Obj *obj = &_objects[objIndex]; + + obj->animIndexIncr += _vm->getRandom(3) - 1; + if (obj->animIndexIncr < 0) + obj->animIndexIncr = 7; + if (obj->animIndexIncr > 7) + obj->animIndexIncr = 0; + obj->animIndexIncr += 4; + if (obj->animIndexIncr >= 8) + obj->animIndexIncr %= 8; + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->xIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].x << 16; + obj->yIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].y << 16; + obj->anim = objKindAnimTable[obj->animIndex + obj->animIndexIncr]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + obj->x += obj->xIncr; + obj->y += obj->yIncr; +} + +void MinigameBbAnt::insertRandomBugObj(int kind) { + int x, y, animIndexIncr, field30; + getRandomBugObjValues(x, y, animIndexIncr, field30); + insertBugObj(kind, animIndexIncr, 0, x, y, field30, 1); +} + +bool MinigameBbAnt::isBugOutOfScreen(int objIndex) { + Obj *obj = &_objects[objIndex]; + + return + obj->x < (-10 << 16) || obj->x > (330 << 16) || + obj->y < (-10 << 16) || obj->y > (250 << 16); +} + +void MinigameBbAnt::updateObjAnim3(int objIndex) { + Obj *obj = &_objects[objIndex]; + + obj->animIndexIncr += _vm->getRandom(3) - 1; + if (obj->animIndexIncr < 0) + obj->animIndexIncr = 7; + if (obj->animIndexIncr > 7) + obj->animIndexIncr = 0; + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->xIncr = kPosIncrTbl1[obj->animIndexIncr].x << 16; + obj->yIncr = kPosIncrTbl1[obj->animIndexIncr].y << 16; + obj->anim = objKindAnimTable[obj->animIndexIncr]; +} + +void MinigameBbAnt::updateBugObj1(int objIndex) { + Obj *obj = &_objects[objIndex]; + bool flag1 = false; + bool flag2 = false; + + if (--obj->ticks == 0) { + ++obj->frameIndex; + if (obj->anim->frameCount == obj->frameIndex) { + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + flag1 = true; + } else { + obj->ticks = obj->anim->frameTicks[obj->frameIndex]; + flag2 = true; + } + } + + obj->x += obj->xIncr; + obj->y += obj->yIncr; + + if (obj->status != 7) { + if (obj->damageCtr <= 5) { + obj->hasSmoke = false; + } else if (!obj->hasSmoke) { + obj->smokeCtr = 6; + insertBugSmokeObj(obj->x, obj->y, objIndex); + } else if (obj->damageCtr > 200 && obj->status != 4 && obj->status != 6) { + _score += kScoreTbl[obj->kind]; + if (obj->status == 3) { + _objects[obj->otherObjIndex].status = 9; + _objects[obj->otherObjIndex].priority = 600; + if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10)) + playSound(kSoundTbl3[_vm->getRandom(3)]); + } else { + if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10)) + playSound(kSoundTbl2[_vm->getRandom(3)]); + } + flag1 = false; + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->hasSmoke = false; + obj->status = 4; + obj->xIncr = 0; + obj->yIncr = 0; + obj->anim = objKindAnimTable[16]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + obj->priority = 605; + if (obj->kind == 5) { + // Skull Beetle + if (_stompCount < 10) + insertStompObj(obj->x, obj->y); + obj->kind = 4; + obj->anim = getObjAnim(70); + obj->ticks = obj->anim->frameTicks[0]; + } + } else if (--obj->smokeCtr == 0) { + obj->smokeCtr = 6; + insertBugSmokeObj(obj->x, obj->y, objIndex); + } + } + + switch (obj->status) { + + case 1: + if (isBugOutOfScreen(objIndex)) + removeBugObj(objIndex); + else if (flag1 && !obj->flag) + updateObjAnim3(objIndex); + break; + + case 3: + // Bug carries candy + _objects[obj->otherObjIndex].x = obj->x; + _objects[obj->otherObjIndex].y = obj->y; + if (isBugOutOfScreen(objIndex)) { + _objects[obj->otherObjIndex].status = 13; + _objects[obj->otherObjIndex].x = (500 << 16); + _objects[obj->otherObjIndex].y = (500 << 16); + removeBugObj(objIndex); + --_counter1; + } + break; + + case 4: + if (flag1) { + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->status = 6; + obj->xIncr = 0; + obj->yIncr = 0; + obj->anim = objKindAnimTable[17]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + } + break; + + case 6: + if (flag1) { + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind); + obj->status = 7; + obj->xIncr = kPosIncrTbl2[obj->animIndexIncr].x << 16; + obj->yIncr = kPosIncrTbl2[obj->animIndexIncr].y << 16; + obj->anim = objKindAnimTable[obj->animIndexIncr + 8]; + obj->frameIndex = 0; + obj->ticks = obj->anim->frameTicks[0]; + obj->animIndex = 8; + obj->priority = 610; + } + break; + + case 7: + if (isBugOutOfScreen(objIndex)) + removeBugObj(objIndex); + break; + + case 8: + if (--obj->counter != 0) { + if (flag2 && obj->frameIndex == 13) { + obj->frameIndex = 4; + obj->ticks = obj->anim->frameTicks[4]; + } + } else { + obj->status = obj->status2; + obj->anim = obj->anim2; + obj->frameIndex = obj->frameIndex2; + obj->ticks = obj->ticks2; + obj->xIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].x << 16; + obj->yIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].y << 16; + obj->priority = 610; + } + break; + + } + +} + +void MinigameBbAnt::updateObjKind2(int objIndex) { + updateBugObj1(objIndex); +} + +void MinigameBbAnt::updateObjKind3(int objIndex) { + updateBugObj1(objIndex); +} + +void MinigameBbAnt::updateObjKind4(int objIndex) { + updateBugObj1(objIndex); +} + +void MinigameBbAnt::updateObjKind5(int objIndex) { + ++_skullBugCtr; + updateBugObj1(objIndex); +} + +void MinigameBbAnt::updateStompObj(int objIndex) { + Obj *obj = &_objects[objIndex]; + + obj->x += obj->xIncr; + obj->y += obj->yIncr; + if (--obj->ticks == 0) + removeStompObj(obj); +} + +void MinigameBbAnt::updateSmokeObj(int objIndex) { + Obj *obj = &_objects[objIndex]; + + obj->x += obj->xIncr; + obj->y += obj->yIncr; + + if (--obj->ticks == 0) { + ++obj->frameIndex; + if (obj->anim->frameCount == obj->frameIndex) + resetObj(objIndex); + else + obj->ticks = obj->anim->frameTicks[obj->frameIndex]; + } +} + +void MinigameBbAnt::updateFootObj(int objIndex) { + Obj *obj = &_objects[objIndex]; + + switch (obj->status) { + + case 1: + obj->xIncr = -0x8000; + obj->yIncr = (-4 << 16); + obj->status = 2; + _stompCounter1 += 5; + _stompCounter2 = 100; + break; + + case 2: + obj->x += obj->xIncr; + obj->y += obj->yIncr; + obj->yIncr += 0x2000; + if (obj->y < (20 << 16)) { + obj->xIncr = 0x8000; + obj->yIncr = (7 << 16); + obj->status = 3; + } + break; + + case 3: + obj->x += obj->xIncr; + obj->y += obj->yIncr; + obj->yIncr += 0x2000; + if (obj->y >= 0x4B0000) { + obj->x = (40 << 16); + obj->y = (75 << 16); + obj->status = 4; + _stompDelay1 = 6; + _stompY = 0; + playSound(14); + } + break; + + case 4: + if (--_stompDelay1 == 0) { + _gameTicks = 0; + if (_stompDelay1 % 2) + _stompY = _stompY < 1 ? -8 : 0; + } else { + obj->status = 0; + _stompX = 0; + _stompY = 0; + // Stun all bugs + for (int i = 12; i < kMaxObjectsCount; ++i) { + Obj *bugObj = &_objects[i]; + if (bugObj->kind >= 1 && bugObj->kind <= 5) { + bugObj->counter = _vm->getRandom(200) + 360; + const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(bugObj->kind); + if (bugObj->status == 8) { + bugObj->hasSmoke = false; + bugObj->xIncr = 0; + bugObj->yIncr = 0; + bugObj->status2 = 7; + bugObj->anim2 = objKindAnimTable[bugObj->animIndexIncr + 8]; + bugObj->frameIndex2 = 0; + bugObj->ticks2 = obj->anim->frameTicks[0]; + bugObj->anim = objKindAnimTable[17]; + bugObj->frameIndex = 0; + bugObj->ticks = _vm->getRandom(4) + obj->anim->frameTicks[0]; + bugObj->animIndex = 8; + } else { + if (bugObj->status == 3) { + bugObj->priority = 610; + _objects[bugObj->otherObjIndex].status = 9; + _objects[bugObj->otherObjIndex].priority = 600; + } + bugObj->hasSmoke = false; + bugObj->xIncr = 0; + bugObj->yIncr = 0; + bugObj->status2 = 1; + bugObj->anim2 = bugObj->anim; + bugObj->frameIndex2 = bugObj->frameIndex; + bugObj->ticks2 = bugObj->ticks; + bugObj->anim = objKindAnimTable[17]; + bugObj->frameIndex = 0; + bugObj->ticks = _vm->getRandom(4) + obj->anim->frameTicks[0]; + } + bugObj->status = 8; + bugObj->priority = 605; + } + } + } + break; + + } + +} + +bool MinigameBbAnt::isBugAtCandy(int objIndex, int &candyObjIndex) { + Obj *obj = &_objects[objIndex]; + bool result = false; + + if (obj->kind >= 1 && obj->kind <= 4) { + const BBRect &frameRect1 = obj->anim->frameRects[obj->frameIndex]; + const int obj1X1 = frameRect1.x + (obj->x >> 16); + const int obj1Y1 = frameRect1.y + (obj->y >> 16); + const int obj1X2 = obj1X1 + frameRect1.width; + const int obj1Y2 = obj1Y1 + frameRect1.height; + for (int i = 3; i < 12 && !result; ++i) { + Obj *obj2 = &_objects[i]; + const BBRect &frameRect2 = obj->anim->frameRects[obj2->frameIndex]; // sic + const int obj2X1 = (obj2->x >> 16) + frameRect2.x; + const int obj2Y1 = (obj2->y >> 16) + frameRect2.y; + const int obj2X2 = obj2X1 + frameRect2.width; + const int obj2Y2 = obj2Y1 + frameRect2.height; + if (obj2->status == 9 && obj1X1 <= obj2X2 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1) { + result = true; + candyObjIndex = i; + } + } + } + return result; +} + +bool MinigameBbAnt::isMagGlassAtBug(int objIndex) { + Obj *obj = &_objects[objIndex]; + Obj *obj0 = &_objects[0]; + bool result = false; + + if (obj->kind >= 1 && obj->kind <= 5) { + const BBRect &frameRect1 = obj0->anim->frameRects[0]; + const int obj1X1 = obj0->x + frameRect1.x; + const int obj1Y1 = obj0->y + frameRect1.y; + const int obj1X2 = obj1X1 + frameRect1.width; + const int obj1Y2 = obj1Y1 + frameRect1.height; + const BBRect &frameRect2 = obj->anim->frameRects[obj->frameIndex]; + const int obj2X1 = (obj->x >> 16) + frameRect2.x; + const int obj2Y1 = (obj->y >> 16) + frameRect2.y; + const int obj2X2 = obj2X1 + frameRect2.width; + const int obj2Y2 = obj2Y1 + frameRect2.height; + if (obj2X2 >= obj1X1 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1) + result = true; + } + return result; +} + +bool MinigameBbAnt::isMagGlassAtBeavisLeg(int objIndex) { + Obj *obj = &_objects[objIndex]; + Obj *magGlassObj = &_objects[0]; + bool result = false; + + const BBRect &frameRect1 = magGlassObj->anim->frameRects[0]; + const int obj1X1 = magGlassObj->x + frameRect1.x; + const int obj1Y1 = magGlassObj->y + frameRect1.y; + const int obj1X2 = obj1X1 + frameRect1.width; + const int obj1Y2 = obj1Y1 + frameRect1.height; + const BBRect &frameRect2 = obj->anim->frameRects[obj->frameIndex]; + const int obj2X1 = (obj->x >> 16) + frameRect2.x; + const int obj2Y1 = (obj->y >> 16) + frameRect2.y; + const int obj2X2 = obj2X1 + frameRect2.width; + const int obj2Y2 = obj2Y1 + frameRect2.height; + if (obj2X2 >= obj1X1 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1) + result = true; + return result; +} + +bool MinigameBbAnt::testObj5(int objIndex) { + Obj *obj = &_objects[objIndex]; + bool result = false; + if (obj->kind >= 1 && obj->kind <= 5) { + const int x = obj->x >> 16; + const int y = obj->y >> 16; + if (x < 0 || x >= 110 || y < 0 || y >= 110) { + obj->flag = 0; + } else if (!obj->flag) { + obj->flag = 1; + result = true; + } + } + return result; +} + +void MinigameBbAnt::updateObjs(uint mouseButtons) { + + for (int i = 12; i < kMaxObjectsCount; ++i) { + Obj *obj = &_objects[i]; + + if (obj->kind) { + + if ((mouseButtons & kLeftButtonClicked) && isMagGlassAtBug(i)) + obj->damageCtr += 100; + + if (obj->status == 1) { + int candyObjIndex; + if (isBugAtCandy(i, candyObjIndex)) { + obj->status = 3; + obj->otherObjIndex = candyObjIndex; + _objects[candyObjIndex].otherObjIndex = i; + _objects[candyObjIndex].status = 10; + _objects[candyObjIndex].priority = 620; + _objects[candyObjIndex].status = 11; + _objects[candyObjIndex].anim = getObjInit(candyObjIndex - 3)->anim3; + updateBugObjAnim(i); + if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10)) + playSound(kSoundTbl1[_vm->getRandom(4)]); + } + } + + if (testObj5(i)) { + updateObjAnim2(i); + } + + if (obj->damageCtr) { + --obj->damageCtr; + if (!isSoundPlaying(13)) + playSound(13); + } + + switch (obj->kind) { + case 1: + updateBugObj1(i); + break; + case 2: + updateObjKind2(i); + break; + case 3: + updateObjKind3(i); + break; + case 4: + updateObjKind4(i); + break; + case 5: + updateObjKind5(i); + break; + case 7: + updateSmokeObj(i); + break; + case 9: + updateStompObj(i); + break; + } + + } + + } + +} + +int MinigameBbAnt::run(bool fromMainGame) { + + memset(_objects, 0, sizeof(_objects)); + + _numbersAnim = getAnimation(167); + + _backgroundSpriteIndex = 303; + _titleScreenSpriteIndex = 304; + + _fromMainGame = fromMainGame; + + _hiScore = 0; + if (!_fromMainGame) + _hiScore = loadHiscore(kMinigameBbAnt); + + _gameState = 0; + _gameResult = 0; + _gameDone = false; + initObjects(); + initVars(); + + _spriteModule = new SpriteModule(); + _spriteModule->load("bbant/bbant.000"); + + Palette palette = _spriteModule->getPalette(); + _vm->_screen->setPalette(palette); + + loadSounds(); + + _gameTicks = 0; + playSound(12, true); + + while (!_vm->shouldQuit() &&!_gameDone) { + _vm->updateEvents(); + update(); + } + + _vm->_sound->unloadSounds(); + + if (!_fromMainGame) + saveHiscore(kMinigameBbAnt, _hiScore); + + delete _spriteModule; + + return _gameResult; +} + +void MinigameBbAnt::update() { + + int currTicks, inputTicks; + + if (_gameTicks > 0) { + currTicks = _vm->_system->getMillis(); + inputTicks = 3 * (currTicks - _gameTicks) / 50; + _gameTicks = currTicks - (currTicks - _gameTicks - 50 * inputTicks / 3); + } else { + inputTicks = 1; + _gameTicks = _vm->_system->getMillis(); + } + + if (_vm->_keyCode == Common::KEYCODE_ESCAPE) { + _gameDone = true; + return; + } + + if (inputTicks == 0) + return; + + bool done; + + do { + done = !updateStatus(_vm->_mouseX, _vm->_mouseY, _vm->_mouseButtons); + _vm->_mouseButtons &= ~kLeftButtonClicked; + _vm->_mouseButtons &= ~kRightButtonClicked; + _vm->_keyCode = Common::KEYCODE_INVALID; + } while (--inputTicks && _gameTicks > 0 && !done); + + drawSprites(); + + _vm->_system->delayMillis(10); + +} + +void MinigameBbAnt::scale2x(int x, int y) { + Graphics::Surface *surface = _vm->_screen->_surface; + + int srcX = x + 14, srcY = y + 14; + int srcW = kScaleDim, srcH = kScaleDim; + + if (srcX < 0) { + srcW += srcX; + srcX = 0; + } + + if (srcY < 0) { + srcH += srcY; + srcY = 0; + } + + if (srcX + srcW >= 320) + srcW = 320 - srcX - 1; + + if (srcY + srcH >= 240) + srcH = 240 - srcY - 1; + + for (int yc = 0; yc < srcH; ++yc) { + byte *src = (byte*)surface->getBasePtr(srcX, srcY + yc); + memcpy(&_scaleBuf[yc * kScaleDim], src, srcW); + } + + int dstX = x, dstY = y; + int dstW = 2 * kScaleDim, dstH = 2 * kScaleDim; + + if (dstX < 0) { + dstW += dstX; + dstX = 0; + } + + if (dstY < 0) { + dstH += dstY; + dstY = 0; + } + + if (dstX + dstW >= 320) + dstW = 320 - dstX - 1; + + if (dstY + dstH >= 240) + dstH = 240 - dstY - 1; + + int w = MIN(srcW * 2, dstW), h = MIN(srcH * 2, dstH); + + for (int yc = 0; yc < h; ++yc) { + byte *src = _scaleBuf + kScaleDim * (yc / 2); + byte *dst = (byte*)surface->getBasePtr(dstX, dstY + yc); + for (int xc = 0; xc < w; ++xc) + dst[xc] = src[xc / 2]; + } + +} + +void MinigameBbAnt::loadSounds() { + for (uint i = 0; i < kSoundFilenamesCount; ++i) { + Common::String filename = Common::String::format("bbant/%s", kSoundFilenames[i]); + _vm->_sound->loadSound(filename.c_str()); + } +} + +} // End of namespace Bbvs |