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),
44 light(0.0f,0.0f,0.0f),
45 lightsprite(sprite_manager->create("images/objects/lightmap_light/lightmap_light.sprite"))
47 reader.get("x", start_position.x);
48 sprite->set_action("falling");
49 physic.enable_gravity(false);
52 lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
53 lightsprite->set_color(Color(0.2f, 0.1f, 0.0f));
57 Kugelblitz::initialize()
59 physic.set_velocity_y(300);
60 physic.set_velocity_x(-20); //fall a little to the left
66 Kugelblitz::collision_solid(const CollisionHit& chit)
72 Kugelblitz::collision_player(Player& player, const CollisionHit& )
74 if(player.is_invincible()) {
79 if(player.get_movement().y - get_movement().y > 0 && player.get_bbox().p2.y <
80 (get_bbox().p1.y + get_bbox().p2.y) / 2) {
81 // if it's not is it possible to squish us, then this will hurt
82 if(!collision_squished(player))
93 Kugelblitz::collision_badguy(BadGuy& other , const CollisionHit& chit)
95 //Let the Kugelblitz explode, too? The problem with that is that
96 //two Kugelblitzes would cancel each other out on contact...
102 Kugelblitz::hit(const CollisionHit& hit)
106 if (!groundhit_pos_set)
108 pos_groundhit = get_pos();
109 groundhit_pos_set = true;
111 sprite->set_action("flying");
112 physic.set_velocity_y(0);
113 //Set random initial speed and direction
114 direction = gameRandom.rand(2)? 1: -1;
115 int speed = (BASE_SPEED + (gameRandom.rand(RAND_SPEED))) * direction;
116 physic.set_velocity_x(speed);
117 movement_timer.start(MOVETIME);
118 lifetime.start(LIFETIME);
120 } else if(hit.top) { // bumped on roof
121 physic.set_velocity_y(0);
128 Kugelblitz::active_update(float elapsed_time)
130 if (lifetime.check()) {
134 if (groundhit_pos_set) {
135 if (movement_timer.check()) {
136 if (direction == 1) direction = -1; else direction = 1;
137 int speed = (BASE_SPEED + (gameRandom.rand(RAND_SPEED))) * direction;
138 physic.set_velocity_x(speed);
139 movement_timer.start(MOVETIME);
143 if (Sector::current()->solids->get_tile_at(get_pos())->getAttributes() == 16) {
145 Sector::current()->add_object(new Electrifier(75,1421,1.5));
146 Sector::current()->add_object(new Electrifier(76,1422,1.5));
149 if (Sector::current()->solids->get_tile_at(get_pos())->getAttributes() == 48) {
150 //HIT ELECTRIFIED WATER
155 BadGuy::active_update(elapsed_time);
159 Kugelblitz::draw(DrawingContext& context)
161 sprite->draw(context, get_pos(), layer);
163 //Only draw light in dark areas
164 context.get_light( get_bbox().get_middle(), &light );
165 if (light.red + light.green < 2.0){
166 context.push_target();
167 context.set_target(DrawingContext::LIGHTMAP);
168 sprite->draw(context, get_pos(), layer);
169 lightsprite->draw(context, get_bbox().get_middle(), 0);
170 context.pop_target();
175 Kugelblitz::kill_fall()
180 Kugelblitz::explode()
183 sprite->set_action("pop");
184 lifetime.start(0.2f);
191 Kugelblitz::try_activate()
193 // Much smaller offscreen distances to pop out of nowhere and surprise Tux
194 float X_OFFSCREEN_DISTANCE = 400;
195 float Y_OFFSCREEN_DISTANCE = 600;
197 Player* player = get_nearest_player();
199 Vector dist = player->get_bbox().get_middle() - get_bbox().get_middle();
200 if ((fabsf(dist.x) <= X_OFFSCREEN_DISTANCE) && (fabsf(dist.y) <= Y_OFFSCREEN_DISTANCE)) {
201 set_state(STATE_ACTIVE);
202 if (!is_initialized) {
204 // if starting direction was set to AUTO, this is our chance to re-orient the badguy
205 if (start_dir == AUTO) {
206 Player* player = get_nearest_player();
207 if (player && (player->get_bbox().p1.x > get_bbox().p2.x)) {
215 is_initialized = true;