particlesystem_interactive.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // SuperTux
  2. // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include "object/particlesystem_interactive.hpp"
  17. #include "collision/collision.hpp"
  18. #include "editor/editor.hpp"
  19. #include "math/aatriangle.hpp"
  20. #include "object/tilemap.hpp"
  21. #include "supertux/globals.hpp"
  22. #include "supertux/sector.hpp"
  23. #include "supertux/tile.hpp"
  24. #include "video/drawing_context.hpp"
  25. #include "video/surface_batch.hpp"
  26. #include "video/video_system.hpp"
  27. #include "video/viewport.hpp"
  28. //TODO: Find a way to make rain collide with objects like bonus blocks
  29. // Add an option to set rain strength
  30. // Fix rain being "respawned" over solid tiles
  31. ParticleSystem_Interactive::ParticleSystem_Interactive() :
  32. ParticleSystem()
  33. {
  34. virtual_width = static_cast<float>(SCREEN_WIDTH);
  35. virtual_height = static_cast<float>(SCREEN_HEIGHT);
  36. if (!Editor::is_active()) {
  37. z_pos = 0;
  38. }
  39. }
  40. ParticleSystem_Interactive::ParticleSystem_Interactive(const ReaderMapping& mapping) :
  41. ParticleSystem(mapping)
  42. {
  43. virtual_width = static_cast<float>(SCREEN_WIDTH);
  44. virtual_height = static_cast<float>(SCREEN_HEIGHT);
  45. if (!Editor::is_active()) {
  46. z_pos = 0;
  47. }
  48. }
  49. ParticleSystem_Interactive::~ParticleSystem_Interactive()
  50. {
  51. }
  52. void
  53. ParticleSystem_Interactive::draw(DrawingContext& context)
  54. {
  55. if (!enabled)
  56. return;
  57. context.push_transform();
  58. const auto& region = Sector::current()->get_active_region();
  59. std::unordered_map<SurfacePtr, SurfaceBatch> batches;
  60. for (const auto& particle : particles) {
  61. if(!region.contains(particle->pos))
  62. continue;
  63. auto it = batches.find(particle->texture);
  64. if (it == batches.end()) {
  65. const auto& batch_it = batches.emplace(particle->texture,
  66. SurfaceBatch(particle->texture));
  67. batch_it.first->second.draw(particle->pos, particle->angle);
  68. } else {
  69. it->second.draw(particle->pos, particle->angle);
  70. }
  71. }
  72. for(auto& it : batches) {
  73. auto& surface = it.first;
  74. auto& batch = it.second;
  75. // FIXME: What is the colour used for?
  76. context.color().draw_surface_batch(surface, batch.move_srcrects(),
  77. batch.move_dstrects(), batch.move_angles(), Color::WHITE, z_pos);
  78. }
  79. context.pop_transform();
  80. }
  81. int
  82. ParticleSystem_Interactive::collision(Particle* object, const Vector& movement)
  83. {
  84. using namespace collision;
  85. // calculate rectangle where the object will move
  86. float x1, x2;
  87. float y1, y2;
  88. x1 = object->pos.x;
  89. x2 = x1 + 32 + movement.x;
  90. if (x2 < x1) {
  91. x1 = x2;
  92. x2 = object->pos.x;
  93. }
  94. y1 = object->pos.y;
  95. y2 = y1 + 32 + movement.y;
  96. if (y2 < y1) {
  97. y1 = y2;
  98. y2 = object->pos.y;
  99. }
  100. bool water = false;
  101. // test with all tiles in this rectangle
  102. int starttilex = int(x1-1) / 32;
  103. int starttiley = int(y1-1) / 32;
  104. int max_x = int(x2+1);
  105. int max_y = int(y2+1);
  106. Rectf dest(x1, y1, x2, y2);
  107. dest.move(movement);
  108. Constraints constraints;
  109. for (const auto& solids : Sector::get().get_solid_tilemaps()) {
  110. // FIXME Handle a nonzero tilemap offset
  111. for (int x = starttilex; x*32 < max_x; ++x) {
  112. for (int y = starttiley; y*32 < max_y; ++y) {
  113. const Tile& tile = solids->get_tile(x, y);
  114. // skip non-solid tiles, except water
  115. if (! (tile.get_attributes() & (Tile::WATER | Tile::SOLID)))
  116. continue;
  117. Rectf rect = solids->get_tile_bbox(x, y);
  118. if (tile.is_slope ()) { // slope tile
  119. AATriangle triangle = AATriangle(rect, tile.get_data());
  120. if (rectangle_aatriangle(&constraints, dest, triangle)) {
  121. if (tile.get_attributes() & Tile::WATER)
  122. water = true;
  123. }
  124. } else { // normal rectangular tile
  125. if (dest.overlaps(rect)) {
  126. if (tile.get_attributes() & Tile::WATER)
  127. water = true;
  128. set_rectangle_rectangle_constraints(&constraints, dest, rect);
  129. }
  130. }
  131. }
  132. }
  133. }
  134. // TODO don't use magic numbers here...
  135. // did we collide at all?
  136. if (!constraints.has_constraints())
  137. return -1;
  138. const CollisionHit& hit = constraints.hit;
  139. if (water) {
  140. return 0; //collision with water tile - don't draw splash
  141. } else {
  142. if (hit.right || hit.left) {
  143. return 2; //collision from right
  144. } else {
  145. return 1; //collision from above
  146. }
  147. }
  148. }
  149. /* EOF */