#include #include "Enemy.h" #include "Gameplay.h" #include "constant.h" extern RLE_SPRITE *enemy[4]; extern bool blitEnemies; extern BITMAP *vramEnemy[4]; extern BITMAP *tileImage; extern void drawPupils(BITMAP *canvas, int x, int y, direction headed); extern void go(int *x, int *y, int step, int xMax, int yMax, direction way); int Enemy::getX() { return x; } int Enemy::getY() { return y; } enemyId Enemy::getId() { return id; } void Enemy::move() { const bool alignedToGrid = x % tileSize == 0 && y % tileSize == 0; const tile above = game->getLevelPointer()->getTile(x / tileSize, y / tileSize + boardH - 1); const tile toTheLeft = game->getLevelPointer()->getTile(x / tileSize + boardW - 1, y / tileSize); const tile toTheRight = game->getLevelPointer()->getTile(x / tileSize + 1, y / tileSize); const tile below = game->getLevelPointer()->getTile(x / tileSize, y / tileSize + 1); const int manX = game->getPlayerPointer()->getX(); const int manY = game->getPlayerPointer()->getY(); const int distanceUpToPacMan = y > manY ? y - manY : boardH * tileSize - (manY - y); const int distanceLeftToPacMan = x > manX ? x - manX : boardW * tileSize - (manX - x); const int distanceRightToPacMan = x < manX ? manX - x : boardW * tileSize - (x - manX); const int distanceDownToPacMan = y < manY ? manY - y : boardH * tileSize - (y - manY); bool think; bool gatesAreOkay; switch (cageStatus) { case insideCage: if (alignedToGrid && !game->energized() && rand() % 100 < 24 / (id + 1) && (above == gateTile || above == gateEnergyTile || toTheLeft == gateTile || toTheLeft == gateEnergyTile || toTheRight == gateTile || toTheRight == gateEnergyTile || below == gateTile || below == gateEnergyTile)) { think = true; gatesAreOkay = true; cageStatus = leavingRoute; } else { think = false; headed = game->getLevelPointer()->getEnemyDirection((((game->getCagePosition() + game->getLevelPointer()->getEnemyRouteSize() * tileSize * id / 4) % (game->getLevelPointer()->getEnemyRouteSize() * tileSize)) / enemyStep * enemyStep) / tileSize); } break; case leavingRoute: if (alignedToGrid) { think = true; gatesAreOkay = false; cageStatus = leavingGate; } else think = false; break; case leavingGate: if (alignedToGrid) { think = true; gatesAreOkay = false; cageStatus = outsideCage; } else think = false; break; case outsideCage: if (alignedToGrid) { think = true; gatesAreOkay = false; } else think = false; } if (think) { int upRating, leftRating, rightRating, downRating; if (distanceUpToPacMan < distanceDownToPacMan) { upRating = distanceUpToPacMan; downRating = distanceUpToPacMan * id / 100; } else if (distanceUpToPacMan == distanceDownToPacMan) upRating = downRating = distanceUpToPacMan * id / 100; else if (distanceUpToPacMan > distanceDownToPacMan) { upRating = distanceDownToPacMan * id / 100; downRating = distanceDownToPacMan; } if (distanceLeftToPacMan < distanceRightToPacMan) { leftRating = distanceLeftToPacMan; rightRating = distanceLeftToPacMan * id / 100; } else if (distanceLeftToPacMan == distanceRightToPacMan) leftRating = rightRating = distanceLeftToPacMan * id / 100; else if (distanceLeftToPacMan > distanceRightToPacMan) { leftRating = distanceRightToPacMan * id / 100; rightRating = distanceRightToPacMan; } if (upRating <= 0) upRating = 1; if (leftRating <= 0) leftRating = 1; if (rightRating <= 0) rightRating = 1; if (downRating <= 0) downRating = 1; if (game->energized()) { upRating ^= downRating; downRating ^= upRating; upRating ^= downRating; leftRating ^= rightRating; rightRating ^= leftRating; leftRating ^= rightRating; } if (above == wallTile || above == forbiddenTile || above == forbiddenEnergyTile || !gatesAreOkay && (above == gateTile || above == gateEnergyTile)) upRating = 0; if (toTheLeft == wallTile || toTheLeft == forbiddenTile || toTheLeft == forbiddenEnergyTile || !gatesAreOkay && (toTheLeft == gateTile || toTheLeft == gateEnergyTile)) leftRating = 0; if (toTheRight == wallTile || toTheRight == forbiddenTile || toTheRight == forbiddenEnergyTile || !gatesAreOkay && (toTheRight == gateTile || toTheRight == gateEnergyTile)) rightRating = 0; if (below == wallTile || below == forbiddenTile || below == forbiddenEnergyTile || !gatesAreOkay && (below == gateTile || below == gateEnergyTile)) downRating = 0; switch (headed) { case up: downRating = 0; break; case left: rightRating = 0; break; case right: leftRating = 0; break; case down: upRating = 0; } if (upRating == 0 && leftRating == 0 && rightRating == 0 && downRating == 0) headed = otherWay[headed]; else { const int selectionIndex = rand() % (upRating + leftRating + rightRating + downRating); if (selectionIndex < upRating) headed = up; else if (selectionIndex < upRating + leftRating) headed = left; else if (selectionIndex < upRating + leftRating + rightRating) headed = right; else if (selectionIndex < upRating + leftRating + rightRating + downRating) headed = down; } } go(&x, &y, enemyStep, boardW * tileSize, boardH * tileSize, headed); } void Enemy::turnAroundIfAcceptable() { if (cageStatus == outsideCage) headed = otherWay[headed]; } void Enemy::goToCage() { const int desiredEnemyRoutePosition = ((game->getCagePosition() + game->getLevelPointer()->getEnemyRouteSize() * tileSize * id / 4) % (game->getLevelPointer()->getEnemyRouteSize() * tileSize)) / enemyStep * enemyStep; x = game->getLevelPointer()->getEnemyStartX() * tileSize; y = game->getLevelPointer()->getEnemyStartY() * tileSize; for (int enemyRoutePosition = 0; enemyRoutePosition < desiredEnemyRoutePosition; enemyRoutePosition += enemyStep) go(&x, &y, enemyStep, boardW * tileSize, boardH * tileSize, game->getLevelPointer()->getEnemyDirection(enemyRoutePosition / tileSize)); headed = game->getLevelPointer()->getEnemyDirection(((desiredEnemyRoutePosition + game->getLevelPointer()->getEnemyRouteSize() * tileSize - 1) % (game->getLevelPointer()->getEnemyRouteSize() * tileSize)) / tileSize); cageStatus = insideCage; } void Enemy::draw(BITMAP *canvas) { if (blitEnemies) blit(vramEnemy[id], tileImage, 0, 0, 0, 0, tileSize, tileSize); else { clear_bitmap(tileImage); draw_rle_sprite(tileImage, enemy[id], 0, 0); } drawPupils(tileImage, 0, 0, headed); draw_sprite(canvas, tileImage, x, y); if (x > boardW * tileSize - tileSize) draw_sprite(canvas, tileImage, x - boardW * tileSize, y); if (y > boardH * tileSize - tileSize) { draw_sprite(canvas, tileImage, x, y - boardH * tileSize); if (x > boardW * tileSize) draw_sprite(canvas, tileImage, x - boardW * tileSize, y - boardH * tileSize); } }