234 |
JUMPING, |
JUMPING, |
235 |
DEAD, // marble is dead |
DEAD, // marble is dead |
236 |
RESURRECTED, // has been resurrected; about to respawn |
RESURRECTED, // has been resurrected; about to respawn |
237 |
APPEARING, |
APPEARING, // appearing when level starts/after respawn |
238 |
DISAPPEARING, |
DISAPPEARING, // disappearing when level finished |
239 |
FALLING_VORTEX, // falling into vortex |
FALLING_VORTEX, // falling into vortex |
240 |
RISING_VORTEX, // appear in vortex |
RISING_VORTEX, // appear in vortex |
241 |
JUMP_VORTEX, // jump out of vortex (here player controls actor) |
JUMP_VORTEX, // jump out of vortex (here player controls actor) |
255 |
} vortex; |
} vortex; |
256 |
} shared; |
} shared; |
257 |
|
|
258 |
|
display::SpriteHandle m_halosprite; |
259 |
|
double m_shield_rest_time; |
260 |
|
static const double SHIELD_TIME = 10.0; |
261 |
|
enum HaloState { NOHALO, HALOBLINK, HALONORMAL } m_halostate; |
262 |
|
|
263 |
|
void update_halo(); |
264 |
|
bool has_halo(); |
265 |
|
void change_state_noshield (State newstate); |
266 |
|
|
267 |
|
|
268 |
void set_model_cb(const string &m) { |
void set_model_cb(const string &m) { |
269 |
set_model(m.c_str()); |
set_model(m.c_str()); |
270 |
get_sprite().set_callback (this); |
get_sprite().set_callback (this); |
305 |
} |
} |
306 |
|
|
307 |
BasicBall::BasicBall(const char *kind, double radius, double mass) |
BasicBall::BasicBall(const char *kind, double radius, double mass) |
308 |
: Actor(kind, V2()), state(NO_STATE) |
: Actor(kind, V2()), state(NO_STATE), |
309 |
|
m_shield_rest_time(0), |
310 |
|
m_halostate(NOHALO) |
311 |
|
|
312 |
//, sinkDepth (0), sinkModel(-1) |
//, sinkDepth (0), sinkModel(-1) |
313 |
{ |
{ |
314 |
world::ActorInfo *ai = get_actorinfo(); |
world::ActorInfo *ai = get_actorinfo(); |
316 |
ai->mass = mass; |
ai->mass = mass; |
317 |
} |
} |
318 |
|
|
319 |
|
void BasicBall::change_state_noshield (State newstate) |
320 |
|
{ |
321 |
|
if (!has_halo()) |
322 |
|
change_state(newstate); |
323 |
|
} |
324 |
|
|
325 |
void BasicBall::message(const string &m, const Value &) |
void BasicBall::message(const string &m, const Value &) |
326 |
{ |
{ |
327 |
switch (state) { |
switch (state) { |
328 |
case NORMAL: |
case NORMAL: |
329 |
if (m == "shatter") change_state(SHATTERING); |
if (m == "shatter") change_state_noshield(SHATTERING); |
330 |
else if (m == "laserhit") change_state(SHATTERING); |
else if (m == "laserhit") change_state_noshield(SHATTERING); |
331 |
else if (m == "sink") change_state(SINKING); |
else if (m == "sink") change_state_noshield(SINKING); |
332 |
else if (m == "drown") change_state(DROWNING); |
else if (m == "drown") change_state_noshield(DROWNING); |
333 |
else if (m == "fall") change_state(FALLING); |
else if (m == "fall") change_state_noshield(FALLING); |
334 |
else if (m == "fallvortex") change_state(FALLING_VORTEX); |
else if (m == "fallvortex") change_state(FALLING_VORTEX); |
335 |
else if (m == "jump") change_state(JUMPING); |
else if (m == "jump") change_state(JUMPING); |
336 |
else if (m == "appear") change_state(APPEARING); |
else if (m == "appear") change_state(APPEARING); |
337 |
else if (m == "disappear") change_state(DISAPPEARING); |
else if (m == "disappear") change_state(DISAPPEARING); |
338 |
break; |
break; |
339 |
case JUMPING: |
case JUMPING: |
340 |
if (m == "shatter") change_state(SHATTERING); |
if (m == "shatter") change_state_noshield(SHATTERING); |
341 |
else if (m == "disappear") change_state(DISAPPEARING); |
else if (m == "disappear") change_state(DISAPPEARING); |
342 |
break; |
break; |
343 |
case DEAD: |
case DEAD: |
344 |
if (m == "resurrect") change_state(RESURRECTED); |
if (m == "resurrect") change_state(RESURRECTED); |
345 |
break; |
break; |
346 |
case SINKING: |
case SINKING: |
347 |
if (m == "getout") change_state(NORMAL); |
if (m == "getout") change_state(NORMAL); |
348 |
break; |
break; |
349 |
case FALLING_VORTEX: |
case FALLING_VORTEX: |
350 |
if (m == "rise") change_state(RISING_VORTEX); // vortex->vortex teleportation |
if (m == "rise") change_state(RISING_VORTEX); // vortex->vortex teleportation |
351 |
else if (m == "appear") change_state(APPEARING); // vortex->non-vortex teleportation |
else if (m == "appear") change_state(APPEARING); // vortex->non-vortex teleportation |
352 |
break; |
break; |
353 |
case JUMP_VORTEX: |
case JUMP_VORTEX: |
354 |
if (m == "laserhit") change_state(SHATTERING); |
if (m == "laserhit") change_state(SHATTERING); |
355 |
break; |
break; |
356 |
|
|
357 |
default: |
default: |
358 |
break; |
break; |
359 |
|
} |
360 |
|
|
361 |
|
// Shield can be activated in all states except DEAD |
362 |
|
|
363 |
|
if (state != DEAD && m == "shield") { |
364 |
|
m_shield_rest_time += SHIELD_TIME; |
365 |
|
update_halo(); |
366 |
} |
} |
367 |
} |
} |
368 |
|
|
401 |
if (shared.vortex.normal_time > dtime) // ensure min. one tick in state JUMP_VORTEX! |
if (shared.vortex.normal_time > dtime) // ensure min. one tick in state JUMP_VORTEX! |
402 |
change_state(JUMPING); // end of short control over actor |
change_state(JUMPING); // end of short control over actor |
403 |
} |
} |
404 |
|
|
405 |
|
// Update protection shield |
406 |
|
if (m_shield_rest_time > 0) { |
407 |
|
m_shield_rest_time -= dtime; |
408 |
|
update_halo(); |
409 |
|
} |
410 |
} |
} |
411 |
|
|
412 |
void BasicBall::set_sink_model(const string &m) |
void BasicBall::set_sink_model(const string &m) |
565 |
} |
} |
566 |
} |
} |
567 |
|
|
568 |
|
bool |
569 |
|
BasicBall::has_halo() |
570 |
|
{ |
571 |
|
return m_shield_rest_time > 0; |
572 |
|
} |
573 |
|
|
574 |
|
void |
575 |
|
BasicBall::update_halo() |
576 |
|
{ |
577 |
|
HaloState newstate = m_halostate; |
578 |
|
|
579 |
|
if (m_shield_rest_time <= 0) |
580 |
|
newstate = NOHALO; |
581 |
|
else if (m_shield_rest_time <= 3.0) |
582 |
|
newstate = HALOBLINK; |
583 |
|
else |
584 |
|
newstate = HALONORMAL; |
585 |
|
|
586 |
|
if (newstate != m_halostate) { |
587 |
|
switch (newstate) { |
588 |
|
case NOHALO: |
589 |
|
// remove halo |
590 |
|
m_halosprite.kill(); |
591 |
|
m_halosprite = display::SpriteHandle(); |
592 |
|
break; |
593 |
|
case HALOBLINK: |
594 |
|
// blink for the last 3 seconds |
595 |
|
m_halosprite.replace_model (display::MakeModel ("halo-blink")); |
596 |
|
break; |
597 |
|
case HALONORMAL: |
598 |
|
if (m_halostate == NOHALO) |
599 |
|
m_halosprite = display::AddSprite (get_pos(), "halo"); |
600 |
|
else |
601 |
|
m_halosprite.replace_model (display::MakeModel ("halo")); |
602 |
|
break; |
603 |
|
} |
604 |
|
m_halostate = newstate; |
605 |
|
} |
606 |
|
else if (m_halostate != NOHALO) { |
607 |
|
m_halosprite.move (get_pos()); |
608 |
|
} |
609 |
|
} |
610 |
|
|
611 |
|
|
612 |
|
|
613 |
//---------------------------------------- |
//---------------------------------------- |
614 |
// Balls of different sorts |
// Balls of different sorts |
615 |
//---------------------------------------- |
//---------------------------------------- |
619 |
class BlackBall : public BasicBall { |
class BlackBall : public BasicBall { |
620 |
CLONEACTOR(BlackBall); |
CLONEACTOR(BlackBall); |
621 |
public: |
public: |
622 |
BlackBall() : BasicBall("ac-blackball", 19.0/64.0, 1.0) |
BlackBall() : BasicBall("ac-blackball", 19.0/64, 1.0) |
623 |
{ |
{ |
624 |
set_attrib("mouseforce", Value(true)); |
set_attrib("mouseforce", Value(true)); |
625 |
set_attrib("color", Value(0.0)); |
set_attrib("color", Value(0.0)); |
630 |
class WhiteBall : public BasicBall { |
class WhiteBall : public BasicBall { |
631 |
CLONEACTOR(WhiteBall); |
CLONEACTOR(WhiteBall); |
632 |
public: |
public: |
633 |
WhiteBall() : BasicBall("ac-whiteball", 19.0/64.0, 1.0) |
WhiteBall() : BasicBall("ac-whiteball", 19.0/64, 1.0) |
634 |
{ |
{ |
635 |
set_attrib("mouseforce", Value(true)); |
set_attrib("mouseforce", Value(true)); |
636 |
set_attrib("color", Value(1.0)); |
set_attrib("color", Value(1.0)); |