magicblock.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // SuperTux - MagicBlock
  2. //
  3. // Magic Blocks are tile-like game objects that are sensitive to
  4. // lighting conditions. They are rendered in a color and
  5. // will only be solid as long as light of the same color shines
  6. // on the block.
  7. //
  8. // Copyright (C) 2006 Wolfgang Becker <uafr@gmx.de>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. #include "object/magicblock.hpp"
  23. #include "editor/editor.hpp"
  24. #include "object/camera.hpp"
  25. #include "sprite/sprite.hpp"
  26. #include "supertux/constants.hpp"
  27. #include "supertux/flip_level_transformer.hpp"
  28. #include "supertux/sector.hpp"
  29. #include "util/reader_mapping.hpp"
  30. #include "video/video_system.hpp"
  31. #include "video/viewport.hpp"
  32. namespace {
  33. const float MIN_INTENSITY = 0.8f;
  34. const float ALPHA_SOLID = 0.7f;
  35. const float ALPHA_NONSOLID = 0.3f;
  36. const float MIN_SOLIDTIME = 1.0f;
  37. const float SWITCH_DELAY = 0.0f; /**< seconds to wait for stable conditions until switching solidity */
  38. } // namespace
  39. MagicBlock::MagicBlock(const ReaderMapping& mapping) :
  40. MovingSprite(mapping, "images/objects/magicblock/magicblock.sprite"),
  41. m_is_solid(false),
  42. m_trigger_red(),
  43. m_trigger_green(),
  44. m_trigger_blue(),
  45. m_solid_time(0),
  46. m_switch_delay(0),
  47. m_solid_box(),
  48. m_color(),
  49. m_light(std::make_shared<Color>(1.0f,1.0f,1.0f)),
  50. m_center(0.0f, 0.0f),
  51. m_black()
  52. {
  53. set_group(COLGROUP_STATIC);
  54. std::vector<float> vColor;
  55. if (mapping.get("color", vColor )) {
  56. m_color = Color( vColor );
  57. } else {
  58. m_color = Color(0, 0, 0);
  59. }
  60. if (!Editor::is_active()) {
  61. // all alpha to make the sprite still visible
  62. m_color.alpha = ALPHA_SOLID;
  63. // set trigger
  64. if (m_color.red == 0 && m_color.green == 0 && m_color.blue == 0) { // is it black?
  65. m_black = true;
  66. m_trigger_red = MIN_INTENSITY;
  67. m_trigger_green = MIN_INTENSITY;
  68. m_trigger_blue = MIN_INTENSITY;
  69. } else {
  70. m_black = false;
  71. m_trigger_red = m_color.red;
  72. m_trigger_green = m_color.green;
  73. m_trigger_blue = m_color.blue;
  74. }
  75. }
  76. m_center = m_col.m_bbox.get_middle();
  77. m_solid_box = Rectf(m_col.m_bbox.get_left() + SHIFT_DELTA, m_col.m_bbox.get_top() + SHIFT_DELTA, m_col.m_bbox.get_right() - SHIFT_DELTA, m_col.m_bbox.get_bottom() - SHIFT_DELTA);
  78. }
  79. ObjectSettings
  80. MagicBlock::get_settings()
  81. {
  82. ObjectSettings result = MovingSprite::get_settings();
  83. result.add_rgb(_("Color"), &m_color, "color", Color::BLACK);
  84. result.reorder({"color", "x", "y"});
  85. return result;
  86. }
  87. void
  88. MagicBlock::after_editor_set()
  89. {
  90. MovingSprite::after_editor_set();
  91. if (m_color.red == 0 && m_color.green == 0 && m_color.blue == 0) { //is it black?
  92. m_black = true;
  93. m_trigger_red = MIN_INTENSITY;
  94. m_trigger_green = MIN_INTENSITY;
  95. m_trigger_blue = MIN_INTENSITY;
  96. } else {
  97. m_black = false;
  98. m_trigger_red = m_color.red;
  99. m_trigger_green = m_color.green;
  100. m_trigger_blue = m_color.blue;
  101. }
  102. m_sprite->set_color(m_color);
  103. }
  104. void
  105. MagicBlock::update(float dt_sec)
  106. {
  107. // Check if center of this block is on screen.
  108. // Don't update if not, because there is no light off screen.
  109. float screen_left = Sector::get().get_camera().get_translation().x;
  110. float screen_top = Sector::get().get_camera().get_translation().y;
  111. float screen_right = screen_left + static_cast<float>(SCREEN_WIDTH);
  112. float screen_bottom = screen_top + static_cast<float>(SCREEN_HEIGHT);
  113. if ((m_center.x > screen_right ) || (m_center.y > screen_bottom) ||
  114. (m_center.x < screen_left) || (m_center.y < screen_top)) {
  115. m_switch_delay = SWITCH_DELAY;
  116. return;
  117. }
  118. bool lighting_ok;
  119. if (m_black) {
  120. lighting_ok = (m_light->red >= m_trigger_red ||
  121. m_light->green >= m_trigger_green ||
  122. m_light->blue >= m_trigger_blue);
  123. } else {
  124. lighting_ok = (m_light->red >= m_trigger_red &&
  125. m_light->green >= m_trigger_green &&
  126. m_light->blue >= m_trigger_blue);
  127. }
  128. // overrule lighting_ok if switch_delay has not yet passed
  129. if (lighting_ok == m_is_solid) {
  130. m_switch_delay = SWITCH_DELAY;
  131. } else {
  132. if (m_switch_delay > 0) {
  133. lighting_ok = m_is_solid;
  134. m_switch_delay -= dt_sec;
  135. }
  136. }
  137. if (lighting_ok) {
  138. // lighting suggests going solid
  139. if (!m_is_solid) {
  140. if (Sector::get().is_free_of_movingstatics(m_solid_box, this)) {
  141. m_is_solid = true;
  142. m_solid_time = 0;
  143. m_switch_delay = SWITCH_DELAY;
  144. }
  145. }
  146. } else {
  147. // lighting suggests going nonsolid
  148. if ( m_solid_time >= MIN_SOLIDTIME ){
  149. m_is_solid = false;
  150. }
  151. }
  152. // Update Sprite.
  153. if (m_is_solid) {
  154. m_solid_time+=dt_sec;
  155. m_color.alpha = ALPHA_SOLID;
  156. set_action("solid");
  157. set_group(COLGROUP_STATIC);
  158. } else {
  159. m_color.alpha = ALPHA_NONSOLID;
  160. set_action("normal");
  161. set_group(COLGROUP_DISABLED);
  162. }
  163. }
  164. void
  165. MagicBlock::draw(DrawingContext& context)
  166. {
  167. // Ask for update about lightmap at center of this block
  168. context.light().get_pixel(m_center, m_light);
  169. MovingSprite::draw(context);
  170. context.color().draw_filled_rect(m_col.m_bbox, m_color, m_layer);
  171. }
  172. bool
  173. MagicBlock::collides(GameObject& /*other*/, const CollisionHit& /*hit*/) const
  174. {
  175. return m_is_solid;
  176. }
  177. HitResponse
  178. MagicBlock::collision(GameObject& /*other*/, const CollisionHit& /*hit*/)
  179. {
  180. return FORCE_MOVE;
  181. }
  182. void
  183. MagicBlock::on_flip(float height)
  184. {
  185. MovingSprite::on_flip(height);
  186. FlipLevelTransformer::transform_flip(m_flip);
  187. m_center = m_col.m_bbox.get_middle();
  188. }
  189. /* EOF */