Advertisement
Guest User

Untitled

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