From be79a2085027d3c990b621d1cf58fafaba1bcc67 Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Thu, 4 May 2006 19:29:09 +0000 Subject: [PATCH] New Badguy "Igel" SVN-Revision: 3492 --- data/images/creatures/igel/igel.sprite | 14 +++ data/images/creatures/igel/walking-0.png | Bin 0 -> 3711 bytes data/levels/world2/christoph5.stl | 6 +- data/levels/world2/level2.stl | 2 +- src/badguy/igel.cpp | 200 +++++++++++++++++++++++++++++++ src/badguy/igel.hpp | 60 ++++++++++ 6 files changed, 278 insertions(+), 4 deletions(-) create mode 100644 data/images/creatures/igel/igel.sprite create mode 100755 data/images/creatures/igel/walking-0.png create mode 100644 src/badguy/igel.cpp create mode 100644 src/badguy/igel.hpp 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 0000000000000000000000000000000000000000..2fd7cac8b4df85d0adba6159112860f5004b5324 GIT binary patch literal 3711 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 +// +// 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 + -- 2.11.0