diff options
Diffstat (limited to 'src/game.cpp')
-rw-r--r-- | src/game.cpp | 516 |
1 files changed, 88 insertions, 428 deletions
diff --git a/src/game.cpp b/src/game.cpp index 046b7bdbf..a2d94ac0a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -59,6 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "subgame.h" #include "quicktune_shortcutter.h" #include "clientmap.h" +#include "hud.h" #include "sky.h" #include "sound.h" #if USE_SOUND @@ -230,296 +231,6 @@ public: }; /* - Item draw routine -*/ -void draw_item(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, - v2s32 upperleftpos, s32 imgsize, s32 itemcount, - InventoryList *mainlist, u16 selectitem, unsigned short int direction) - //NOTE: selectitem = 0 -> no selected; selectitem 1-based - //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top -{ - s32 padding = imgsize/12; - s32 height = imgsize + padding*2; - s32 width = itemcount*(imgsize+padding*2); - if(direction == 2 or direction == 3){ - width = imgsize + padding*2; - height = itemcount*(imgsize+padding*2); - } - s32 fullimglen = imgsize + padding*2; - - // Position of upper left corner of bar - v2s32 pos = upperleftpos; - - // Draw background color - /*core::rect<s32> barrect(0,0,width,height); - barrect += pos; - video::SColor bgcolor(255,128,128,128); - driver->draw2DRectangle(bgcolor, barrect, NULL);*/ - - core::rect<s32> imgrect(0,0,imgsize,imgsize); - - for(s32 i=0; i<itemcount; i++) - { - const ItemStack &item = mainlist->getItem(i); - - v2s32 steppos; - if(direction == 1){ - steppos = v2s32(-(padding+i*fullimglen), padding); - } else if(direction == 2) { - steppos = v2s32(padding, padding+i*fullimglen); - } else if(direction == 3) { - steppos = v2s32(padding, -(padding+i*fullimglen)); - } else { - steppos = v2s32(padding+i*fullimglen, padding); - } - core::rect<s32> rect = imgrect + pos - + steppos; - - if(selectitem == (i+1)) - { - video::SColor c_outside(255,255,0,0); - //video::SColor c_outside(255,0,0,0); - //video::SColor c_inside(255,192,192,192); - s32 x1 = rect.UpperLeftCorner.X; - s32 y1 = rect.UpperLeftCorner.Y; - s32 x2 = rect.LowerRightCorner.X; - s32 y2 = rect.LowerRightCorner.Y; - // Black base borders - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1 - padding), - v2s32(x2 + padding, y1) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y2), - v2s32(x2 + padding, y2 + padding) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding, y2) - ), NULL); - /*// Light inside borders - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1 - padding/2), - v2s32(x2 + padding/2, y1) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y2), - v2s32(x2 + padding/2, y2 + padding/2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding/2, y2) - ), NULL); - */ - } - - video::SColor bgcolor2(128,0,0,0); - driver->draw2DRectangle(bgcolor2, rect, NULL); - drawItemStack(driver, font, item, rect, NULL, gamedef); - } -} - -/* - Statbar draw routine -*/ -void draw_statbar(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef, - v2s32 upperleftpos, std::string texture, s32 count) - //NOTE: selectitem = 0 -> no selected; selectitem 1-based - //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top -{ - video::ITexture *stat_texture = - gamedef->getTextureSource()->getTextureRaw(texture); - if(stat_texture) - { - v2s32 p = upperleftpos; - for(s32 i=0; i<count/2; i++) - { - core::dimension2di srcd(stat_texture->getOriginalSize()); - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,srcd.Width,srcd.Height); - rect += p; - driver->draw2DImage(stat_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), srcd), - NULL, colors, true); - p += v2s32(srcd.Width,0); - } - if(count % 2 == 1) - { - core::dimension2di srcd(stat_texture->getOriginalSize()); - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,srcd.Width/2,srcd.Height); - rect += p; - srcd.Width /= 2; - driver->draw2DImage(stat_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), srcd), - NULL, colors, true); - p += v2s32(srcd.Width*2,0); - } - } -} - -/* - Hotbar draw routine -*/ -void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, - IGameDef *gamedef, - v2s32 centerlowerpos, s32 imgsize, s32 itemcount, - Inventory *inventory, s32 halfheartcount, u16 playeritem) -{ - InventoryList *mainlist = inventory->getList("main"); - if(mainlist == NULL) - { - errorstream<<"draw_hotbar(): mainlist == NULL"<<std::endl; - return; - } -#if 0 - s32 padding = imgsize/12; - //s32 height = imgsize + padding*2; - s32 width = itemcount*(imgsize+padding*2); - - // Position of upper left corner of bar - v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2); - - // Draw background color - /*core::rect<s32> barrect(0,0,width,height); - barrect += pos; - video::SColor bgcolor(255,128,128,128); - driver->draw2DRectangle(bgcolor, barrect, NULL);*/ - - core::rect<s32> imgrect(0,0,imgsize,imgsize); - - for(s32 i=0; i<itemcount; i++) - { - const ItemStack &item = mainlist->getItem(i); - - core::rect<s32> rect = imgrect + pos - + v2s32(padding+i*(imgsize+padding*2), padding); - - if(playeritem == i) - { - video::SColor c_outside(255,255,0,0); - //video::SColor c_outside(255,0,0,0); - //video::SColor c_inside(255,192,192,192); - s32 x1 = rect.UpperLeftCorner.X; - s32 y1 = rect.UpperLeftCorner.Y; - s32 x2 = rect.LowerRightCorner.X; - s32 y2 = rect.LowerRightCorner.Y; - // Black base borders - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1 - padding), - v2s32(x2 + padding, y1) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y2), - v2s32(x2 + padding, y2 + padding) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x1 - padding, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_outside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding, y2) - ), NULL); - /*// Light inside borders - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1 - padding/2), - v2s32(x2 + padding/2, y1) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y2), - v2s32(x2 + padding/2, y2 + padding/2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x1 - padding/2, y1), - v2s32(x1, y2) - ), NULL); - driver->draw2DRectangle(c_inside, - core::rect<s32>( - v2s32(x2, y1), - v2s32(x2 + padding/2, y2) - ), NULL); - */ - } - - video::SColor bgcolor2(128,0,0,0); - driver->draw2DRectangle(bgcolor2, rect, NULL); - drawItemStack(driver, font, item, rect, NULL, gamedef); - } -#else - s32 padding = imgsize/12; - s32 width = itemcount*(imgsize+padding*2); - v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2); - draw_item(driver, font, gamedef, pos, imgsize, itemcount, - mainlist, playeritem + 1, 0); -#endif -#if 0 - /* - Draw hearts - */ - video::ITexture *heart_texture = - gamedef->getTextureSource()->getTextureRaw("heart.png"); - if(heart_texture) - { - v2s32 p = pos + v2s32(0, -20); - for(s32 i=0; i<halfheartcount/2; i++) - { - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,16,16); - rect += p; - driver->draw2DImage(heart_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), - core::dimension2di(heart_texture->getOriginalSize())), - NULL, colors, true); - p += v2s32(16,0); - } - if(halfheartcount % 2 == 1) - { - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::rect<s32> rect(0,0,16/2,16); - rect += p; - core::dimension2di srcd(heart_texture->getOriginalSize()); - srcd.Width /= 2; - driver->draw2DImage(heart_texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), srcd), - NULL, colors, true); - p += v2s32(16,0); - } - } -#else - draw_statbar(driver, font, gamedef, pos + v2s32(0, -20), - "heart.png", halfheartcount); -#endif -} - -/* Check if a node is pointable */ inline bool isPointableNode(const MapNode& n, @@ -1103,14 +814,8 @@ void the_game( // Calculate text height using the font u32 text_height = font->getDimension(L"Random test string").Height; - v2u32 screensize(0,0); v2u32 last_screensize(0,0); - screensize = driver->getScreenSize(); - - const s32 hotbar_itemcount = 8; - //const s32 hotbar_imagesize = 36; - //const s32 hotbar_imagesize = 64; - s32 hotbar_imagesize = 48; + v2u32 screensize = driver->getScreenSize(); /* Draw "Loading" screen @@ -1534,6 +1239,12 @@ void the_game( LocalPlayer* player = client.getEnv().getLocalPlayer(); player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; + + /* + HUD object + */ + Hud hud(driver, guienv, font, text_height, + gamedef, player, &local_inventory); for(;;) { @@ -1707,13 +1418,11 @@ void the_game( v2s32 displaycenter(screensize.X/2,screensize.Y/2); //bool screensize_changed = screensize != last_screensize; - // Resize hotbar - if(screensize.Y <= 800) - hotbar_imagesize = 32; - else if(screensize.Y <= 1280) - hotbar_imagesize = 48; - else - hotbar_imagesize = 64; + + // Update HUD values + hud.screensize = screensize; + hud.displaycenter = displaycenter; + hud.resizeHotbar(); // Hilight boxes collected during the loop and displayed std::vector<aabb3f> hilightboxes; @@ -2077,7 +1786,7 @@ void the_game( { s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1, - hotbar_itemcount-1); + hud.hotbar_itemcount-1); if(wheel < 0) { @@ -2101,7 +1810,7 @@ void the_game( const KeyPress *kp = NumberKey + (i + 1) % 10; if(input->wasKeyDown(*kp)) { - if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount) + if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount) { new_playeritem = i; @@ -2390,8 +2099,18 @@ void the_game( } else if (event.type == CE_HUDADD) { - HudElement* e = new HudElement; - e->type = event.hudadd.type; + u32 id = event.hudadd.id; + size_t nhudelem = player->hud.size(); + if (id > nhudelem || (id < nhudelem && player->hud[id])) { + delete event.hudadd.pos; + delete event.hudadd.name; + delete event.hudadd.scale; + delete event.hudadd.text; + continue; + } + + HudElement *e = new HudElement; + e->type = (HudElementType)event.hudadd.type; e->pos = *event.hudadd.pos; e->name = *event.hudadd.name; e->scale = *event.hudadd.scale; @@ -2399,33 +2118,61 @@ void the_game( e->number = event.hudadd.number; e->item = event.hudadd.item; e->dir = event.hudadd.dir; - player->hud[event.hudadd.id] = e; - delete(event.hudadd.pos); - delete(event.hudadd.name); - delete(event.hudadd.scale); - delete(event.hudadd.text); + + if (id == nhudelem) + player->hud.push_back(e); + else + player->hud[id] = e; + + delete event.hudadd.pos; + delete event.hudadd.name; + delete event.hudadd.scale; + delete event.hudadd.text; } else if (event.type == CE_HUDRM) { - player->hud.erase(event.hudrm.id); + u32 id = event.hudrm.id; + if (id < player->hud.size() && player->hud[id]) { + delete player->hud[id]; + player->hud[id] = NULL; + } } else if (event.type == CE_HUDCHANGE) { - HudElement* e = player->hud[event.hudchange.id]; - if(event.hudchange.stat == 0) - e->pos = *event.hudchange.v2fdata; - else if(event.hudchange.stat == 1) - e->name = *event.hudchange.sdata; - else if(event.hudchange.stat == 2) - e->scale = *event.hudchange.v2fdata; - else if(event.hudchange.stat == 3) - e->text = *event.hudchange.sdata; - else if(event.hudchange.stat == 4) - e->number = event.hudchange.data; - else if(event.hudchange.stat == 5) - e->item = event.hudchange.data; - else if(event.hudchange.stat == 6) - e->dir = event.hudchange.data; + u32 id = event.hudchange.id; + if (id >= player->hud.size() || !player->hud[id]) { + delete event.hudchange.v2fdata; + delete event.hudchange.sdata; + continue; + } + + HudElement* e = player->hud[id]; + switch (event.hudchange.stat) { + case HUD_STAT_POS: + e->pos = *event.hudchange.v2fdata; + break; + case HUD_STAT_NAME: + e->name = *event.hudchange.sdata; + break; + case HUD_STAT_SCALE: + e->scale = *event.hudchange.v2fdata; + break; + case HUD_STAT_TEXT: + e->text = *event.hudchange.sdata; + break; + case HUD_STAT_NUMBER: + e->number = event.hudchange.data; + break; + case HUD_STAT_ITEM: + e->item = event.hudchange.data; + break; + case HUD_STAT_DIR: + e->dir = event.hudchange.data; + break; + } + + delete event.hudchange.v2fdata; + delete event.hudchange.sdata; } } } @@ -3203,7 +2950,6 @@ void the_game( */ TimeTaker tt_draw("mainloop: draw"); - { TimeTaker timer("beginScene"); @@ -3307,26 +3053,8 @@ void the_game( driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - if(show_hud) - { - v3f selectionbox_color = g_settings->getV3F("selectionbox_color"); - u32 selectionbox_color_r = rangelim(myround(selectionbox_color.X), 0, 255); - u32 selectionbox_color_g = rangelim(myround(selectionbox_color.Y), 0, 255); - u32 selectionbox_color_b = rangelim(myround(selectionbox_color.Z), 0, 255); - - for(std::vector<aabb3f>::const_iterator - i = hilightboxes.begin(); - i != hilightboxes.end(); i++) - { - /*infostream<<"hilightbox min=" - <<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")" - <<" max=" - <<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")" - <<std::endl;*/ - driver->draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b)); - } - } - + if (show_hud) + hud.drawSelectionBoxes(hilightboxes); /* Wielded tool */ @@ -3354,22 +3082,9 @@ void the_game( /* Draw crosshair */ - if(show_hud) - { - v3f crosshair_color = g_settings->getV3F("crosshair_color"); - u32 crosshair_color_r = rangelim(myround(crosshair_color.X), 0, 255); - u32 crosshair_color_g = rangelim(myround(crosshair_color.Y), 0, 255); - u32 crosshair_color_b = rangelim(myround(crosshair_color.Z), 0, 255); - u32 crosshair_alpha = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255); - - driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0), - displaycenter + core::vector2d<s32>(10,0), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10), - displaycenter + core::vector2d<s32>(0,10), - video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); - } - + if (show_hud) + hud.drawCrosshair(); + } // timer //timer10.stop(); @@ -3379,11 +3094,9 @@ void the_game( /* Draw hotbar */ - if(show_hud) + if (show_hud) { - draw_hotbar(driver, font, gamedef, - v2s32(displaycenter.X, screensize.Y), - hotbar_imagesize, hotbar_itemcount, &local_inventory, + hud.drawHotbar(v2s32(displaycenter.X, screensize.Y), client.getHP(), client.getPlayerItem()); } @@ -3413,54 +3126,8 @@ void the_game( /* Draw lua hud items */ - std::deque<gui::IGUIStaticText *> luaguitexts; - if(show_hud) - { - for(std::map<u32, HudElement*>::iterator it = player->hud.begin(); - it != player->hud.end(); ++it) - { - HudElement* e = it->second; - v2f posp(e->pos * v2f(screensize.X, screensize.Y)); - core::vector2d<s32> pos(posp.X, posp.Y); - if(e->type == 'I'){ //Img - video::ITexture *texture = - gamedef->getTextureSource()->getTextureRaw(e->text); - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - core::dimension2di imgsize(texture->getOriginalSize()); - core::rect<s32> rect(0, 0, imgsize.Width*e->scale.X, - imgsize.Height*e->scale.X); - rect += pos; - driver->draw2DImage(texture, rect, - core::rect<s32>(core::position2d<s32>(0,0), imgsize), - NULL, colors, true); - } else if(e->type == 'T') { //Text - std::wstring t; - t.assign(e->text.begin(), e->text.end()); - gui::IGUIStaticText *luaguitext = guienv->addStaticText( - t.c_str(), - core::rect<s32>(0, 0, e->scale.X, text_height*(e->scale.Y))+pos, - false, false); - luaguitexts.push_back(luaguitext); - } else if(e->type == 'S') { //Statbar - draw_statbar(driver, font, gamedef, pos, e->text, e->number); - } else if(e->type == 's') { //Non-conflict Statbar - v2s32 p(displaycenter.X - 143, screensize.Y - 76); - p.X += e->pos.X*173; - p.Y += e->pos.X*20; - p.Y -= e->pos.Y*20; - draw_statbar(driver, font, gamedef, p, e->text, e->number); - } else if(e->type == 'i') { //Inv - InventoryList* inv = local_inventory.getList(e->text); - draw_item(driver, font, gamedef, pos, hotbar_imagesize, - e->number, inv, e->item, e->dir); - } else { - actionstream<<"luadraw: ignoring drawform "<<it->second<< - "of key "<<it->first<<" due to incorrect command."<<std::endl; - continue; - } - } - } + if (show_hud) + hud.drawLuaElements(); /* Draw gui @@ -3469,13 +3136,6 @@ void the_game( guienv->drawAll(); /* - Remove lua-texts - */ - for(std::deque<gui::IGUIStaticText *>::iterator it = luaguitexts.begin(); - it != luaguitexts.end(); ++it) - (*it)->remove(); - - /* End scene */ { @@ -3517,11 +3177,11 @@ void the_game( /* Drop stuff */ - if(clouds) + if (clouds) clouds->drop(); - if(gui_chat_console) + if (gui_chat_console) gui_chat_console->drop(); - clear_particles (); + clear_particles(); /* Draw a "shutting down" screen, which will be shown while the map |