src/interface/interface.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * Graphical interface showing various information about the game.
00020  *****************************************************************************/
00021 
00022 #include "interface.h"
00023 #include "mouse.h"
00024 #include <iostream>
00025 #include <SDL.h>
00026 #include <sstream>
00027 #include "../game/game_loop.h"
00028 #include "../game/game_mode.h"
00029 #include "../game/time.h"
00030 #include "../graphic/colors.h"
00031 #include "../graphic/video.h"
00032 #include "../graphic/font.h"
00033 #include "../include/app.h"
00034 #include "../map/camera.h"
00035 #include "../map/map.h"
00036 #include "../team/teams_list.h"
00037 #include "../team/macro.h"
00038 #include "../tool/debug.h"
00039 #include "../tool/string_tools.h"
00040 #include "../tool/i18n.h"
00041 #include "../tool/resource_manager.h"
00042 #include "../weapon/weapons_list.h"
00043 
00044 WeaponStrengthBar weapon_strength_bar;
00045 
00046 const Point2i BORDER_POSITION(5, 5);
00047 
00048 const uint MARGIN = 10;
00049 
00050 Interface * Interface::singleton = NULL;
00051 
00052 Interface * Interface::GetInstance()
00053 {
00054   if (singleton == NULL) {
00055     singleton = new Interface();
00056   }
00057   return singleton;
00058 }
00059 
00060 Interface::Interface()
00061 {
00062   display = true;
00063   start_hide_display = 0;
00064   start_show_display = 0;
00065 
00066   Profile *res = resource_manager.LoadXMLProfile( "graphism.xml", false);
00067   game_menu = resource_manager.LoadImage( res, "interface/background_interface");
00068   small_background_interface = resource_manager.LoadImage( res, "interface/small_background_interface");
00069   clock_background = resource_manager.LoadImage( res, "interface/clock_background");
00070   clock = new Sprite(resource_manager.LoadImage( res, "interface/clock"));
00071   wind_icon = resource_manager.LoadImage( res, "interface/wind");
00072   wind_indicator = resource_manager.LoadImage( res, "interface/wind_indicator");
00073 
00074   // energy bar
00075   energy_bar.InitVal(0, 0, GameMode::GetInstance()->character.init_energy);
00076   energy_bar.InitPos(0, 0, 120, 15);
00077 
00078   // wind bar
00079   wind_bar.InitPos(0, 0, wind_indicator.GetWidth() - 4, wind_indicator.GetHeight() - 4);
00080   wind_bar.InitVal(0, -100, 100);
00081   wind_bar.border_color.SetColor(0, 0, 0, 0);
00082   wind_bar.background_color.SetColor(0, 0, 0, 0);
00083   wind_bar.value_color = c_red;
00084   wind_bar.SetReferenceValue (true, 0);
00085 
00086   // strength bar initialisation
00087   weapon_strength_bar.InitPos (0, 0, 400, 20);
00088   weapon_strength_bar.InitVal (0, 0, 100);
00089 
00090   weapon_strength_bar.SetValueColor(resource_manager.LoadColor(res, "interface/weapon_strength_bar_value"));
00091   weapon_strength_bar.SetBorderColor(resource_manager.LoadColor(res, "interface/weapon_strength_bar_border"));
00092   weapon_strength_bar.SetBackgroundColor(resource_manager.LoadColor(res, "interface/weapon_strength_bar_background"));
00093 
00094   // constant text initialisation
00095   Font * big_font = Font::GetInstance(Font::FONT_BIG,Font::NORMAL);
00096   Font * normal_font_bold = Font::GetInstance(Font::FONT_NORMAL,Font::BOLD);
00097   Font * small_font_bold = Font::GetInstance(Font::FONT_SMALL,Font::BOLD);
00098 
00099   Color text_color = resource_manager.LoadColor(res, "interface/text_color");
00100   Color energy_text_color = resource_manager.LoadColor(res, "interface/energy_text_color");
00101   Color turn_timer_text_color = resource_manager.LoadColor(res, "interface/turn_timer_text_color");
00102   Color global_clock_text_color = resource_manager.LoadColor(res, "interface/global_clock_text_color");
00103 
00104   global_timer = new Text(ulong2str(0), gray_color, big_font, false);
00105   timer = new Text(ulong2str(0), black_color, normal_font_bold, false);
00106 
00107   t_character_name = new Text("None", text_color, small_font_bold, false);
00108   t_team_name = new Text("None", text_color, small_font_bold, false);
00109   t_player_name = new Text("None", text_color, small_font_bold, false);
00110   t_weapon_name = new Text("None", text_color, small_font_bold, false);
00111   t_weapon_stock = new Text("0", text_color, small_font_bold, false);
00112   t_character_energy = new Text("Dead", energy_text_color, small_font_bold);
00113 
00114   resource_manager.UnLoadXMLProfile( res);
00115 }
00116 
00117 Interface::~Interface()
00118 {
00119   if (global_timer) delete global_timer;
00120   if (timer) delete timer;
00121   if (t_character_name) delete t_character_name;
00122   if (t_team_name) delete t_team_name;
00123   if (t_player_name) delete t_player_name;
00124   if (t_character_energy) delete t_character_energy;
00125   if (t_weapon_name) delete t_weapon_name;
00126   if (t_weapon_stock) delete t_weapon_stock;
00127 }
00128 
00129 void Interface::Reset()
00130 {
00131   start_hide_display = 0;
00132   start_show_display = 0;
00133   character_under_cursor = NULL;
00134   weapon_under_cursor = NULL;
00135   weapons_menu.Reset();
00136   energy_bar.InitVal(0, 0, GameMode::GetInstance()->character.init_energy);
00137 }
00138 
00139 void Interface::DrawCharacterInfo()
00140 {
00141   AppWormux * app = AppWormux::GetInstance();
00142   Point2i pos = (app->video.window.GetSize() - GetSize()) * Point2d(0.5, 1);
00143 
00144   // Get the character
00145   if (character_under_cursor == NULL) character_under_cursor = &ActiveCharacter();
00146 
00147   // Display energy bar
00148   Point2i energy_bar_offset = BORDER_POSITION + Point2i(MARGIN + character_under_cursor->GetTeam().flag.GetWidth(),
00149                                                         character_under_cursor->GetTeam().flag.GetHeight() / 2);
00150   energy_bar.DrawXY(bottom_bar_pos + energy_bar_offset);
00151 
00152   // Display team logo
00153   app->video.window.Blit(character_under_cursor->GetTeam().flag, bottom_bar_pos + BORDER_POSITION);
00154 
00155   // Display team name
00156   t_team_name->Set(character_under_cursor->GetTeam().GetName());
00157   Point2i team_name_offset = energy_bar_offset + Point2i(energy_bar.GetWidth() / 2, energy_bar.GetHeight() + t_team_name->GetHeight() / 2);
00158   t_team_name->DrawCenter(bottom_bar_pos + team_name_offset);
00159 
00160   // Display character's name
00161   t_character_name->Set(character_under_cursor->GetName());
00162   Point2i character_name_offset = energy_bar_offset + Point2i((energy_bar.GetWidth() > t_character_name->GetWidth() ? energy_bar.GetWidth() : t_character_name->GetWidth()) / 2, -t_character_name->GetHeight() / 2);
00163   t_character_name->DrawCenter(bottom_bar_pos + character_name_offset);
00164 
00165   // Display player's name
00166   t_player_name->Set(_("general: ") + character_under_cursor->GetTeam().GetPlayerName());
00167   Point2i player_name_offset = energy_bar_offset + Point2i(energy_bar.GetWidth() / 2, t_team_name->GetHeight() + t_player_name->GetHeight() + MARGIN);
00168   t_player_name->DrawCenter(bottom_bar_pos + player_name_offset);
00169 
00170   // Display energy
00171   if (!character_under_cursor->IsDead()) {
00172     t_character_energy->Set(ulong2str(character_under_cursor->GetEnergy())+"%");
00173     energy_bar.Actu(character_under_cursor->GetEnergy());
00174   } else {
00175     t_character_energy->Set(_("(dead)"));
00176     energy_bar.Actu(0);
00177   }
00178 
00179   t_character_energy->DrawCenter(bottom_bar_pos + energy_bar_offset + energy_bar.GetSize()/2);
00180 }
00181 
00182 void Interface::DrawWeaponInfo() const
00183 {
00184   Weapon* weapon;
00185   int nbr_munition;
00186   float icon_scale_factor = 0.75;
00187 
00188   // Get the weapon
00189   if(weapon_under_cursor==NULL) {
00190     weapon = &ActiveTeam().AccessWeapon();
00191     nbr_munition = ActiveTeam().ReadNbAmmos();
00192   } else {
00193     weapon = weapon_under_cursor;
00194     nbr_munition = ActiveTeam().ReadNbAmmos(weapon_under_cursor->GetName());
00195     icon_scale_factor = cos((float)Time::GetInstance()->Read() / 1000 * M_PI) * 0.9;
00196   }
00197 
00198   std::string tmp;
00199 
00200   // Draw weapon name
00201   t_weapon_name->Set(weapon->GetName());
00202   Point2i weapon_name_offset = Point2i(game_menu.GetWidth() / 2 - clock_background.GetWidth() / 2 - t_weapon_name->GetWidth() - MARGIN, 0);
00203   t_weapon_name->DrawTopLeft(bottom_bar_pos + weapon_name_offset);
00204 
00205   // Display number of ammo
00206   t_weapon_stock->Set((nbr_munition ==  INFINITE_AMMO ? _("(unlimited)") : _("Stock:") + Format("%i", nbr_munition)));
00207   Point2i weapon_stock_offset = Point2i(game_menu.GetWidth() / 2 - clock_background.GetWidth() / 2 - t_weapon_stock->GetWidth() - MARGIN, t_weapon_name->GetHeight());
00208   t_weapon_stock->DrawTopLeft(bottom_bar_pos + weapon_stock_offset);
00209 
00210   // Draw weapon icon
00211   weapon->GetIcon().Scale(icon_scale_factor, 0.75);
00212   Point2i weapon_icon_offset = game_menu.GetSize() / 2 - weapon->GetIcon().GetSize() / 2 + Point2i(- clock_background.GetWidth(), MARGIN);
00213   weapon->GetIcon().DrawXY(bottom_bar_pos + weapon_icon_offset);
00214 }
00215 
00216 void Interface::DrawTimeInfo() const
00217 {
00218   AppWormux * app = AppWormux::GetInstance();
00219   Point2i turn_time_pos = (app->video.window.GetSize() - clock_background.GetSize()) * Point2d(0.5, 1) + 
00220       Point2i(0, - GetHeight() + clock_background.GetHeight());
00221   Rectanglei dr(turn_time_pos, clock_background.GetSize());
00222 
00223   // Draw background interface
00224   app->video.window.Blit(clock_background, turn_time_pos);
00225   world.ToRedrawOnScreen(dr);
00226   DrawClock(turn_time_pos + clock_background.GetSize() / 2);
00227 }
00228 
00229 // display time left in a turn
00230 void Interface::DrawClock(const Point2i &time_pos) const
00231 {
00232   // Draw turn time
00233   if (display_timer)
00234     timer->DrawCenter(time_pos - Point2i(0, clock_background.GetHeight()/3));
00235 
00236   // Draw clock
00237   float scale;
00238   if(remaining_turn_time < 10)  // Hurry up !
00239     scale = 0.9 + cos((float)Time::GetInstance()->Read() / 250 * M_PI) * 0.1;
00240   else
00241     scale = 1.0;
00242   clock->Scale(1.0, scale);
00243   Point2i tmp_point = time_pos - clock->GetSize() / 2;
00244   clock->DrawXY(tmp_point);
00245 
00246   // Draw global timer
00247   std::string tmp(Time::GetInstance()->GetString());
00248   global_timer->Set(tmp);
00249   global_timer->DrawCenter(time_pos + Point2i(0, clock_background.GetHeight()/3));
00250 }
00251 
00252 // draw wind indicator
00253 void Interface::DrawWindIndicator(const Point2i &wind_bar_pos, const bool draw_icon) const
00254 {
00255   AppWormux * app = AppWormux::GetInstance();
00256   int height;
00257 
00258   // draw wind icon
00259   if(draw_icon) {
00260     app->video.window.Blit(wind_icon, wind_bar_pos);
00261     world.ToRedrawOnScreen(Rectanglei(wind_bar_pos, wind_icon.GetSize()));
00262     height = wind_icon.GetHeight() - wind_indicator.GetHeight();
00263   } else {
00264     height = MARGIN;
00265   }
00266 
00267   // draw wind indicator
00268   Point2i wind_bar_offset = Point2i(0, height);
00269   Point2i tmp = wind_bar_pos + wind_bar_offset + Point2i(2, 2);
00270   app->video.window.Blit(wind_indicator, wind_bar_pos + wind_bar_offset);
00271   wind_bar.DrawXY(tmp);
00272   world.ToRedrawOnScreen(Rectanglei(wind_bar_pos + wind_bar_offset, wind_indicator.GetSize()));
00273 }
00274 
00275 // display wind info
00276 void Interface::DrawWindInfo() const
00277 {
00278   Point2i wind_pos_offset = Point2i(game_menu.GetWidth() / 2 + clock_background.GetWidth() / 2 + MARGIN, game_menu.GetHeight() / 2 - wind_icon.GetHeight() / 2);
00279   DrawWindIndicator(bottom_bar_pos + wind_pos_offset, true);
00280 }
00281 
00282 // draw mini info when hidding interface
00283 void Interface::DrawSmallInterface() const
00284 {
00285   if(display) return;
00286   AppWormux * app = AppWormux::GetInstance();
00287   int height;
00288   height = ((int)Time::GetInstance()->Read() - start_hide_display - 1000) / 3 - 30;
00289   height = (height > 0 ? height : 0);
00290   height = (height < small_background_interface.GetHeight() ? height : small_background_interface.GetHeight());
00291   Point2i small_interface_position = Point2i(app->video.window.GetWidth() / 2 - small_background_interface.GetWidth() / 2, app->video.window.GetHeight() - height);
00292   app->video.window.Blit(small_background_interface,small_interface_position);
00293   world.ToRedrawOnScreen(Rectanglei(small_interface_position,small_background_interface.GetSize()));
00294   DrawWindIndicator(small_interface_position + Point2i(MARGIN, 0), false);
00295   if (display_timer)
00296     timer->DrawTopLeft(small_interface_position + Point2i(MARGIN * 2 + wind_bar.GetWidth(), MARGIN));
00297 }
00298 
00299 // draw team energy
00300 void Interface::DrawTeamEnergy() const
00301 {
00302   Point2i team_bar_offset = Point2i(game_menu.GetWidth() / 2 + clock_background.GetWidth() / 2 + wind_icon.GetWidth() + MARGIN, MARGIN);
00303   FOR_EACH_TEAM(tmp_team) {
00304     if(!display) // Fix bug #7753 (Team energy bar visible when the interface is hidden)
00305       (**tmp_team).GetEnergyBar().FinalizeMove();
00306     (**tmp_team).DrawEnergy(bottom_bar_pos + team_bar_offset);
00307   }
00308 }
00309 
00310 void Interface::Draw()
00311 {
00312   AppWormux * app = AppWormux::GetInstance();
00313   bottom_bar_pos = (app->video.window.GetSize() - GetSize()) * Point2d(0.5, 1);
00314 
00315   if ( GameLoop::GetInstance()->ReadState() == GameLoop::PLAYING && weapon_strength_bar.visible)
00316   {
00317     // Position on the screen
00318     Point2i barPos = (app->video.window.GetSize() - weapon_strength_bar.GetSize()) * Point2d(0.5, 1)
00319         - Point2i(0, game_menu.GetHeight() + MARGIN);
00320 
00321     // Drawing on the screen
00322      weapon_strength_bar.DrawXY(barPos);
00323   }
00324 
00325   weapons_menu.Draw();
00326 
00327   // Display the background of both Character info and weapon info
00328   Rectanglei dr(bottom_bar_pos, game_menu.GetSize());
00329   app->video.window.Blit(game_menu, bottom_bar_pos);
00330 
00331   world.ToRedrawOnScreen(dr);
00332 
00333   // display wind, character and weapon info
00334   DrawWindInfo();
00335   DrawTimeInfo();
00336   DrawCharacterInfo();
00337   DrawTeamEnergy();
00338   DrawWeaponInfo();
00339   DrawSmallInterface();
00340 }
00341 
00342 int Interface::GetWidth() const
00343 {
00344   return game_menu.GetWidth();
00345 }
00346 
00347 int Interface::GetHeight() const
00348 {
00349   if(!display) {
00350     int height = GetMenuHeight() - ((int)Time::GetInstance()->Read() - start_hide_display)/3;
00351     height = (height > 0 ? height : 0);
00352     return (height < GetMenuHeight() ? height : GetMenuHeight());
00353   } else if(start_show_display != 0) {
00354     int height = ((int)Time::GetInstance()->Read() - start_show_display)/3;
00355     height = (height < GetMenuHeight() ? height : GetMenuHeight());
00356     return (height < GetMenuHeight() ? height : GetMenuHeight());
00357   }
00358   return GetMenuHeight();
00359 }
00360 
00361 int Interface::GetMenuHeight() const
00362 {
00363   return game_menu.GetHeight() + MARGIN;
00364 }
00365 
00366 Point2i Interface::GetSize() const
00367 {
00368   return Point2i(GetWidth(), GetHeight());
00369 }
00370 
00371 void Interface::EnableDisplay(bool _display)
00372 {
00373   display = _display;
00374   camera.CenterOnFollowedObject();
00375 }
00376 
00377 void Interface::Show()
00378 {
00379   if(display) return;
00380   display = true;
00381   start_show_display = Time::GetInstance()->Read();
00382 }
00383 
00384 void Interface::Hide()
00385 {
00386   if(!display) return;
00387   display = false;
00388   start_hide_display = Time::GetInstance()->Read() + 1000;
00389 }
00390 
00391 bool Interface::IsVisible() const
00392 {
00393   return display;
00394 }
00395 
00396 void Interface::UpdateTimer(uint utimer)
00397 {
00398   timer->Set(ulong2str(utimer));
00399   remaining_turn_time = utimer;
00400 }
00401 
00402 void Interface::UpdateWindIndicator(int wind_value)
00403 {
00404   wind_bar.UpdateValue(wind_value);
00405 }
00406 
00407 void AbsoluteDraw(const Surface &s, Point2i pos)
00408 {
00409   Rectanglei rectSurface(pos, s.GetSize());
00410 
00411   if( !rectSurface.Intersect(camera) )
00412     return;
00413 
00414   world.ToRedrawOnMap(rectSurface);
00415 
00416   rectSurface.Clip( camera );
00417 
00418   Rectanglei rectSource(rectSurface.GetPosition() - pos, rectSurface.GetSize());
00419   Point2i ptDest = rectSurface.GetPosition() - camera.GetPosition();
00420 
00421   AppWormux::GetInstance()->video.window.Blit(s, rectSource, ptDest);
00422 }
00423 
00424 void HideGameInterface()
00425 {
00426   if(Interface::GetInstance()->GetWeaponsMenu().IsDisplayed()) return;
00427   Mouse::GetInstance()->Hide();
00428   Interface::GetInstance()->Hide();
00429 }
00430 
00431 void ShowGameInterface()
00432 {
00433   Mouse::GetInstance()->Show();
00434   Interface::GetInstance()->Show();
00435 }

Generated on Mon Jan 1 13:10:58 2007 for Wormux by  doxygen 1.4.7