From c14535b1ae4e5a4aefe215978424cb6ed2ca08de Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 18 Jan 2020 17:51:01 -0800 Subject: [PATCH] ULTIMA1: Beginnings of dungeon drawing support methods --- engines/ultima/shared/core/map.h | 16 +++++ engines/ultima/shared/core/monsters.h | 2 +- .../ultima/shared/gfx/viewport_dungeon.cpp | 63 +++++++++++++++++++ engines/ultima/shared/gfx/viewport_dungeon.h | 20 ++++++ engines/ultima/ultima1/core/map.cpp | 15 +++++ engines/ultima/ultima1/core/map.h | 15 +++++ engines/ultima/ultima1/core/monsters.cpp | 2 +- engines/ultima/ultima1/core/monsters.h | 2 +- 8 files changed, 132 insertions(+), 3 deletions(-) diff --git a/engines/ultima/shared/core/map.h b/engines/ultima/shared/core/map.h index 7b71ba7af6e..43005a56367 100644 --- a/engines/ultima/shared/core/map.h +++ b/engines/ultima/shared/core/map.h @@ -164,6 +164,7 @@ class Map { Common::Array _data; public: byte &operator[](int idx) { return _data[idx]; } + byte operator[](int idx) const { return _data[idx]; } }; protected: byte _mapId; // The map Id @@ -244,6 +245,21 @@ public: * Load a given map */ virtual void loadMap(int mapId, uint videoMode); + + /** + * Returns true if the cell at the given position is a door + */ + virtual bool isDoor(const Point &pt) const = 0; + + /** + * Returns true if the cell at the given position is a wall or secret door + */ + virtual bool isWallOrSecretDoor(const Point &pt) const = 0; + + /** + * Returns true if the cell is a type that has walls on it: walls, doors, or secret doors + */ + virtual bool isWallOrDoorway(const Point &pt) const = 0; }; } // End of namespace Shared diff --git a/engines/ultima/shared/core/monsters.h b/engines/ultima/shared/core/monsters.h index 4cfffa3b3f8..2608cf6b999 100644 --- a/engines/ultima/shared/core/monsters.h +++ b/engines/ultima/shared/core/monsters.h @@ -58,7 +58,7 @@ public: /** * Returns true if a monster blocks the background behind him */ - virtual bool isBlockedView() const = 0; + virtual bool isBlockingView() const = 0; }; } // End of namespace Ultima1 diff --git a/engines/ultima/shared/gfx/viewport_dungeon.cpp b/engines/ultima/shared/gfx/viewport_dungeon.cpp index 0bfa73acb7f..cb815e50405 100644 --- a/engines/ultima/shared/gfx/viewport_dungeon.cpp +++ b/engines/ultima/shared/gfx/viewport_dungeon.cpp @@ -21,11 +21,74 @@ */ #include "ultima/shared/gfx/viewport_dungeon.h" +#include "ultima/shared/core/monsters.h" +#include "ultima/shared/core/map.h" namespace Ultima { namespace Shared { EMPTY_MESSAGE_MAP(ViewportDungeon, Shared::Gfx::VisualItem); +void ViewportDungeon::draw() { + // Get a surface reference and clear it's contents + Gfx::VisualSurface s = getSurface(); + s.clear(); + + // Get the position delta for the cells to the left and right of the player's position + Map *map = getMap(); + Point rightDelta, leftDelta, delta; + switch (map->_direction) { + case DIR_LEFT: + leftDelta.y = 1; + rightDelta.y = -1; + delta.x = -1; + break; + case DIR_RIGHT: + leftDelta.y = -1; + rightDelta.y = 1; + delta.x = 1; + break; + case DIR_UP: + leftDelta.x = -1; + rightDelta.x = 1; + delta.y = -1; + break; + case DIR_DOWN: + leftDelta.x = 1; + rightDelta.x = -1; + delta.y = 1; + break; + } + + bool isDoor = map->isDoor(map->getPosition()); + bool isWall = map->isWallOrSecretDoor(map->getPosition()); + int distance = distanceToOccupiedCell(delta); + +} + +int ViewportDungeon::distanceToOccupiedCell(const Point &delta) { + Point d = delta; + int distance; + for (distance = 1; !isCellOccupied(d); ++distance, d.x += ABS(d.x), d.y += ABS(d.y)) {} + + return MIN(distance, 5); +} + +bool ViewportDungeon::isCellOccupied(const Point &delta) { + Map *map = getMap(); + Point pt = map->getPosition() + delta; + if (map->isWallOrDoorway(pt)) + return true; + + return isMonsterBlocking(pt); +} + +bool ViewportDungeon::isMonsterBlocking(const Point &pt) { + MapTile tile; + getMap()->getTileAt(pt, &tile); + DungeonMonster *monster = dynamic_cast(tile._widget); + return monster != nullptr && monster->isBlockingView(); +} + } // End of namespace Shared } // End of namespace Ultima diff --git a/engines/ultima/shared/gfx/viewport_dungeon.h b/engines/ultima/shared/gfx/viewport_dungeon.h index e8552f6a7c5..721363104ab 100644 --- a/engines/ultima/shared/gfx/viewport_dungeon.h +++ b/engines/ultima/shared/gfx/viewport_dungeon.h @@ -30,10 +30,30 @@ namespace Shared { class ViewportDungeon : public Gfx::VisualItem { DECLARE_MESSAGE_MAP; +private: + /** + * Returns the distance to an occupied cell, if any + */ + int distanceToOccupiedCell(const Point &delta); + + /** + * Returns if a cell at a given delta to the player is occupied + */ + bool isCellOccupied(const Point &delta); + + /** + * Returns true if a monster is at a given position, and it has the blocking attribute + */ + bool isMonsterBlocking(const Point &pt); public: CLASSDEF; ViewportDungeon(TreeItem *parent) : Gfx::VisualItem("ViewportDungeon", Rect(8, 8, 312, 168), parent) {} virtual ~ViewportDungeon() {} + + /** + * Draws the dungeon + */ + virtual void draw(); }; } // End of namespace Shared diff --git a/engines/ultima/ultima1/core/map.cpp b/engines/ultima/ultima1/core/map.cpp index 66df6c16405..f624e009582 100644 --- a/engines/ultima/ultima1/core/map.cpp +++ b/engines/ultima/ultima1/core/map.cpp @@ -326,5 +326,20 @@ void Ultima1Map::spawnMonster() { // TODO } +bool Ultima1Map::isDoor(const Point &pt) const { + return _data[pt.y][pt.x] == DTILE_DOOR; +} + +bool Ultima1Map::isWallOrSecretDoor(const Point &pt) const { + return _data[pt.y][pt.x] == DTILE_WALL || _data[pt.y][pt.x] == DTILE_SECRET_DOOR; +} + +/** + * Returns true if the cell is a type that has walls on it: walls, doors, or secret doors + */ +bool Ultima1Map::isWallOrDoorway(const Point &pt) const { + return _data[pt.y][pt.x] == DTILE_WALL || _data[pt.y][pt.x] == DTILE_DOOR || _data[pt.y][pt.x] == DTILE_SECRET_DOOR; +} + } // End of namespace Ultima1 } // End of namespace Ultima diff --git a/engines/ultima/ultima1/core/map.h b/engines/ultima/ultima1/core/map.h index 1e2f0ca24ac..8065d64dc2f 100644 --- a/engines/ultima/ultima1/core/map.h +++ b/engines/ultima/ultima1/core/map.h @@ -185,6 +185,21 @@ public: * Spawns a monster within dungeons */ void spawnMonster(); + + /** + * Returns true if the cell at the given position is a door + */ + virtual bool isDoor(const Point &pt) const; + + /** + * Returns true if the cell at the given position is a wall or secret door + */ + virtual bool isWallOrSecretDoor(const Point &pt) const; + + /** + * Returns true if the cell is a type that has walls on it: walls, doors, or secret doors + */ + virtual bool isWallOrDoorway(const Point &pt) const; }; } // End of namespace Ultima1 diff --git a/engines/ultima/ultima1/core/monsters.cpp b/engines/ultima/ultima1/core/monsters.cpp index 384a7bca7d9..0a33ae9c1d5 100644 --- a/engines/ultima/ultima1/core/monsters.cpp +++ b/engines/ultima/ultima1/core/monsters.cpp @@ -25,7 +25,7 @@ namespace Ultima { namespace Ultima1 { -bool U1DungeonMonster::isBlockedView() const { +bool U1DungeonMonster::isBlockingView() const { return _monsterId != MONSTER_INVISIBLE_SEEKER && _monsterId != MONSTER_MIMIC && _monsterId != MONSTER_GELATINOUS_CUBE; } diff --git a/engines/ultima/ultima1/core/monsters.h b/engines/ultima/ultima1/core/monsters.h index 37f025b227f..105a9e88510 100644 --- a/engines/ultima/ultima1/core/monsters.h +++ b/engines/ultima/ultima1/core/monsters.h @@ -55,7 +55,7 @@ public: /** * Returns true if a monster blocks the background behind him */ - virtual bool isBlockedView() const; + virtual bool isBlockingView() const; };