src/interface/weapon_menu.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  * Interface showing various informations about the game.
00020  *****************************************************************************/
00021 
00022 #include "weapon_menu.h"
00023 
00024 #include <sstream>
00025 #include <math.h>
00026 #include "interface.h"
00027 #include "../graphic/video.h"
00028 #include "../graphic/font.h"
00029 #include "../game/time.h"
00030 #include "../include/action_handler.h"
00031 #include "../include/app.h"
00032 #include "../interface/mouse.h"
00033 #include "../map/camera.h"
00034 #include "../map/map.h"
00035 #include "../team/team.h"
00036 #include "../team/teams_list.h"
00037 #include "../tool/point.h"
00038 #include "../tool/rectangle.h"
00039 #include "../tool/string_tools.h"
00040 #include "../tool/resource_manager.h"
00041 #include "../graphic/sprite.h"
00042 #include "../weapon/weapon.h"
00043 #include "../weapon/weapons_list.h"
00044 
00045 
00046 // Weapon menu
00047 const uint BUTTON_ICO_WIDTH = 58;  // Width of the button icon
00048 const uint BUTTON_ICO_HEIGHT = 58; // Height of the button icon
00049 
00050 const uint WEAPON_ICO_WIDTH = 48;   // Width of the weapon icon
00051 const uint WEAPON_ICO_HEIGHT = 48;  // Height of the button icon
00052 
00053 const uint BUTTON_ICO_GAP = 8; // Gap between buttons when a button is zoomed
00054 
00055 
00056 const uint ICONS_DRAW_TIME = 600; // Time to display all icons (in ms)
00057 const uint ICON_ZOOM_TIME = 150; // Time to zomm one icon.
00058 
00059 const double DEFAULT_ICON_SCALE = 0.7;
00060 const double MAX_ICON_SCALE = 1.1;
00061 
00062 const uint BUTTON_WIDTH = (int)(BUTTON_ICO_GAP + BUTTON_ICO_WIDTH  *
00063                                (DEFAULT_ICON_SCALE+MAX_ICON_SCALE)/2);
00064 
00065 const uint BUTTON_HEIGHT = (int)(BUTTON_ICO_GAP + BUTTON_ICO_HEIGHT  *
00066                                 (DEFAULT_ICON_SCALE+MAX_ICON_SCALE)/2);
00067 
00068 WeaponMenuItem::WeaponMenuItem(uint num_sort)
00069 {
00070   zoom_start_time = 0;
00071   weapon_type = num_sort;
00072   Reset();
00073 }
00074 
00075 void WeaponMenuItem::Reset()
00076 {
00077   scale = DEFAULT_ICON_SCALE;
00078   zoom = false;
00079   dezoom = false;
00080 }
00081 
00082 void WeaponMenuItem::ChangeZoom()
00083 {
00084   zoom_start_time = Time::GetInstance()->Read();
00085 
00086   if(!zoom && scale < 1)
00087     {
00088       zoom = true;
00089       dezoom = false;
00090     }
00091   else
00092     {
00093       zoom = false;
00094       dezoom = true;
00095     }
00096 }
00097 
00098 void WeaponMenuItem::ComputeScale()
00099 {
00100   double scale_range, time_range;
00101 
00102   time_range = ((double)Time::GetInstance()->Read() - zoom_start_time) / ICON_ZOOM_TIME;
00103   if (time_range > 1)
00104     time_range = 1;
00105 
00106   scale_range = sin (time_range * M_PI / 2) * (MAX_ICON_SCALE - DEFAULT_ICON_SCALE);
00107 
00108   if(zoom)
00109   {
00110     scale = DEFAULT_ICON_SCALE + scale_range ;
00111 
00112     if(time_range == 1)
00113       zoom = false;
00114   }
00115   else
00116     if(dezoom)
00117       {
00118         scale = MAX_ICON_SCALE - scale_range ;
00119 
00120         if(time_range == 1)
00121           dezoom = false;
00122       }
00123 }
00124 
00125 bool WeaponMenuItem::MouseOn(const Point2i &mousePos)
00126 {
00127   ComputeScale();
00128 
00129   Point2i scaled( (int)(BUTTON_ICO_WIDTH * scale), (int)(BUTTON_ICO_HEIGHT * scale) );
00130   Rectanglei rect(Interface::GetInstance()->weapons_menu.GetPosition() - scaled/2 + position, scaled );
00131 
00132   if( rect.Contains(mousePos) )
00133      return true;
00134   else
00135     {
00136       if(scale > DEFAULT_ICON_SCALE && !dezoom)
00137         dezoom = true;
00138       return false;
00139     }
00140 }
00141 
00142 // Draw a button
00143 void WeaponMenuItem::Draw()
00144 {
00145   Interface * interface = Interface::GetInstance();
00146 
00147   ComputeScale();
00148   Point2i buttonCenter(interface->weapons_menu.GetPosition() + position);
00149   Point2i buttonSize( (int)(BUTTON_ICO_WIDTH * scale), (int)(BUTTON_ICO_HEIGHT * scale) );
00150   Point2i iconSize( (int)(WEAPON_ICO_WIDTH * scale), (int)(WEAPON_ICO_HEIGHT * scale) );
00151   std::ostringstream txt;
00152   int nb_bullets;
00153 
00154   Sprite *button;
00155 
00156   switch(weapon_type){
00157     case 1:
00158       button = interface->weapons_menu.my_button1;
00159       break ;
00160 
00161     case 2:
00162       button = interface->weapons_menu.my_button2;
00163       break ;
00164 
00165     case 3:
00166       button = interface->weapons_menu.my_button3;
00167       break ;
00168 
00169     case 4:
00170       button = interface->weapons_menu.my_button4;
00171       break ;
00172 
00173     case 5:
00174       button = interface->weapons_menu.my_button5;
00175       break ;
00176 
00177   default:
00178       button = interface->weapons_menu.my_button1;
00179       break ;
00180   }
00181 
00182   // Button display
00183   button->Scale(scale, scale);
00184   button->Blit(AppWormux::GetInstance()->video.window, buttonCenter - buttonSize/2);
00185 
00186   // Weapon display
00187   weapon_icon->Scale(scale, scale);
00188   weapon_icon->Blit(AppWormux::GetInstance()->video.window, buttonCenter - iconSize/2);
00189 
00190   // Amunitions display
00191   nb_bullets = ActiveTeam().ReadNbAmmos(weapon->GetName());
00192   txt.str ("");
00193   if (nb_bullets ==  INFINITE_AMMO)
00194     txt << ("§");
00195   else
00196     txt << nb_bullets;
00197 
00198   (*Font::GetInstance(Font::FONT_TINY)).WriteLeftBottom(buttonCenter + Point2i(-1, 1) * iconSize / 2,
00199                             txt.str(), white_color);
00200 }
00201 
00202 WeaponsMenu::WeaponsMenu()
00203 {
00204   display = false;
00205   show = false;
00206   hide = false;
00207   nbr_weapon_type = 0;
00208   motion_start_time = Time::GetInstance()->Read();
00209 
00210   Profile *res = resource_manager.LoadXMLProfile( "graphism.xml", false);
00211   my_button1 = new Sprite( resource_manager.LoadImage(res,"interface/button1_icon"));
00212   my_button1->cache.EnableLastFrameCache();
00213   my_button2 = new Sprite( resource_manager.LoadImage(res,"interface/button2_icon"));
00214   my_button2->cache.EnableLastFrameCache();
00215   my_button3 = new Sprite( resource_manager.LoadImage(res,"interface/button3_icon"));
00216   my_button3->cache.EnableLastFrameCache();
00217   my_button4 = new Sprite( resource_manager.LoadImage(res,"interface/button4_icon"));
00218   my_button4->cache.EnableLastFrameCache();
00219   my_button5 = new Sprite( resource_manager.LoadImage(res,"interface/button5_icon"));
00220   my_button5->cache.EnableLastFrameCache();
00221   resource_manager.UnLoadXMLProfile( res);
00222 }
00223 
00224 // Add a new weapon to the weapon menu.
00225 void WeaponsMenu::NewItem(Weapon* new_item, uint num_sort)
00226 {
00227   WeaponMenuItem item(num_sort);
00228   item.position.Clear();
00229   item.weapon = new_item;
00230 
00231   item.weapon_icon = new Sprite(new_item->GetIcon());
00232   item.weapon_icon->cache.EnableLastFrameCache();
00233 
00234   boutons.push_back (item);
00235 
00236   if(num_sort>nbr_weapon_type)
00237     nbr_weapon_type = num_sort;
00238 }
00239 
00240 // Weapon menu display (init of the animation)
00241 void WeaponsMenu::Show()
00242 {
00243   ShowGameInterface();
00244   Time * global_time = Time::GetInstance();
00245   if(display && hide)
00246     motion_start_time = global_time->Read() - (ICONS_DRAW_TIME - (global_time->Read()-motion_start_time));
00247   else
00248     motion_start_time = global_time->Read();
00249 
00250   display = true;
00251   show = true;
00252   hide = false;
00253 }
00254 
00255 // Compute maximum number of icons in weapon menu columns.
00256 void WeaponsMenu::ComputeSize()
00257 {
00258   max_weapon = 0;
00259   uint nbr_current_type = 0;
00260 
00261   iterator it=boutons.begin(), fin=boutons.end();
00262   for (; it != fin; ++it)
00263   {
00264     if(it != boutons.begin())
00265     if(((it-1)->weapon_type) != (it->weapon_type))
00266     {
00267       if(nbr_current_type > max_weapon)
00268         max_weapon = nbr_current_type;
00269       nbr_current_type = 0;
00270     }
00271     if(ActiveTeam().ReadNbAmmos(it->weapon->GetName())>0
00272        || ActiveTeam().ReadNbAmmos(it->weapon->GetName())==INFINITE_AMMO)
00273       nbr_current_type++;
00274   }
00275 
00276   if(nbr_current_type > max_weapon)
00277     max_weapon = nbr_current_type;
00278 }
00279 
00280 void WeaponsMenu::Hide()
00281 {
00282   if(display && show)
00283     motion_start_time = Time::GetInstance()->Read() - (ICONS_DRAW_TIME - (Time::GetInstance()->Read()-motion_start_time));
00284   else
00285     motion_start_time = Time::GetInstance()->Read();
00286 
00287   hide = true;
00288   show = false;
00289 }
00290 
00291 void WeaponsMenu::SwitchDisplay()
00292 {
00293   if(display && !hide)
00294     Hide();
00295   else
00296     Show();
00297 }
00298 
00299 int WeaponsMenu::GetX() const
00300 {
00301   return AppWormux::GetInstance()->video.window.GetWidth()-GetWidth();
00302 }
00303 
00304 int WeaponsMenu::GetY() const
00305 {
00306   return AppWormux::GetInstance()->video.window.GetHeight() - GetHeight() - Interface::GetInstance()->GetHeight();
00307 }
00308 
00309 Point2i WeaponsMenu::GetPosition() const{
00310   return AppWormux::GetInstance()->video.window.GetSize() - GetSize() - Point2i(0, Interface::GetInstance()->GetHeight());
00311 }
00312 
00313 int WeaponsMenu::GetWidth() const
00314 {
00315   return BUTTON_ICO_GAP + ((nbr_weapon_type +1) * BUTTON_WIDTH) ;
00316 }
00317 
00318 int WeaponsMenu::GetHeight() const
00319 {
00320   return BUTTON_ICO_GAP + BUTTON_HEIGHT * max_weapon;
00321 }
00322 
00323 Point2i WeaponsMenu::GetSize() const
00324 {
00325   return Point2i( BUTTON_ICO_GAP + ((nbr_weapon_type +1) * BUTTON_WIDTH), BUTTON_ICO_GAP + BUTTON_HEIGHT * max_weapon);
00326 }
00327 
00328 bool WeaponsMenu::IsDisplayed() const
00329 {
00330   return display;
00331 }
00332 
00333 void WeaponsMenu::Reset()
00334 {
00335   display = false;
00336   show = false;
00337   hide = false;
00338   motion_start_time = Time::GetInstance()->Read();
00339 }
00340 
00341 void WeaponsMenu::ShowMotion(int nr_buttons,int button_no,iterator it,int column)
00342 {
00343   int delta_t=ICONS_DRAW_TIME/(2*nr_buttons);
00344   Time * global_time = Time::GetInstance();
00345 
00346   if((global_time->Read() > motion_start_time + (delta_t*button_no))
00347      && (global_time->Read() < motion_start_time + (ICONS_DRAW_TIME/2)+(delta_t*(button_no))))
00348     {
00349       double delta_sin = -(asin((column+1.0)/(column+2.0)) - (M_PI/2));
00350 
00351       uint tps = global_time->Read() - (motion_start_time + delta_t*button_no);
00352 
00353       double tps_sin = ((double)tps * ((M_PI/2) + delta_sin)/(ICONS_DRAW_TIME/2));
00354 
00355       it->position.x -= (int)(sin(tps_sin) * BUTTON_WIDTH * (column+2.0));
00356       it->position.x += (BUTTON_WIDTH * (column+1));
00357     }
00358   else
00359     if(global_time->Read() < motion_start_time + (delta_t*button_no))
00360       {
00361         it->position.x += (BUTTON_WIDTH * (column+1));
00362       }
00363 
00364   if(global_time->Read() > motion_start_time + ICONS_DRAW_TIME)
00365     {
00366       show = false;
00367     }
00368 }
00369 
00370 bool WeaponsMenu::HideMotion(int nr_buttons,int button_no,iterator it,int column)
00371 {
00372   int delta_t=ICONS_DRAW_TIME/(2*nr_buttons);
00373 
00374   Time * global_time = Time::GetInstance();
00375   if((global_time->Read() > motion_start_time + (delta_t*(nr_buttons-button_no)))
00376      && (global_time->Read() < motion_start_time + (ICONS_DRAW_TIME/2)+(delta_t*(nr_buttons-button_no))))
00377     {
00378       double delta_sin = -(asin((column+1.0)/(column+2.0)) - (M_PI/2));
00379 
00380       uint tps = global_time->Read() - (motion_start_time + delta_t*(nr_buttons-button_no));
00381       double tps_sin = ((double)tps * ((M_PI/2) + delta_sin)/(ICONS_DRAW_TIME/2));
00382       tps_sin = ((M_PI/2) + delta_sin) - tps_sin;
00383 
00384       it->position.x -= (int)(sin(tps_sin) * BUTTON_WIDTH * (column+2.0));
00385       it->position.x += BUTTON_WIDTH * (column+1);
00386     }
00387   else
00388     if(global_time->Read() > motion_start_time + (delta_t*(nr_buttons-button_no)))
00389       {
00390         it->position.x += BUTTON_WIDTH * (column+1);
00391         it->Reset();
00392       }
00393 
00394   if(global_time->Read() > motion_start_time + ICONS_DRAW_TIME)
00395     {
00396       hide = false;
00397       display = false;
00398       return true;
00399     }
00400 
00401   return false;
00402 }
00403 
00404 void WeaponsMenu::Draw()
00405 {
00406   if (!display)
00407     return;
00408 
00409   MouseOver(Mouse::GetInstance()->GetWorldPosition() - camera.GetPosition());
00410   ComputeSize();
00411 
00412   uint nr_buttons = max_weapon * nbr_weapon_type;
00413   uint button_no = 0;
00414   uint current_type = 0;
00415 
00416   iterator it=boutons.begin(), fin=boutons.end();
00417   for (it=boutons.begin(); it != fin; ++it)
00418   {
00419     if(!it->weapon->CanBeUsedOnClosedMap()
00420        && !world.EstOuvert())
00421       continue;
00422 
00423     if(ActiveTeam().ReadNbAmmos(it->weapon->GetName())<=0
00424        && ActiveTeam().ReadNbAmmos(it->weapon->GetName())!=INFINITE_AMMO)
00425       continue;
00426 
00427     if(it->weapon_type!=current_type)
00428     {
00429       button_no = 0;
00430       current_type = it->weapon_type;
00431     }
00432 
00433     int column = nbr_weapon_type - current_type;
00434     int row = button_no;
00435 
00436     it->position.x = GetWidth() - (int)(BUTTON_WIDTH * (column+0.5));
00437     it->position.y = BUTTON_ICO_GAP + (row * BUTTON_HEIGHT);
00438 
00439     if(show)
00440       ShowMotion(nr_buttons,(column * max_weapon) + row,it,column);
00441     else
00442     if(hide)
00443       if(HideMotion(nr_buttons,(column * max_weapon) + row,it,column))
00444         return;
00445 
00446     it->Draw();
00447     button_no++;
00448   }
00449 }
00450 
00451 void WeaponsMenu::MouseOver(const Point2i &mousePos)
00452 {
00453   static int bouton_sous_souris = -1; // button under mouse cursor
00454 
00455   // analized button
00456   int button_no=0;
00457   int nv_bouton_sous_souris=-1;
00458   iterator it=boutons.begin(), fin=boutons.end();
00459   Interface::GetInstance()->weapon_under_cursor = NULL;
00460   for (; it != fin; ++it)
00461     {
00462       if(it->MouseOn(mousePos))
00463       {
00464         Interface::GetInstance()->weapon_under_cursor = it->weapon;
00465         nv_bouton_sous_souris = button_no;
00466         if(button_no != bouton_sous_souris)
00467         { // mouse cursor is on a new button
00468           it->ChangeZoom();
00469         }
00470       }
00471       else
00472         if(button_no == bouton_sous_souris)
00473       {
00474         it->ChangeZoom();
00475       }
00476       button_no++;
00477     }
00478   bouton_sous_souris = nv_bouton_sous_souris;
00479 }
00480 
00481 bool WeaponsMenu::ActionClic(const Point2i &mousePos)
00482 {
00483   if (!display) return false;
00484 
00485   iterator it=boutons.begin(), fin=boutons.end();
00486   for (; it != fin; ++it)
00487   {
00488     if( it->MouseOn(mousePos) )
00489     {
00490       ActionHandler::GetInstance()->NewAction (new Action(Action::ACTION_CHANGE_WEAPON,
00491       it -> weapon -> GetType()));
00492       SwitchDisplay();
00493       return true;
00494     }
00495   }
00496   return false;
00497 }

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