@@ -39,13 +39,16 @@ static const float SUCK_TARGET_SPREAD = 8;
39
39
40
40
GhostTree::GhostTree (const ReaderMapping& mapping) :
41
41
Boss(mapping, " images/creatures/ghosttree/ghosttree.sprite" , LAYER_OBJECTS - 10 ),
42
- m_state(STATE_IDLE ),
42
+ m_state(STATE_INIT ),
43
43
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),*/
49
52
// glow_sprite(SpriteManager::current()->create("images/creatures/ghosttree/ghosttree-glow.sprite")),
50
53
/* colorchange_timer(),
51
54
suck_timer(),
@@ -62,6 +65,8 @@ GhostTree::GhostTree(const ReaderMapping& mapping) :
62
65
set_colgroup_active (COLGROUP_TOUCHABLE);
63
66
SoundManager::current ()->preload (" sounds/tree_howling.ogg" );
64
67
SoundManager::current ()->preload (" sounds/tree_suck.ogg" );
68
+
69
+ set_state (STATE_INIT);
65
70
}
66
71
67
72
void
@@ -94,22 +99,50 @@ GhostTree::active_update(float dt_sec)
94
99
Boss::boss_update (dt_sec);
95
100
switch (m_state) {
96
101
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
+ }
98
111
break ;
99
112
case STATE_SCREAM:
100
- // TODO
113
+ if (m_state_timer.check ()) {
114
+ set_state (STATE_IDLE);
115
+ }
101
116
break ;
102
117
case STATE_IDLE:
103
- // TODO
118
+ if (m_state_timer.check ()) {
119
+ set_state (STATE_SUCKING);
120
+ }
104
121
break ;
105
122
case STATE_SUCKING:
106
- // TODO
107
123
break ;
108
124
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
+ }
110
144
break ;
111
145
case STATE_DEAD:
112
- // TODO
113
146
break ;
114
147
default :
115
148
break ;
@@ -222,8 +255,118 @@ GhostTree::active_update(float dt_sec)
222
255
}*/
223
256
}
224
257
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
+ }
226
277
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;
227
370
}
228
371
229
372
/* bool
238
381
GhostTree::willowisp_died (TreeWillOWisp* willowisp)
239
382
{
240
383
if ((m_state == STATE_SUCKING) && (willowisp->was_sucked )) {
241
- m_state = STATE_ATTACKING;
384
+ set_state ( STATE_ATTACKING) ;
242
385
}
243
386
m_willowisps.erase (std::find_if (m_willowisps.begin (), m_willowisps.end (),
244
387
[willowisp](const GameObject* lhs)
@@ -272,9 +415,10 @@ GhostTree::collides(MovingObject& other, const CollisionHit& ) const
272
415
}
273
416
274
417
HitResponse
275
- GhostTree::collision (MovingObject& other, const CollisionHit& )
418
+ GhostTree::collision (MovingObject& other, const CollisionHit& hit )
276
419
{
277
420
if (m_state != STATE_RECHARGING) return ABORT_MOVE;
421
+ return BadGuy::collision (other, hit);
278
422
279
423
// TODO collision from above? subtract one life
280
424
/* auto player = dynamic_cast<Player*>(&other);
@@ -290,9 +434,40 @@ GhostTree::collision(MovingObject& other, const CollisionHit& )
290
434
mystate = STATE_SWALLOWING;
291
435
}*/
292
436
293
- return ABORT_MOVE;
437
+ // return ABORT_MOVE;
294
438
}
295
439
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
+
296
471
/* void
297
472
GhostTree::spawn_lantern()
298
473
{
0 commit comments