1// SuperTux - "Will-O-Wisp" Badguy
2// Copyright (C) 2007 Matthias Braun
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
17#include "badguy/treewillowisp.hpp"
18
19#include <math.h>
20
21#include "audio/sound_manager.hpp"
22#include "audio/sound_source.hpp"
23#include "badguy/ghosttree.hpp"
24#include "math/util.hpp"
25#include "object/lantern.hpp"
26#include "object/player.hpp"
27#include "sprite/sprite.hpp"
28
29static const std::string TREEWILLOSOUND = "sounds/willowisp.wav";
30
31TreeWillOWisp::TreeWillOWisp(GhostTree* tree_, const Vector& pos,
32 float radius_, float speed_) :
33 BadGuy(tree_->get_pos() + pos, "images/creatures/willowisp/willowisp.sprite",
34 LAYER_OBJECTS - 20),
35 was_sucked(false),
36 mystate(STATE_DEFAULT),
37 color(),
38 angle(0),
39 radius(radius_),
40 speed(speed_),
41 sound_source(),
42 tree(tree_),
43 suck_target()
44{
45 SoundManager::current()->preload(TREEWILLOSOUND);
46 set_colgroup_active(COLGROUP_MOVING);
47}
48
49TreeWillOWisp::~TreeWillOWisp()
50{
51}
52
53void
54TreeWillOWisp::activate()
55{
56 sound_source = SoundManager::current()->create_sound_source(TREEWILLOSOUND);
57 sound_source->set_position(get_pos());
58 sound_source->set_looping(true);
59 sound_source->set_gain(1.0f);
60 sound_source->set_reference_distance(32);
61 sound_source->play();
62}
63
64void
65TreeWillOWisp::vanish()
66{
67 mystate = STATE_VANISHING;
68 m_sprite->set_action("vanishing", 1);
69 set_colgroup_active(COLGROUP_DISABLED);
70}
71
72void
73TreeWillOWisp::start_sucking(const Vector& suck_target_)
74{
75 mystate = STATE_SUCKED;
76 suck_target = suck_target_;
77 was_sucked = true;
78}
79
80HitResponse
81TreeWillOWisp::collision_player(Player& player, const CollisionHit& hit)
82{
83 //TODO: basically a no-op. Remove if this doesn't change.
84 return BadGuy::collision_player(player, hit);
85}
86
87bool
88TreeWillOWisp::collides(GameObject& other, const CollisionHit& ) const
89{
90 auto lantern = dynamic_cast<Lantern*>(&other);
91 if (lantern && lantern->is_open())
92 return true;
93 if (dynamic_cast<Player*>(&other))
94 return true;
95
96 return false;
97}
98
99void
100TreeWillOWisp::draw(DrawingContext& context)
101{
102 m_sprite->draw(context.color(), get_pos(), m_layer);
103 m_sprite->draw(context.light(), get_pos(), m_layer);
104}
105
106void
107TreeWillOWisp::active_update(float dt_sec)
108{
109 // remove TreeWillOWisp if it has completely vanished
110 if (mystate == STATE_VANISHING) {
111 if (m_sprite->animation_done()) {
112 remove_me();
113 tree->willowisp_died(this);
114 }
115 return;
116 }
117
118 if (mystate == STATE_SUCKED) {
119 Vector dir_ = suck_target - get_pos();
120 if (dir_.norm() < 5) {
121 vanish();
122 return;
123 }
124 Vector newpos = get_pos() + dir_ * dt_sec;
125 m_col.m_movement = newpos - get_pos();
126 return;
127 }
128
129 angle = fmodf(angle + dt_sec * speed, math::TAU);
130 Vector newpos(m_start_position + Vector(sinf(angle) * radius, 0));
131 m_col.m_movement = newpos - get_pos();
132 float sizemod = cosf(angle) * 0.8f;
133 /* TODO: modify sprite size */
134
135 sound_source->set_position(get_pos());
136
137 if (sizemod < 0) {
138 m_layer = LAYER_OBJECTS + 5;
139 } else {
140 m_layer = LAYER_OBJECTS - 20;
141 }
142}
143
144void
145TreeWillOWisp::set_color(const Color& color_)
146{
147 color = color_;
148 m_sprite->set_color(color_);
149}
150
151Color
152TreeWillOWisp::get_color() const
153{
154 return color;
155}
156
157void TreeWillOWisp::stop_looping_sounds()
158{
159 if (sound_source) {
160 sound_source->stop();
161 }
162}
163
164void TreeWillOWisp::play_looping_sounds()
165{
166 if (sound_source) {
167 sound_source->play();
168 }
169}
170
171/* EOF */
172