2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "badguy/kugelblitz.hpp"
21 #include "math/random_generator.hpp"
22 #include "object/camera.hpp"
23 #include "object/player.hpp"
24 #include "sprite/sprite.hpp"
25 #include "sprite/sprite_manager.hpp"
26 #include "supertux/object_factory.hpp"
27 #include "supertux/sector.hpp"
28 #include "util/reader.hpp"
32 #define BASE_SPEED 200
33 #define RAND_SPEED 150
35 Kugelblitz::Kugelblitz(const Reader& reader) :
36 BadGuy(reader, "images/creatures/kugelblitz/kugelblitz.sprite"),
38 groundhit_pos_set(false),
43 light(0.0f,0.0f,0.0f),
44 lightsprite(SpriteManager::current()->create("images/objects/lightmap_light/lightmap_light.sprite"))
46 reader.get("x", start_position.x);
47 sprite->set_action("falling");
48 physic.enable_gravity(false);
51 lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
52 lightsprite->set_color(Color(0.2f, 0.1f, 0.0f));
56 Kugelblitz::initialize()
58 physic.set_velocity_y(300);
59 physic.set_velocity_x(-20); //fall a little to the left
65 Kugelblitz::collision_solid(const CollisionHit& chit)
71 Kugelblitz::collision_player(Player& player, const CollisionHit& )
73 if(player.is_invincible()) {
78 if(player.get_movement().y - get_movement().y > 0 && player.get_bbox().p2.y <
79 (get_bbox().p1.y + get_bbox().p2.y) / 2) {
80 // if it's not is it possible to squish us, then this will hurt
81 if(!collision_squished(player))
92 Kugelblitz::collision_badguy(BadGuy& other , const CollisionHit& chit)
94 //Let the Kugelblitz explode, too? The problem with that is that
95 //two Kugelblitzes would cancel each other out on contact...
101 Kugelblitz::hit(const CollisionHit& hit_)
105 if (!groundhit_pos_set)
107 pos_groundhit = get_pos();
108 groundhit_pos_set = true;
110 sprite->set_action("flying");
111 physic.set_velocity_y(0);
112 //Set random initial speed and direction
113 direction = gameRandom.rand(2)? 1: -1;
114 int speed = (BASE_SPEED + (gameRandom.rand(RAND_SPEED))) * direction;
115 physic.set_velocity_x(speed);
116 movement_timer.start(MOVETIME);
117 lifetime.start(LIFETIME);
119 } else if(hit_.top) { // bumped on roof
120 physic.set_velocity_y(0);
127 Kugelblitz::active_update(float elapsed_time)
129 if (lifetime.check()) {
133 if (groundhit_pos_set) {
134 if (movement_timer.check()) {
135 if (direction == 1) direction = -1; else direction = 1;
136 int speed = (BASE_SPEED + (gameRandom.rand(RAND_SPEED))) * direction;
137 physic.set_velocity_x(speed);
138 movement_timer.start(MOVETIME);
142 if (Sector::current()->solids->get_tile_at(get_pos())->getAttributes() == 16) {
144 Sector::current()->add_object(new Electrifier(75,1421,1.5));
145 Sector::current()->add_object(new Electrifier(76,1422,1.5));
148 if (Sector::current()->solids->get_tile_at(get_pos())->getAttributes() == 48) {
149 //HIT ELECTRIFIED WATER
154 BadGuy::active_update(elapsed_time);
158 Kugelblitz::draw(DrawingContext& context)
160 sprite->draw(context, get_pos(), layer);
162 //Only draw light in dark areas
163 context.get_light( get_bbox().get_middle(), &light );
164 if (light.red + light.green < 2.0){
165 context.push_target();
166 context.set_target(DrawingContext::LIGHTMAP);
167 sprite->draw(context, get_pos(), layer);
168 lightsprite->draw(context, get_bbox().get_middle(), 0);
169 context.pop_target();
174 Kugelblitz::kill_fall()
179 Kugelblitz::explode()
182 sprite->set_action("pop");
183 lifetime.start(0.2f);
190 Kugelblitz::try_activate()
192 // Much smaller offscreen distances to pop out of nowhere and surprise Tux
193 float X_OFFSCREEN_DISTANCE = 400;
194 float Y_OFFSCREEN_DISTANCE = 600;
196 Player* player_ = get_nearest_player();
197 if (!player_) return;
198 Vector dist = player_->get_bbox().get_middle() - get_bbox().get_middle();
199 if ((fabsf(dist.x) <= X_OFFSCREEN_DISTANCE) && (fabsf(dist.y) <= Y_OFFSCREEN_DISTANCE)) {
200 set_state(STATE_ACTIVE);
201 if (!is_initialized) {
203 // if starting direction was set to AUTO, this is our chance to re-orient the badguy
204 if (start_dir == AUTO) {
205 Player* player__ = get_nearest_player();
206 if (player__ && (player__->get_bbox().p1.x > get_bbox().p2.x)) {
214 is_initialized = true;