diff --git a/ADG5.cpp b/ADG5.cpp index c1a55f2..3b4e8b2 100644 --- a/ADG5.cpp +++ b/ADG5.cpp @@ -14,7 +14,8 @@ int main(int argc, char **argv) { auto console = tcod::Console(80, 50); auto params = TCOD_ContextParams{}; - + auto tileset = tcod::load_tilesheet("terminal10x16_gs_ro.png", { 16, 16 }, tcod::CHARMAP_CP437); + params.tileset = tileset.get(); params.console = console.get(); params.window_title = "Andrew's Dungeon Game 5"; params.sdl_window_flags = SDL_WINDOW_RESIZABLE; diff --git a/Actor.cpp b/Actor.cpp index 8c5a67d..3e5b2cb 100644 --- a/Actor.cpp +++ b/Actor.cpp @@ -16,7 +16,12 @@ Actor::Actor(int x, int y, std::string_view ch, std::string name, const TCOD_Col } void Actor::render(TCOD_Console& cons) const { - tcod::print(cons, { x, y }, ch, col, std::nullopt); + int offset_x = engine->player->x - Engine::VIEW_WIDTH / 2; + int offset_y = engine->player->y - Engine::VIEW_HEIGHT / 2; + if (offset_x > x || Engine::VIEW_WIDTH + offset_x < x || offset_y > y || Engine::VIEW_HEIGHT + offset_y < y) { + return; + } + tcod::print(cons, { x - offset_x, y - offset_y}, ch, col, std::nullopt); } void Actor::update() { diff --git a/Ai.cpp b/Ai.cpp index 7d2459a..ff8943a 100644 --- a/Ai.cpp +++ b/Ai.cpp @@ -27,7 +27,7 @@ void PlayerAi::update(Actor* owner) { if (owner->destructible->xp >= levelUpXp) { xpLevel++; owner->destructible->xp -= levelUpXp; - engine->gui->message(TCOD_ColorRGB(255, 255, 100), "Your battle skills grow stronger! You reached level %d", xpLevel); + engine->gui->message(engine->gui->lightYellow, "Your battle skills grow stronger! You reached level %d", xpLevel); engine->gui->menu.clear(); engine->gui->menu.addItem(Menu::CONSTITUTION, "Constitution (+20HP)"); engine->gui->menu.addItem(Menu::STRENGTH, "Strength (+1 attack)"); @@ -120,18 +120,18 @@ void PlayerAi::handleActionKey(Actor* owner, int sdlkey, int mod) { if (actor->pickable && actor->x == owner->x && actor->y == owner->y) { if (actor->pickable->pick(actor, owner)) { found = true; - engine->gui->message(TCOD_ColorRGB(200,200,200), "You pick up the %s.", + engine->gui->message(engine->gui->lightGrey, "You pick up the %s.", actor->name.c_str()); break; } else if (!found) { found = true; - engine->gui->message(TCOD_ColorRGB(255,0,0), "Your inventory is full."); + engine->gui->message(engine->gui->red, "Your inventory is full."); } } } if (!found) { - engine->gui->message(TCOD_ColorRGB(200,200,200), "There's nothing here that you can pick up."); + engine->gui->message(engine->gui->lightGrey, "There's nothing here that you can pick up."); } if (engine->gameStatus != Engine::QUIT) engine->gameStatus = Engine::NEW_TURN; @@ -163,7 +163,7 @@ void PlayerAi::handleActionKey(Actor* owner, int sdlkey, int mod) { engine->nextLevel(); } else { - engine->gui->message(TCOD_ColorRGB(200, 200, 200), "There are no stairs here."); + engine->gui->message(engine->gui->lightGrey, "There are no stairs here."); } } break; @@ -189,7 +189,7 @@ bool PlayerAi::moveOrAttack(Actor* owner, int targetx, int targety) { || actor->pickable; if (corpseOrItem && actor->x == targetx && actor->y == targety) { - engine->gui->message(TCOD_ColorRGB(200,200,200), "There's a %s here.", actor->name.c_str()); + engine->gui->message(engine->gui->lightGrey, "There's a %s here.", actor->name.c_str()); } } owner->x = targetx; diff --git a/Attacker.cpp b/Attacker.cpp index 0973597..045718a 100644 --- a/Attacker.cpp +++ b/Attacker.cpp @@ -10,16 +10,16 @@ Attacker::Attacker(float power) : power(power) { void Attacker::attack(Actor* owner, Actor* target) { if (target->destructible && !target->destructible->isDead()) { if (power - target->destructible->defense > 0) { - engine->gui->message(TCOD_ColorRGB(150, 150, 150), "%s attacks %s for %g hit points.\n", owner->name.c_str(), target->name.c_str(), + engine->gui->message(engine->gui->lightGrey, "%s attacks %s for %g hit points.\n", owner->name.c_str(), target->name.c_str(), power - target->destructible->defense); } else { - engine->gui->message(TCOD_ColorRGB(150, 150, 150), "%s attacks %s but it has no effect!\n", owner->name.c_str(), target->name.c_str()); + engine->gui->message(engine->gui->lightGrey, "%s attacks %s but it has no effect!\n", owner->name.c_str(), target->name.c_str()); } target->destructible->takeDamage(target, power); } else { - engine->gui->message(TCOD_ColorRGB(150, 150, 150), "%s attacks %s in vain.\n", owner->name.c_str(), target->name.c_str()); + engine->gui->message(engine->gui->lightGrey, "%s attacks %s in vain.\n", owner->name.c_str(), target->name.c_str()); } } diff --git a/Confuser.cpp b/Confuser.cpp index e6b13c7..5fa5ce0 100644 --- a/Confuser.cpp +++ b/Confuser.cpp @@ -10,7 +10,7 @@ Confuser::Confuser(int nbTurns, float range) : nbTurns(nbTurns), range(range) { } bool Confuser::use(Actor* owner, Actor* wearer) { - engine->gui->message(TCOD_ColorRGB(0, 255, 255), "Left-click an enemy to confuse it,\nor right-click to cancel."); + engine->gui->message(engine->gui->lightBlue, "Left-click an enemy to confuse it,\nor right-click to cancel."); int x, y; if (!engine->pickATile(&x, &y, range)) { return false; @@ -22,7 +22,7 @@ bool Confuser::use(Actor* owner, Actor* wearer) { // confuse the monster for turns Ai* confusedAi = new ConfusedMonsterAi(nbTurns, actor->ai); actor->ai = confusedAi; - engine->gui->message(TCOD_ColorRGB(100, 255, 100), "The eyes of the %s look vacant,\nas he starts to stumble around!", + engine->gui->message(engine->gui->lightGreen, "The eyes of the %s look vacant,\nas he starts to stumble around!", actor->name.c_str()); return Pickable::use(owner, wearer); } diff --git a/Destructible.cpp b/Destructible.cpp index 23067f1..7bd6fce 100644 --- a/Destructible.cpp +++ b/Destructible.cpp @@ -60,7 +60,7 @@ void MonsterDestructible::save(TCODZip& zip) { void MonsterDestructible::die(Actor* owner) { // transform it into a nasty corpse! it doesn't block, can't be // attacked and doesn't move - engine->gui->message(TCOD_ColorRGB(150, 150, 150), "%s is dead. You gain %d xp", + engine->gui->message(engine->gui->lightGrey, "%s is dead. You gain %d xp", owner->name.c_str(), xp); engine->player->destructible->xp += xp; @@ -68,7 +68,7 @@ void MonsterDestructible::die(Actor* owner) { } void PlayerDestructible::die(Actor* owner) { - engine->gui->message(TCOD_ColorRGB(150, 0, 0), "You died!\n"); + engine->gui->message(engine->gui->red, "You died!\n"); Destructible::die(owner); engine->gameStatus = Engine::DEFEAT; } diff --git a/Engine.cpp b/Engine.cpp index e003d0f..2c83580 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -27,7 +27,7 @@ Engine::Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod:: } void Engine::init() { - player = new Actor(40, 25, "@", "player", TCOD_ColorRGB(255, 255, 255)); + player = new Actor(40, 25, "@", "player", engine->gui->white); player->destructible = new PlayerDestructible(30, 2, "player corpse"); player->attacker = new Attacker(5); player->ai = new PlayerAi(); @@ -37,7 +37,7 @@ void Engine::init() { stairs->blocks = false; stairs->fovOnly = false; actors.push(stairs); - map = new Map(80, 43); + map = new Map(200, 100); map->init(true); gui->message(TCOD_ColorRGB(150,0,0), "Welcome stranger!\nPrepare to perish in the Tombs of Andrew's Dunegon."); @@ -46,9 +46,9 @@ void Engine::init() { void Engine::nextLevel() { level++; - gui->message(TCOD_ColorRGB(255, 100, 255), "You take a moment to rest, and recover your strength."); + gui->message(engine->gui->lightPurple, "You take a moment to rest, and recover your strength."); player->destructible->heal(player->destructible->maxHp / 2); - gui->message(TCOD_ColorRGB(255, 100, 100), "After a rare moment of peace, you descend\ndeeper into the heart of the dungeon..."); + gui->message(engine->gui->lightRed, "After a rare moment of peace, you descend\ndeeper into the heart of the dungeon..."); delete map; // delete all actors but player and stairs for (Actor** it = actors.begin(); it != actors.end(); it++) { @@ -58,7 +58,7 @@ void Engine::nextLevel() { } } // create a new map - map = new Map(80, 43); + map = new Map(200, 100); map->init(true); gameStatus = STARTUP; } diff --git a/Engine.h b/Engine.h index 883e6ec..b98ff91 100644 --- a/Engine.h +++ b/Engine.h @@ -7,6 +7,8 @@ class Gui; class Engine { public: + const static int VIEW_WIDTH = 80; + const static int VIEW_HEIGHT = 43; enum GameStatus { STARTUP, IDLE, diff --git a/Fireball.cpp b/Fireball.cpp index dbe0753..5d50896 100644 --- a/Fireball.cpp +++ b/Fireball.cpp @@ -10,18 +10,18 @@ Fireball::Fireball(float range, float damage) } bool Fireball::use(Actor* owner, Actor* wearer) { - engine->gui->message(TCOD_ColorRGB(0, 255, 255), "Left-click a target tile for the fireball,\nor right-click to cancel."); + engine->gui->message(engine->gui->lightBlue, "Left-click a target tile for the fireball,\nor right-click to cancel."); int x, y; if (!engine->pickATile(&x, &y)) { return false; } - engine->gui->message(TCOD_ColorRGB(255, 255, 100), "The fireball explodes, burning everything within %g tiles!", range); + engine->gui->message(engine->gui->lightYellow, "The fireball explodes, burning everything within %g tiles!", range); for (Actor** iterator = engine->actors.begin(); iterator != engine->actors.end(); iterator++) { Actor* actor = *iterator; if (actor->destructible && !actor->destructible->isDead() && actor->getDistance(x, y) <= range) { - engine->gui->message(TCOD_ColorRGB(255, 255, 100), "The %s gets burned for %g hit points.", + engine->gui->message(engine->gui->lightYellow, "The %s gets burned for %g hit points.", actor->name.c_str(), damage); actor->destructible->takeDamage(actor, damage); } diff --git a/Gui.cpp b/Gui.cpp index a28caf5..8e0b8e8 100644 --- a/Gui.cpp +++ b/Gui.cpp @@ -15,6 +15,20 @@ static const int MSG_HEIGHT = PANEL_HEIGHT - 1; Gui::Gui(tcod::Context *ctx, tcod::Console *root) { con = ctx->new_console(engine->screenWidth, PANEL_HEIGHT); this->root = root; + darkGrey = TCOD_ColorRGB(100,100,100); + lightGrey = TCOD_ColorRGB(200,200,200); + white = TCOD_ColorRGB(255,255,255); + red = TCOD_ColorRGB(100, 50, 50); + green = TCOD_ColorRGB(50, 100, 50); + blue = TCOD_ColorRGB(50, 50, 100); + yellow = TCOD_ColorRGB(100, 100, 50); + black = TCOD_ColorRGB(0, 0, 0); + lightBlue = TCOD_ColorRGB(100, 100, 255); + lightGreen = TCOD_ColorRGB(100, 255, 100); + lightRed = TCOD_ColorRGB(255, 100, 100); + lightYellow = TCOD_ColorRGB(255, 255, 100); + lightPurple = TCOD_ColorRGB(255, 100, 255); + purple = TCOD_ColorRGB(100, 50, 100); } void Gui::clear() { @@ -186,8 +200,10 @@ Menu::MenuItemCode Menu::pick(tcod::Context *ctx, tcod::Console *con, DisplayMod else { static TCODImage img("menu_background1.png"); img.blit2x(*con, 0, 0); - menux = 10; - menuy = con->get_height() / 3; + TCOD_ColorRGB fg(200, 180, 50); + TCOD_ColorRGB bg(0, 0, 0); + menux = 7; + menuy = 30; } int currentItem = 0; diff --git a/Gui.h b/Gui.h index ef110c7..1cb7dce 100644 --- a/Gui.h +++ b/Gui.h @@ -5,6 +5,7 @@ class Menu { public: + enum MenuItemCode { NONE, NEW_GAME, @@ -32,6 +33,20 @@ protected: class Gui : public Persistent { public: + TCOD_ColorRGB darkGrey; + TCOD_ColorRGB lightGrey; + TCOD_ColorRGB white; + TCOD_ColorRGB red; + TCOD_ColorRGB green; + TCOD_ColorRGB blue; + TCOD_ColorRGB yellow; + TCOD_ColorRGB black; + TCOD_ColorRGB lightBlue; + TCOD_ColorRGB lightGreen; + TCOD_ColorRGB lightRed; + TCOD_ColorRGB lightYellow; + TCOD_ColorRGB lightPurple; + TCOD_ColorRGB purple; Gui(tcod::Context *ctx, tcod::Console *root); ~Gui(); void render(); diff --git a/Lightningbolt.cpp b/Lightningbolt.cpp index c1f6c0e..f4dc2b3 100644 --- a/Lightningbolt.cpp +++ b/Lightningbolt.cpp @@ -11,11 +11,11 @@ LightningBolt::LightningBolt(float range, float damage) bool LightningBolt::use(Actor* owner, Actor* wearer) { Actor* closestMonster = engine->getClosestMonster(wearer->x, wearer->y, range); if (!closestMonster) { - engine->gui->message(TCOD_ColorRGB(200,200,200), "No enemy is close enough to strike."); + engine->gui->message(engine->gui->white, "No enemy is close enough to strike."); return false; } // hit closest monster for hit points - engine->gui->message(TCOD_ColorRGB(100, 255, 100), + engine->gui->message(engine->gui->lightBlue, "A lighting bolt strikes the %s with a crack of thunder!\n" "The damage is %g hit points.", closestMonster->name.c_str(), damage); diff --git a/Map.cpp b/Map.cpp index c491dd5..a0a505d 100644 --- a/Map.cpp +++ b/Map.cpp @@ -9,6 +9,7 @@ #include "Lightningbolt.h" #include "Fireball.h" #include "Confuser.h" +#include "Gui.h" static const int ROOM_MAX_SIZE = 12; static const int ROOM_MIN_SIZE = 6; @@ -114,13 +115,16 @@ void Map::render(TCOD_Console& cons) const { static const TCOD_ColorRGB lightGround(200, 180, 50); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { + int offset_x = engine->player->x - Engine::VIEW_WIDTH / 2; + int offset_y = engine->player->y - Engine::VIEW_HEIGHT / 2; + if (offset_x > x || Engine::VIEW_WIDTH + offset_x < x || offset_y > y || Engine::VIEW_HEIGHT + offset_y < y) { + continue; + } if (isInFov(x, y)) { - tcod::print(cons, { x, y }, " ", std::nullopt, isWall(x, y) ? lightWall : lightGround); + tcod::print(cons, { x - offset_x, y - offset_y }, " ", std::nullopt, isWall(x, y) ? lightWall : lightGround); } else if (isExplored(x, y)) { - tcod::print(cons, { x, y }, " ", std::nullopt, isWall(x, y) ? darkWall : darkGround); - - + tcod::print(cons, { x- offset_x, y - offset_y }, " ", std::nullopt, isWall(x, y) ? darkWall : darkGround); } } } @@ -185,7 +189,7 @@ void Map::addMonster(int x, int y) { if (rng->getInt(0, 100) < 80) { // create an orc Actor* orc = new Actor(x, y, "o", "orc", - TCOD_ColorRGB(0, 100, 0)); + engine->gui->green); orc->destructible = new MonsterDestructible(10, 0, "dead orc", 5); orc->attacker = new Attacker(3); orc->ai = new MonsterAi(); @@ -194,7 +198,7 @@ void Map::addMonster(int x, int y) { else { // create a troll Actor* troll = new Actor(x, y, "T", "troll", - TCOD_ColorRGB(0, 255, 0)); + engine->gui->lightGreen); troll->destructible = new MonsterDestructible(16, 1, "troll carcass", 10); troll->attacker = new Attacker(4); troll->ai = new MonsterAi(); @@ -208,7 +212,7 @@ void Map::addItem(int x, int y) { if (dice < 70) { // create a health potion Actor* healthPotion = new Actor(x, y, "!", "health potion", - TCOD_ColorRGB(128, 0, 128)); + engine->gui->purple); healthPotion->blocks = false; healthPotion->pickable = new Healer(4); engine->actors.push(healthPotion); @@ -216,7 +220,7 @@ void Map::addItem(int x, int y) { else if (dice < 70 + 10) { // create a scroll of lightning bolt Actor* scrollOfLightningBolt = new Actor(x, y, "#", "scroll of lightning bolt", - TCOD_ColorRGB(255, 100, 100)); + engine->gui->lightRed); scrollOfLightningBolt->blocks = false; scrollOfLightningBolt->pickable = new LightningBolt(5, 20); engine->actors.push(scrollOfLightningBolt); @@ -225,7 +229,7 @@ void Map::addItem(int x, int y) { else if (dice < 70 + 10 + 10) { // create a scroll of fireball Actor* scrollOfFireball = new Actor(x, y, "#", "scroll of fireball", - TCOD_ColorRGB(255, 100, 100)); + engine->gui->lightRed); scrollOfFireball->blocks = false; scrollOfFireball->pickable = new Fireball(3, 12); engine->actors.push(scrollOfFireball); @@ -233,7 +237,7 @@ void Map::addItem(int x, int y) { else { // create a scroll of confusion Actor* scrollOfConfusion = new Actor(x, y, "#", "scroll of confusion", - TCOD_ColorRGB(255, 100, 100)); + engine->gui->lightRed); scrollOfConfusion->blocks = false; scrollOfConfusion->pickable = new Confuser(10, 8); engine->actors.push(scrollOfConfusion); diff --git a/Pickable.cpp b/Pickable.cpp index c258dc7..39577cb 100644 --- a/Pickable.cpp +++ b/Pickable.cpp @@ -32,7 +32,7 @@ void Pickable::drop(Actor* owner, Actor* wearer) { engine->actors.push(owner); owner->x = wearer->x; owner->y = wearer->y; - engine->gui->message(TCOD_ColorRGB(200,200,200), "%s drops a %s.", + engine->gui->message(engine->gui->lightGrey, "%s drops a %s.", wearer->name.c_str(), owner->name.c_str()); } } diff --git a/menu_background1.png b/menu_background1.png index 3690898..960c6b5 100644 Binary files a/menu_background1.png and b/menu_background1.png differ diff --git a/terminal10x16_gs_ro.png b/terminal10x16_gs_ro.png new file mode 100644 index 0000000..e40aa99 Binary files /dev/null and b/terminal10x16_gs_ro.png differ