From: Christoph Sommer Date: Thu, 4 May 2006 19:29:09 +0000 (+0000) Subject: New Badguy "Igel" X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=be79a2085027d3c990b621d1cf58fafaba1bcc67;p=supertux.git New Badguy "Igel" SVN-Revision: 3492 --- diff --git a/data/images/creatures/igel/igel.sprite b/data/images/creatures/igel/igel.sprite new file mode 100644 index 000000000..a143fe1ad --- /dev/null +++ b/data/images/creatures/igel/igel.sprite @@ -0,0 +1,14 @@ +(supertux-sprite + (action + (name "walking-left") + (hitbox 2.1 6.1 45.8 25.8) + (images + "walking-0.png" + ) + ) + (action + (name "walking-right") + (hitbox 2.1 6.1 45.8 25.8) + (mirror-action "walking-left") + ) +) diff --git a/data/images/creatures/igel/walking-0.png b/data/images/creatures/igel/walking-0.png new file mode 100755 index 000000000..2fd7cac8b Binary files /dev/null and b/data/images/creatures/igel/walking-0.png differ diff --git a/data/levels/world2/christoph5.stl b/data/levels/world2/christoph5.stl index 37a1e0c65..6d53145f9 100755 --- a/data/levels/world2/christoph5.stl +++ b/data/levels/world2/christoph5.stl @@ -21,15 +21,15 @@ (x 516.3934) (y 1660.307) ) - (spiky + (igel (x 3927.36) (y 1838.617) ) - (spiky + (igel (x 3515.824) (y 1842.859) ) - (spiky + (igel (x 3128.329) (y 1838.617) ) diff --git a/data/levels/world2/level2.stl b/data/levels/world2/level2.stl index 6648c3b39..d9902eb51 100644 --- a/data/levels/world2/level2.stl +++ b/data/levels/world2/level2.stl @@ -261,7 +261,7 @@ (poisonivy (x 6758) (y 398)) (poisonivy (x 6555) (y 399)) (jumpy (x 4704) (y 1315)) - (spiky (x 5645) (y 876)) + (igel (x 5645) (y 876)) (poisonivy (x 2898) (y 1487)) (poisonivy (x 2781) (y 1489)) (mrtree (x 4066) (y 272)) diff --git a/src/badguy/igel.cpp b/src/badguy/igel.cpp new file mode 100644 index 000000000..880096548 --- /dev/null +++ b/src/badguy/igel.cpp @@ -0,0 +1,200 @@ +// $Id: igel.cpp 3478 2006-04-30 23:14:15Z sommer $ +// +// SuperTux - Badguy "Igel" +// Copyright (C) 2006 Christoph Sommer +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include + +#include "igel.hpp" +#include "object/block.hpp" +#include "sector.hpp" +#include "object/bullet.hpp" + +namespace { + const float WALKSPEED = 80; /**< speed at which we walk around */ + const float TURN_RECOVER_TIME = 0.5; /**< seconds before we will again turn around when shot at */ + const float RANGE_OF_VISION = 256; /**< range in px at which we can see bullets */ +} + +Igel::Igel(const lisp::Lisp& reader) + : state(STATE_NORMAL) +{ + reader.get("x", start_position.x); + reader.get("y", start_position.y); + sprite = sprite_manager->create("images/creatures/igel/igel.sprite"); + bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); + set_direction = false; +} + +Igel::Igel(float pos_x, float pos_y, Direction d) + : state(STATE_NORMAL) +{ + start_position.x = pos_x; + start_position.y = pos_y; + sprite = sprite_manager->create("images/creatures/igel/igel.sprite"); + bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); + set_direction = true; + initial_direction = d; +} + +void +Igel::write(lisp::Writer& writer) +{ + writer.start_list("igel"); + + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); + + writer.end_list("igel"); +} + +void +Igel::activate() +{ + if (set_direction) {dir = initial_direction;} + + be_normal(); +} + +void +Igel::be_normal() +{ + state = STATE_NORMAL; + sprite->set_action(dir == LEFT ? "walking-left" : "walking-right"); + + physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); +} + +void +Igel::turn_around() +{ + dir = (dir == LEFT ? RIGHT : LEFT); + turn_recover_timer.start(TURN_RECOVER_TIME); + be_normal(); +} + +bool +Igel::can_see(const MovingObject& o) +{ + Rect mb = get_bbox(); + Rect ob = o.get_bbox(); + + bool inReach_left = (ob.p2.x >= mb.p1.x-((dir == LEFT) ? RANGE_OF_VISION : 0)); + bool inReach_right = (ob.p1.x <= mb.p2.x+((dir == RIGHT) ? RANGE_OF_VISION : 0)); + bool inReach_top = (ob.p2.y >= mb.p1.y); + bool inReach_bottom = (ob.p1.y <= mb.p2.y); + + return (inReach_left && inReach_right && inReach_top && inReach_bottom); +} + +void +Igel::active_update(float elapsed_time) +{ + switch (state) { + + case STATE_NORMAL: + if (might_fall()) { + // turn around when we are at a ledge + turn_around(); + } + else if (!turn_recover_timer.started()) { + // turn around when we see a Bullet + Sector* sector = Sector::current(); + for (Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) { + Bullet* bullet = dynamic_cast(*i); + if (bullet) { + if (can_see(*bullet)) turn_around(); + } + } + } + break; + + } + + BadGuy::active_update(elapsed_time); +} + +HitResponse +Igel::collision_solid(GameObject& , const CollisionHit& hit) +{ + if(fabsf(hit.normal.y) > .5) { // floor or roof + physic.set_velocity_y(0); + return CONTINUE; + } + + // hit left or right + switch(state) { + + case STATE_NORMAL: + turn_around(); + break; + + } + + return CONTINUE; +} + +HitResponse +Igel::collision_badguy(BadGuy& , const CollisionHit& hit) +{ + if(fabsf(hit.normal.y) > .5) { // floor or roof + physic.set_velocity_y(0); + return CONTINUE; + } + + // hit left or right + switch(state) { + + case STATE_NORMAL: + turn_around(); + break; + + } + + return CONTINUE; +} + +HitResponse +Igel::collision_bullet(Bullet& , const CollisionHit& hit) +{ + // die if hit on front side + if (((dir == LEFT) && (hit.normal.x > 0)) || ((dir == RIGHT) && (hit.normal.x < 0))) { + kill_fall(); + return ABORT_MOVE; + } + + // else ignore bullet + return FORCE_MOVE; +} + +bool +Igel::collision_squished(Player& ) +{ + switch(state) { + + case STATE_NORMAL: + // this will hurt + return false; + break; + + } + + kill_fall(); + return true; +} + +IMPLEMENT_FACTORY(Igel, "igel") diff --git a/src/badguy/igel.hpp b/src/badguy/igel.hpp new file mode 100644 index 000000000..14b8ee50a --- /dev/null +++ b/src/badguy/igel.hpp @@ -0,0 +1,60 @@ +// $Id: igel.hpp 3452 2006-04-27 18:19:15Z sommer $ +// +// SuperTux - Badguy "Igel" +// Copyright (C) 2006 Christoph Sommer +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef __IGEL_H__ +#define __IGEL_H__ + +#include "badguy.hpp" +#include "moving_object.hpp" + +/** + * Badguy "Igel" - a hedgehog that can absorb bullets + */ +class Igel : public BadGuy +{ +public: + Igel(const lisp::Lisp& reader); + Igel(float pos_x, float pos_y, Direction d); + + void activate(); + void write(lisp::Writer& writer); + HitResponse collision_solid(GameObject& object, const CollisionHit& hit); + HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit); + HitResponse collision_bullet(Bullet& bullet, const CollisionHit& hit); + + void active_update(float elapsed_time); + +protected: + bool collision_squished(Player& player); + void be_normal(); /**< switch to state STATE_NORMAL */ + void turn_around(); /**< reverse direction, assumes we are in STATE_NORMAL */ + bool can_see(const MovingObject& o); /**< check if we can see o */ + +private: + enum State { + STATE_NORMAL /**< walking around */ + }; + State state; + Timer turn_recover_timer; /**< wait time until we will turn around again when shot at */ + bool set_direction; + Direction initial_direction; +}; + +#endif +