Skip to content

Commit 0ff1a00

Browse files
committed
ghosttree: implement state logic
1 parent b5fbb87 commit 0ff1a00

File tree

4 files changed

+208
-26
lines changed

4 files changed

+208
-26
lines changed

src/badguy/ghosttree.cpp

Lines changed: 191 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,16 @@ static const float SUCK_TARGET_SPREAD = 8;
3939

4040
GhostTree::GhostTree(const ReaderMapping& mapping) :
4141
Boss(mapping, "images/creatures/ghosttree/ghosttree.sprite", LAYER_OBJECTS - 10),
42-
m_state(STATE_IDLE),
42+
m_state(STATE_INIT),
4343
m_attack(ATTACK_RED),
44-
/*willowisp_timer(),
45-
willo_spawn_y(0),
46-
willo_radius(200),
47-
willo_speed(1.8f),
48-
willo_color(0),*/
44+
m_state_timer(),
45+
//m_willowisp_timer(),
46+
m_willo_spawn_y(0),
47+
m_willo_radius(200),
48+
m_willo_speed(1.8f),
49+
m_willo_to_spawn(9),
50+
m_next_willo(ATTACK_RED),
51+
/*willo_color(0),*/
4952
//glow_sprite(SpriteManager::current()->create("images/creatures/ghosttree/ghosttree-glow.sprite")),
5053
/*colorchange_timer(),
5154
suck_timer(),
@@ -62,6 +65,8 @@ GhostTree::GhostTree(const ReaderMapping& mapping) :
6265
set_colgroup_active(COLGROUP_TOUCHABLE);
6366
SoundManager::current()->preload("sounds/tree_howling.ogg");
6467
SoundManager::current()->preload("sounds/tree_suck.ogg");
68+
69+
set_state(STATE_INIT);
6570
}
6671

6772
void
@@ -94,22 +99,50 @@ GhostTree::active_update(float dt_sec)
9499
Boss::boss_update(dt_sec);
95100
switch (m_state) {
96101
case STATE_INIT:
97-
//TODO
102+
if (m_state_timer.check()) {
103+
spawn_willowisp(m_next_willo);
104+
rotate_willo_color();
105+
m_state_timer.start(0.1);
106+
--m_willo_to_spawn;
107+
if (m_willo_to_spawn <= 0) {
108+
set_state(STATE_SCREAM);
109+
}
110+
}
98111
break;
99112
case STATE_SCREAM:
100-
//TODO
113+
if (m_state_timer.check()) {
114+
set_state(STATE_IDLE);
115+
}
101116
break;
102117
case STATE_IDLE:
103-
//TODO
118+
if (m_state_timer.check()) {
119+
set_state(STATE_SUCKING);
120+
}
104121
break;
105122
case STATE_SUCKING:
106-
//TODO
107123
break;
108124
case STATE_ATTACKING:
109-
//TODO
125+
if (m_state_timer.check()) {
126+
set_state(STATE_RECHARGING);
127+
}
128+
break;
129+
case STATE_RECHARGING:
130+
if (m_state_timer.check()) {
131+
if (m_attack == ATTACK_PINCH) {
132+
spawn_willowisp(m_next_willo);
133+
rotate_willo_color();
134+
m_state_timer.start(0.3);
135+
} else {
136+
spawn_willowisp(m_attack);
137+
m_state_timer.start(0.9);
138+
}
139+
--m_willo_to_spawn;
140+
if (m_willo_to_spawn <= 0) {
141+
set_state(STATE_IDLE);
142+
}
143+
}
110144
break;
111145
case STATE_DEAD:
112-
//TODO
113146
break;
114147
default:
115148
break;
@@ -222,8 +255,118 @@ GhostTree::active_update(float dt_sec)
222255
}*/
223256
}
224257

225-
void GhostTree::set_state(MyState new_state) {
258+
bool GhostTree::suck_now(const Color& color) const {
259+
switch (m_attack) {
260+
case ATTACK_RED:
261+
return color.red == 1.0;
262+
case ATTACK_GREEN:
263+
return color.green == 1.0;
264+
case ATTACK_BLUE:
265+
return color.blue == 1.0;
266+
case ATTACK_PINCH:
267+
return true;
268+
default:
269+
return false;
270+
}
271+
}
272+
273+
void
274+
GhostTree::rotate_willo_color() {
275+
m_next_willo = static_cast<AttackType>((static_cast<int>(m_next_willo) + 1) % 3);
276+
}
226277

278+
void
279+
GhostTree::spawn_willowisp(AttackType color) {
280+
Vector pos(m_col.m_bbox.get_width() / 2,
281+
m_col.m_bbox.get_height() / 2 + (m_flip == NO_FLIP ? (m_willo_spawn_y + WILLOWISP_TOP_OFFSET) :
282+
-(m_willo_spawn_y + WILLOWISP_TOP_OFFSET + 32.0f)));
283+
auto& willowisp = Sector::get().add<TreeWillOWisp>(this, pos, 200 + m_willo_radius, m_willo_speed);
284+
m_willowisps.push_back(&willowisp);
285+
286+
m_willo_spawn_y -= 40;
287+
if (m_willo_spawn_y < -160)
288+
m_willo_spawn_y = 0;
289+
290+
m_willo_radius += 20;
291+
if (m_willo_radius > 120)
292+
m_willo_radius = 0;
293+
294+
if (m_willo_speed == 1.8f) {
295+
m_willo_speed = 1.5f;
296+
} else {
297+
m_willo_speed = 1.8f;
298+
}
299+
300+
switch (color) {
301+
case ATTACK_RED:
302+
willowisp.set_color(Color(1, 0, 0));
303+
break;
304+
case ATTACK_GREEN:
305+
willowisp.set_color(Color(0, 1, 0));
306+
break;
307+
case ATTACK_BLUE:
308+
willowisp.set_color(Color(0, 0, 1));
309+
break;
310+
case ATTACK_PINCH:
311+
break;
312+
default:
313+
break;
314+
}
315+
}
316+
317+
void
318+
GhostTree::set_state(MyState new_state) {
319+
switch (new_state) {
320+
case STATE_INIT:
321+
std::cout<<"init"<<std::endl;
322+
set_action("idle");
323+
m_state_timer.start(0.1);
324+
break;
325+
case STATE_SCREAM:
326+
std::cout<<"scream"<<std::endl;
327+
set_action("scream");
328+
SoundManager::current()->play("sounds/tree_howling.ogg", get_pos());
329+
m_state_timer.start(2);
330+
break;
331+
case STATE_IDLE:
332+
std::cout<<"idle"<<std::endl;
333+
set_action(m_attack == ATTACK_PINCH ? "idle-pinch" : "idle");
334+
m_state_timer.start(5);
335+
break;
336+
case STATE_SUCKING:
337+
std::cout<<"sucking"<<std::endl;
338+
SoundManager::current()->play("sounds/tree_suck.ogg", get_pos());
339+
for (const auto& willo : m_willowisps) {
340+
if (suck_now(willo->get_color())) {
341+
willo->start_sucking(
342+
m_col.m_bbox.get_middle() + SUCK_TARGET_OFFSET
343+
+ Vector(gameRandom.randf(-SUCK_TARGET_SPREAD, SUCK_TARGET_SPREAD),
344+
gameRandom.randf(-SUCK_TARGET_SPREAD, SUCK_TARGET_SPREAD)));
345+
}
346+
}
347+
break;
348+
case STATE_ATTACKING:
349+
std::cout<<"attacking"<<std::endl;
350+
set_action(m_attack == ATTACK_PINCH ? "scream-pinch" : "scream");
351+
SoundManager::current()->play("sounds/tree_howling.ogg", get_pos());
352+
m_state_timer.start(5);
353+
//TODO
354+
break;
355+
case STATE_RECHARGING:
356+
std::cout<<"recharging"<<std::endl;
357+
set_action(m_attack == ATTACK_PINCH ? "charge-pinch" : "charge");
358+
m_state_timer.start(1);
359+
m_willo_to_spawn = m_attack == ATTACK_PINCH ? 9 : 3;
360+
break;
361+
case STATE_DEAD:
362+
std::cout<<"dead"<<std::endl;
363+
set_action("busted");
364+
run_dead_script();
365+
break;
366+
default:
367+
break;
368+
}
369+
m_state = new_state;
227370
}
228371

229372
/*bool
@@ -238,7 +381,7 @@ void
238381
GhostTree::willowisp_died(TreeWillOWisp* willowisp)
239382
{
240383
if ((m_state == STATE_SUCKING) && (willowisp->was_sucked)) {
241-
m_state = STATE_ATTACKING;
384+
set_state(STATE_ATTACKING);
242385
}
243386
m_willowisps.erase(std::find_if(m_willowisps.begin(), m_willowisps.end(),
244387
[willowisp](const GameObject* lhs)
@@ -272,9 +415,10 @@ GhostTree::collides(MovingObject& other, const CollisionHit& ) const
272415
}
273416

274417
HitResponse
275-
GhostTree::collision(MovingObject& other, const CollisionHit& )
418+
GhostTree::collision(MovingObject& other, const CollisionHit& hit)
276419
{
277420
if (m_state != STATE_RECHARGING) return ABORT_MOVE;
421+
return BadGuy::collision(other, hit);
278422

279423
//TODO collision from above? subtract one life
280424
/*auto player = dynamic_cast<Player*>(&other);
@@ -290,9 +434,40 @@ GhostTree::collision(MovingObject& other, const CollisionHit& )
290434
mystate = STATE_SWALLOWING;
291435
}*/
292436

293-
return ABORT_MOVE;
437+
//return ABORT_MOVE;
294438
}
295439

440+
bool
441+
GhostTree::collision_squished(MovingObject& object)
442+
{
443+
auto player = dynamic_cast<Player*>(&object);
444+
if (player) {
445+
player->bounce(*this);
446+
}
447+
448+
--m_lives;
449+
if (m_lives <= 0) {
450+
set_state(STATE_DEAD);
451+
return true;
452+
}
453+
454+
if (m_attack == ATTACK_PINCH) {
455+
while (m_willo_to_spawn--) {
456+
spawn_willowisp(m_next_willo);
457+
rotate_willo_color();
458+
}
459+
} else {
460+
while (m_willo_to_spawn--) {
461+
spawn_willowisp(m_attack);
462+
}
463+
m_attack = static_cast<AttackType>(static_cast<int>(m_attack) + 1);
464+
}
465+
466+
set_state(STATE_IDLE);
467+
return true;
468+
}
469+
470+
296471
/*void
297472
GhostTree::spawn_lantern()
298473
{

src/badguy/ghosttree.hpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class GhostTree final : public Boss
4848

4949
protected:
5050
virtual std::vector<Direction> get_allowed_directions() const override;
51+
virtual bool collision_squished(MovingObject& object) override;
5152

5253
private:
5354
enum MyState {
@@ -69,17 +70,21 @@ class GhostTree final : public Boss
6970

7071
private:
7172
void set_state(MyState new_state);
73+
bool suck_now(const Color& color) const;
7274
/* bool is_color_deadly(Color color) const;
7375
void spawn_lantern();*/
7476

7577
private:
7678
MyState m_state;
7779
AttackType m_attack;
78-
/*Timer willowisp_timer;
79-
float willo_spawn_y;
80-
float willo_radius;
81-
float willo_speed;
82-
int willo_color;*/
80+
Timer m_state_timer;
81+
//Timer m_willowisp_timer;
82+
float m_willo_spawn_y;
83+
float m_willo_radius;
84+
float m_willo_speed;
85+
int m_willo_to_spawn;
86+
AttackType m_next_willo;
87+
/*int willo_color;*/
8388

8489
//SpritePtr glow_sprite;
8590
/*Timer colorchange_timer;
@@ -93,6 +98,8 @@ class GhostTree final : public Boss
9398
//Lantern* suck_lantern; /**< Lantern that is currently being sucked in */
9499

95100
std::vector<TreeWillOWisp*> m_willowisps;
101+
void spawn_willowisp(AttackType color);
102+
void rotate_willo_color();
96103

97104
private:
98105
GhostTree(const GhostTree&) = delete;

src/badguy/treewillowisp.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,21 @@ TreeWillOWisp::start_sucking(const Vector& suck_target_)
8383
was_sucked = true;
8484
}
8585

86-
HitResponse
86+
/*HitResponse
8787
TreeWillOWisp::collision_player(Player& player, const CollisionHit& hit)
8888
{
8989
// TODO: This function is essentially a no-op. Remove if it doesn't change the behavior.
9090
return BadGuy::collision_player(player, hit);
91-
}
91+
}*/
9292

9393
bool
9494
TreeWillOWisp::collides(MovingObject& other, const CollisionHit& ) const
9595
{
9696
auto lantern = dynamic_cast<Lantern*>(&other);
9797
if (lantern && lantern->is_open())
9898
return true;
99-
if (dynamic_cast<Player*>(&other))
100-
return true;
99+
/*if (dynamic_cast<Player*>(&other))
100+
return true;*/
101101

102102
return false;
103103
}

src/badguy/treewillowisp.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class TreeWillOWisp final : public BadGuy
5050

5151
protected:
5252
virtual bool collides(MovingObject& other, const CollisionHit& hit) const override;
53-
virtual HitResponse collision_player(Player& player, const CollisionHit& hit) override;
53+
//virtual HitResponse collision_player(Player& player, const CollisionHit& hit) override;
5454

5555
private:
5656
enum MyState {

0 commit comments

Comments
 (0)