1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3//
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.
8//
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.
13//
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/>.
16
17#include "badguy/mrtree.hpp"
18
19#include <math.h>
20
21#include "audio/sound_manager.hpp"
22#include "badguy/poisonivy.hpp"
23#include "badguy/stumpy.hpp"
24#include "math/random.hpp"
25#include "math/util.hpp"
26#include "object/player.hpp"
27#include "object/sprite_particle.hpp"
28#include "sprite/sprite.hpp"
29#include "sprite/sprite_manager.hpp"
30#include "supertux/sector.hpp"
31
32static const float TREE_SPEED = 100;
33
34static const float POISONIVY_WIDTH = 32;
35static const float POISONIVY_HEIGHT = 32;
36static const float POISONIVY_Y_OFFSET = 24;
37
38MrTree::MrTree(const ReaderMapping& reader)
39 : WalkingBadguy(reader, "images/creatures/mr_tree/mr_tree.sprite","left","right", LAYER_OBJECTS,
40 "images/objects/lightmap_light/lightmap_light-large.sprite")
41{
42 walk_speed = TREE_SPEED;
43 max_drop_height = 16;
44 SoundManager::current()->preload("sounds/mr_tree.ogg");
45}
46
47bool
48MrTree::is_freezable() const
49{
50 return true;
51}
52
53bool
54MrTree::collision_squished(GameObject& object)
55{
56 auto player = dynamic_cast<Player*>(&object);
57 if (player && (player->m_does_buttjump || player->is_invincible())) {
58 player->bounce(*this);
59 kill_fall();
60 return true;
61 }
62
63 // replace with Stumpy
64 Vector stumpy_pos = get_pos();
65 stumpy_pos.x += 20;
66 stumpy_pos.y += 25;
67 auto& stumpy = Sector::get().add<Stumpy>(stumpy_pos, m_dir);
68 remove_me();
69
70 // give Feedback
71 SoundManager::current()->play("sounds/mr_tree.ogg", get_pos());
72 if (player) player->bounce(*this);
73
74 // spawn some particles
75 // TODO: provide convenience function in MovingSprite or MovingObject?
76 for (int px = static_cast<int>(stumpy.get_bbox().get_left()); px < static_cast<int>(stumpy.get_bbox().get_right()); px+=10) {
77 Vector ppos = Vector(static_cast<float>(px),
78 static_cast<float>(stumpy.get_bbox().get_top()) - 5.0f);
79 float angle = graphicsRandom.randf(-math::PI_2, math::PI_2);
80 float velocity = graphicsRandom.randf(45, 90);
81 float vx = sinf(angle)*velocity;
82 float vy = -cosf(angle)*velocity;
83 Vector pspeed = Vector(vx, vy);
84 Vector paccel = Vector(0, Sector::get().get_gravity()*10);
85 Sector::get().add<SpriteParticle>("images/objects/particles/leaf.sprite",
86 "default",
87 ppos, ANCHOR_MIDDLE,
88 pspeed, paccel,
89 LAYER_OBJECTS-1);
90 }
91
92 if (!m_frozen) { //Frozen Mr.Trees don't spawn any PoisonIvys.
93 // spawn PoisonIvy
94 Vector leaf1_pos(stumpy_pos.x - POISONIVY_WIDTH - 1, stumpy_pos.y - POISONIVY_Y_OFFSET);
95 Rectf leaf1_bbox(leaf1_pos.x, leaf1_pos.y, leaf1_pos.x + POISONIVY_WIDTH, leaf1_pos.y + POISONIVY_HEIGHT);
96 if (Sector::get().is_free_of_movingstatics(leaf1_bbox, this)) {
97 auto& leaf1 = Sector::get().add<PoisonIvy>(leaf1_bbox.p1(), Direction::LEFT);
98 leaf1.m_countMe = false;
99 }
100
101 // spawn PoisonIvy
102 Vector leaf2_pos(stumpy_pos.x + m_sprite->get_current_hitbox_width() + 1, stumpy_pos.y - POISONIVY_Y_OFFSET);
103 Rectf leaf2_bbox(leaf2_pos.x, leaf2_pos.y, leaf2_pos.x + POISONIVY_WIDTH, leaf2_pos.y + POISONIVY_HEIGHT);
104 if (Sector::get().is_free_of_movingstatics(leaf2_bbox, this)) {
105 auto& leaf2 = Sector::get().add<PoisonIvy>(leaf2_bbox.p1(), Direction::RIGHT);
106 leaf2.m_countMe = false;
107 }
108 }
109 return true;
110}
111
112/* EOF */
113