1 | // SuperTux |
2 | // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de> |
3 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de> |
4 | // Copyright (C) 2010 Florian Forster <supertux at octo.it> |
5 | // |
6 | // This program is free software: you can redistribute it and/or modify |
7 | // it under the terms of the GNU General Public License as published by |
8 | // the Free Software Foundation, either version 3 of the License, or |
9 | // (at your option) any later version. |
10 | // |
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. |
15 | // |
16 | // You should have received a copy of the GNU General Public License |
17 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | |
19 | #include "supertux/tile.hpp" |
20 | |
21 | #include "math/aatriangle.hpp" |
22 | #include "supertux/constants.hpp" |
23 | #include "supertux/globals.hpp" |
24 | #include "util/log.hpp" |
25 | #include "video/drawing_context.hpp" |
26 | #include "video/surface.hpp" |
27 | |
28 | bool Tile::draw_editor_images = false; |
29 | |
30 | namespace { |
31 | |
32 | bool is_above_line (float l_x, float l_y, float m, |
33 | float p_x, float p_y) |
34 | { |
35 | float interp_y = (l_y + (m * (p_x - l_x))); |
36 | return (interp_y >= p_y); |
37 | } |
38 | |
39 | bool is_below_line (float l_x, float l_y, float m, |
40 | float p_x, float p_y) |
41 | { |
42 | return !is_above_line (l_x, l_y, m, p_x, p_y); |
43 | } |
44 | |
45 | } // namespace |
46 | |
47 | Tile::Tile() : |
48 | m_images(), |
49 | m_editor_images(), |
50 | m_attributes(0), |
51 | m_data(0), |
52 | m_fps(1), |
53 | m_object_name(), |
54 | m_object_data(), |
55 | m_deprecated(false) |
56 | { |
57 | } |
58 | |
59 | Tile::Tile(const std::vector<SurfacePtr>& images, |
60 | const std::vector<SurfacePtr>& editor_images, |
61 | uint32_t attributes, uint32_t data, float fps, |
62 | const std::string& obj_name, |
63 | const std::string& obj_data, |
64 | bool deprecated) : |
65 | m_images(images), |
66 | m_editor_images(editor_images), |
67 | m_attributes(attributes), |
68 | m_data(data), |
69 | m_fps(fps), |
70 | m_object_name(obj_name), |
71 | m_object_data(obj_data), |
72 | m_deprecated(deprecated) |
73 | { |
74 | } |
75 | |
76 | void |
77 | Tile::draw(Canvas& canvas, const Vector& pos, int z_pos, const Color& color) const |
78 | { |
79 | if (draw_editor_images) { |
80 | if (m_editor_images.size() > 1) { |
81 | size_t frame = size_t(g_game_time * m_fps) % m_editor_images.size(); |
82 | canvas.draw_surface(m_editor_images[frame], pos, 0, color, Blend(), z_pos); |
83 | return; |
84 | } else if (m_editor_images.size() == 1) { |
85 | canvas.draw_surface(m_editor_images[0], pos, 0, color, Blend(), z_pos); |
86 | return; |
87 | } |
88 | } |
89 | |
90 | if (m_images.size() > 1) { |
91 | size_t frame = size_t(g_game_time * m_fps) % m_images.size(); |
92 | canvas.draw_surface(m_images[frame], pos, 0, color, Blend(), z_pos); |
93 | } else if (m_images.size() == 1) { |
94 | canvas.draw_surface(m_images[0], pos, 0, color, Blend(), z_pos); |
95 | } |
96 | } |
97 | |
98 | void |
99 | Tile::draw_debug(Canvas& canvas, const Vector& pos, int z_pos, const Color& color) const |
100 | { |
101 | if (!is_slope()) |
102 | { |
103 | if (m_attributes & SOLID) { |
104 | canvas.draw_filled_rect(Rectf(pos, Sizef(32.0f, 32.0f)), color, z_pos); |
105 | } |
106 | } |
107 | else |
108 | { |
109 | int slope_info = get_data(); |
110 | |
111 | switch (slope_info) |
112 | { |
113 | case AATriangle::SOUTHWEST: |
114 | canvas.draw_triangle({pos.x, pos.y}, {pos.x, pos.y + 32.0f}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
115 | break; |
116 | |
117 | case AATriangle::NORTHEAST: |
118 | canvas.draw_triangle({pos.x, pos.y}, {pos.x + 32.0f, pos.y}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
119 | break; |
120 | |
121 | case AATriangle::SOUTHEAST: |
122 | canvas.draw_triangle({pos.x, pos.y + 32.0f}, {pos.x + 32.0f, pos.y}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
123 | break; |
124 | |
125 | case AATriangle::NORTHWEST: |
126 | canvas.draw_triangle({pos.x, pos.y}, {pos.x + 32.0f, pos.y}, {pos.x, pos.y + 32.0f}, color, z_pos); |
127 | break; |
128 | |
129 | |
130 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_BOTTOM: |
131 | canvas.draw_triangle({pos.x, pos.y + 16.0f}, {pos.x, pos.y + 32.0f}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
132 | break; |
133 | |
134 | case AATriangle::NORTHEAST | AATriangle::DEFORM_BOTTOM: |
135 | canvas.draw_filled_rect(Rectf(pos.x, pos.y, pos.x + 32.0f, pos.y + 16.0f), color, z_pos); |
136 | canvas.draw_triangle({pos.x, pos.y + 16.0f}, {pos.x + 32.0f, pos.y + 16.0f}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
137 | break; |
138 | |
139 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_BOTTOM: |
140 | canvas.draw_triangle({pos.x + 32.0f, pos.y + 32.0f}, {pos.x, pos.y + 32.0f}, {pos.x + 32.0f, pos.y + 16.0f}, color, z_pos); |
141 | break; |
142 | |
143 | case AATriangle::NORTHWEST | AATriangle::DEFORM_BOTTOM: |
144 | canvas.draw_filled_rect(Rectf(pos.x, pos.y, pos.x + 32.0f, pos.y + 16.0f), color, z_pos); |
145 | canvas.draw_triangle({pos.x, pos.y + 32.0f}, {pos.x + 32.0f, pos.y + 16.0f}, {pos.x, pos.y + 16.0f}, color, z_pos); |
146 | break; |
147 | |
148 | |
149 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_TOP: |
150 | canvas.draw_filled_rect(Rectf(pos.x, pos.y + 16.0f, pos.x + 32.0f, pos.y + 32.0f), color, z_pos); |
151 | canvas.draw_triangle({pos.x, pos.y + 16.0f}, {pos.x + 32.0f, pos.y + 16.0f}, {pos.x, pos.y}, color, z_pos); |
152 | break; |
153 | |
154 | case AATriangle::NORTHEAST | AATriangle::DEFORM_TOP: |
155 | canvas.draw_triangle({pos.x + 32.0f, pos.y}, {pos.x + 32.0f, pos.y + 16.0f}, {pos.x, pos.y}, color, z_pos); |
156 | break; |
157 | |
158 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_TOP: |
159 | canvas.draw_filled_rect(Rectf(pos.x, pos.y + 16.0f, pos.x + 32.0f, pos.y + 32.0f), color, z_pos); |
160 | canvas.draw_triangle({pos.x + 32.0f, pos.y + 16.0f}, {pos.x, pos.y + 16.0f}, {pos.x + 32.0f, pos.y}, color, z_pos); |
161 | break; |
162 | |
163 | case AATriangle::NORTHWEST | AATriangle::DEFORM_TOP: |
164 | canvas.draw_triangle({pos.x, pos.y}, {pos.x + 32.0f, pos.y}, {pos.x, pos.y + 16.0f}, color, z_pos); |
165 | break; |
166 | |
167 | |
168 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_LEFT: |
169 | canvas.draw_triangle({pos.x, pos.y + 32.0f}, {pos.x, pos.y}, {pos.x + 16.0f, pos.y + 32.0f}, color, z_pos); |
170 | break; |
171 | |
172 | case AATriangle::NORTHEAST | AATriangle::DEFORM_LEFT: |
173 | canvas.draw_filled_rect(Rectf(pos.x + 16.0f, pos.y, pos.x + 32.0f, pos.y + 32.0f), color, z_pos); |
174 | canvas.draw_triangle({pos.x + 16.0f, pos.y}, {pos.x + 16.0f, pos.y + 32.0f}, {pos.x, pos.y}, color, z_pos); |
175 | break; |
176 | |
177 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_LEFT: |
178 | canvas.draw_filled_rect(Rectf(pos.x + 16.0f, pos.y, pos.x + 32.0f, pos.y + 32.0f), color, z_pos); |
179 | canvas.draw_triangle({pos.x + 16.0f, pos.y + 32.0f}, {pos.x, pos.y + 32.0f}, {pos.x + 16.0f, pos.y}, color, z_pos); |
180 | break; |
181 | |
182 | case AATriangle::NORTHWEST | AATriangle::DEFORM_LEFT: |
183 | canvas.draw_triangle({pos.x, pos.y}, {pos.x + 16.0f, pos.y}, {pos.x, pos.y + 16.0f}, color, z_pos); |
184 | break; |
185 | |
186 | |
187 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_RIGHT: |
188 | canvas.draw_filled_rect(Rectf(pos.x, pos.y, pos.x + 16.0f, pos.y + 32.0f), color, z_pos); |
189 | canvas.draw_triangle({pos.x + 16.0f, pos.y + 32.0f}, {pos.x + 16.0f, pos.y}, {pos.x + 32.0f, pos.y + 32.0f}, color, z_pos); |
190 | break; |
191 | |
192 | case AATriangle::NORTHEAST | AATriangle::DEFORM_RIGHT: |
193 | canvas.draw_triangle({pos.x + 32.0f, pos.y}, {pos.x + 32.0f, pos.y + 32.0f}, {pos.x + 16.0f, pos.y}, color, z_pos); |
194 | break; |
195 | |
196 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_RIGHT: |
197 | canvas.draw_triangle({pos.x + 32.0f, pos.y + 32.0f}, {pos.x + 16.0f, pos.y + 32.0f}, {pos.x + 32.0f, pos.y}, color, z_pos); |
198 | break; |
199 | |
200 | case AATriangle::NORTHWEST | AATriangle::DEFORM_RIGHT: |
201 | canvas.draw_filled_rect(Rectf(pos.x, pos.y, pos.x + 16.0f, pos.y + 32.0f), color, z_pos); |
202 | canvas.draw_triangle({pos.x + 16.0f, pos.y}, {pos.x + 32.0f, pos.y}, {pos.x + 16.0f, pos.y + 32.0f}, color, z_pos); |
203 | break; |
204 | } |
205 | } |
206 | } |
207 | |
208 | SurfacePtr |
209 | Tile::get_current_surface() const |
210 | { |
211 | if (m_images.size() > 1) { |
212 | size_t frame = size_t(g_game_time * m_fps) % m_images.size(); |
213 | return m_images[frame]; |
214 | } else if (m_images.size() == 1) { |
215 | return m_images[0]; |
216 | } else { |
217 | return {}; |
218 | } |
219 | } |
220 | |
221 | SurfacePtr |
222 | Tile::get_current_editor_surface() const |
223 | { |
224 | if (m_editor_images.size() > 1) { |
225 | size_t frame = size_t(g_game_time * m_fps) % m_editor_images.size(); |
226 | return m_editor_images[frame]; |
227 | } else if (m_editor_images.size() == 1) { |
228 | return m_editor_images[0]; |
229 | } else { |
230 | return get_current_surface(); |
231 | } |
232 | } |
233 | |
234 | // Check if the tile is solid given the current movement. This works |
235 | // for south-slopes (which are solid when moving "down") and |
236 | // north-slopes (which are solid when moving "up". "up" and "down" is |
237 | // in quotation marks because because the slope's gradient is taken. |
238 | // Also, this uses the movement relative to the tilemaps own movement |
239 | // (if any). --octo |
240 | bool |
241 | Tile::check_movement_unisolid (const Vector& movement) const |
242 | { |
243 | int slope_info; |
244 | double mv_x; |
245 | double mv_y; |
246 | double mv_tan; |
247 | double slope_tan; |
248 | |
249 | //If the tile is not a slope, this is very easy. |
250 | if (!is_slope()) |
251 | { |
252 | int dir = get_data() & Tile::UNI_DIR_MASK; |
253 | |
254 | return ((dir == Tile::UNI_DIR_NORTH) && (movement.y >= 0)) /* moving down */ |
255 | || ((dir == Tile::UNI_DIR_SOUTH) && (movement.y <= 0)) /* moving up */ |
256 | || ((dir == Tile::UNI_DIR_WEST ) && (movement.x >= 0)) /* moving right */ |
257 | || ((dir == Tile::UNI_DIR_EAST ) && (movement.x <= 0)); /* moving left */ |
258 | } |
259 | |
260 | // Initialize mv_x and mv_y. Depending on the slope the axis are inverted so |
261 | // that we can always use the "SOUTHEAST" case of the slope. The southeast |
262 | // case is the following: |
263 | // . |
264 | // /! |
265 | // / ! |
266 | // +--+ |
267 | mv_x = static_cast<double>(movement.x); // note switch to double for no good reason |
268 | mv_y = static_cast<double>(movement.y); |
269 | |
270 | slope_info = get_data(); |
271 | switch (slope_info & AATriangle::DIRECTION_MASK) |
272 | { |
273 | case AATriangle::SOUTHEAST: /* . */ |
274 | /* do nothing */ /* /! */ |
275 | break; /* / ! */ |
276 | /* +--+ */ |
277 | case AATriangle::SOUTHWEST: /* . */ |
278 | mv_x *= (-1.0); /* !\ */ |
279 | break; /* ! \ */ |
280 | /* +--+ */ |
281 | case AATriangle::NORTHEAST: /* +--+ */ |
282 | mv_y *= (-1.0); /* \ ! */ |
283 | break; /* \! */ |
284 | /* ' */ |
285 | case AATriangle::NORTHWEST: /* +--+ */ |
286 | mv_x *= (-1.0); /* ! / */ |
287 | mv_y *= (-1.0); /* !/ */ |
288 | break; /* ' */ |
289 | } |
290 | |
291 | // Handle the easy cases first |
292 | // If we're moving to the right and down, then the slope is solid. |
293 | if ((mv_x >= 0.0) && (mv_y >= 0.0)) // 4th quadrant |
294 | return true; |
295 | // If we're moving to the left and up, then the slope is not solid. |
296 | else if ((mv_x <= 0.0) && (mv_y <= 0.0)) // 2nd quadrant |
297 | return false; |
298 | |
299 | // The pure up-down and left-right movements have already been handled. |
300 | assert (mv_x != 0.0); |
301 | assert (mv_y != 0.0); |
302 | |
303 | // calculate tangent of movement |
304 | mv_tan = (-1.0) * mv_y / mv_x; |
305 | |
306 | // determine tangent of the slope |
307 | slope_tan = 1.0; |
308 | if (((slope_info & AATriangle::DEFORM_MASK) == AATriangle::DEFORM_BOTTOM) |
309 | || ((slope_info & AATriangle::DEFORM_MASK) == AATriangle::DEFORM_TOP)) |
310 | slope_tan = 0.5; // ~= 26.6 deg |
311 | else if (((slope_info & AATriangle::DEFORM_MASK) == AATriangle::DEFORM_LEFT) |
312 | || ((slope_info & AATriangle::DEFORM_MASK) == AATriangle::DEFORM_RIGHT)) |
313 | slope_tan = 2.0; // ~= 63.4 deg |
314 | |
315 | // up and right |
316 | if (mv_x > 0.0) // 1st quadrant |
317 | { |
318 | assert (mv_y < 0.0); |
319 | return (mv_tan <= slope_tan); |
320 | } |
321 | // down and left |
322 | else if (mv_x < 0.0) // 3rd quadrant |
323 | { |
324 | assert (mv_y > 0.0); |
325 | return (mv_tan >= slope_tan); |
326 | } |
327 | |
328 | return false; |
329 | } |
330 | |
331 | // Check whether the object is already *in* the tile. If so, the tile |
332 | // is non-solid. Otherwise, if the object is "above" (south slopes) or |
333 | // "below" (north slopes), the tile will be solid. |
334 | bool |
335 | Tile::check_position_unisolid (const Rectf& obj_bbox, |
336 | const Rectf& tile_bbox) const |
337 | { |
338 | int slope_info; |
339 | float tile_x; |
340 | float tile_y; |
341 | float gradient; |
342 | float delta_x; |
343 | float delta_y; |
344 | float obj_x = 0.0; |
345 | float obj_y = 0.0; |
346 | |
347 | // If this is not a slope, this is - again - easy |
348 | if (!is_slope()) |
349 | { |
350 | int dir = get_data() & Tile::UNI_DIR_MASK; |
351 | |
352 | return ((dir == Tile::UNI_DIR_NORTH) && ((obj_bbox.get_bottom() - SHIFT_DELTA) <= tile_bbox.get_top() )) |
353 | || ((dir == Tile::UNI_DIR_SOUTH) && ((obj_bbox.get_top() + SHIFT_DELTA) >= tile_bbox.get_bottom())) |
354 | || ((dir == Tile::UNI_DIR_WEST ) && ((obj_bbox.get_right() - SHIFT_DELTA) <= tile_bbox.get_left() )) |
355 | || ((dir == Tile::UNI_DIR_EAST ) && ((obj_bbox.get_left() + SHIFT_DELTA) >= tile_bbox.get_right() )); |
356 | } |
357 | |
358 | // There are 20 different cases. For each case, calculate a line |
359 | // that describes the slope's surface. The line is defined by x, y, |
360 | // and m, the gradient. |
361 | slope_info = get_data(); |
362 | switch (slope_info |
363 | & (AATriangle::DIRECTION_MASK | AATriangle::DEFORM_MASK)) |
364 | { |
365 | case AATriangle::SOUTHWEST: |
366 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_TOP: |
367 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_LEFT: |
368 | case AATriangle::NORTHEAST: |
369 | case AATriangle::NORTHEAST | AATriangle::DEFORM_TOP: |
370 | case AATriangle::NORTHEAST | AATriangle::DEFORM_LEFT: |
371 | tile_x = tile_bbox.get_left(); |
372 | tile_y = tile_bbox.get_top(); |
373 | gradient = 1.0; |
374 | break; |
375 | |
376 | case AATriangle::SOUTHEAST: |
377 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_TOP: |
378 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_RIGHT: |
379 | case AATriangle::NORTHWEST: |
380 | case AATriangle::NORTHWEST | AATriangle::DEFORM_TOP: |
381 | case AATriangle::NORTHWEST | AATriangle::DEFORM_RIGHT: |
382 | tile_x = tile_bbox.get_right(); |
383 | tile_y = tile_bbox.get_top(); |
384 | gradient = -1.0; |
385 | break; |
386 | |
387 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_BOTTOM: |
388 | case AATriangle::SOUTHEAST | AATriangle::DEFORM_LEFT: |
389 | case AATriangle::NORTHWEST | AATriangle::DEFORM_BOTTOM: |
390 | case AATriangle::NORTHWEST | AATriangle::DEFORM_LEFT: |
391 | tile_x = tile_bbox.get_left(); |
392 | tile_y = tile_bbox.get_bottom(); |
393 | gradient = -1.0; |
394 | break; |
395 | |
396 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_BOTTOM: |
397 | case AATriangle::SOUTHWEST | AATriangle::DEFORM_RIGHT: |
398 | case AATriangle::NORTHEAST | AATriangle::DEFORM_BOTTOM: |
399 | case AATriangle::NORTHEAST | AATriangle::DEFORM_RIGHT: |
400 | tile_x = tile_bbox.get_right(); |
401 | tile_y = tile_bbox.get_bottom(); |
402 | gradient = 1.0; |
403 | break; |
404 | |
405 | default: |
406 | assert(false); |
407 | return 0; |
408 | } |
409 | |
410 | // delta_x, delta_y: Gradient aware version of SHIFT_DELTA. Here, we set the |
411 | // sign of the values only. Also, we determine here which corner of the |
412 | // object's bounding box is the interesting one for us. |
413 | delta_x = 1.0f * SHIFT_DELTA; |
414 | delta_y = 1.0f * SHIFT_DELTA; |
415 | switch (slope_info & AATriangle::DIRECTION_MASK) |
416 | { |
417 | case AATriangle::SOUTHWEST: |
418 | delta_x *= 1.f; |
419 | delta_y *= -1.f; |
420 | obj_x = obj_bbox.get_left(); |
421 | obj_y = obj_bbox.get_bottom(); |
422 | break; |
423 | |
424 | case AATriangle::SOUTHEAST: |
425 | delta_x *= -1.f; |
426 | delta_y *= -1.f; |
427 | obj_x = obj_bbox.get_right(); |
428 | obj_y = obj_bbox.get_bottom(); |
429 | break; |
430 | |
431 | case AATriangle::NORTHWEST: |
432 | delta_x *= 1.f; |
433 | delta_y *= 1.f; |
434 | obj_x = obj_bbox.get_left(); |
435 | obj_y = obj_bbox.get_top(); |
436 | break; |
437 | |
438 | case AATriangle::NORTHEAST: |
439 | delta_x *= -1.f; |
440 | delta_y *= 1.f; |
441 | obj_x = obj_bbox.get_right(); |
442 | obj_y = obj_bbox.get_top(); |
443 | break; |
444 | } |
445 | |
446 | // Adapt the delta_x, delta_y and the gradient for the 26.6 deg and |
447 | // 63.4 deg cases. |
448 | switch (slope_info & AATriangle::DEFORM_MASK) |
449 | { |
450 | case 0: |
451 | delta_x *= .70710678118654752440f; // 1/sqrt(2) |
452 | delta_y *= .70710678118654752440f; // 1/sqrt(2) |
453 | break; |
454 | |
455 | case AATriangle::DEFORM_BOTTOM: |
456 | case AATriangle::DEFORM_TOP: |
457 | delta_x *= .44721359549995793928f; // 1/sqrt(5) |
458 | delta_y *= .89442719099991587856f; // 2/sqrt(5) |
459 | gradient *= 0.5f; |
460 | break; |
461 | |
462 | case AATriangle::DEFORM_LEFT: |
463 | case AATriangle::DEFORM_RIGHT: |
464 | delta_x *= .89442719099991587856f; // 2/sqrt(5) |
465 | delta_y *= .44721359549995793928f; // 1/sqrt(5) |
466 | gradient *= 2.f; |
467 | break; |
468 | } |
469 | |
470 | // With a south slope, check if all points are above the line. If |
471 | // one point isn't, the slope is not solid. => You can pass through |
472 | // a south-slope from below but not from above. |
473 | if (((slope_info & AATriangle::DIRECTION_MASK) == AATriangle::SOUTHWEST) || |
474 | ((slope_info & AATriangle::DIRECTION_MASK) == AATriangle::SOUTHEAST)) |
475 | { |
476 | return !is_below_line(tile_x, tile_y, gradient, obj_x + delta_x, obj_y + delta_y); |
477 | } |
478 | // northwest or northeast. Same as above, but inverted. You can pass |
479 | // from top to bottom but not vice versa. |
480 | else |
481 | { |
482 | return !is_above_line (tile_x, tile_y, gradient, obj_x + delta_x, obj_y + delta_y); |
483 | } |
484 | } |
485 | |
486 | bool |
487 | Tile::is_solid (const Rectf& tile_bbox, const Rectf& position, const Vector& movement) const |
488 | { |
489 | if (!(m_attributes & SOLID)) |
490 | return false; |
491 | |
492 | return is_collisionful(tile_bbox, position, movement); |
493 | } |
494 | |
495 | bool |
496 | Tile::is_collisionful(const Rectf& tile_bbox, const Rectf& position, const Vector& movement) const |
497 | { |
498 | if (!(m_attributes & UNISOLID)) |
499 | return true; |
500 | |
501 | return check_movement_unisolid (movement) && |
502 | check_position_unisolid (position, tile_bbox); |
503 | } |
504 | |
505 | /* EOF */ |
506 | |