TombsOfHarc/src/Gui.cpp

229 lines
5.9 KiB
C++

#include <stdio.h>
#include <stdarg.h>
#include "main.hpp"
static const int PANEL_HEIGHT=7;
static const int BAR_WIDTH=20;
static const int MSG_X=BAR_WIDTH+2;
static const int MSG_HEIGHT=PANEL_HEIGHT-1;
Gui::Gui() {
con = new TCODConsole(engine.screenWidth, PANEL_HEIGHT);
}
Gui::~Gui() {
delete con;
clear();
}
void Gui::clear() {
log.clearAndDelete();
}
void Gui::render() {
// Clear the GUI console
con->setDefaultBackground(TCODColor::black);
con->clear();
// Draw the Health bar
renderBar(1, 1, BAR_WIDTH, "HP", engine.player->destructible->hp,
engine.player->destructible->maxHp,
TCODColor::lightRed, TCODColor::darkerRed);
// Draw the XP bar
PlayerAi *ai=(PlayerAi *)engine.player->ai;
char xpTxt[128];
sprintf(xpTxt, "XP(%d)", ai->xpLevel);
renderBar(1, 5, BAR_WIDTH, xpTxt, engine.player->destructible->xp,
ai->getNextLevelXp(), TCODColor::lightViolet, TCODColor::darkerViolet);
// Draw the message log
int y=1;
float colorCoef=0.4f;
for(Message **it=log.begin(); it != log.end(); it++) {
Message *message=*it;
con->setDefaultForeground(message->col * colorCoef);
con->print(MSG_X, y, message->text);
y++;
if(colorCoef < 1.0f) {
colorCoef += 0.3f;
}
}
con->setDefaultForeground(TCODColor::white);
con->print(3, 3, "Dungeon level %d", engine.level);
// blit the GUI console on the root console
TCODConsole::blit(con, 0, 0, engine.screenWidth, PANEL_HEIGHT,
TCODConsole::root, 0, engine.screenHeight - PANEL_HEIGHT);
// Mouse look
renderMouseLook();
}
void Gui::renderBar(int x, int y, int width, const char *name,
float value, float maxValue, const TCODColor &barColor,
const TCODColor &backColor) {
// Fill the background
con->setDefaultBackground(backColor);
con->rect(x, y, width, 1, false, TCOD_BKGND_SET);
int barWidth = (int)(value / maxValue * width);
if(barWidth > 0) {
// Draw the bar
con->setDefaultBackground(barColor);
con->rect(x, y, barWidth, 1, false, TCOD_BKGND_SET);
}
// Print text on top of the bar
con->setDefaultForeground(TCODColor::white);
con->printEx(x + width/2, y, TCOD_BKGND_NONE, TCOD_CENTER,
"%s : %g/%g", name, value, maxValue);
}
Gui::Message::Message(const char *text, const TCODColor &col) : text(strdup(text)), col(col) { }
Gui::Message::~Message() {
free(text);
}
void Gui::message(const TCODColor &col, const char *text, ...) {
// Build the text
va_list ap;
char buf[128];
va_start(ap, text);
vsprintf(buf, text, ap);
va_end(ap);
char *lineBegin=buf;
char *lineEnd;
do {
// make room for the new message
if(log.size() == MSG_HEIGHT) {
Message *toRemove=log.get(0);
log.remove(toRemove);
delete toRemove;
}
// Detect end of the line
lineEnd=strchr(lineBegin, '\n');
if(lineEnd) {
*lineEnd='\0';
}
// Add a new message to the log
Message *msg = new Message(lineBegin, col);
log.push(msg);
// Go to next line
lineBegin = lineEnd + 1;
} while(lineEnd);
}
void Gui::renderMouseLook() {
if(!engine.map->isInFov(engine.mouse.cx, engine.mouse.cy)) {
// If mouse is out of fov, nothing to render
return;
}
char buf[128]="";
bool first=true;
for(Actor **it=engine.actors.begin(); it != engine.actors.end(); it++) {
Actor *actor=*it;
// Find the actors under the mouse cursor
if(actor->x == engine.mouse.cx && actor->y == engine.mouse.cy) {
if(!first) {
strcat(buf, ", ");
} else {
first=false;
}
strcat(buf, actor->name);
}
}
// Display the list of actors under the mouse cursor
con->setDefaultForeground(TCODColor::lightGrey);
con->print(1, 0, buf);
}
void Gui::save(TCODZip &zip) {
zip.putInt(log.size());
for(Message **it = log.begin(); it != log.end(); it++) {
zip.putString((*it)->text);
zip.putColor(&(*it)->col);
}
}
void Gui::load(TCODZip &zip) {
int nbMessages = zip.getInt();
while(nbMessages > 0) {
const char *text = zip.getString();
TCODColor col = zip.getColor();
message(col, text);
nbMessages--;
}
}
Menu::~Menu() {
clear();
}
void Menu::clear() {
items.clearAndDelete();
}
void Menu::addItem(MenuItemCode code, const char *label) {
MenuItem *item=new MenuItem();
item->code=code;
item->label=label;
items.push(item);
}
const int PAUSE_MENU_WIDTH=30;
const int PAUSE_MENU_HEIGHT=15;
Menu::MenuItemCode Menu::pick(DisplayMode mode) {
int selectedItem=0;
int menux, menuy;
if(mode == PAUSE) {
menux = engine.screenWidth/2-PAUSE_MENU_WIDTH/2;
menuy = engine.screenHeight/2-PAUSE_MENU_HEIGHT/2;
TCODConsole::root->setDefaultForeground(TCODColor(200, 180, 50));
TCODConsole::root->printFrame(menux, menuy, PAUSE_MENU_WIDTH, PAUSE_MENU_HEIGHT, true,
TCOD_BKGND_ALPHA(70), "menu");
menux+=2;
menuy+=3;
} else {
static TCODImage img("menu_background1.png");
img.blit2x(TCODConsole::root, 0, 0);
menux = 10;
menuy = TCODConsole::root->getHeight()/3;
}
while(!TCODConsole::isWindowClosed()) {
int currentItem = 0;
for(MenuItem **it = items.begin(); it != items.end(); it++) {
if(currentItem == selectedItem) {
TCODConsole::root->setDefaultForeground(TCODColor::lighterOrange);
} else {
TCODConsole::root->setDefaultForeground(TCODColor::lightGrey);
}
TCODConsole::root->print(menux, menuy + currentItem * 3, (*it)->label);
currentItem++;
}
TCODConsole::flush();
// Check key presses
TCOD_key_t key;
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS, &key, NULL);
switch(key.vk) {
case TCODK_UP:
selectedItem--;
if(selectedItem < 0) {
selectedItem=items.size()-1;
}
break;
case TCODK_DOWN:
selectedItem = (selectedItem + 1) % items.size();
break;
case TCODK_ENTER: return items.get(selectedItem)->code;
default: break;
}
}
return NONE;
}