Simple tips manager (#4146)

This commit is contained in:
杜茂森 2019-12-18 09:23:06 +08:00 committed by Alayan-stk-2
parent 82f83ea1ec
commit 1ade00462d
12 changed files with 233 additions and 6 deletions

View File

@ -292,6 +292,9 @@ when the border that intersect at this corner are enabled.
<!-- Color used to fade out background when a dialog is shown --> <!-- Color used to fade out background when a dialog is shown -->
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" /> <color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Color used for tips in the loading screen -->
<color type="tips_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Text field color --> <!-- Text field color -->
<color type="text_field" state="background" a="255" r="35" g="35" b="35" /> <color type="text_field" state="background" a="255" r="35" g="35" b="35" />
<color type="text_field" state="background_focused" a="255" r="15" g="15" b="15" /> <color type="text_field" state="background_focused" a="255" r="15" g="15" b="15" />

View File

@ -292,6 +292,9 @@ when the border that intersect at this corner are enabled.
<!-- Color used to fade out background when a dialog is shown --> <!-- Color used to fade out background when a dialog is shown -->
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" /> <color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Color used for tips in the loading screen -->
<color type="tips_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Text field color --> <!-- Text field color -->
<color type="text_field" state="background" a="255" r="200" g="200" b="200" /> <color type="text_field" state="background" a="255" r="200" g="200" b="200" />
<color type="text_field" state="background_focused" a="255" r="223" g="250" b="245" /> <color type="text_field" state="background_focused" a="255" r="223" g="250" b="245" />

View File

@ -291,6 +291,9 @@ when the border that intersect at this corner are enabled.
<!-- Color used to fade out background when a dialog is shown --> <!-- Color used to fade out background when a dialog is shown -->
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" /> <color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Color used for tips in the loading screen -->
<color type="tips_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Text field color --> <!-- Text field color -->
<color type="text_field" state="background" a="255" r="200" g="200" b="200" /> <color type="text_field" state="background" a="255" r="200" g="200" b="200" />
<color type="text_field" state="background_focused" a="255" r="223" g="238" b="248" /> <color type="text_field" state="background_focused" a="255" r="223" g="238" b="248" />

View File

@ -309,6 +309,9 @@ all types of ttf.
<!-- Color used to fade out background when a dialog is shown --> <!-- Color used to fade out background when a dialog is shown -->
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" /> <color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Color used for tips in the loading screen -->
<color type="tips_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Text field color --> <!-- Text field color -->
<color type="text_field" state="background" a="255" r="200" g="200" b="200" /> <color type="text_field" state="background" a="255" r="200" g="200" b="200" />
<color type="text_field" state="background_focused" a="255" r="236" g="226" b="201" /> <color type="text_field" state="background_focused" a="255" r="236" g="226" b="201" />

View File

@ -290,6 +290,9 @@ when the border that intersect at this corner are enabled.
<!-- Color used to fade out background when a dialog is shown --> <!-- Color used to fade out background when a dialog is shown -->
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" /> <color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Color used for tips in the loading screen -->
<color type="tips_background" state="neutral" a="120" r="0" g="0" b="0" />
<!-- Text field color --> <!-- Text field color -->
<color type="text_field" state="background" a="255" r="200" g="200" b="200" /> <color type="text_field" state="background" a="255" r="200" g="200" b="200" />
<color type="text_field" state="background_focused" a="255" r="245" g="220" b="235" /> <color type="text_field" state="background_focused" a="255" r="245" g="220" b="235" />

21
data/tips.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<tips>
<tipset id="general">
<tip text="You can change the skin of gui in UI options."/>
<tip text="You can show more information in game by enabling some options in UI options"/>
<tip text="You can change the font size in UI options"/>
<tip text="You can visit https://supertuxkart.net/ for more information of the game."/>
</tipset>
<tipset id="race">
<tip text="Always do short nitro boosts. Re-use the nitro when your speed goes down again."/>
<tip text="Only use zipper when it is safe. Long straight lines are the best."/>
<tip text="Don't use multiple zippers quickly in row, instead, wait until the speed boost wears off."/>
<tip text="Skid more, and you will find you much faster than before."/>
<tip text="Using nitro after skidding can make you speed-up longer."/>
<tip text="You get a startup boost if you start accelerating during &quot;Set&quot;"/>
<tip text="If you slow down when a parachute attaches your kart, you will get rid of it quickly."/>
<tip text="For safety, try to stay away from other karts unless you have a bubble gum."/>
<tip text="Instead of bubblegum, you can also shoot backward a bowling, cake or plunger to kill a basketball."/>
<tip text="Try to avoid crashing into other karts unless you want to throw a kart off the track."/>
</tipset>
</tips>

View File

@ -684,6 +684,7 @@ namespace GUIEngine
#include "modes/cutscene_world.hpp" #include "modes/cutscene_world.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "states_screens/race_gui_base.hpp" #include "states_screens/race_gui_base.hpp"
#include "tips/tips_manager.hpp"
#include "utils/debug.hpp" #include "utils/debug.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/translation.hpp" #include "utils/translation.hpp"
@ -1357,10 +1358,14 @@ namespace GUIEngine
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
std::vector<irr::video::ITexture*> g_loading_icons; std::vector<irr::video::ITexture*> g_loading_icons;
core::stringw g_tips_string;
void renderLoading(bool clearIcons, bool launching) void renderLoading(bool clearIcons, bool launching, bool update_tips)
{ {
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
if(update_tips)
g_tips_string = _("Tip: ") + TipsManager::get()->getTip("general");
if (clearIcons) g_loading_icons.clear(); if (clearIcons) g_loading_icons.clear();
g_skin->drawBgImage(); g_skin->drawBgImage();
@ -1382,6 +1387,10 @@ namespace GUIEngine
const int screen_w = frame_size.Width; const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height; const int screen_h = frame_size.Height;
// used in drawing tips
const int text_height = getFontHeight() * 1.2f;
const int y_from = screen_h - text_height * 0.3f;
const core::rect< s32 > dest_area = const core::rect< s32 > dest_area =
core::rect< s32 >(screen_w/2 - stretched_size/2, core::rect< s32 >(screen_w/2 - stretched_size/2,
screen_h/2 - stretched_size/2, screen_h/2 - stretched_size/2,
@ -1404,11 +1413,18 @@ namespace GUIEngine
SColor(255,255,255,255), SColor(255,255,255,255),
true/* center h */, false /* center v */ ); true/* center h */, false /* center v */ );
// Draw a tip during loading
core::rect<s32> tipRect(core::position2d<s32>(0, y_from - text_height),
core::dimension2d<s32>(screen_w, text_height));
GL32_draw2DRectangle(Skin::getColor("tips_background::neutral"), tipRect);
Private::g_font->draw(g_tips_string.c_str(), tipRect, Skin::getColor("brighttext::neutral"),
true /* hcenter */, true /* vcenter */);
const int icon_count = (int)g_loading_icons.size(); const int icon_count = (int)g_loading_icons.size();
const int icon_size = (int)(std::min(screen_w, screen_h) / 10.0f); const int icon_size = (int)(std::min(screen_w, screen_h) / 12.0f);
const int ICON_MARGIN = 6; const int ICON_MARGIN = 6;
int x = ICON_MARGIN; int x = ICON_MARGIN;
int y = screen_h - icon_size - ICON_MARGIN; int y = y_from - icon_size - ICON_MARGIN - text_height * 1.2f;
for (int n=0; n<icon_count; n++) for (int n=0; n<icon_count; n++)
{ {
draw2DImage(g_loading_icons[n], draw2DImage(g_loading_icons[n],
@ -1458,7 +1474,7 @@ namespace GUIEngine
g_device->getVideoDriver() g_device->getVideoDriver()
->beginScene(true, true, video::SColor(255,100,101,140)); ->beginScene(true, true, video::SColor(255,100,101,140));
renderLoading(false, true); renderLoading(false, true, false);
g_device->getVideoDriver()->endScene(); g_device->getVideoDriver()->endScene();
} }
else else

View File

@ -232,7 +232,7 @@ namespace GUIEngine
void render(float dt, bool is_loading = false); void render(float dt, bool is_loading = false);
/** \brief renders a "loading" screen */ /** \brief renders a "loading" screen */
void renderLoading(bool clearIcons = true, bool launching = false); void renderLoading(bool clearIcons = true, bool launching = false, bool update_tips = true);
/** \brief to spice up a bit the loading icon : add icons to the loading screen */ /** \brief to spice up a bit the loading icon : add icons to the loading screen */
void addLoadingIcon(irr::video::ITexture* icon); void addLoadingIcon(irr::video::ITexture* icon);

View File

@ -197,6 +197,7 @@
#include "guiengine/engine.hpp" #include "guiengine/engine.hpp"
#include "guiengine/event_handler.hpp" #include "guiengine/event_handler.hpp"
#include "guiengine/dialog_queue.hpp" #include "guiengine/dialog_queue.hpp"
#include "guiengine/message_queue.hpp"
#include "input/device_manager.hpp" #include "input/device_manager.hpp"
#include "input/input_manager.hpp" #include "input/input_manager.hpp"
#include "input/keyboard_device.hpp" #include "input/keyboard_device.hpp"
@ -243,6 +244,7 @@
#include "states_screens/options/user_screen.hpp" #include "states_screens/options/user_screen.hpp"
#include "states_screens/dialogs/init_android_dialog.hpp" #include "states_screens/dialogs/init_android_dialog.hpp"
#include "states_screens/dialogs/message_dialog.hpp" #include "states_screens/dialogs/message_dialog.hpp"
#include "tips/tips_manager.hpp"
#include "tracks/arena_graph.hpp" #include "tracks/arena_graph.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "tracks/track_manager.hpp" #include "tracks/track_manager.hpp"
@ -1792,7 +1794,7 @@ void initRest()
GUIEngine::init(device, driver, StateManager::get()); GUIEngine::init(device, driver, StateManager::get());
GUIEngine::renderLoading(true, true); GUIEngine::renderLoading(true, true, false);
input_manager = new InputManager(); input_manager = new InputManager();
// Get into menu mode initially. // Get into menu mode initially.
input_manager->setMode(InputManager::MENU); input_manager->setMode(InputManager::MENU);
@ -2025,6 +2027,9 @@ int main(int argc, char *argv[])
// ServerConfig will use stk_config for server version testing // ServerConfig will use stk_config for server version testing
stk_config->load(file_manager->getAsset("stk_config.xml")); stk_config->load(file_manager->getAsset("stk_config.xml"));
bool no_graphics = !CommandLine::has("--graphical-server"); bool no_graphics = !CommandLine::has("--graphical-server");
TipsManager::create();
// Load current server config first, if any option is specified than // Load current server config first, if any option is specified than
// override it later // override it later
// Disable sound if found server-config or wan/lan server name // Disable sound if found server-config or wan/lan server name

View File

@ -60,10 +60,12 @@
#include "states_screens/main_menu_screen.hpp" #include "states_screens/main_menu_screen.hpp"
#include "states_screens/online/networking_lobby.hpp" #include "states_screens/online/networking_lobby.hpp"
#include "states_screens/race_setup_screen.hpp" #include "states_screens/race_setup_screen.hpp"
#include "tips/tips_manager.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "tracks/track_manager.hpp" #include "tracks/track_manager.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/translation.hpp" #include "utils/translation.hpp"
#include <algorithm> #include <algorithm>
/** Constructor, initialises internal data structures. /** Constructor, initialises internal data structures.
@ -141,6 +143,9 @@ void RaceResultGUI::init()
m_start_track = 0; m_start_track = 0;
m_end_track = (int)tracks.size(); m_end_track = (int)tracks.size();
} }
core::stringw tips_string = _("Tip: ") + TipsManager::get()->getTip("race");
MessageQueue::add(MessageQueue::MT_GENERIC, tips_string);
} // init } // init
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

90
src/tips/tips_manager.cpp Normal file
View File

@ -0,0 +1,90 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2019 dumaosen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "tips/tips_manager.hpp"
#include "io/file_manager.hpp"
#include "utils/log.hpp"
#include "utils/random_generator.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
TipsManager* TipsManager::m_tips_manager = NULL;
// ----------------------------------------------------------------------------
/** Constructor, which reads data/tips.xml and stores the information
* in objects.
*/
TipsManager::TipsManager()
{
const std::string file_name = file_manager->getAsset("tips.xml");
const XMLNode *root = file_manager->createXMLTree(file_name);
unsigned int num_nodes = root->getNumNodes();
for(unsigned int i = 0; i < num_nodes; i++)
{
const XMLNode *node = root->getNode(i);
addTipSet(node);
}
if(num_nodes != m_all_tip_sets.size())
Log::error("TipsManager",
"Multiple tipsets with the same id!");
delete root;
} // TipsManager
// ----------------------------------------------------------------------------
TipsManager::~TipsManager()
{
m_all_tip_sets.clear();
} // ~TipsManager
// ----------------------------------------------------------------------------
void TipsManager::addTipSet(const XMLNode *input)
{
std::string id;
if(!input->get("id", &id))
Log::error("TipSet",
"Undefined id for tipset.");
for(unsigned int n = 0; n < input->getNumNodes(); n++)
{
const XMLNode *node = input->getNode(n);
if (node->getName() != "tip")
continue; // ignore incorrect node
std::string text;
if(!node->get("text", &text))
continue; // missing text, ignore node
// Gettext is used here
m_all_tip_sets[id].push_back(_(text.c_str()));
}
if(m_all_tip_sets[id].size() != input->getNumNodes())
Log::error("TipSet",
"Incorrect tips for the entries of tipset \"%s\".", id.c_str());
}
// ----------------------------------------------------------------------------
irr::core::stringw TipsManager::getTip(std::string id)
{
RandomGenerator randgen;
return m_all_tip_sets[id][randgen.get(m_all_tip_sets[id].size())];
} // getTipSet

75
src/tips/tips_manager.hpp Normal file
View File

@ -0,0 +1,75 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2019 dumaosen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_TIPS_MANAGER_HPP
#define HEADER_TIPS_MANAGER_HPP
#include "io/xml_node.hpp"
#include <assert.h>
#include <irrString.h>
#include <string>
#include <map>
#include <vector>
typedef std::vector<irr::core::stringw> TipSet;
/** This class manages the list of all tips. It reads the
* data/tips.xml file, which contains the contents for
* each tip.
*/
class TipsManager
{
private:
/** Pointer to the single instance. */
static TipsManager *m_tips_manager;
std::map<std::string, TipSet> m_all_tip_sets;
TipsManager ();
~TipsManager ();
void addTipSet(const XMLNode *input);
public:
/** Static function to create the instance of the tips manager. */
static void create()
{
assert(!m_tips_manager);
m_tips_manager = new TipsManager();
} // create
// ------------------------------------------------------------------------
/** Static function to get the tips manager. */
static TipsManager* get()
{
assert(m_tips_manager);
return m_tips_manager;
} // get
// ------------------------------------------------------------------------
static void destroy()
{
delete m_tips_manager;
m_tips_manager = NULL;
} // destroy
// ========================================================================
/** Get a tip by ID. */
irr::core::stringw getTip(std::string id);
// ------------------------------------------------------------------------
}; // class TipsManager
#endif