Advertisement
Guest User

Untitled

a guest
Aug 24th, 2012
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.43 KB | None | 0 0
  1. #include <SDL.h>
  2. #include "SDL_ttf.h"
  3. #include "SDL_gfxPrimitives.h"
  4. #include <vector>
  5. #include <map>
  6. #include <cmath>
  7. #include <algorithm>
  8. using namespace std;
  9.  
  10. template <typename T>
  11. bool erase_in_vec(vector<T>& vec, const T& val)
  12. {
  13.     for (size_t i=0; i<vec.size(); i++)
  14.     {
  15.         if (vec[i] == val)
  16.         {
  17.             vec.erase(vec.begin()+i);
  18.             return true;
  19.         }
  20.     }
  21.     return false;
  22. }
  23.  
  24. const int map_width = 640;
  25. const int map_height = 480;
  26.  
  27. SDL_Surface* window = 0;
  28. const int window_width = 640;
  29.  
  30. float deceleration = 0.99f;
  31.  
  32. size_t ticks = 0;
  33.  
  34. SDL_Color black = {0,0,0,255};
  35. SDL_Color white = {255,255,255,255};
  36. SDL_Color red = {255,0,0,255};
  37. SDL_Color green = {0,255,0,255};
  38. SDL_Color blue = {0,0,255,255};
  39. SDL_Color cyan = {0,255,255,255};
  40. SDL_Color magenta = {255,255,255,255};
  41. SDL_Color yellow = {255,255,0,255};
  42.  
  43. float powerup_max_age = 9.0f;
  44. float explosion_max_radius = 0.5f;
  45.  
  46. struct point
  47. {
  48.     float a[2];
  49.     point() { a[0] = a[1] = 0.0f; }
  50.     point(float x, float y) { a[0] = x; a[1] = y; }
  51.     float& operator[](int i) { return a[i]; }
  52.     const float& operator[](int i) const { return a[i]; }
  53. };
  54.  
  55. struct mob;
  56. struct world;
  57. struct ship;
  58.  
  59. ///************************************************************************/
  60. /// SDL
  61. ///************************************************************************/
  62.  
  63. struct SDLSystem
  64. {
  65.     void init();
  66.     void quit();
  67.     size_t get_ticks();
  68.     void clear_display(const SDL_Color&  color);
  69.     void draw_string(float x, float y, const SDL_Color&  color, const char* format, ...);
  70.     void draw_polygon(const point* p, int points, const SDL_Color& color);
  71.     void draw_circle(const point& center, float radius, const SDL_Color& color);
  72.  
  73.     TTF_Font* font;
  74. };
  75.  
  76. SDLSystem sdl;
  77.  
  78. ///************************************************************************/
  79. /// Utilities
  80. ///************************************************************************/
  81.  
  82. inline point vector_sum(const point& a, const point& b)
  83. {
  84.     point v = point(a[0]+b[0], a[1]+b[1]);
  85.     return v;
  86. }
  87.  
  88. inline point vector_scale(const point& a, float factor)
  89. {
  90.     point v = point(a[0]*factor, a[1]*factor);
  91.     return v;
  92. }
  93.  
  94. inline point vector_subtract(const point& a, const point& b)
  95. {
  96.     point v = point(a[0]-b[0], a[1]-b[1]);
  97.     return v;
  98. }
  99.  
  100. inline float my_distance(const point& a, const point& b)
  101. {
  102.     point v = vector_subtract(a,b);
  103.     return sqrtf(v[0]*v[0]+v[1]*v[1]);
  104. }
  105.  
  106. inline float deg2rad(float degs)
  107. {
  108.     return degs*(3.1415926f/180.0f);
  109. }
  110. inline float rad2deg(float rads)
  111. {
  112.     return rads*(180.0f/3.1415926f);
  113. }
  114.  
  115. inline float calc_angle(const point& a, const point& b)
  116. {
  117.     point p = vector_subtract(b,a);
  118.     return rad2deg(atan2(p[0],p[1]));
  119. }
  120.  
  121. inline point radial_point_from(const point& p, float radius, float angle)
  122. {
  123.     angle = deg2rad(angle);
  124.     return point(radius * sin(angle) + p[0], radius * cos(angle) + p[1]);
  125. }
  126.  
  127. inline size_t get_ticks()
  128. {
  129.     size_t t = ticks;
  130.     ticks = sdl.get_ticks();
  131.     return ticks - t;
  132. }
  133.  
  134. inline float random()
  135. {
  136.     return float(rand())/float(RAND_MAX);
  137. }
  138.  
  139. inline float round(float r)
  140. {
  141.     return (r > 0.0f) ? floor(r + 0.5f) : ceil(r - 0.5f);
  142. }
  143.  
  144. ///************************************************************************/
  145. /// Timer
  146. ///************************************************************************/
  147.  
  148. struct timer
  149. {
  150.     float remaining;
  151.     timer(float rem = 0) {
  152.         remaining = rem; /// initarg seconds
  153.     }
  154.  
  155.     bool done() const { return remaining <= 0; };
  156.     void add_seconds(float sec) { remaining += sec; }
  157.     void update_timer(float sec) { if (!done()) remaining -= sec; }
  158. };
  159.  
  160. ///************************************************************************/
  161. /// Mob
  162. ///************************************************************************/
  163.  
  164. struct mob
  165. {
  166.     point pos;
  167.     float radius;
  168.     point velocity;
  169.     bool dead;
  170.     virtual ~mob() {}
  171.  
  172.     mob() {
  173.         pos = point(0.5f, 0.5f);
  174.         radius = 0;
  175.         velocity = point(0.0f, 0.0f);
  176.         dead = false;
  177.     }
  178.  
  179.     virtual int type() const { return 'mob'; }
  180.  
  181.     virtual void collide(mob& other, world& world) {}
  182.     point map_coords()
  183.     {
  184.         return point(round(pos[0]*map_width), round(pos[1]*map_height));
  185.     }
  186.  
  187.     float map_radius() { return round(radius * map_width); }
  188.  
  189.     virtual void update(float delta, world& world)
  190.     {
  191.         pos = vector_sum(pos, vector_scale(velocity, delta));
  192.         pos = point(fmod(pos[0]+100.0f,1.0f), fmod(pos[1]+100.0f,1.0f));
  193.     }
  194.  
  195.     bool intersects_p(const mob& other)
  196.     {
  197.         return my_distance(pos,other.pos) < (other.radius + radius);
  198.     }
  199.  
  200.     virtual void render()
  201.     {
  202.         /// ...
  203.     }
  204. };
  205.  
  206. ///************************************************************************/
  207. /// Asteroid
  208. ///************************************************************************/
  209.  
  210. struct asteroid : mob
  211. {
  212.     int size;
  213.     float radii[20];
  214.     float rotation;
  215.     float facing;
  216.  
  217.     asteroid(const point& p = point(random(),random()), int s = 'big') {
  218.         size = s;
  219.         memset(radii, 0, sizeof(radii));
  220.         rotation = (random()-0.5f)*5;
  221.         facing = 0;
  222.         pos = p;
  223.  
  224.         reset();
  225.     }
  226.     virtual ~asteroid() {}
  227.  
  228.     virtual int type() const { return 'ast'; }
  229.  
  230.     void reset();
  231.  
  232.     pair<mob*,mob*> break_down(world& world);
  233.  
  234.     virtual void update(float delta, world& world);
  235.  
  236.     virtual void render();
  237. };
  238.  
  239. ///************************************************************************/
  240. /// Bullet
  241. ///************************************************************************/
  242.  
  243. struct bullet : mob
  244. {
  245.     ship* theship;
  246.     bool super;
  247.     bullet(const point& p, ship* sh) {
  248.         radius = 0.005f;
  249.         pos = p;
  250.         theship = sh;
  251.         super = false;
  252.     }
  253.  
  254.     virtual void collide(mob& other, world& world);
  255.  
  256.     virtual void update(float delta, world& world);
  257.  
  258.     virtual void render();
  259. };
  260.  
  261. ///************************************************************************/
  262. /// Explosion
  263. ///************************************************************************/
  264.  
  265. struct explosion : mob
  266. {
  267.     explosion(const point& p) {
  268.         pos = p;
  269.         radius = 0;
  270.     }
  271.  
  272.     virtual void render();
  273.  
  274.     virtual void update(float delta, world& world);
  275. };
  276.  
  277. ///************************************************************************/
  278. /// Powerup
  279. ///************************************************************************/
  280.  
  281. struct powerup : mob
  282. {
  283.     float age;
  284.     powerup(const point& p) {
  285.         pos = p;
  286.         radius = 0.03f;
  287.         age = 0;
  288.     }
  289.  
  290.     virtual void update(float delta, world& world);
  291.  
  292.     virtual int type() const { return 'pwr'; }
  293. };
  294.  
  295. ///************************************************************************/
  296. /// Bullet Powerup
  297. ///************************************************************************/
  298.  
  299. struct bullet_powerup : powerup
  300. {
  301.     bullet_powerup(const point& p) : powerup(p) {}
  302.     virtual int type() const { return 'bpwr'; }
  303.  
  304.     virtual void render();
  305. };
  306.  
  307. ///************************************************************************/
  308. /// Freeze Powerup
  309. ///************************************************************************/
  310.  
  311. struct freeze_powerup : powerup
  312. {
  313.     freeze_powerup(const point& p) : powerup(p) {}
  314.     virtual int type() const { return 'fpwr'; }
  315.  
  316.     virtual void render();
  317. };
  318.  
  319. ///************************************************************************/
  320. /// Shield Powerup
  321. ///************************************************************************/
  322.  
  323. struct shield_powerup : powerup
  324. {
  325.     shield_powerup(const point& p) : powerup(p) {}
  326.     virtual void render();
  327.     virtual int type() const { return 'spwr'; }
  328. };
  329.  
  330. ///************************************************************************/
  331. /// Ship
  332. ///************************************************************************/
  333.  
  334. struct ship : mob
  335. {
  336.     map<int,timer> timers;
  337.     point acceleration;
  338.     float facing;
  339.     ship() {
  340.         facing = 0;
  341.         radius = 0.04f;
  342.     }
  343.  
  344.     virtual ~ship() {}
  345.  
  346.     virtual int type() const { return 'ship'; }
  347.  
  348.     virtual void update(float delta, world& world);
  349.  
  350.     virtual void collide(mob& other, world& world);
  351.  
  352.     void thrust_at(const point& coords)
  353.     {
  354.         acceleration = vector_sum(acceleration, vector_scale(vector_subtract(coords, pos), 0.03f));
  355.     }
  356.  
  357.     void stop_thrust()
  358.     {
  359.         acceleration = point(0,0);
  360.     }
  361.  
  362.     void shoot_at(const point& coords, world& world);
  363.  
  364.     bool shield_active_p();
  365.     void add_shield(float seconds = 0);
  366.  
  367.     bool super_bullets_active_p();
  368.     void add_super_bullets(float seconds = 0);
  369.  
  370.     virtual void render();
  371.  
  372. };
  373.  
  374. ///************************************************************************/
  375. /// World
  376. ///************************************************************************/
  377.  
  378. struct world
  379. {
  380.     vector<mob*> mobs;
  381.     ship* theship;
  382.     //vector<bullet*> bullets;
  383.     map<int,timer> timers;
  384.     int level;
  385.     int num_asteroids;
  386.     int score;
  387.     int max_level;
  388.     int high_score;
  389.     int lives;
  390.     world() {
  391.         theship = 0;
  392.         level = 0;
  393.         num_asteroids = 0;
  394.         score = 0;
  395.         max_level = 0;
  396.         high_score = 0;
  397.         lives = 0;
  398.     }
  399.  
  400.     void start_next_level();
  401.  
  402.     bool level_cleared_p()
  403.     {
  404.         return num_asteroids < 1;
  405.     }
  406.  
  407.     void after(int timer_name, float seconds, void(*func)(world&));
  408.  
  409.     static void static_next_level(world& world);
  410.     static void static_respawn_sip(world& world);
  411.     static bool is_zero(const mob* m) { return m==0; }
  412.  
  413.     void update_world(float delta);
  414.     void render_world(bool paused);
  415.  
  416.     void add_score(int sc)
  417.     {
  418.         high_score = max(score += sc, high_score);
  419.     }
  420.  
  421.     void add_score(const powerup& pwr)
  422.     {
  423.         add_score(level * 10);
  424.     }
  425.  
  426.     void add_score(const asteroid& astr)
  427.     {
  428.         switch (astr.size)
  429.         {
  430.         case 'big': add_score(1); break;
  431.         case 'med': add_score(2); break;
  432.         case 'sm': add_score(5); break;
  433.         }
  434.     }
  435.  
  436.     ship* ship_moved(ship* sh);
  437.     bullet* bullet_moved(bullet* b);
  438.  
  439.     void add_freeze(float seconds = 0);
  440.     bool frozen_p();
  441.  
  442.     bool in_world(mob* mob);
  443.     mob* add_to_world(mob* mob);
  444.     void remove_from_world(mob* mob);
  445. };
  446.  
  447. ///************************************************************************/
  448. /// random_powerup
  449. ///************************************************************************/
  450.  
  451. powerup* random_powerup(const point& pos)
  452. {
  453.     switch (rand()%3)
  454.     {
  455.     case 0: return new bullet_powerup(pos);
  456.     case 1: return new freeze_powerup(pos);
  457.     case 2: return new shield_powerup(pos);
  458.     }
  459.     return 0;
  460. }
  461.  
  462.  
  463. ///************************************************************************/
  464. /// main
  465. ///************************************************************************/
  466.  
  467. int main(int argc, char *argv[])
  468. {
  469.   sdl.init();
  470.  
  471.   int frame_rate = 60;
  472.   sdl.clear_display(black);
  473.  
  474.   world* wrld = new world();
  475.   bool paused = false, big_paused = false;
  476.  
  477.   SDL_Event event;
  478.  
  479.   bool quit = false;
  480.   while (!quit)
  481.   {
  482.     while ( SDL_PollEvent(&event) )
  483.     {
  484.       switch (event.type) {
  485.       case SDL_ACTIVEEVENT: {
  486.         if ( event.active.state & SDL_APPACTIVE ) {
  487.           if ( event.active.gain ) {
  488.             big_paused = false;
  489.           } else {
  490.             big_paused = true;
  491.           }
  492.         }
  493.       }
  494.       break;
  495.              
  496.       case SDL_MOUSEBUTTONDOWN: {
  497.         if (wrld->level > 0 && wrld->theship && !(big_paused || paused))
  498.         {
  499.           wrld->theship->shoot_at(point(float(event.button.x)/float(map_width), float(event.button.y/float(map_height))), *wrld);
  500.           wrld->theship->thrust_at(point(float(event.button.x)/float(map_width), float(event.button.y)/float(map_height)));
  501.         }
  502.       }
  503.       break;
  504.      
  505.       case SDL_MOUSEBUTTONUP: {
  506.         if (wrld->level > 0 && wrld->theship)
  507.         {
  508.           wrld->theship->stop_thrust();
  509.         }
  510.       }
  511.       break;
  512.      
  513.       case SDL_MOUSEMOTION: {
  514.         if (wrld->theship)
  515.           wrld->theship->facing = calc_angle(wrld->theship->pos, point(float(event.motion.x)/float(map_width), float(event.motion.y)/float(map_height)));
  516.       }
  517.      
  518.       case SDL_KEYUP: {
  519.         if (event.key.keysym.sym == SDLK_ESCAPE) quit = true;
  520.         if (event.key.keysym.sym == SDLK_m) wrld->level = 0;
  521.         if (event.key.keysym.sym == SDLK_p) {
  522.           if (wrld->level == 0) /// start
  523.           {
  524.             wrld->score = 0;
  525.             wrld->lives = 1;
  526.             ticks = SDL_GetTicks();
  527.             wrld->start_next_level();
  528.           } else
  529.             paused = !paused;
  530.         }
  531.       }
  532.       break;
  533.  
  534.       case SDL_QUIT:
  535.         quit = true;
  536.         break;
  537.       }
  538.     }
  539.    
  540.         float delta = get_ticks()*0.001f;
  541.     if (wrld->level > 0 && !(paused || big_paused))
  542.       wrld->update_world(delta);
  543.  
  544.         wrld->render_world(paused || big_paused);
  545.         SDL_Flip(window);
  546.   }
  547.  
  548.   sdl.quit();
  549.  
  550.     return 0;
  551. }
  552.  
  553.  
  554.  
  555. void SDLSystem::init()
  556. {
  557.     SDL_Init(SDL_INIT_VIDEO);
  558.     TTF_Init();
  559.  
  560.     window = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
  561.     SDL_WM_SetCaption("ASTeroids", "ASTeroids");
  562.     font = TTF_OpenFont("font.ttf", 18);
  563.  
  564.    
  565. }
  566.  
  567.  
  568. void SDLSystem::quit()
  569. {
  570.     TTF_CloseFont(font);
  571.     TTF_Quit();
  572.     SDL_Quit();
  573. }
  574.  
  575. size_t SDLSystem::get_ticks()
  576. {
  577.     return SDL_GetTicks();
  578. }
  579.  
  580. void SDLSystem::clear_display( const SDL_Color& color )
  581. {
  582.     SDL_FillRect(window, 0, SDL_MapRGB(window->format, color.r, color.g, color.b));
  583. }
  584.  
  585. void SDLSystem::draw_string( float x, float y, const SDL_Color& color, const char* format, ... )
  586. {
  587.     va_list list;
  588.     list = va_start(list,format);
  589.     char buf[256];
  590.     vsprintf(buf,format,list);
  591.  
  592.  
  593.     SDL_Surface *text_surface;
  594.     if(!(text_surface=TTF_RenderText_Solid(font,buf,color))) {
  595.        
  596.     } else {
  597.         SDL_Rect dest = {x,y,100,100};
  598.         SDL_BlitSurface(text_surface,NULL,window,&dest);
  599.         SDL_FreeSurface(text_surface);
  600.     }
  601.  
  602.     va_end(list);
  603. }
  604.  
  605. void SDLSystem::draw_polygon( const point* p, int points, const SDL_Color& color )
  606. {
  607.     vector<Sint16> px(points), py(points);
  608.     for (int i=0; i<points; i++)
  609.     {
  610.         px[i] = Sint16(p[i][0]);
  611.         py[i] = Sint16(p[i][1]);
  612.     }
  613.     polygonRGBA(window, &px[0], &py[0], points, color.r, color.g, color.b, color.unused);
  614. }
  615.  
  616. void SDLSystem::draw_circle( const point& center, float radius, const SDL_Color& color )
  617. {
  618.     circleRGBA (window, Sint16(center[0]), Sint16(center[1]), Sint16(radius), color.r, color.g, color.b, color.unused);
  619. }
  620. pair<mob*,mob*> asteroid::break_down( world& world )
  621. {
  622.     if (size == 'sm')
  623.     {
  624.         /// gradually reduce the probability of powerups appearing
  625.         if (random()*100.0f < 100.0f/(float(world.level)*0.3f+4.0f))
  626.             return make_pair(random_powerup(pos),(mob*)0);
  627.         else return make_pair((mob*)0, (mob*)0);
  628.     } else
  629.     {
  630.         int smaller = (size=='big')?'med':'sm';
  631.         return make_pair(new asteroid(pos, smaller), new asteroid(pos, smaller));
  632.     }
  633. }
  634.  
  635. void asteroid::reset()
  636. {
  637.     float spd = 0;
  638.     switch (size)
  639.     {
  640.     case 'big':
  641.         radius = 0.1f;
  642.         spd = 0.1f;
  643.         break;
  644.     case 'med':
  645.         radius = 0.075f;
  646.         spd = 0.15f;
  647.         break;
  648.     case 'sm':
  649.         radius = 0.05f;
  650.         spd = 0.25f;
  651.         break;
  652.     }
  653.  
  654.     for (int i=0; i<20; i++)
  655.         radii[i] = (random()*0.2f+0.9f)*map_radius();
  656.  
  657.     velocity = point(random()*2*spd-spd, random()*2*spd-spd);
  658. }
  659.  
  660. void asteroid::update( float delta, world& world )
  661. {
  662.     if (!world.frozen_p())
  663.     {
  664.         facing += rotation;
  665.         mob::update(delta, world);
  666.     }
  667. }
  668.  
  669. void asteroid::render()
  670. {
  671.     point p[20];
  672.     for (int i=0; i<20; i++)
  673.         p[i] = radial_point_from(map_coords(), radii[i], facing+i*18);
  674.     sdl.draw_polygon(p, 20, white);
  675. }
  676.  
  677. void bullet::collide( mob& other, world& world )
  678. {
  679.     if (other.type() == 'ast')
  680.     {
  681.         world.remove_from_world(&other);
  682.         if (!super)
  683.             world.remove_from_world(this);
  684.         asteroid& ast = (asteroid&)other;
  685.         pair<mob*,mob*> newmobs = ast.break_down(world);
  686.         if (newmobs.first) world.add_to_world(newmobs.first);
  687.         if (newmobs.second) world.add_to_world(newmobs.second);
  688.         world.add_to_world(new explosion(ast.pos));
  689.         world.add_score(ast);
  690.     }
  691. }
  692.  
  693. void bullet::update( float delta, world& world )
  694. {
  695.     pos = vector_sum(pos, vector_scale(velocity, delta));
  696.     if (pos[0] < 0 || pos[1] < 0 || pos[0] > map_width || pos[1] > map_height)
  697.         world.remove_from_world(this);
  698.     world.bullet_moved(this);
  699. }
  700.  
  701. void bullet::render()
  702. {
  703.     point coords = map_coords();
  704.     float rad = map_radius();
  705.     sdl.draw_circle(coords, rad, red);
  706.     if (super)
  707.         sdl.draw_circle(coords, rad+random()*3, magenta);
  708. }
  709.  
  710. void explosion::render()
  711. {
  712.     point coords = map_coords();
  713.     float rad = map_radius();
  714.     sdl.draw_circle(coords, rad, red);
  715.     sdl.draw_circle(coords, rad+random()*3, red);
  716. }
  717.  
  718. void explosion::update( float delta, world& world )
  719. {
  720.     if ((radius += delta) > explosion_max_radius)
  721.         world.remove_from_world(this);
  722. }
  723.  
  724. void powerup::update( float delta, world& world )
  725. {
  726.     age += delta;
  727.     if (ceil(age) > powerup_max_age)
  728.         world.remove_from_world(this);
  729. }
  730.  
  731. void bullet_powerup::render()
  732. {
  733.     point coords = map_coords();
  734.     float rad = map_radius();
  735.     sdl.draw_circle(coords, rad, magenta);
  736.     sdl.draw_circle(coords, round(rad*0.3f), white);
  737. }
  738.  
  739. void freeze_powerup::render()
  740. {
  741.     point coords = map_coords();
  742.     float rad = map_radius();
  743.     sdl.draw_circle(coords, rad, cyan);
  744.     point poly[11];
  745.     for (int i=0; i<11; i++)
  746.         poly[i] = radial_point_from(coords, round(((i%2)?0.2f:0.7f)*rad), i*30.0f);
  747.     sdl.draw_polygon(poly,11,white);
  748. }
  749.  
  750. void shield_powerup::render()
  751. {
  752.     point coords = map_coords();
  753.     float rad = map_radius();
  754.     sdl.draw_circle(coords, rad, green);
  755.     point poly[] = {
  756.         radial_point_from(coords, round(rad*0.8f), 40),
  757.         radial_point_from(coords, round(rad*0.8f), 0),
  758.         radial_point_from(coords, round(rad*0.8f), -40),
  759.         radial_point_from(coords, round(rad*0.8f), -135),
  760.         radial_point_from(coords, round(rad*0.8f), 135),
  761.     };
  762.     sdl.draw_polygon(poly, 5, white);
  763. }
  764.  
  765. void ship::update( float delta, world& world )
  766. {
  767.     velocity = vector_scale(vector_sum(velocity,acceleration), deceleration);
  768.     for (map<int,timer>::iterator it=timers.begin(); it != timers.end(); it++)
  769.         it->second.update_timer(delta);
  770.     mob::update(delta,world);
  771.     world.ship_moved(this);
  772. }
  773.  
  774. void ship::collide( mob& other, world& world )
  775. {
  776.     if (other.type() == 'ast')
  777.     {
  778.         if (!shield_active_p())
  779.         {
  780.             world.add_to_world(new explosion(pos));
  781.             world.lives--;
  782.             world.remove_from_world(this);
  783.             return;
  784.         }
  785.     }
  786.     else if (other.type() == 'spwr')
  787.     {
  788.         add_shield(6);
  789.         world.remove_from_world(&other);
  790.         world.add_score((const powerup&)other);
  791.     }
  792.     else if (other.type() == 'bpwr')
  793.     {
  794.         add_super_bullets(6);
  795.         world.remove_from_world(&other);
  796.         world.add_score((const powerup&)other);
  797.     }
  798.     else if (other.type() == 'fpwr')
  799.     {
  800.         world.add_freeze(6);
  801.         world.remove_from_world(&other);
  802.         world.add_score((const powerup&)other);
  803.     }
  804. }
  805.  
  806. void ship::shoot_at( const point& coords, world& world )
  807. {
  808.     bullet* b = new bullet(pos, this);
  809.     b->velocity = vector_scale(vector_subtract(coords, b->pos), 3);
  810.     if (super_bullets_active_p())
  811.         b->super = true;
  812.     world.add_to_world(b);
  813. }
  814.  
  815. bool ship::shield_active_p()
  816. {
  817.     return !timers['shld'].done();
  818. }
  819.  
  820. void ship::add_shield( float seconds /*= 0*/ )
  821. {
  822.     if (shield_active_p())
  823.         timers['shld'].add_seconds(seconds);
  824.     else
  825.         timers['shld'] = timer(seconds);
  826. }
  827.  
  828. bool ship::super_bullets_active_p()
  829. {
  830.     return !timers['supb'].done();
  831. }
  832.  
  833. void ship::add_super_bullets( float seconds /*= 0*/ )
  834. {
  835.     if (shield_active_p())
  836.         timers['supb'].add_seconds(seconds);
  837.     else
  838.         timers['supb'] = timer(seconds);
  839. }
  840.  
  841. void ship::render()
  842. {
  843.     point coords = map_coords();
  844.     float rad = map_radius();
  845.     point poly[] = {
  846.         radial_point_from(coords, rad, facing),
  847.         radial_point_from(coords, rad, facing-130),
  848.         radial_point_from(coords, rad, facing+130),
  849.         radial_point_from(coords, round(rad*0.5f), facing+180)
  850.     };
  851.  
  852.     sdl.draw_polygon(poly, 4, white);
  853.     if (shield_active_p())
  854.     {
  855.         sdl.draw_circle(coords, round(rad+random()*3), green);
  856.     }
  857. }
  858.  
  859. void world::start_next_level()
  860. {
  861.     level++;
  862.     max_level = max(level, max_level);
  863.     for (size_t i=0; i<mobs.size(); i++)
  864.     {
  865.         if (theship != mobs[i])
  866.             delete mobs[i];
  867.     }
  868.     mobs.clear();
  869.     timers.clear();
  870.     for (int i=0; i<level; i++)
  871.         add_to_world(new asteroid());
  872.     add_to_world(theship?theship:(new ship()));
  873.     theship->add_shield(6);
  874. }
  875.  
  876. void world::after( int timer_name, float seconds, void(*func)(world&) )
  877. {
  878.     if (timers.count(timer_name))
  879.     {
  880.         if (timers[timer_name].done())
  881.         {
  882.             timers.erase(timer_name);
  883.             if (func) func(*this);
  884.         }
  885.     } else
  886.     {
  887.         timers[timer_name] = timer(seconds);
  888.     }
  889. }
  890.  
  891. void world::static_next_level( world& world )
  892. {
  893.     world.lives++;
  894.     world.start_next_level();
  895. }
  896.  
  897. void world::static_respawn_sip( world& world )
  898. {
  899.     if (world.lives < 1)
  900.         world.level = 0;
  901.     else
  902.     {
  903.         world.theship = new ship();
  904.         world.add_to_world(world.theship);
  905.         world.theship->add_shield(6);
  906.     }
  907. }
  908.  
  909. void world::update_world( float delta )
  910. {
  911.     for (map<int,timer>::iterator it = timers.begin(); it != timers.end(); it++)
  912.     {
  913.         it->second.update_timer(delta);
  914.     }
  915.  
  916.     for (size_t i=0; i<mobs.size(); i++)
  917.         if (!mobs[i]->dead)
  918.             mobs[i]->update(delta, *this);
  919.  
  920.     /// C++ ONLY
  921.     /// Delete the dead objects
  922.     for (size_t i=0; i<mobs.size(); i++)
  923.         if (mobs[i]->dead)
  924.         {
  925.             delete mobs[i];
  926.             mobs[i] = 0;
  927.         }
  928.  
  929.         mobs.erase(remove_if(mobs.begin(), mobs.end(), is_zero), mobs.end());
  930.         /// END C++ ONLY
  931.  
  932.         /// start next level 3 seconds after clearing
  933.         if (level_cleared_p())
  934.             after('clrd', 3, static_next_level);
  935.         if (!theship)
  936.             after('deth', 3, static_respawn_sip);
  937. }
  938.  
  939. void world::render_world( bool paused )
  940. {
  941.     sdl.clear_display(black);
  942.     /// hud
  943.     sdl.draw_string(10, 10, green, "Level %i", level);
  944.     sdl.draw_string(10, map_height-28, green, "Lives %i", lives);
  945.     sdl.draw_string(map_width-127, map_height-28, green, "Score %i", score);
  946.     sdl.draw_string(map_width-140, 10, green, "%s [M]enu", (level==0)?"[P]lay":"[P]ause");
  947.  
  948.     if (level == 0)
  949.     {
  950.         /// title screen
  951.         sdl.draw_string(round((map_width-81)*0.5f), round((map_height-18)*0.25f), green, "ASTeroids");
  952.         sdl.draw_string(round((map_width-171)*0.5f), round((map_height-18)*0.5f), green, "High score: %i", high_score);
  953.         sdl.draw_string(round((map_width-135)*0.5f), round((map_height-18)*0.75f), green, "Max level: %i", max_level);
  954.     } else
  955.     {
  956.         /// game world
  957.         SDL_Rect clip = {0, 0, map_width, map_height};
  958.         SDL_SetClipRect(window, &clip);
  959.         for (size_t i=0; i<mobs.size(); i++)
  960.             if (!mobs[i]->dead)
  961.                 mobs[i]->render();
  962.         SDL_SetClipRect(window, 0);
  963.  
  964.         /// pause text
  965.         if (paused)
  966.             sdl.draw_string(round((map_width-54)*0.5f), round((map_width-18)*0.5f), green, "PAUSED");
  967.     }
  968. }
  969.  
  970. ship* world::ship_moved( ship* sh )
  971. {
  972.     vector<mob*> checkmobs;
  973.     for (size_t i=0; i<mobs.size(); i++)
  974.     {
  975.         if (!mobs[i]->dead && sh != mobs[i] && sh->intersects_p(*mobs[i]))
  976.             checkmobs.push_back(mobs[i]);
  977.     }
  978.     for (size_t i=0; i<checkmobs.size(); i++)
  979.     {
  980.         sh->collide(*checkmobs[i], *this);
  981.         if (!in_world(sh))
  982.             return sh;
  983.     }
  984.     return 0;
  985. }
  986.  
  987. bullet* world::bullet_moved( bullet* b )
  988. {
  989.     if (b->dead) return 0;
  990.     vector<mob*> checkmobs;
  991.     for (size_t i=0; i<mobs.size(); i++)
  992.     {
  993.         if (!mobs[i]->dead && b != mobs[i] && b->intersects_p(*mobs[i]))
  994.             checkmobs.push_back(mobs[i]);
  995.     }
  996.     for (size_t i=0; i<checkmobs.size(); i++)
  997.     {
  998.         b->collide(*checkmobs[i], *this);
  999.         if (!in_world(b))
  1000.             return b;
  1001.     }
  1002.     return 0;
  1003. }
  1004.  
  1005. void world::add_freeze( float seconds /*= 0*/ )
  1006. {
  1007.     if (frozen_p())
  1008.         timers['frz'].add_seconds(seconds);
  1009.     else
  1010.         timers['frz'] = timer(seconds);
  1011. }
  1012.  
  1013. bool world::frozen_p()
  1014. {
  1015.     return !timers['frz'].done();
  1016. }
  1017.  
  1018. bool world::in_world( mob* m )
  1019. {
  1020.     vector<mob*>::iterator it = find(mobs.begin(), mobs.end(), m);
  1021.     if (it == mobs.end()) return false;
  1022.     return !(*it)->dead;
  1023. }
  1024.  
  1025. mob* world::add_to_world( mob* m )
  1026. {
  1027.     mobs.push_back(m);
  1028.     if (m->type() == 'ship')
  1029.         theship = (ship*)m;
  1030.     else if (m->type() == 'ast')
  1031.         num_asteroids++;
  1032.     return m;
  1033. }
  1034.  
  1035. void world::remove_from_world( mob* mob )
  1036. {
  1037.     if (mob->type() == 'ast')
  1038.         num_asteroids--;
  1039.  
  1040.     mob->dead = true;
  1041.  
  1042.     if (mob == theship)
  1043.         theship = 0;
  1044. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement