scripted objects correctly slide now
[supertux.git] / src / object / scripted_object.cpp
1 #include <config.h>
2
3 #include <stdexcept>
4 #include <math.h>
5
6 #include "scripted_object.hpp"
7 #include "video/drawing_context.hpp"
8 #include "sprite/sprite_manager.hpp"
9 #include "resources.hpp"
10 #include "object_factory.hpp"
11 #include "math/vector.hpp"
12
13 ScriptedObject::ScriptedObject(const lisp::Lisp& lisp)
14   : solid(true), physic_enabled(true), visible(true), new_vel_set(false),
15     layer(LAYER_OBJECTS)
16 {
17   lisp.get("name", name);
18   if(name == "")
19     throw std::runtime_error("Scripted object must have a name specified");
20   
21   std::string spritename;
22   lisp.get("sprite", spritename);
23   if(spritename == "")
24     throw std::runtime_error("Scripted object must have a sprite name specified");
25   sprite = sprite_manager->create(spritename);
26
27   lisp.get("x", bbox.p1.x);
28   lisp.get("y", bbox.p1.y);
29   float width = sprite->get_width();
30   float height = sprite->get_height();
31   lisp.get("width", width);
32   lisp.get("height", height);
33   bbox.set_size(width, height);
34
35   lisp.get("solid", solid);
36   lisp.get("physic-enabled", physic_enabled);
37   lisp.get("visible", visible);
38   lisp.get("layer", layer);
39   if(solid)
40     flags |= FLAG_SOLID;
41 }
42
43 ScriptedObject::~ScriptedObject()
44 {
45   delete sprite;
46 }
47
48 void
49 ScriptedObject::move(float x, float y)
50 {
51   bbox.move(Vector(x, y));
52 }
53
54 void
55 ScriptedObject::set_pos(float x, float y)
56 {
57   bbox.set_pos(Vector(x, y));
58 }
59
60 float
61 ScriptedObject::get_pos_x()
62 {
63   return get_pos().x;
64 }
65
66 float
67 ScriptedObject::get_pos_y()
68 {
69   return get_pos().y;
70 }
71
72 void
73 ScriptedObject::set_velocity(float x, float y)
74 {
75   new_vel = Vector(x, y);
76   new_vel_set = true;
77 }
78
79 float
80 ScriptedObject::get_velocity_x()
81 {
82   return physic.get_velocity_x();
83 }
84
85 float
86 ScriptedObject::get_velocity_y()
87 {
88   return physic.get_velocity_y();
89 }
90
91 void
92 ScriptedObject::set_visible(bool visible)
93 {
94   this->visible = visible;
95 }
96
97 bool
98 ScriptedObject::is_visible()
99 {
100   return visible;
101 }
102
103 void
104 ScriptedObject::set_action(const std::string& animation)
105 {
106   sprite->set_action(animation);
107 }
108
109 std::string
110 ScriptedObject::get_action()
111 {
112   return sprite->get_action_name();
113 }
114
115 std::string
116 ScriptedObject::get_name()
117 {
118   return name;
119 }
120
121 void
122 ScriptedObject::update(float elapsed_time)
123 {
124   if(!physic_enabled)
125     return;
126
127   if(new_vel_set) {
128     physic.set_velocity(new_vel.x, new_vel.y);
129     new_vel_set = false;
130   }
131   movement = physic.get_movement(elapsed_time);
132 }
133
134 void
135 ScriptedObject::draw(DrawingContext& context)
136 {
137   if(!visible)
138     return;
139
140   sprite->draw(context, get_pos(), layer);
141 }
142
143 HitResponse
144 ScriptedObject::collision(GameObject& other, const CollisionHit& hit)
145 {
146   if(!physic_enabled)
147     return FORCE_MOVE;
148
149   if(!(other.get_flags() & FLAG_SOLID))
150     return FORCE_MOVE;
151
152   if(other.get_flags() & FLAG_SOLID) {
153     if(hit.normal.y < 0) { // landed on floor
154       if(physic.get_velocity_y() < 0)
155         physic.set_velocity_y(0);
156     } else if(hit.normal.y > 0) { // bumped against roof
157       physic.set_velocity_y(.1);
158     }
159
160     if(fabsf(hit.normal.x) > .9) { // hit on side?
161       physic.set_velocity_x(0);
162     }
163         
164     return CONTINUE;
165   }
166
167   return FORCE_MOVE;
168 }
169
170 IMPLEMENT_FACTORY(ScriptedObject, "scriptedobject");