src/map/ground.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  * Terrain de jeu.
00020  *****************************************************************************/
00021 
00022 #include "ground.h"
00023 #include <iostream>
00024 #include <SDL_video.h>
00025 #include <SDL_gfxPrimitives.h>
00026 #include <limits.h>
00027 #include "camera.h"
00028 #include "map.h"
00029 #include "maps_list.h"
00030 #include "../graphic/surface.h"
00031 #include "../graphic/video.h"
00032 #include "../include/app.h"
00033 #include "../include/constant.h"
00034 #include "../tool/i18n.h"
00035 #include "../tool/resource_manager.h"
00036 
00037 Ground::Ground()
00038 { //FIXME (a effacer)
00039 }
00040 
00041 void Ground::Init(){
00042   std::cout << "o " << _("Ground initialization...") << ' ';
00043   std::cout.flush();
00044 
00045   // Load ground data
00046   Surface m_image = ActiveMap().ReadImgGround();
00047   LoadImage ( m_image );
00048 
00049   // V�ifie la taille du terrain
00050   assert(Constants::MAP_MIN_SIZE <= GetSize());
00051   assert(GetSizeX()*GetSizeY() <= Constants::MAP_MAX_SIZE);
00052 
00053   // V�ifie si c'est un terrain ouvert ou ferm�
00054   ouvert = ActiveMap().IsOpened();
00055 
00056   std::cout << _("done") << std::endl;
00057 }
00058 
00059 void Ground::Reset(){
00060   Init();
00061   lastPos.SetValues(INT_MAX, INT_MAX);
00062 }
00063 
00064 // Lit la valeur alpha du pixel (x,y)
00065 bool Ground::IsEmpty(const Point2i &pos){
00066         assert( !world.EstHorsMondeXY(pos.x, pos.y) );
00067 
00068         // Lit le monde
00069         return GetAlpha( pos ) != 255; // IsTransparent
00070 }
00071 
00072 /*
00073  * Returns the angle between the tangent at point (x,y) of the ground and
00074  * horizontal
00075  * the angle is always > 0.
00076  * returns -1.0 if no tangent was found (pixel (x,y) does not touch any
00077  * other piece of ground
00078  */
00079 double Ground::Tangeante(int x,int y){
00080   //Approxiamtion : on renvoie la corde de la courbe form�
00081   //par le terrain...
00082 
00083   /* We try to find 2 points on the ground on each side of (x,y)
00084    * the points should be at the limit between land and vaccum
00085    * (p1 =  point on the left
00086    * p2 =  point on the right
00087    */
00088   Point2i p1,p2;
00089   if(!PointContigu(x,y, p1.x,p1.y, -1,-1))
00090     return NAN;
00091 
00092   if(!PointContigu(x,y, p2.x,p2.y, p1.x,p1.y))
00093   {
00094     p2.x = x;
00095     p2.y = y;
00096   }
00097 
00098   if(p1.x == p2.x)
00099     return M_PI / 2.0;
00100   if(p1.y == p2.y)
00101     return M_PI;
00102 
00103   assert (p1.x != p2.x);
00104 
00105   double tangeante = atan((double)(p2.y-p1.y)/(double)(p2.x-p1.x));
00106 
00107   while(tangeante <= 0.0)
00108     tangeante += M_PI;
00109   while(tangeante > 2 * M_PI)
00110     tangeante -= M_PI;
00111 
00112   return tangeante;
00113 }
00114 
00115 bool Ground::PointContigu(int x,int y,  int & p_x,int & p_y,
00116                            int pas_bon_x,int pas_bon_y)
00117 {
00118   //Cherche un pixel autour du pixel(x,y) qui est �la limite entre
00119   //le terrin et le vide.
00120   //renvoie true (+ p_x et p_y) si on a trouv�qqch, sinon false
00121   if(world.EstHorsMonde(Point2i(x-1,y))
00122   || world.EstHorsMonde(Point2i(x+1,y))
00123   || world.EstHorsMonde(Point2i(x,y-1))
00124   || world.EstHorsMonde(Point2i(x,y+1)) )
00125     return false;
00126 
00127   //regarde en haut �gauche
00128   if(x-1 != pas_bon_x
00129   || y-1 != pas_bon_y)
00130   if( !IsEmpty(Point2i(x-1,y-1) )
00131   &&( IsEmpty(Point2i(x-1,y))
00132   || IsEmpty(Point2i(x,y-1))))
00133   {
00134     p_x=x-1;
00135     p_y=y-1;
00136     return true;
00137   }
00138   //regarde en haut
00139   if(x != pas_bon_x
00140   || y-1 != pas_bon_y)
00141   if(!IsEmpty(Point2i(x,y-1))
00142   &&(IsEmpty(Point2i(x-1,y-1))
00143   || IsEmpty(Point2i(x+1,y-1))))
00144   {
00145     p_x=x;
00146     p_y=y-1;
00147     return true;
00148   }
00149   //regarde en haut �droite
00150   if(x+1 != pas_bon_x
00151   || y-1 != pas_bon_y)
00152   if(!IsEmpty(Point2i(x+1,y-1))
00153   &&(IsEmpty(Point2i(x,y-1))
00154   || IsEmpty(Point2i(x+1,y))))
00155   {
00156     p_x=x+1;
00157     p_y=y-1;
00158     return true;
00159   }
00160   //regarde �droite
00161   if(x+1 != pas_bon_x
00162   || y != pas_bon_y)
00163   if(!IsEmpty(Point2i(x+1,y))
00164   &&(IsEmpty(Point2i(x+1,y-1))
00165   || IsEmpty(Point2i(x,y+1))))
00166   {
00167     p_x=x+1;
00168     p_y=y;
00169     return true;
00170   }
00171   //regarde en bas �droite
00172   if(x+1 != pas_bon_x
00173   || y+1 != pas_bon_y)
00174   if(!IsEmpty(Point2i(x+1,y+1))
00175   &&(IsEmpty(Point2i(x+1,y))
00176   || IsEmpty(Point2i(x,y+1))))
00177   {
00178     p_x=x+1;
00179     p_y=y+1;
00180     return true;
00181   }
00182   //regarde en bas
00183   if(x != pas_bon_x
00184   || y+1 != pas_bon_y)
00185   if(!IsEmpty(Point2i(x,y+1))
00186   &&(IsEmpty(Point2i(x-1,y+1))
00187   || IsEmpty(Point2i(x+1,y+1))))
00188   {
00189     p_x=x;
00190     p_y=y+1;
00191     return true;
00192   }
00193   //regarde en bas �gauche
00194   if(x-1 != pas_bon_x
00195   || y+1 != pas_bon_y)
00196   if(!IsEmpty(Point2i(x-1,y+1))
00197   &&(IsEmpty(Point2i(x-1,y))
00198   || IsEmpty(Point2i(x,y+1))))
00199   {
00200     p_x=x-1;
00201     p_y=y+1;
00202     return true;
00203   }
00204   //regarde �gauche
00205   if(x-1 == pas_bon_x
00206   && y == pas_bon_y)
00207   if(!IsEmpty(Point2i(x-1,y))
00208   &&(IsEmpty(Point2i(x-1,y-1))
00209   || IsEmpty(Point2i(x-1,y+1))))
00210   {
00211     p_x=x-1;
00212     p_y=y;
00213     return true;
00214   }
00215   return false;
00216 }
00217 
00218 void Ground::Draw()
00219 {
00220   CheckEmptyTiles();
00221   AppWormux * app = AppWormux::GetInstance();
00222 
00223   Point2i cPos = camera.GetPosition();
00224   Point2i windowSize = app->video.window.GetSize();
00225   Point2i margin = (windowSize - GetSize())/2;
00226 
00227   if( camera.HasFixedX() ){// ground is less wide than screen !
00228     app->video.window.BoxColor( Rectanglei(0, 0, margin.x, windowSize.y), black_color);
00229     app->video.window.BoxColor( Rectanglei(windowSize.x - margin.x, 0, margin.x, windowSize.y), black_color);
00230   }
00231 
00232   if( camera.HasFixedY() ){// ground is less wide than screen !
00233     app->video.window.BoxColor( Rectanglei(0, 0, windowSize.x, margin.y), black_color);
00234     app->video.window.BoxColor( Rectanglei(0, windowSize.y - margin.y, windowSize.x, margin.y), black_color);
00235   }
00236 
00237   if( lastPos != cPos ){
00238     lastPos = cPos;
00239     DrawTile();
00240     return;
00241   }
00242 
00243   RedrawParticleList(*world.to_redraw_now);
00244 
00245   // Draw on top of sky (redisplayed on top of particles)
00246   RedrawParticleList(*world.to_redraw_particles_now);
00247 
00248   // Draw on top of new position of particles (redisplayed on top of particles)
00249   RedrawParticleList(*world.to_redraw_particles);
00250 }
00251 
00252 void Ground::RedrawParticleList(std::list<Rectanglei> &list){
00253         std::list<Rectanglei>::iterator it;
00254 
00255         for( it = list.begin(); it != list.end(); ++it )
00256                 DrawTile_Clipped(*it);
00257 }

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