/* explosion.cpp - explosion animation mover Copyright (C) 2006 Mark boyd 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be fun to play, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "etc.h" #include "explosion.h" struct gib { int o_x,o_y; std::vector > pixels; float dx,dy; }; Uint8 getalpha(SDL_Surface *bmp, int x, int y) { Uint8 r,g,b,a; SDL_GetRGBA(getpixel(bmp,x,y), bmp->format, &r, &g, &b, &a); return a; } explosion *explosion_pool::get_explosion(const std::string &name, SDL_Surface *start) { const int MAX_VEL=11; const int FRAMES=20; //todo: fixed frame numer has to be considered a bug, because it's not framerate-indepedent if (m_explosions.find(name)==m_explosions.end()) { //create an explosion then std::vector gibs; for(int x=1; xw; x+=2) { for(int y=1; yh; y+=2) { if (getalpha(start,x,y) != SDL_ALPHA_TRANSPARENT && randint(3)==0) { gib g; g.o_x=x;g.o_y=y; g.dx=(1.0*g.o_x-start->w/2)*MAX_VEL/(start->w+start->h+1) + 3.5*(randu()-0.5); g.dy=(1.0*g.o_y-start->h/2)*MAX_VEL/(start->w+start->h+1) + 3.5*(randu()-0.5); gibs.push_back(g); } } } //Attach adjacent pixels to each gib for(int x=0; xw; x++) { for(int y=0; yh; y++) { if (getalpha(start,x,y) != SDL_ALPHA_TRANSPARENT) { int gx=x,gy=y; if (gx%2==0) gx+=randint(2)*2-1; if (gy%2==0) gy+=randint(2)*2-1; for(int i=0; i frames; for(int i=0; iw*5, start->h*5); int x_adj = (frame->w-start->w)/2; int y_adj = (frame->h-start->h)/2; SDL_LockSurface(frame); SDL_LockSurface(start); for(int gi=0; giw && 0<=dest_y && dest_yh) { Uint8 r,g,b,a; SDL_GetRGBA(getpixel(start, gibs[gi].pixels[p].first, gibs[gi].pixels[p].second), start->format, &r, &g, &b, &a); if (i>FRAMES/2) { a = (SDL_ALPHA_TRANSPARENT*(i-FRAMES/2) + a*(FRAMES-i))*2/FRAMES; } putpixel(frame, dest_x, dest_y, SDL_MapRGBA(frame->format, r, g, b, a)); } } } SDL_UnlockSurface(start); SDL_UnlockSurface(frame); SDL_UpdateRect(frame, 0,0,0,0); frames.push_back(frame); } m_explosions[name]=frames; } return new explosion(&(m_explosions[name])); } explosion_pool::~explosion_pool() { for (std::map >::iterator i=m_explosions.begin(); i!=m_explosions.end(); ++i) { for (int j=0; jsecond.size(); ++j) { SDL_FreeSurface(i->second[j]); } } } explosion::explosion(std::vector *frames) { m_frames=frames; m_frame_index=0; } void explosion::do_stuff(float time_interval) { m_frame_index++; if (m_frame_index >= m_frames->size()) { m_frame_index=m_frames->size()-1; die(); } } SDL_Surface *explosion::pic() const { return (*m_frames)[m_frame_index]; }