/* etc.cpp - contains everything not contained in some other file 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 /* For std::min and std::max (which aren't algorithms IMO) (and which don't appear in this file either!) */ #include #include #include "game.h" #include "text.h" #include "etc.h" //These 2 functions are right out of the SDL manual. /* * Return the pixel value at (x, y) * NOTE: The surface must be locked before calling this! */ Uint32 getpixel(SDL_Surface *surface, int x, int y) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) return p[0] << 16 | p[1] << 8 | p[2]; else return p[0] | p[1] << 8 | p[2] << 16; case 4: return *(Uint32 *)p; default: return 0; /* shouldn't happen, but avoids warnings */ } } /* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! */ void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } } float dist(float x, float y) { return std::sqrt(x*x+y*y); } SDL_Surface *create_surface(int w, int h, alphanity al) { Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif if (al==no_alpha_channel) amask=0; SDL_Surface *sur=SDL_CreateRGBSurface(SDL_HWSURFACE, w, h, 32, rmask, gmask, bmask, amask); SDL_SetColorKey(sur, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0); return sur; } inline int dfloor(float f) { return f>=0?int(f):int(f-1); } void rotate(SDL_Surface *from, SDL_Surface *to, double angle) { SDL_LockSurface(from); SDL_LockSurface(to); for (int x=0; xw; ++x) for(int y=0;yh;++y) { //centre of the pixel double x_cen=(float(x)-float(to->w)/2.0+0.5); double y_cen=(float(y)-float(to->h)/2.0+0.5); double s=std::sin(angle),c=std::cos(angle); double r_x_cen=x_cen* c+y_cen*s; double r_y_cen=x_cen*-s+y_cen*c; int irx_cen=dfloor(r_x_cen+float(from->w)/2.0); int iry_cen=dfloor(r_y_cen+float(from->h)/2.0); if (irx_cen>=0 && irx_cenw && iry_cen>=0&&iry_cenh) { Uint8 r,g,b,a; SDL_GetRGBA(getpixel(from,irx_cen,iry_cen), from->format, &r, &g, &b, &a); putpixel(to,x,y,SDL_MapRGBA(to->format,r,g,b,a)); } } SDL_UnlockSurface(to); SDL_UnlockSurface(from); } int randint(int i) { return minmax(0, int(1.0*i*randu()), i-1); } float randn() { //box-muller method. int r; double d=RAND_MAX; while(!(r=rand())); return cos(2.0*M_PI*rand()/d) * sqrt(2.0*log(d/r)); } std::string int2str(int i) { std::stringstream ss; ss<format, 0,0,0); const int frames=30; const int delay=30; SDL_Surface *fade=create_surface(rect.w, rect.h, no_alpha_channel); SDL_BlitSurface(screen, &rect, fade, 0); for(int i=0; iformat, 0,0,0); Uint32 white=SDL_MapRGB(screen->format, 255,255,255); int top=screen->h-TILE_SIZE; SDL_Rect statusrect={0, top, screen->w, TILE_SIZE}; SDL_FillRect(screen, &statusrect, black); SDL_Rect sep={0, top, screen->w, 1}; SDL_FillRect(screen, &sep, white); player_status &ps=game::the_game->m_player_status; text::draw("Lives: "+int2str(ps.lives), screen, 20, top+5, white); text::draw("Score: "+int2str(ps.score), screen, 20, top+20, white); text::draw("Shield:", screen, 190, top+3, white); SDL_Rect sh={250,top+3,202,12}; SDL_FillRect(screen, &sh, white); sh.x++;sh.y++;sh.h-=2;sh.w-=2; SDL_FillRect(screen, &sh, black); float shield_frac = 1.0*minmax(0, ps.shield, MAX_SHIELD)/MAX_SHIELD; sh.w=int(shield_frac*sh.w); SDL_FillRect(screen, &sh, SDL_MapRGB(screen->format, int((1.0-shield_frac)*255), int((shield_frac)*255),0)); if (ps.invulnerability>0) { SDL_Rect iv={250,top+3,202,12}; float inv_frac = 1.0*minmax(0, ps.invulnerability, MAX_INVULNERABILITY)/MAX_INVULNERABILITY; iv.w=int(inv_frac*iv.w); SDL_FillRect(screen, &iv, white); } text::draw("Energy:", screen, 190, top+18, white); SDL_Rect en={250,top+18,202,12}; SDL_FillRect(screen, &en, white); en.x++;en.y++;en.h-=2;en.w-=2; SDL_FillRect(screen, &en, black); float energy_frac=1.0*minmax(0, ps.energy, ps.max_energy)/ps.max_energy; en.w=int(energy_frac*en.w); SDL_FillRect(screen, &en, SDL_MapRGB(screen->format, int((1.0-energy_frac)*255), int((energy_frac)*255),0)); text::draw("/"+int2str(int(ps.max_energy+0.5)), screen, 250+202+5,top+18, white); text::draw("Money: "+int2str(ps.money), screen, 500, top+5, white); } int calc_ship_mass() { int total_mass=ship_empty_mass; //Weapons for(int i=0; im_weapon_mounts.size(); ++i) total_mass+=weapon_types()[game::the_game->m_weapon_mounts[i].type].mass; //Engine total_mass += engine_types()[game::the_game->m_engine].mass; //Todo: other equipment for(int i=0; im_systems.size(); ++i) total_mass+=system_types()[game::the_game->m_systems[i]].mass; return total_mass; } float calc_ship_battery() { float total=ship_base_battery; for(int i=0; im_systems.size(); ++i) if(game::the_game->m_systems[i] == ST_BATTERY) total+=15; return total; } float calc_ship_generate() { float total=ship_base_generate; for(int i=0; im_systems.size(); ++i) if(game::the_game->m_systems[i] == ST_GENERATOR) total+=0.2; else if(game::the_game->m_systems[i] == ST_SUPERGENERATOR) total+=0.6; return total; }