1 // $Id: totem.cpp 3096 2006-03-17 12:03:02Z sommer $
3 // SuperTux - "Totem" Badguy
4 // Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 static const float WALKSPEED = 100;
27 static const float WALKSPEED_SMALL = 120;
28 static const float INVINCIBLE_TIME = 1;
30 static const float JUMP_OFF_SPEED_Y = 500;
32 Totem::Totem(const lisp::Lisp& reader)
34 stay_on_platform = false;
37 bbox.set_size(48, 49);
39 reader.get("x", start_position.x);
40 reader.get("y", start_position.y);
41 reader.get("stay-on-platform", stay_on_platform);
42 sprite = sprite_manager->create("images/creatures/totem/totem.sprite");
47 if (carrying) carrying->jump_off();
48 if (carried_by) jump_off();
52 Totem::write(lisp::Writer& writer)
54 writer.start_list("totem");
56 writer.write_float("x", start_position.x);
57 writer.write_float("y", start_position.y);
58 writer.write_bool("stay-on-platform", stay_on_platform);
60 writer.end_list("totem");
67 physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
68 sprite->set_action(dir == LEFT ? "walking-left" : "walking-right");
71 synchronize_with(carried_by);
72 sprite->set_action(dir == LEFT ? "stacked-left" : "stacked-right");
78 Totem::active_update(float elapsed_time)
80 BadGuy::active_update(elapsed_time);
83 if (stay_on_platform && may_fall_off_platform())
85 dir = (dir == LEFT ? RIGHT : LEFT);
91 this->synchronize_with(carried_by);
95 carrying->synchronize_with(this);
101 Totem::collision_squished(Player& player)
103 if (carrying) carrying->jump_off();
105 player.bounce(*this);
109 sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
110 this->bbox.set_size(48, 45);
111 kill_squished(player);
116 Totem::collision_solid(GameObject& object, const CollisionHit& hit)
118 // if we are being carried around, pass event to bottom of stack and ignore it
120 carried_by->collision_solid(object, hit);
124 // If we hit something from above or below: stop moving in this direction
125 if (hit.normal.y != 0) {
126 physic.set_velocity_y(0);
129 // If we are hit from the direction we are facing: turn around
130 if ((hit.normal.x > .8) && (dir == LEFT)) {
134 if ((hit.normal.x < -.8) && (dir == RIGHT)) {
143 Totem::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
145 // if we are being carried around, pass event to bottom of stack and ignore it
147 carried_by->collision_badguy(badguy, hit);
151 // if we hit a Totem that is not from our stack: have our base jump on its top
152 Totem* totem = dynamic_cast<Totem*>(&badguy);
154 Totem* thisBase = this; while (thisBase->carried_by) thisBase=thisBase->carried_by;
155 Totem* srcBase = totem; while (srcBase->carried_by) srcBase=srcBase->carried_by;
156 Totem* thisTop = this; while (thisTop->carrying) thisTop=thisTop->carrying;
157 if (srcBase != thisBase) {
158 srcBase->jump_on(thisTop);
162 // If we are hit from the direction we are facing: turn around
163 if ((hit.normal.x > .8) && (dir == LEFT)) {
167 if ((hit.normal.x < -.8) && (dir == RIGHT)) {
178 if (carrying) carrying->jump_off();
179 if (carried_by) jump_off();
185 Totem::jump_on(Totem* target)
187 if (target->carrying) {
188 msg_warning("target is already carrying someone");
192 target->carrying = this;
194 this->carried_by = target;
195 this->bbox.set_size(48, 45);
198 this->synchronize_with(target);
204 msg_warning("not carried by anyone");
208 carried_by->carrying = 0;
210 this->carried_by = 0;
211 this->bbox.set_size(48, 49);
215 physic.set_velocity_y(JUMP_OFF_SPEED_Y);
219 Totem::synchronize_with(Totem* base)
222 if (dir != base->dir) {
224 sprite->set_action(dir == LEFT ? "stacked-left" : "stacked-right");
227 Vector pos = base->get_pos();
231 physic.set_velocity_x(base->physic.get_velocity_x());
232 physic.set_velocity_y(base->physic.get_velocity_y());
236 IMPLEMENT_FACTORY(Totem, "totem")