From 89ecbfcacb9abac599f8feba52792392b8199cf1 Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Wed, 16 Aug 2006 01:08:19 +0000 Subject: [PATCH] Committed gnomino's iceflower patch. Also added placeholder graphics (selfmade, PD) for Tux. SVN-Revision: 4188 --- .../creatures/tux_big/big-ice-tux-head.sprite | 91 +++++++++++++++++++++ data/images/creatures/tux_big/head-ice-duck-0.png | Bin 0 -> 2997 bytes data/images/creatures/tux_big/head-ice-skid-0.png | Bin 0 -> 2557 bytes data/images/creatures/tux_big/head-ice-stand-0.png | Bin 0 -> 2386 bytes data/images/objects/bullets/icebullet.sprite | 2 +- data/images/objects/particles/icetux-cap.png | Bin 0 -> 1723 bytes data/images/objects/particles/icetux-cap.sprite | 14 ++++ data/scripts/console.nut | 5 ++ src/badguy/badguy.cpp | 44 +++++++++- src/badguy/badguy.hpp | 16 ++++ src/badguy/dispenser.cpp | 21 +++++ src/badguy/dispenser.hpp | 4 + src/badguy/fish.cpp | 27 +++++- src/badguy/fish.hpp | 4 + src/badguy/jumpy.cpp | 19 ++++- src/badguy/jumpy.hpp | 3 + src/badguy/mrbomb.cpp | 64 +++++++++++++++ src/badguy/mrbomb.hpp | 17 +++- src/badguy/spiky.cpp | 13 +++ src/badguy/spiky.hpp | 3 + src/badguy/sspiky.cpp | 14 ++++ src/badguy/sspiky.hpp | 3 + src/badguy/walking_badguy.cpp | 20 ++++- src/badguy/walking_badguy.hpp | 2 + src/object/bullet.cpp | 24 ++++-- src/object/bullet.hpp | 9 +- src/object/player.cpp | 10 ++- src/resources.cpp | 2 +- src/sector.cpp | 7 +- 29 files changed, 415 insertions(+), 23 deletions(-) create mode 100644 data/images/creatures/tux_big/big-ice-tux-head.sprite create mode 100644 data/images/creatures/tux_big/head-ice-duck-0.png create mode 100644 data/images/creatures/tux_big/head-ice-skid-0.png create mode 100644 data/images/creatures/tux_big/head-ice-stand-0.png create mode 100644 data/images/objects/particles/icetux-cap.png create mode 100644 data/images/objects/particles/icetux-cap.sprite diff --git a/data/images/creatures/tux_big/big-ice-tux-head.sprite b/data/images/creatures/tux_big/big-ice-tux-head.sprite new file mode 100644 index 000000000..10ffb881d --- /dev/null +++ b/data/images/creatures/tux_big/big-ice-tux-head.sprite @@ -0,0 +1,91 @@ +(supertux-sprite + (action + (name "walk-right") + (fps 15.0) + (hitbox 5 32 0 0) + (images "head-ice-stand-0.png")) + + (action + (name "walk-left") + (fps 15.0) + (hitbox 27 32 0 0) + (mirror-action "walk-right")) + + (action + (name "stand-right") + (fps 15.0) + (hitbox 5 32 0 0) + (images "head-ice-stand-0.png")) + + (action + (name "stand-left") + (fps 15.0) + (hitbox 27 32 0 0) + (mirror-action "stand-right")) + + (action + (name "jump-right") + (fps 15.0) + (hitbox 5 30 0 0) + (images "head-ice-stand-0.png")) + + (action + (name "jump-left") + (fps 15.0) + (hitbox 27 30 0 0) + (mirror-action "jump-right")) + + (action + (name "duck-right") + (fps 15.0) + (hitbox 5 62 0 0) + (images "head-ice-duck-0.png")) + + (action + (name "duck-left") + (fps 15.0) + (hitbox 27 62 0 0) + (mirror-action "duck-right")) + + (action + (name "skid-right") + (hitbox 6 31 0 0) + (images "head-ice-skid-0.png")) + + (action + (name "skid-left") + (hitbox 27 31 0 0) + (mirror-action "skid-right")) + + (action + (name "kick-right") + (hitbox 5 32 0 0) + (images "head-ice-stand-0.png")) + + (action + (name "kick-left") + (hitbox 27 32 0 0) + (mirror-action "kick-right")) + + (action + (name "buttjump-right") + (hitbox 5 32 0 0) + (images "head-ice-stand-0.png")) + + (action + (name "buttjump-left") + (hitbox 27 32 0 0) + (mirror-action "buttjump-right")) + + (action + (name "idle-right") + (fps 1.0) + (hitbox 6 31 0 0) + (images "head-idle-blink-0.png" + "head-idle-blink-1.png")) + + (action + (name "idle-left") + (fps 1.0) + (hitbox 27 31 0 0) + (mirror-action "idle-right"))) diff --git a/data/images/creatures/tux_big/head-ice-duck-0.png b/data/images/creatures/tux_big/head-ice-duck-0.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab94a2055578215339e0d2405025baf6df18690 GIT binary patch literal 2997 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 literal 0 HcmV?d00001 diff --git a/data/images/creatures/tux_big/head-ice-skid-0.png b/data/images/creatures/tux_big/head-ice-skid-0.png new file mode 100644 index 0000000000000000000000000000000000000000..65dc805171b9b0d53ea4c3bf3c19c700c635f953 GIT binary patch literal 2557 zcmVWFU8GbZ8({Xk{QrNlj4iWF>9@01079L_t(|+U?kTj9oTD27CZqGH4dQpL7FYq8yxZFjf(ymue>aqd0OnemS`)jy52VIlKLPI8iyOwRdc zelv4^fTAdhq9}@@D2k#eilQirqA1GgVF1tpI1BX!$(b7Xv)6y|>`voj8$7eOYiRsL ze^X2H`qMAnJxB-n zGZ_Fq9UuRz?;pGP&EKBb-D6+g<<}w>CmfSAvt(#|3?ma0I59qs;%pg7%Aso-Y|Daa z8gMi7#{)yt(b}8?7Xop}QLDvmtCn1Pe&5*_b?$w7;PM3>z|novh26jY-nU%6ZP|a7 z6iK;2l*Rx6&gXZ#C<#FsMLlRh*L3idBZ%h9ywM1easkUW(3HzyMeCJzdA7FciD&Qc zU9cq}r8Ez{I(3cf=GOOG*VxmuzO084wM`v`d=qqyff5SSG*OzH#$0s+PD0|?wp%9 z;)v^p&PWi25))G=v3zw4?zr>`ggJYXFZ@v@2&IJ{~-lzJ#rc5ELF}t6 zF*7rRjT<+fbNKM#tIkva|91&&`0BakC~0(#P7Vr2ft071t(7rX^)XxZ(d;x~dH1zYY|+l83zVm#&G#BU}g%&Cw^>!8sHL1>7Vk3I<9=D6|38*$G)-vB_+)zt+lBK+v?HMnqn3f&2y8yu#= zKq=7h83?g3cvA4`z?*T+wx@+3?lBPzL8Pe^Twb~DwfFtQ#NJoa2p~3S!q=}Ex@GJ1F19;%BCagY>z_B%WIRQH( z!5D$Y0MlY{TwqbBNjvheEwgeNNP3IkU|&m#T{K8MddsJJ<6XZQmLJF>2mn`qVaeLgA$5+0-K`!Eb0hOWVnOAwM{Z1f}s`vs2XC$Vxxh?_UHBkKe(%n(dV z(TH`VzWMJ-Ns-0`JYtYC0_QQQR}I#fk)D<&UaE^n>so%qp)+p);2&530I+Or{wK#q zo#kO1_P^mqXkq61*CwTNx?utD1np` zf>ZFAAxR0+m_R^+fg$24ia}Bny8VNMW!_ru&7>dLHh5|k)ze=Hq!&>$`J9=v?CFsj zk~BaqE;TP893#6Cuk9P4k70 zudG;c&QEnaAMAMG;nUhFdfzi(bnXCO-{BoQc96aA>=06Nn(}Cq?HICsQHvlpuZIBW4zw6?Xu^YUnI&7(9MAxa36gpZun)BA@7+YgB2n5|p4jsVzd7{;9M`=U~* z5Zkt)>-v1d!!W=(KXqlZS#)=IgHi^=FyLi9I8Fwpn}^hF43EztiXt9G5pQj6y5}kN_BCpp*hq zqEfA(Se!;K=gFl@mnP+Mxpe&aabsj;q!YmKf|>!_w{Ir^uxHPn%c3ZH4L~1bOxm_h zq?C|S!m=#nayhuJ3&SuF1OZIbgyT4{GY*`L15MKq#|c0vCMS!sr>9303hgMD%htfa zK(~}~y_7QO>+8!xQ4~c{6h%=KMNt$*Q4~c{6h%=KMNt$*Q4~c{6h%=K<$v@qa@=Nz T$Bd2M00000NkvXXu0mjfN2Ih) literal 0 HcmV?d00001 diff --git a/data/images/creatures/tux_big/head-ice-stand-0.png b/data/images/creatures/tux_big/head-ice-stand-0.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca5337dc494cf88ac6138456b7fa54c32628c00 GIT binary patch literal 2386 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 RbgKXW002ovPDHLkV1g31Gg|-v literal 0 HcmV?d00001 diff --git a/data/images/objects/particles/icetux-cap.sprite b/data/images/objects/particles/icetux-cap.sprite new file mode 100644 index 000000000..772fc3e7f --- /dev/null +++ b/data/images/objects/particles/icetux-cap.sprite @@ -0,0 +1,14 @@ +(supertux-sprite + (action + (name "right") + (fps 1) + (images + "icetux-cap.png" + ) + ) + (action + (name "left") + (fps 1) + (mirror-action "right") + ) +) diff --git a/data/scripts/console.nut b/data/scripts/console.nut index 131ef436f..5da37752f 100644 --- a/data/scripts/console.nut +++ b/data/scripts/console.nut @@ -24,6 +24,11 @@ function fire() sector.Tux.add_bonus("fireflower"); } +function ice() +{ + sector.Tux.add_bonus("iceflower"); +} + function shrink() { sector.Tux.add_bonus("none"); diff --git a/src/badguy/badguy.cpp b/src/badguy/badguy.cpp index 299dece64..f99b808f9 100644 --- a/src/badguy/badguy.cpp +++ b/src/badguy/badguy.cpp @@ -34,7 +34,7 @@ static const float X_OFFSCREEN_DISTANCE = 1600; static const float Y_OFFSCREEN_DISTANCE = 1200; BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer) - : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false) + : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), frozen(false), state(STATE_INIT), on_ground_flag(false) { start_position = bbox.p1; @@ -43,7 +43,7 @@ BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer) } BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite_name, int layer) - : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), state(STATE_INIT), on_ground_flag(false) + : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), frozen(false), state(STATE_INIT), on_ground_flag(false) { start_position = bbox.p1; @@ -52,7 +52,7 @@ BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite } BadGuy::BadGuy(const lisp::Lisp& reader, const std::string& sprite_name, int layer) - : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false) + : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), frozen(false), state(STATE_INIT), on_ground_flag(false) { start_position = bbox.p1; @@ -222,6 +222,8 @@ BadGuy::collision_player(Player& player, const CollisionHit& ) return ABORT_MOVE; } + if(frozen) + unfreeze(); player.kill(false); return FORCE_MOVE; } @@ -241,8 +243,16 @@ BadGuy::collision_squished(Player& ) HitResponse BadGuy::collision_bullet(Bullet& bullet, const CollisionHit& ) { + if(frozen) { + if(bullet.get_type() == FIRE_BONUS) + unfreeze(); + else + return FORCE_MOVE; + } else if(bullet.get_type() == ICE_BONUS && is_freezable()) { + freeze(); + } else + kill_fall(); bullet.remove_me(); - kill_fall(); return ABORT_MOVE; } @@ -425,3 +435,29 @@ BadGuy::on_ground() { return on_ground_flag; } + +void +BadGuy::freeze() +{ + set_group(COLGROUP_MOVING_STATIC); + frozen = true; +} + +void +BadGuy::unfreeze() +{ + set_group(COLGROUP_MOVING); + frozen = false; +} + +bool +BadGuy::is_freezable() const +{ + return false; +} + +bool +BadGuy::is_frozen() const +{ + return frozen; +} diff --git a/src/badguy/badguy.hpp b/src/badguy/badguy.hpp index d5cf8739e..bbcbad8f0 100644 --- a/src/badguy/badguy.hpp +++ b/src/badguy/badguy.hpp @@ -93,6 +93,20 @@ public: * during runtime. */ bool countMe; + /** + * Called when hit by an ice bullet, and is_freezable() returns true. + */ + virtual void freeze(); + + /** + * Called to unfreeze the badguy. + */ + virtual void unfreeze(); + + virtual bool is_freezable() const; + + bool is_frozen() const; + protected: enum State { STATE_INIT, @@ -185,6 +199,8 @@ protected: */ bool on_ground(); + bool frozen; + private: void try_activate(); diff --git a/src/badguy/dispenser.cpp b/src/badguy/dispenser.cpp index 67ef6fcc3..c0fdbf8f6 100644 --- a/src/badguy/dispenser.cpp +++ b/src/badguy/dispenser.cpp @@ -60,6 +60,8 @@ Dispenser::write(lisp::Writer& writer) void Dispenser::activate() { + if(frozen) + return; dispense_timer.start(cycle, true); launch_badguy(); } @@ -122,4 +124,23 @@ Dispenser::launch_badguy() } } +void +Dispenser::freeze() +{ + BadGuy::freeze(); + dispense_timer.stop(); +} + +void +Dispenser::unfreeze() +{ + BadGuy::unfreeze(); + activate(); +} + +bool +Dispenser::is_freezable() const +{ + return true; +} IMPLEMENT_FACTORY(Dispenser, "dispenser") diff --git a/src/badguy/dispenser.hpp b/src/badguy/dispenser.hpp index c01e19e1d..90f2a3a06 100644 --- a/src/badguy/dispenser.hpp +++ b/src/badguy/dispenser.hpp @@ -32,6 +32,10 @@ public: void write(lisp::Writer& writer); void active_update(float elapsed_time); + void freeze(); + void unfreeze(); + bool is_freezable() const; + virtual Dispenser* clone() const { return new Dispenser(*this); } protected: diff --git a/src/badguy/fish.cpp b/src/badguy/fish.cpp index b60312509..803512096 100644 --- a/src/badguy/fish.cpp +++ b/src/badguy/fish.cpp @@ -91,7 +91,8 @@ Fish::collision_tile(uint32_t tile_attributes) // stop when we have reached the stop position if (get_pos().y >= stop_y) { - start_waiting(); + if(!frozen) + start_waiting(); movement = Vector(0, 0); } @@ -109,7 +110,8 @@ Fish::active_update(float elapsed_time) } // set sprite - sprite->set_action(physic.get_velocity_y() < 0 ? "normal" : "down"); + if(!frozen) + sprite->set_action(physic.get_velocity_y() < 0 ? "normal" : "down"); // we can't afford flying out of the tilemap, 'cause the engine would remove us. if ((get_pos().y - 31.8) < 0) // too high, let us fall @@ -136,4 +138,25 @@ Fish::jump() set_group(COLGROUP_MOVING); } +void +Fish::freeze() +{ + BadGuy::freeze(); + sprite->set_action(physic.get_velocity_y() < 0 ? "iced" : "iced-down"); + waiting.stop(); +} + +void +Fish::unfreeze() +{ // does this happen at all? (or do fishes die when they fall frozen?) + BadGuy::unfreeze(); + start_waiting(); +} + +bool +Fish::is_freezable() const +{ + return true; +} + IMPLEMENT_FACTORY(Fish, "fish") diff --git a/src/badguy/fish.hpp b/src/badguy/fish.hpp index 413b5c27e..fa36dee97 100644 --- a/src/badguy/fish.hpp +++ b/src/badguy/fish.hpp @@ -37,6 +37,10 @@ public: void write(lisp::Writer& ); void active_update(float); + void freeze(); + void unfreeze(); + bool is_freezable() const; + virtual Fish* clone() const { return new Fish(*this); } private: diff --git a/src/badguy/jumpy.cpp b/src/badguy/jumpy.cpp index 012adaa5c..706a7d7bb 100644 --- a/src/badguy/jumpy.cpp +++ b/src/badguy/jumpy.cpp @@ -63,7 +63,7 @@ Jumpy::hit(const CollisionHit& chit) groundhit_pos_set = true; } - physic.set_velocity_y(JUMPSPEED); + physic.set_velocity_y(frozen ? 0 : JUMPSPEED); // TODO create a nice sound for this... //sound_manager->play("sounds/skid.wav"); } else if(chit.top) { @@ -78,6 +78,9 @@ Jumpy::active_update(float elapsed_time) { BadGuy::active_update(elapsed_time); + if(frozen) + return; + Player* player = this->get_nearest_player(); if (player) { @@ -99,4 +102,18 @@ Jumpy::active_update(float elapsed_time) sprite->set_action(dir == LEFT ? "left-down" : "right-down"); } +void +Jumpy::freeze() +{ + BadGuy::freeze(); + physic.set_velocity_y(std::max(0.0f, physic.get_velocity_y())); + sprite->set_action(dir == LEFT ? "left-iced" : "right-iced"); +} + +bool +Jumpy::is_freezable() const +{ + return true; +} + IMPLEMENT_FACTORY(Jumpy, "jumpy") diff --git a/src/badguy/jumpy.hpp b/src/badguy/jumpy.hpp index fa39085d6..b0f9e3ebd 100644 --- a/src/badguy/jumpy.hpp +++ b/src/badguy/jumpy.hpp @@ -33,6 +33,9 @@ public: void write(lisp::Writer& writer); void active_update(float); + void freeze(); + bool is_freezable() const; + virtual Jumpy* clone() const { return new Jumpy(*this); } private: diff --git a/src/badguy/mrbomb.cpp b/src/badguy/mrbomb.cpp index 68e076892..0526c9514 100644 --- a/src/badguy/mrbomb.cpp +++ b/src/badguy/mrbomb.cpp @@ -28,6 +28,7 @@ MrBomb::MrBomb(const lisp::Lisp& reader) { walk_speed = 80; max_drop_height = 0; + grabbed = false; //Check if we need another sprite if( !reader.get( "sprite", sprite_name ) ){ @@ -47,6 +48,7 @@ MrBomb::MrBomb(const Vector& pos, Direction d) { walk_speed = 80; max_drop_height = 0; + grabbed = false; } void @@ -57,6 +59,22 @@ MrBomb::write(lisp::Writer& writer) writer.end_list("mrbomb"); } +HitResponse +MrBomb::collision(GameObject& object, const CollisionHit& hit) +{ + if(grabbed) + return FORCE_MOVE; + return WalkingBadguy::collision(object, hit); +} + +HitResponse +MrBomb::collision_player(Player& player, const CollisionHit& hit) +{ + if(grabbed) + return FORCE_MOVE; + return WalkingBadguy::collision_player(player, hit); +} + bool MrBomb::collision_squished(Player& player) { @@ -67,6 +85,14 @@ MrBomb::collision_squished(Player& player) } void +MrBomb::active_update(float elapsed_time) +{ + if(grabbed) + return; + WalkingBadguy::active_update(elapsed_time); +} + +void MrBomb::kill_fall() { remove_me(); @@ -75,4 +101,42 @@ MrBomb::kill_fall() bomb->explode(); } +void +MrBomb::grab(MovingObject&, const Vector& pos, Direction dir) +{ + assert(frozen); + movement = pos - get_pos(); + this->dir = dir; + sprite->set_action(dir == LEFT ? "iced-left" : "iced-right"); + set_group(COLGROUP_DISABLED); + grabbed = true; +} + +void +MrBomb::ungrab(MovingObject& , Direction dir) +{ + this->dir = dir; + set_group(COLGROUP_MOVING); + grabbed = false; +} + +void +MrBomb::freeze() +{ + WalkingBadguy::freeze(); + sprite->set_action(dir == LEFT ? "iced-left" : "iced-right"); +} + +bool +MrBomb::is_freezable() const +{ + return true; +} + +bool +MrBomb::is_portable() const +{ + return frozen; +} + IMPLEMENT_FACTORY(MrBomb, "mrbomb") diff --git a/src/badguy/mrbomb.hpp b/src/badguy/mrbomb.hpp index 845c063a3..3a0adaf65 100644 --- a/src/badguy/mrbomb.hpp +++ b/src/badguy/mrbomb.hpp @@ -21,8 +21,9 @@ #define __MRBOMB_H__ #include "walking_badguy.hpp" +#include "object/portable.hpp" -class MrBomb : public WalkingBadguy +class MrBomb : public WalkingBadguy, public Portable { public: MrBomb(const lisp::Lisp& reader); @@ -30,11 +31,25 @@ public: void write(lisp::Writer& writer); void kill_fall(); + HitResponse collision(GameObject& object, const CollisionHit& hit); + HitResponse collision_player(Player& player, const CollisionHit& hit); + + void active_update(float elapsed_time); + + void grab(MovingObject& object, const Vector& pos, Direction dir); + void ungrab(MovingObject& object, Direction dir); + bool is_portable() const; + + void freeze(); + bool is_freezable() const; virtual MrBomb* clone() const { return new MrBomb(*this); } protected: bool collision_squished(Player& player); + +private: + bool grabbed; }; #endif diff --git a/src/badguy/spiky.cpp b/src/badguy/spiky.cpp index f2b42ac8c..eebf19a1d 100644 --- a/src/badguy/spiky.cpp +++ b/src/badguy/spiky.cpp @@ -36,4 +36,17 @@ Spiky::write(lisp::Writer& writer) writer.end_list("spiky"); } +void +Spiky::freeze() +{ + WalkingBadguy::freeze(); + sprite->set_action(dir == LEFT ? "iced-left" : "iced-right"); +} + +bool +Spiky::is_freezable() const +{ + return true; +} + IMPLEMENT_FACTORY(Spiky, "spiky") diff --git a/src/badguy/spiky.hpp b/src/badguy/spiky.hpp index 98f7e28e0..b90a0ecca 100644 --- a/src/badguy/spiky.hpp +++ b/src/badguy/spiky.hpp @@ -30,6 +30,9 @@ public: void write(lisp::Writer& writer); virtual Spiky* clone() const { return new Spiky(*this); } + void freeze(); + bool is_freezable() const; + private: }; diff --git a/src/badguy/sspiky.cpp b/src/badguy/sspiky.cpp index c81ea1d79..ad80b8de8 100644 --- a/src/badguy/sspiky.cpp +++ b/src/badguy/sspiky.cpp @@ -106,4 +106,18 @@ SSpiky::active_update(float elapsed_time) { } } +void +SSpiky::freeze() +{ + WalkingBadguy::freeze(); + sprite->set_action(dir == LEFT ? "iced-left" : "iced-right"); + state = SSPIKY_WALKING; // if we get hit while sleeping, wake up :) +} + +bool +SSpiky::is_freezable() const +{ + return true; +} + IMPLEMENT_FACTORY(SSpiky, "sspiky") diff --git a/src/badguy/sspiky.hpp b/src/badguy/sspiky.hpp index d99629d58..8e346cdfe 100644 --- a/src/badguy/sspiky.hpp +++ b/src/badguy/sspiky.hpp @@ -33,6 +33,9 @@ public: HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit); void active_update(float elapsed_time); + void freeze(); + bool is_freezable() const; + virtual SSpiky* clone() const { return new SSpiky(*this); } protected: diff --git a/src/badguy/walking_badguy.cpp b/src/badguy/walking_badguy.cpp index 66cc3f99b..74c2fd3b0 100644 --- a/src/badguy/walking_badguy.cpp +++ b/src/badguy/walking_badguy.cpp @@ -48,6 +48,8 @@ WalkingBadguy::write(lisp::Writer& writer) void WalkingBadguy::activate() { + if(frozen) + return; sprite->set_action(dir == LEFT ? walk_left_action : walk_right_action); bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); physic.set_velocity_x(dir == LEFT ? -walk_speed : walk_speed); @@ -97,7 +99,23 @@ WalkingBadguy::collision_badguy(BadGuy& , const CollisionHit& hit) void WalkingBadguy::turn_around() { + if(frozen) + return; dir = dir == LEFT ? RIGHT : LEFT; sprite->set_action(dir == LEFT ? walk_left_action : walk_right_action); - physic.set_velocity_x(dir == LEFT ? -walk_speed : walk_speed); + physic.set_velocity_x(-physic.get_velocity_x()); +} + +void +WalkingBadguy::freeze() +{ + BadGuy::freeze(); + physic.set_velocity_x(0); +} + +void +WalkingBadguy::unfreeze() +{ + BadGuy::unfreeze(); + WalkingBadguy::activate(); } diff --git a/src/badguy/walking_badguy.hpp b/src/badguy/walking_badguy.hpp index 6f023a833..313a52937 100644 --- a/src/badguy/walking_badguy.hpp +++ b/src/badguy/walking_badguy.hpp @@ -37,6 +37,8 @@ public: void active_update(float elapsed_time); void collision_solid(const CollisionHit& hit); HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit); + void freeze(); + void unfreeze(); protected: void turn_around(); diff --git a/src/object/bullet.cpp b/src/object/bullet.cpp index b6145e621..3a35faf6e 100644 --- a/src/object/bullet.cpp +++ b/src/object/bullet.cpp @@ -33,17 +33,21 @@ namespace { const float BULLET_STARTING_YM = 0; } -Bullet::Bullet(const Vector& pos, float xm, int dir) - : life_count(3) +Bullet::Bullet(const Vector& pos, float xm, int dir, BonusType type) + : life_count(3), type(type) { - sprite.reset(sprite_manager->create("images/objects/bullets/firebullet.sprite")); + float speed = dir == RIGHT ? BULLET_XM : -BULLET_XM; + physic.set_velocity_x(speed + xm); + + if(type == FIRE_BONUS) { + sprite.reset(sprite_manager->create("images/objects/bullets/firebullet.sprite")); + } else if(type == ICE_BONUS) { + life_count = 10; + sprite.reset(sprite_manager->create("images/objects/bullets/icebullet.sprite")); + } bbox.set_pos(pos); bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); - - float speed = dir == RIGHT ? BULLET_XM : -BULLET_XM; - physic.set_velocity_x(speed + xm); - physic.set_velocity_y(BULLET_STARTING_YM); } Bullet::~Bullet() @@ -83,7 +87,11 @@ Bullet::collision_solid(const CollisionHit& hit) physic.set_velocity_y(-physic.get_velocity_y()); life_count--; } else if(hit.left || hit.right) { - remove_me(); + if(type == ICE_BONUS) { + physic.set_velocity_x(-physic.get_velocity_x()); + life_count--; + } else + remove_me(); } } diff --git a/src/object/bullet.hpp b/src/object/bullet.hpp index c5eb76dc7..90547a32e 100644 --- a/src/object/bullet.hpp +++ b/src/object/bullet.hpp @@ -23,22 +23,29 @@ #include "moving_object.hpp" #include "physic.hpp" #include "sprite/sprite.hpp" +#include "player_status.hpp" class Bullet : public MovingObject { public: - Bullet(const Vector& pos, float xm, int dir); + Bullet(const Vector& pos, float xm, int dir, BonusType type); ~Bullet(); void update(float elapsed_time); void draw(DrawingContext& context); void collision_solid(const CollisionHit& hit); HitResponse collision(GameObject& other, const CollisionHit& hit); + + BonusType get_type() + { + return type; + } private: int life_count; Physic physic; std::auto_ptr sprite; + BonusType type; }; #endif diff --git a/src/object/player.cpp b/src/object/player.cpp index 0379da314..12d440a12 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -591,7 +591,7 @@ Player::handle_input() handle_vertical_input(); /* Shoot! */ - if (controller->pressed(Controller::ACTION) && player_status->bonus == FIRE_BONUS) { + if (controller->pressed(Controller::ACTION) && (player_status->bonus == FIRE_BONUS || player_status->bonus == ICE_BONUS)) { if(Sector::current()->add_bullet( get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2) : Vector(32, bbox.get_height()/2)), @@ -757,6 +757,14 @@ Player::set_bonus(BonusType type, bool animate) std::string action = (dir==LEFT)?"left":"right"; Sector::current()->add_object(new SpriteParticle("images/objects/particles/firetux-helmet.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); } + if ((player_status->bonus == ICE_BONUS) && (animate)) { + // visually lose cap + Vector ppos = Vector((bbox.p1.x + bbox.p2.x) / 2, bbox.p1.y); + Vector pspeed = Vector(((dir==LEFT) ? +100 : -100), -300); + Vector paccel = Vector(0, 1000); + std::string action = (dir==LEFT)?"left":"right"; + Sector::current()->add_object(new SpriteParticle("images/objects/particles/icetux-cap.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); + } player_status->max_fire_bullets = 0; player_status->max_ice_bullets = 0; } diff --git a/src/resources.cpp b/src/resources.cpp index 5c49081e9..215d6d5e6 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -99,7 +99,7 @@ void load_shared() fire_tux->feet = sprite_manager->create("images/creatures/tux_big/big-tux-feet.sprite"); ice_tux = new TuxBodyParts(); - ice_tux->head = sprite_manager->create("images/creatures/tux_big/big-tux-head.sprite"); + ice_tux->head = sprite_manager->create("images/creatures/tux_big/big-ice-tux-head.sprite"); ice_tux->body = sprite_manager->create("images/creatures/tux_big/big-tux-body.sprite"); ice_tux->arms = sprite_manager->create("images/creatures/tux_big/big-tux-arms.sprite"); ice_tux->feet = sprite_manager->create("images/creatures/tux_big/big-tux-feet.sprite"); diff --git a/src/sector.cpp b/src/sector.cpp index ddc62a286..eede80b1f 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -1283,9 +1283,12 @@ Sector::add_bullet(const Vector& pos, float xm, Direction dir) // TODO remove this function and move these checks elsewhere... Bullet* new_bullet = 0; - if((int)bullets.size() >= player_status->max_fire_bullets) + if((player_status->bonus == FIRE_BONUS && + (int)bullets.size() >= player_status->max_fire_bullets) || + (player_status->bonus == ICE_BONUS && + (int)bullets.size() >= player_status->max_ice_bullets)) return false; - new_bullet = new Bullet(pos, xm, dir); + new_bullet = new Bullet(pos, xm, dir, player_status->bonus); add_object(new_bullet); sound_manager->play("sounds/shoot.wav"); -- 2.11.0