src/graphic/spritecache.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  * Sprite cache.
00020  ******************************************************************************
00021  * 2005/09/21: Jean-Christophe Duberga (jcduberga@gmx.de)
00022  *             Initial version
00023  *****************************************************************************/
00024 
00025 #include "spritecache.h"
00026 #include <SDL_rotozoom.h>
00027 
00028 #define BUGGY_SDLGFX
00029 
00030 SpriteFrameCache::SpriteFrameCache() {
00031   use_rotation = false;
00032 }
00033 #include <iostream>
00034 void SpriteFrameCache::CreateRotationCache(Surface &surface, unsigned int cache_size){
00035   assert (use_rotation == false);
00036   use_rotation = true;
00037 
00038   rotated_surface.push_back( surface );
00039   for(unsigned int i=1 ; i< cache_size ; i++){
00040     double angle = 2* M_PI * (1 /* to inverte rotation angle */ - static_cast<double>(i) / static_cast<double>(cache_size));
00041     rotated_surface.push_back( surface.RotoZoom(angle, 1.0, 1.0, SMOOTHING_ON) );
00042   }
00043 }
00044 
00045 Surface SpriteFrameCache::GetFlippedSurfaceForAngle(double angle) const
00046 {
00047   double angle_tmp = angle;
00048   while(angle_tmp >= 2 * M_PI)
00049     angle_tmp -= 2 * M_PI;
00050   while(angle_tmp < 0.0)
00051     angle_tmp += 2 * M_PI;
00052   int index = static_cast<uint>(angle_tmp*static_cast<double>(rotated_flipped_surface.size()) / (2*M_PI));
00053   return rotated_flipped_surface[index];
00054 }
00055 
00056 Surface SpriteFrameCache::GetSurfaceForAngle(double angle) const
00057 {
00058   double angle_tmp = angle;
00059   while(angle_tmp >= 2 * M_PI)
00060     angle_tmp -= 2 * M_PI;
00061   while(angle_tmp < 0.0)
00062     angle_tmp += 2 * M_PI;
00063 
00064   int index = static_cast<uint>(angle_tmp*static_cast<double>(rotated_surface.size()) / (2*M_PI));
00065   return rotated_surface[index];
00066 }
00067 
00068 void SpriteFrameCache::CreateFlippingCache(Surface &surface)
00069 {
00070   assert (flipped_surface.IsNull());
00071   flipped_surface = surface.RotoZoom( 0.0, -1.0, 1.0, SMOOTHING_OFF);
00072   if (use_rotation)
00073   {
00074     assert (rotated_surface.size() != 0);
00075     assert (rotated_flipped_surface.size() == 0);
00076     rotated_flipped_surface.push_back( flipped_surface );
00077     const unsigned int n = rotated_surface.size();
00078     for(unsigned int i=1 ; i<n; i++)
00079     {
00080       double angle = 2 * M_PI * (1 - (float) i / (float) n);
00081       rotated_flipped_surface.push_back( surface.RotoZoom(angle, -1.0, 1.0, SMOOTHING_ON) );
00082     }
00083   }
00084 }
00085 
00086 
00087 
00088 
00089 SpriteCache::SpriteCache(Sprite &p_sprite) :
00090   sprite(p_sprite)
00091 {
00092   have_rotation_cache = false;
00093   have_flipping_cache = false;
00094   have_lastframe_cache = false;
00095   rotation_cache_size = 0;
00096 }
00097 
00098 #if 0
00099 SpriteCache::SpriteCache(Sprite &p_sprite, const SpriteCache &other)  :
00100   sprite(p_sprite),
00101   frames(other.frames)
00102 {
00103   have_rotation_cache = false;
00104   have_flipping_cache = false;
00105   have_lastframe_cache = false;
00106   rotation_cache_size = 0;
00107 
00108   for ( unsigned int f = 0 ; f < other.frames.size() ; f++)
00109   {
00110     Surface new_surf = Surface(frame_width_pix, frame_height_pix, SDL_SWSURFACE|SDL_SRCALPHA, true);
00111 
00112         // Disable per pixel alpha on the source surface
00113     // in order to properly copy the alpha chanel to the destination suface
00114         // see the SDL_SetAlpha man page for more infos (RGBA->RGBA without SDL_SRCALPHA)
00115         other.frames[f].surface.SetAlpha( 0, 0);
00116         new_surf.Blit( other.frames[f].surface, NULL, NULL);
00117 
00118         // re-enable the per pixel alpha in the
00119         other.frames[f].surface.SetAlpha( SDL_SRCALPHA, 0);
00120     frames.push_back( SpriteFrame(new_surf,other.frames[f].delay));
00121   }
00122 
00123   if(other.have_rotation_cache)
00124     EnableRotationCache(other.rotation_cache_size);
00125   if(other.have_flipping_cache)
00126     EnableFlippingCache();
00127   if(other.have_lastframe_cache)
00128     EnableLastFrameCache();
00129 }
00130 #endif
00131 
00132 void SpriteCache::EnableRotationCache(std::vector<SpriteFrame> &sprite_frames, unsigned int cache_size){
00133   //For each frame, we pre-render 'cache_size' rotated surface
00134   //At runtime the prerender Surface with the nearest angle to what is asked is displayed
00135   assert(1 < cache_size and cache_size <= 360);
00136   assert(!have_lastframe_cache);
00137   assert(!have_flipping_cache); //Always compute rotation cache before flipping cache!
00138   assert(!have_rotation_cache);
00139   have_rotation_cache = true;
00140 
00141   if (frames.empty())
00142     frames.resize( sprite_frames.size() );
00143   assert( frames.size() == sprite_frames.size() );
00144   rotation_cache_size = cache_size;
00145 
00146   for ( unsigned int f = 0 ; f < frames.size() ; f++)
00147   {
00148     frames[f].CreateRotationCache(sprite_frames[f].surface, cache_size);
00149   }
00150 }
00151 
00152 void SpriteCache::EnableFlippingCache(std::vector<SpriteFrame> &sprite_frames){
00153   //For each frame, we pre-render the flipped frame
00154   assert(!have_flipping_cache);
00155   assert(!have_lastframe_cache);
00156 
00157   if (frames.empty())
00158     frames.resize( sprite_frames.size() );
00159   assert( frames.size() == sprite_frames.size() );
00160 
00161   have_flipping_cache = true;
00162 
00163   for ( unsigned int f = 0 ; f < frames.size() ; f++)
00164     frames[f].CreateFlippingCache(sprite_frames[f].surface);
00165 }
00166 
00167 void SpriteCache::EnableLastFrameCache(){
00168   //The result of the last call to SDLgfx is kept in memory
00169   //to display it again if rotation / scale / alpha didn't changed
00170   assert(!have_rotation_cache);
00171   assert(!have_flipping_cache);
00172   have_lastframe_cache = true;
00173 }
00174 
00175 void SpriteCache::DisableLastFrameCache(){
00176   //The result of the last call to SDLgfx is kept in memory
00177   //to display it again if rotation / scale / alpha didn't changed
00178   assert(!have_rotation_cache);
00179   assert(!have_flipping_cache);
00180   have_lastframe_cache = false;
00181 }
00182 
00183 void SpriteCache::InvalidLastFrame(){
00184   //Free lastframe_cache if the next frame to be displayed
00185   //is not the same as the last one.
00186   if(!have_lastframe_cache)
00187     return;
00188   last_frame.Free();
00189 }
00190 

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