/* shop.cpp - implements the shop function, which lets you buy nifty equipment (and badly needs cleaning up) 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 "game.h" #include "etc.h" #include "text.h" #include "shop.h" namespace { //the shop id in fact a department store :) enum department { D_WEAPONS, D_SYSTEMS, D_ENGINE, }; department cur_department; //todo! int mount_width, mount_height; } bool point_in_rect(int x, int y, SDL_Rect rect) { return (rect.xformat, 0,0,0); SDL_Surface *ship_bmp=game::the_game->m_bmp_pool.get_bitmap("ship.png"); SDL_Surface *tile=create_surface(square,square); SDL_Rect from={0,0,square,square}; SDL_Rect to=from; SDL_FillRect(screen, 0, black); SDL_LockSurface(ship_bmp); for(int x=0; xw; ++x) for(int y=0; yh; ++y) { Uint8 r,g,b,a; SDL_GetRGBA(getpixel(ship_bmp, x, y), ship_bmp->format, &r,&g,&b,&a); float darken=0.4; r=int(darken*r);g=int(darken*g);b=int(darken*b); SDL_FillRect(tile, 0, SDL_MapRGBA(tile->format, r, g, b, a)); SDL_UpdateRect(tile,0,0,0,0); to.x=left+x*square; to.y=top+y*square; SDL_BlitSurface(tile, &from, screen, &to); } SDL_UnlockSurface(ship_bmp); SDL_FreeSurface(tile); } void shop(SDL_Surface *screen) { SDL_ShowCursor(SDL_ENABLE); //initialise stuff cur_department = D_WEAPONS; //Uint32 black=SDL_MapRGB(screen->format, 0,0,0); Uint32 white=SDL_MapRGB(screen->format, 255,255,255); Uint32 button_col =SDL_MapRGB(screen->format, 32, 32,64); Uint32 button_sel_col=SDL_MapRGB(screen->format, 64, 64,128); int square=11; const int top=40,left=40; SDL_Surface *ship_bmp=game::the_game->m_bmp_pool.get_bitmap("ship.png"); int x_centre = left+(square*ship_bmp->w)/2; int y_centre = top+(square*ship_bmp->h)/2; int selected_mount=-1; int selected_weapon=-1; int selected_system_slot=-1; int selected_system=-1; int selected_engine=-1; SDL_Rect weapons={350,30,100,20}; SDL_Rect systems={350,55,100,20}; SDL_Rect engine= {350,80,100,20}; SDL_Rect buy ={480,420,40,20}; SDL_Rect sell={530,420,40,20}; SDL_Rect exit={580,420,40,20}; std::vector weapon_rects; { int w_left=500; int w_top=40; int w_gap=5; int w_height=20; int w_width=100; for(int i=0; i engine_rects; { int w_left=500; int w_top=40; int w_gap=5; int w_height=20; int w_width=100; for(int i=0; i system_rects; { int w_left=500; int w_top=40; int w_gap=5; int w_height=20; int w_width=100; for(int i=0; i system_mount_rects; SDL_Surface *sys_mount_bmp=game::the_game->m_bmp_pool.get_bitmap("s_system_mount.png"); for(int i=0; iw+2*gap)-sys_mount_bmp->w/2 ); int y=y_centre+int( (i/4-2)*(sys_mount_bmp->h+2*gap)-sys_mount_bmp->h/2 ); SDL_Rect r={x,y,sys_mount_bmp->w,sys_mount_bmp->h}; system_mount_rects.push_back(r); } //main loop const int frame=40; bool abort=false; do { bool click=false; int click_x=0, click_y=0; int time=SDL_GetTicks(); //Get input SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type==SDL_KEYDOWN) { if (event.key.keysym.sym==SDLK_ESCAPE) abort=true;; } else if (event.type==SDL_MOUSEBUTTONDOWN) { click=true; click_x=event.button.x; click_y=event.button.y; } if (event.type==SDL_KEYUP) //todo: unduplicate this! { if (event.key.keysym.sym==SDLK_UP) game::the_game->m_key_flags.up=false; if (event.key.keysym.sym==SDLK_LEFT) game::the_game->m_key_flags.left=false; if (event.key.keysym.sym==SDLK_RIGHT) game::the_game->m_key_flags.right=false; if (event.key.keysym.sym==SDLK_z) game::the_game->m_key_flags.tractor=false; if (event.key.keysym.sym==SDLK_SPACE) game::the_game->m_key_flags.fire=false; } } draw_ship_background(screen, left, top, square); //shop department buttons SDL_FillRect(screen, &weapons, (cur_department==D_WEAPONS)?button_sel_col:button_col); SDL_FillRect(screen, &systems, (cur_department==D_SYSTEMS)?button_sel_col:button_col); SDL_FillRect(screen, &engine, (cur_department==D_ENGINE)?button_sel_col:button_col); text::draw_centre("Weapons", screen, weapons.x+weapons.w/2, weapons.y+weapons.h/2, white); text::draw_centre("Systems", screen, systems.x+systems.w/2, systems.y+systems.h/2, white); text::draw_centre("Engine", screen, engine.x+engine.w/2, engine.y+engine.h/2, white); switch(cur_department) { case D_WEAPONS: { //draw weapon mounts SDL_Surface *mount_bmp=game::the_game->m_bmp_pool.get_bitmap("weapon_point.png"); mount_width=mount_bmp->w; mount_height=mount_bmp->h; int rot_size=3*(mount_bmp->w+mount_bmp->h)/2; if (rot_size%2)rot_size++; for (int i=0; im_weapon_mounts.size(); ++i) { const weapon_mount &m=game::the_game->m_weapon_mounts[i]; //rotate the mount bitmap into a new bitmap; SDL_Surface *rotated; rotated=create_surface(rot_size, rot_size); rotate(mount_bmp, rotated, m.angle); SDL_Rect from={0,0, rotated->w,rotated->h}; SDL_Rect to={int(x_centre+m.loc_x*square-rotated->w/2), int(y_centre+m.loc_y*square-rotated->h/2), rotated->w,rotated->h}; SDL_BlitSurface(rotated, &from, screen, &to); SDL_FreeSurface(rotated); if (weapon_types()[m.type].shop_graphic) { SDL_Surface *weapon_bmp=game::the_game->m_bmp_pool.get_bitmap(weapon_types()[m.type].shop_graphic); rot_size=3*(weapon_bmp->w+weapon_bmp->h)/2; if (rot_size%2)rot_size++; rotated=create_surface(rot_size, rot_size); rotate(weapon_bmp, rotated, m.angle); SDL_Rect from={0,0, rotated->w,rotated->h}; SDL_Rect to={int(x_centre+m.loc_x*square-rotated->w/2), int(y_centre+m.loc_y*square-rotated->h/2), rotated->w,rotated->h}; SDL_BlitSurface(rotated, &from, screen, &to); SDL_FreeSurface(rotated); } } //Generic statussy things if (selected_mount>=0 && selected_mount < game::the_game->m_weapon_mounts.size()) { const weapon_mount &wm=game::the_game->m_weapon_mounts[selected_mount]; text::draw(std::string("Selected Mount: ")+wm.name+" ("+weapon_types()[wm.type].name+")", screen, 10, 430, white); //todo: highlight selected mount? } if (selected_weapon >=0 && selected_weapon < weapon_types().size()) { int x=400; int y=300; const weapon_type &wt=weapon_types()[selected_weapon]; text::draw(std::string("Selected Weapon: ")+wt.name, screen, x,y, white); y+=20; text::draw(weapon_types()[selected_weapon].description, screen, x, y, white); y+=15; text::draw("Cost: "+int2str(wt.cost), screen, x, y, white); y+=15; text::draw("Damage: "+int2str(wt.damage), screen, x, y, white); y+=15; text::draw("Reload Time: "+int2str(wt.reload), screen, x, y, white); y+=15; text::draw("Recoil : "+int2str(int(wt.recoil*100)), screen, x, y, white); y+=15; text::draw("Mass : "+int2str(wt.mass), screen, x, y, white); } //Weapon list for buying for(int i=0; im_engine].name, screen, x,y, white); y+=15; float base_thrust=engine_types()[game::the_game->m_engine].thrust; text::draw(std::string("Thrust: ")+int2str(int(base_thrust)), screen,x,y,white); y+=15; text::draw(std::string("Weight(normal/loaded): ")+int2str(int(gravity*calc_ship_mass()))+ "/"+int2str(int(gravity*(calc_ship_mass()+ball_mass))), screen,x,y,white); y+=25; text::draw(std::string("Ship Mass: ")+int2str(calc_ship_mass()), screen,x,y,white); y+=15; text::draw(std::string("Ship Acceleration: ")+int2str(int(base_thrust/calc_ship_mass())), screen,x,y,white); } if (selected_engine>=0 && selected_engine < engine_types().size()) { const engine_type &eng=engine_types()[selected_engine]; int x=350; int y=240; text::draw(std::string("Selected Engine: ")+eng.name, screen, x,y, white); y+=20; text::draw(eng.description, screen, x, y, white); y+=15; text::draw("Cost: "+int2str(eng.cost), screen, x, y, white); y+=15; text::draw("Thrust: "+int2str(int(eng.thrust*100)), screen, x, y, white); y+=15; text::draw("Mass: "+int2str(eng.mass), screen, x, y, white); y+=15; } //Engine list for buying for(int i=0; im_systems[i]].shop_graphic) { SDL_Surface *bmp=game::the_game->m_bmp_pool.get_bitmap(system_types()[game::the_game->m_systems[i]].shop_graphic); SDL_Rect src={0,0,bmp->w, bmp->h}; SDL_Rect dest={system_mount_rects[i].x+(system_mount_rects[i].w-bmp->w)/2, system_mount_rects[i].y+(system_mount_rects[i].h-bmp->h)/2, bmp->w, bmp->h}; SDL_BlitSurface(bmp, &src, screen, &dest); } } //system list for buying for(int i=0; i=0 && selected_systemm_bmp_pool.get_bitmap("engine_point.png"); for (int i=0; im_engine_points.size(); ++i) { const engine_point &ep=game::the_game->m_engine_points[i]; SDL_Rect from={0,0, engine_bmp->w,engine_bmp->h}; SDL_Rect to={int(x_centre+ep.x*square-engine_bmp->w/2), int(y_centre+ep.y*square-engine_bmp->h/2), engine_bmp->w,engine_bmp->h}; SDL_BlitSurface(engine_bmp, &from, screen, &to); } } #endif //buy/sell/exit butons { SDL_FillRect(screen, &buy, button_col); SDL_FillRect(screen, &sell, button_col); SDL_FillRect(screen, &exit, button_col); text::draw_centre("Buy", screen, buy.x+buy.w/2, buy.y+buy.h/2, white); text::draw_centre("Sell", screen, sell.x+sell.w/2, sell.y+sell.h/2, white); text::draw_centre("Exit", screen, exit.x+exit.w/2, exit.y+exit.h/2, white); } if (click) { if (point_in_rect(click_x, click_y, weapons)) cur_department=D_WEAPONS; if (point_in_rect(click_x, click_y, systems)) cur_department=D_SYSTEMS; if (point_in_rect(click_x, click_y, engine)) cur_department=D_ENGINE; switch(cur_department) { case D_WEAPONS: //clicked on weapon mount? for (int i=0; im_weapon_mounts.size(); ++i) { const weapon_mount &m=game::the_game->m_weapon_mounts[i]; float rel_x=click_x-(x_centre+m.loc_x*square); float rel_y=click_y-(y_centre+m.loc_y*square); float rot_x=1.0*rel_x*cos(-m.angle) - 1.0*rel_y*sin(-m.angle); float rot_y=1.0*rel_x*sin(-m.angle) - 1.0*rel_y*cos(-m.angle); if (-mount_width/2 < rot_x && rot_x < mount_width/2 && -mount_height/2 < rot_y && rot_y < mount_height/2) { selected_mount=i; } } //clicked on weapon rect? for(int i=0; i=0 && selected_mount < game::the_game->m_weapon_mounts.size() && selected_weapon >=0 && selected_weapon < weapon_types().size() && game::the_game->m_player_status.money >= weapon_types()[selected_weapon].cost) { game::the_game->m_player_status.money += weapon_types()[game::the_game->m_weapon_mounts[selected_mount].type].cost; game::the_game->m_player_status.money -= weapon_types()[selected_weapon].cost; game::the_game->m_weapon_mounts[selected_mount].type = weapon_id(selected_weapon); } if (point_in_rect(click_x, click_y, sell) && selected_mount>=0 && selected_mount < game::the_game->m_weapon_mounts.size()) { game::the_game->m_player_status.money += weapon_types()[game::the_game->m_weapon_mounts[selected_mount].type].cost; game::the_game->m_weapon_mounts[selected_mount].type = WT_NOTHING; } break; case D_SYSTEMS: for(int i=0; i=0 && selected_system_slot < system_slots && selected_system>=0 && selected_system < system_types().size() && game::the_game->m_player_status.money >= system_types()[selected_system].cost) { game::the_game->m_player_status.money += system_types()[game::the_game->m_systems[selected_system_slot]].cost; //autosell existing item game::the_game->m_player_status.money -= system_types()[selected_system].cost; game::the_game->m_systems[selected_system_slot]=system_id(selected_system); } //Sell if (point_in_rect(click_x, click_y, sell) && selected_system_slot>=0 && selected_system_slot < system_slots) { game::the_game->m_player_status.money += system_types()[game::the_game->m_systems[selected_system_slot]].cost; game::the_game->game::the_game->m_systems[selected_system_slot] = ST_EMPTY; } //stuff may need updating game::the_game->m_player_status.max_energy=calc_ship_battery(); break; case D_ENGINE: for(int i=0; i=0 && selected_engine < engine_types().size() && game::the_game->m_player_status.money >= engine_types()[selected_engine].cost) { game::the_game->m_player_status.money += engine_types()[game::the_game->m_engine].cost; game::the_game->m_player_status.money -= engine_types()[selected_engine].cost; game::the_game->m_engine = engine_id(selected_engine); } break; } if (point_in_rect(click_x, click_y, exit)) abort=true; } update_player_status(screen); SDL_UpdateRect(screen,0,0,0,0); SDL_Delay(std::max(0, time+frame-SDL_GetTicks())); }while(!abort); //End of main loop game::the_game->m_player_status.in_shop=false; SDL_ShowCursor(SDL_DISABLE); }