diff --git a/src/CGraphics.cpp b/src/CGraphics.cpp index af43c1f91..47bd4b8cc 100644 --- a/src/CGraphics.cpp +++ b/src/CGraphics.cpp @@ -312,6 +312,21 @@ unsigned char xa,ya; } } +void CGraphics::drawCharacter(float x, float y, int f) +{ + assert(f >= 0 && f < 256); +unsigned char xa,ya; + + for(ya=0;ya<8;ya++) + { + for(xa=0;xa<8;xa++) + { + g_pVideoDriver->setpixel((unsigned int)((x*320)+xa), (unsigned int)((y*200)+ya), (unsigned char)font[f][ya][xa]); + } + } +} + + void CGraphics::sb_drawCharacter(int x, int y, int f) { unsigned char xa,ya; @@ -605,7 +620,7 @@ unsigned int i,x=xoff,y; if (c!=13) { if (highlight) c|=128; - drawCharacter(x, y, c); + drawCharacter((int)x, (int)y, c); x+=8; } else @@ -615,6 +630,14 @@ unsigned int i,x=xoff,y; } } } + +// font drawing functions (float version) +void CGraphics::drawFont(const std::string& text, float xoff, float yoff, int highlight) +{ + drawFont(text, (int)(xoff*320), (int)(yoff*200), highlight); +} + + void CGraphics::sb_font_draw(const std::string& text, int xoff, int yoff) { unsigned int i,x,y; diff --git a/src/CGraphics.h b/src/CGraphics.h index 878744b65..25f86e1e5 100644 --- a/src/CGraphics.h +++ b/src/CGraphics.h @@ -31,6 +31,7 @@ public: void drawSprite(int x, int y, unsigned int s, int objectnum); void eraseSprite(int x, int y, unsigned int s, int objectnum); void drawCharacter(int x, int y, int f); + void drawCharacter(float x, float y, int f); void sb_drawCharacter(int x, int y, int f); void sb_drawCharacterwithmask(int x, int y, int f, char mask); void sb_drawColorcharacter(int x, int y, int f, unsigned short colour, unsigned short bgcolour); @@ -46,6 +47,7 @@ public: int getBitmapNumberFromName(const char *bmname); void sb_drawCharacterinverse(int x, int y, int f); void drawFont(const std::string& text, int xoff, int yoff, int highlight); + void drawFont(const std::string& text, float xoff, float yoff, int highlight); void sb_font_draw(const std::string& text, int xoff, int yoff); void sb_mask_font_draw(const std::string& text, int xoff, int yoff, char mask); void sb_color_font_draw(const std::string& text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour); diff --git a/src/dialog/CTextBox.cpp b/src/dialog/CTextBox.cpp new file mode 100644 index 000000000..3bbe9929f --- /dev/null +++ b/src/dialog/CTextBox.cpp @@ -0,0 +1,61 @@ +/* + * CTextBox.cpp + * + * Created on: 30.07.2009 + * Author: gerstrong + */ + +#include "CTextBox.h" +#include "../CGraphics.h" +#include "../StringUtils.h" + +CTextBox::CTextBox(float x, float y, float w, float h, float font_w, float font_h, const std::string& text) { + m_fontwidth = font_w; + m_fontheight = font_h; + m_x = x; + m_y = y; + m_w = w; + m_h = h; + m_String = text; +} + +void CTextBox::format() +{ + // This function format properly the text into a box (multiple lines), + // separating the strings by words. + + std::string word; + std::string::iterator it = m_String.begin(); + std::string oneline; + unsigned int i = 0; + + while(m_String.length() > i) + { + word = GetNextWord(it, m_String); + + if((oneline.length() + word.length()) > m_w/m_fontwidth) + { + if(*(oneline.end()-1) == ' ') oneline.erase(oneline.end()-1); + m_Textline.push_back(oneline); + oneline.clear(); + } + oneline += word + " "; + + it += word.length() + 1; + i += word.length() + 1; + } + // The last line might not be full, but must also be printed + m_Textline.push_back(oneline); + +} + +void CTextBox::draw() +{ + // Draw Routine for the Textbox + for(unsigned int i=0 ; idrawFont(m_Textline[i], m_x, m_y+i*m_fontheight, 0); // 0 is blank colour + if( i*m_fontheight>m_h ) + break; + } +} diff --git a/src/dialog/CTextBox.h b/src/dialog/CTextBox.h new file mode 100644 index 000000000..f9d1892fd --- /dev/null +++ b/src/dialog/CTextBox.h @@ -0,0 +1,29 @@ +/* + * CTextBox.h + * + * Created on: 30.07.2009 + * Author: gerstrong + */ + +#ifndef CTEXTBOX_H_ +#define CTEXTBOX_H_ + +#include +#include + +class CTextBox { +public: + CTextBox(float x, float y, float w, float h, float font_w, float font_h, const std::string& text); + + void format(); + void draw(); + +private: + + std::string m_String; + std::vector m_Textline; + float m_x, m_y, m_w, m_h; + float m_fontwidth, m_fontheight; +}; + +#endif /* CTEXTBOX_H_ */ diff --git a/src/dialog/CWindow.cpp b/src/dialog/CWindow.cpp new file mode 100644 index 000000000..b091f862f --- /dev/null +++ b/src/dialog/CWindow.cpp @@ -0,0 +1,120 @@ +/* + * CWindow.cpp + * + * Created on: 29.07.2009 + * Author: gerstrong + */ + +#include "CWindow.h" + +#include "../CGraphics.h" + +CWindow::CWindow(float x, float y, float w, float h) +{ + m_x = x; + m_y = y; + m_w = w; + m_h = h; + + m_8x8tileheight = 8.0/200.0; + m_8x8tilewidth = 8.0/320.0; +} + +CWindow::~CWindow() { + // Empty list ID, while also emptying + int textbox_ctr = 0; + while(!m_ID_List.empty()) + { + switch(*m_ID_List.begin()) + { + case OBJ_TYPE_TEXT: + delete m_TextBox[textbox_ctr++]; + break; + } + m_ID_List.pop_front(); + } +} + +/////////////////////// +// Creation Routines // +/////////////////////// +void CWindow::addTextBox(float x, float y, float w, float h, const std::string& text, bool border_rel) +{ + // Element coordinates are all relative and must go inside the borders if desired! + // if false it will be relative to the window itself and can be used as title border + if(border_rel) + { + x *= m_w; + x += (m_8x8tilewidth); + y *= m_h; + y += (m_8x8tileheight); + w -= 2*m_8x8tilewidth/(m_w); + h -= 2*m_8x8tileheight/(m_h); + } + + CTextBox* ptr = new CTextBox(x + m_x, + y + m_y, + w*(m_w), + h*(m_h), + m_8x8tilewidth, m_8x8tileheight, text); + m_TextBox.push_back(ptr); + m_TextBox.back()->format(); + m_ID_List.push_back(OBJ_TYPE_TEXT); +} + +//////////////////////// +// Rendering Routines // +//////////////////////// +void CWindow::render() +{ + // draw the window + drawWindow(); + + // Draw the window objects which are inside + // Process the ID-List and render every Element of the Window + std::list :: iterator i; + int textbox_ctr = 0; + for( i = m_ID_List.begin() ; i != m_ID_List.end() ; i++ ) + { + switch(*i) + { + case OBJ_TYPE_TEXT: + m_TextBox[textbox_ctr++]->draw(); + break; + } + } +} + +void CWindow::drawWindow() +{ + // Use we use floating values, the drawing routine is very important to get a well sized window. + + // first draw the blank rect + float i, j; + for(j = 0.0 ; j < m_h - m_8x8tileheight ; j+= (m_8x8tileheight*(7.0/8.0)) ) + { + for(i = 0.0 ; i < m_w - m_8x8tilewidth ; i+= m_8x8tilewidth ) + g_pGraphics->drawCharacter( m_x + i, m_y + j, 32); // 32 is blank tile + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y + j, 32); // for the last tile + } + + // then the borders + for( i = m_8x8tilewidth ; i < m_w-m_8x8tilewidth ; i+= m_8x8tilewidth ) + { + g_pGraphics->drawCharacter( m_x + i, m_y, 2); // 2 is one upper-border + g_pGraphics->drawCharacter( m_x + i, m_y + m_h - m_8x8tileheight, 7); // 2 is also the lower-border + } + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y, 2); // for the last tile + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y + m_h - m_8x8tileheight, 2); // for the last tile + for( j = m_8x8tileheight ; j < m_h-m_8x8tileheight ; j+= (m_8x8tileheight*(7.0/8.0)) ) + { + g_pGraphics->drawCharacter( m_x, m_y + j, 4); // 4 is one left-border + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y + j, 5); // 4 is also the right-border + } + + // At last the corners + g_pGraphics->drawCharacter( m_x, m_y , 1); // Upper-Left corner + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y, 3); // Upper-Right corner + g_pGraphics->drawCharacter( m_x, m_y + m_h - m_8x8tileheight, 6); // Lower-Left corner + g_pGraphics->drawCharacter( m_x + m_w - m_8x8tilewidth, m_y + m_h - m_8x8tileheight, 8); // Lower-Right corner +} diff --git a/src/dialog/CWindow.h b/src/dialog/CWindow.h new file mode 100644 index 000000000..cea29688a --- /dev/null +++ b/src/dialog/CWindow.h @@ -0,0 +1,44 @@ +/* + * CWindow.h + * + * Created on: 29.07.2009 + * Author: gerstrong + */ + +#ifndef CWINDOW_H_ +#define CWINDOW_H_ + +#include +#include +#include +#include "CTextBox.h" + +enum{ + OBJ_TYPE_TEXT +}; + +class CWindow { +public: + CWindow(float x, float y, float w, float h); + virtual ~CWindow(); + + void addTextBox(float x, float y, float w, float h, const std::string& text, bool border_rel); + + void render(); + +private: + float m_x; + float m_y; + float m_h; + float m_w; + + float m_8x8tileheight; + float m_8x8tilewidth; + + std::list m_ID_List; + std::vector m_TextBox; + + void drawWindow(); +}; + +#endif /* CWINDOW_H_ */ diff --git a/src/game.cpp b/src/game.cpp index 1ab35bb3b..d9e1eff3d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1314,14 +1314,8 @@ void procgoodie(int t, int mpx, int mpy, int theplayer, stCloneKeenPlus *pCKP) pCKP->Control.levelcontrol.tobonuslevel = 1; break; - case YORPSTATUEHEAD: - if(pCKP->Control.levelcontrol.episode == 1) - { - youseeinyourmind(mpx, mpy, pCKP); - } - else if(pCKP->Control.levelcontrol.episode == 2) - if(!player[theplayer].blockedr && !player[theplayer].blockedl) - VorticonElder(mpx, mpy, pCKP); + case 22: // Game info block (Youseein your mind or vorticon elder...) + showGameHint(mpx, mpy, pCKP->Control.levelcontrol.episode, pCKP->Control.levelcontrol.curlevel); break; case 27: diff --git a/src/include/misc.h b/src/include/misc.h index 87d34a8e3..33e0f8949 100644 --- a/src/include/misc.h +++ b/src/include/misc.h @@ -13,5 +13,6 @@ char gameiswon(stCloneKeenPlus *pCKP); void game_save(char *fname, stCloneKeenPlus *pCKP); int game_load(char *fname, stCloneKeenPlus *pCKP); void showTextMB(int lines, char **text, stCloneKeenPlus *pCKP); +void showGameHint(int mpx, int mpy, int episode, int level); unsigned int rnd(void); diff --git a/src/misc.cpp b/src/misc.cpp index edc042ae9..32ee08514 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -27,6 +27,8 @@ #include "StringUtils.h" #include "FindFile.h" +#include "dialog/CWindow.h" + void banner(void) { @@ -153,98 +155,78 @@ void sb_dialogbox(int x1, int y1, int w, int h) } } -#define YORPSTATUEHEADUSED 485 -void youseeinyourmind(int mpx, int mpy, stCloneKeenPlus *pCKP) +void showGameHint(int mpx, int mpy, int episode, int level) { -int twirlframe, twirltimer; -char strname[80]; -int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY; + std::string strname; -bool isgarg; + // First check, if the item has really been activated + if(!map_isanimated(mpx, mpy+(episode==2) )) + return; -int i; - - isgarg = false; - if(map.mapdata[mpx][mpy] >= 435 && map.mapdata[mpx][mpy] <= 438) - isgarg = true; - - if (!isgarg) - { - if(!map_isanimated(mpx, mpy)) - return; - } - else - { // it's a garg statue - if(!map_isanimated(mpx, mpy)) - return; - } - - for(i=0; i < 4 ; i++) + if(episode == 1) { - player[0].playcontrol[PA_JUMP+i] = 0; + if(map.mapdata[mpx][mpy] >= 435 && map.mapdata[mpx][mpy] <= 438) + // it's a garg statue + map_chgtile(mpx, mpy, 434); + else + map_chgtile(mpx, mpy, 485); + + strname = "EP1_YSIYM_LVL" + itoa(level); } + else if(episode == 2) + { + // make the switch stop glowing + // There may be a bug. Be careful + map_chgtile(mpx, mpy+1, 432); - const int twirl_speed = 100; + switch(level) + { + case 8: + strname = "EP2_VE_NOJUMPINDARK"; + break; + case 10: + strname = "EP2_VE_EVILBELTS"; + break; + } + } + map_deanimate(mpx, mpy+(episode==2)); - // get the name of the string we need to display - sprintf(strname, "EP1_YSIYM_LVL%d", pCKP->Control.levelcontrol.curlevel); + // In Episode 2 the floor must be deanimated, instead of the player, the player is at.? - dlgX = GetStringAttribute(strname, "LEFT"); - dlgY = GetStringAttribute(strname, "TOP"); - dlgW = GetStringAttribute(strname, "WIDTH"); - dlgH = GetStringAttribute(strname, "HEIGHT"); - twirlX = GetStringAttribute(strname, "TWIRLX"); - twirlY = GetStringAttribute(strname, "TWIRLY"); + CWindow *InfoTextWindow = new CWindow(0.2, 0.2, 0.6, 0.6); + InfoTextWindow->addTextBox(0.0f, 0.0f, 1.0f, 0.8f, getstring(strname), true); + InfoTextWindow->addTextBox(0.2f, 0.8f, 1.0f, 0.2f, "Okay!", true); + g_pInput->flushAll(); - dialogbox(dlgX,dlgY,dlgW,dlgH); - g_pGraphics->drawFont(getstring(strname), (dlgX+1)<<3, (dlgY+1)<<3,0); - - twirlframe = 0; - twirltimer = twirl_speed+1; - // wait for enter do { - if (twirltimer>twirl_speed) - { - g_pGraphics->drawCharacter((dlgX+twirlX)<<3, (dlgY+twirlY)<<3, 9+twirlframe); + g_pInput->pollEvents(); + g_pTimer->SpeedThrottle(); + InfoTextWindow->render(); g_pVideoDriver->update_screen(); - twirlframe++; - if (twirlframe>5) twirlframe=0; - twirltimer=0; - } else twirltimer++; - g_pInput->pollEvents(); - g_pTimer->SpeedThrottle(); - g_pVideoDriver->update_screen(); - } while(!g_pInput->getPressedKey(KENTER) /*&& !immediate_keytable[KQUIT] && !getanyevent(pCKP)*/); + } while(!g_pInput->getPressedAnyCommand()); - // make the statue head stop glowing - if (!isgarg) - { - map_chgtile(mpx, mpy, YORPSTATUEHEADUSED); - map_deanimate(mpx, mpy); - } - else - { // it's a garg statue - - map_chgtile(mpx, mpy, 434); - map_deanimate(mpx, mpy); - } + delete InfoTextWindow; } void VorticonElder(int mpx, int mpy, stCloneKeenPlus *pCKP) { + CWindow *ElderTextWindow; + + /* int twirlframe, twirltimer; int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY; + const int twirl_speed = 100;*/ const char *strName=""; - const int twirl_speed = 100; - for(int i=0; i < 4 ; i++) - { - player[0].playcontrol[PA_JUMP+i] = 0; - } + // TODO: Pause the game, because CWindow won't do that + + g_pInput->flushAll(); g_pSound->pauseSound(); + ElderTextWindow = new CWindow(0.2, 0.2, 0.6, 0.6); + switch(pCKP->Control.levelcontrol.curlevel) { case 8: @@ -260,35 +242,39 @@ void VorticonElder(int mpx, int mpy, stCloneKeenPlus *pCKP) break; } - dlgX = GetStringAttribute(strName, "LEFT"); + /*dlgX = GetStringAttribute(strName, "LEFT"); dlgY = GetStringAttribute(strName, "TOP"); dlgW = GetStringAttribute(strName, "WIDTH"); dlgH = GetStringAttribute(strName, "HEIGHT"); twirlX = GetStringAttribute(strName, "TWIRLX"); - twirlY = GetStringAttribute(strName, "TWIRLY"); + twirlY = GetStringAttribute(strName, "TWIRLY");*/ - dialogbox(dlgX, dlgY, dlgW, dlgH); - g_pGraphics->drawFont( getstring(strName), (dlgX+1)<<3, (dlgY+1)<<3,0); + //dialogbox(dlgX, dlgY, dlgW, dlgH); + //g_pGraphics->drawFont( getstring(strName), (dlgX+1)<<3, (dlgY+1)<<3,0); + // For what was pGraphics->drawFont - twirlframe = 0; - twirltimer = twirl_speed+1; - // wait for enter + //twirlframe = 0; + //twirltimer = twirl_speed+1; + // wait for enter do { - if (twirltimer>twirl_speed) + /*if (twirltimer>twirl_speed) { g_pGraphics->drawCharacter((dlgX+twirlX)<<3, (dlgY+twirlY)<<3, 9+twirlframe); g_pVideoDriver->update_screen(); twirlframe++; if (twirlframe>5) twirlframe=0; twirltimer=0; - } else twirltimer++; - g_pInput->pollEvents(); - g_pTimer->SpeedThrottle(); - g_pVideoDriver->update_screen(); + } else twirltimer++;*/ + + g_pInput->pollEvents(); + g_pTimer->SpeedThrottle(); + ElderTextWindow->render(); + g_pVideoDriver->update_screen(); } while(!g_pInput->getPressedKey(KENTER) ); // make the switch stop glowing + // There may be a bug. Be careful map_chgtile(mpx, mpy+1, 432); map_deanimate(mpx, mpy+1);