3 void collision_displace(vec2d
*desired_pos
,
4 jumpnrun_moveable
*current
,
5 rectangle
const *obstacle
,
7 rectangle desired
= current
->current_box
;
8 rectangle_move_to(&desired
, *desired_pos
);
10 if(!rectangle_intersect(obstacle
, &desired
)) {
14 fixed_point x
= FIXED_INT(1000), y
= FIXED_INT(1000);
15 fixed_point dx
= desired_pos
->x
, dy
= desired_pos
->y
;
16 bool bottom_collision
= false;
18 if(fixed_point_le(rectangle_top ( obstacle
), rectangle_top(&desired
)) &&
19 fixed_point_gt(rectangle_bottom( obstacle
), rectangle_top(&desired
)) &&
20 fixed_point_lt(rectangle_top (&desired
), rectangle_top(¤t
->current_box
))) {
22 y
= fixed_point_sub(rectangle_bottom(obstacle
), rectangle_top(&desired
));
23 dy
= rectangle_bottom(obstacle
);
25 } else if(fixed_point_gt(rectangle_bottom( obstacle
), rectangle_bottom(&desired
)) &&
26 fixed_point_le(rectangle_top ( obstacle
), rectangle_bottom(&desired
)) &&
27 fixed_point_gt(rectangle_top (&desired
), rectangle_top (¤t
->current_box
))) {
29 y
= fixed_point_sub(rectangle_bottom(&desired
), rectangle_top ( obstacle
));
30 dy
= fixed_point_sub(rectangle_top ( obstacle
), rectangle_height(&desired
));
31 bottom_collision
= true;
35 if(fixed_point_le(rectangle_left ( obstacle
), rectangle_left(&desired
)) &&
36 fixed_point_gt(rectangle_right( obstacle
), rectangle_left(&desired
)) &&
37 fixed_point_lt(rectangle_left (&desired
), rectangle_left(¤t
->current_box
))) {
39 x
= fixed_point_sub(rectangle_right(obstacle
), rectangle_left(&desired
));
40 dx
= rectangle_right(obstacle
);
42 } else if(fixed_point_gt(rectangle_right( obstacle
), rectangle_right(&desired
)) &&
43 fixed_point_le(rectangle_left ( obstacle
), rectangle_right(&desired
)) &&
44 fixed_point_gt(rectangle_left (&desired
), rectangle_left (¤t
->current_box
))) {
46 x
= fixed_point_sub(rectangle_right(&desired
), rectangle_left ( obstacle
));
47 dx
= fixed_point_sub(rectangle_left ( obstacle
), rectangle_width(&desired
));
51 if(fixed_point_eq(x
, y
)) {
54 } else if(fixed_point_gt(x
, y
)) {
56 inertia_mod
->y
= FIXED_INT(0);
58 current
->touching_ground
= bottom_collision
;
61 inertia_mod
->x
= FIXED_INT(0);
67 void collisions_tiles_displace(vec2d
*desired_position
,
68 jumpnrun_moveable
*thing
,
69 jumpnrun_level
const *lv
,
70 jumpnrun_tile_range
const *visible_tiles
,
73 int collision_tile
[] = { -1, -1, -1,
77 static int const collision_order
[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
79 vec2d midpoint
= rectangle_mid(&thing
->current_box
);
81 jumpnrun_tile_position midtile_pos
= {
82 fixed_point_cast_int(fixed_point_div(midpoint
.x
, FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH
))),
83 fixed_point_cast_int(fixed_point_div(midpoint
.y
, FIXED_INT(JUMPNRUN_TILE_PIXEL_HEIGHT
)))
88 for(tile
= visible_tiles
->first
; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
- 1; ++tile
)
90 for(; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
+ 2; ++tile
) {
91 int xdiff
= lv
->tiles
[tile
].pos
.x
- midtile_pos
.x
;
92 int ydiff
= lv
->tiles
[tile
].pos
.y
- midtile_pos
.y
;
98 case -1: collision_tile
[0] = tile
; break;
99 case 0: collision_tile
[1] = tile
; break;
100 case 1: collision_tile
[2] = tile
; break;
107 case -1: collision_tile
[3] = tile
; break;
108 case 0: collision_tile
[4] = tile
; break;
109 case 1: collision_tile
[5] = tile
; break;
116 case -1: collision_tile
[6] = tile
; break;
117 case 0: collision_tile
[7] = tile
; break;
118 case 1: collision_tile
[8] = tile
; break;
125 /* collision: sort by priority (top/bottom, left/right, then diagonal) */
126 thing
->touching_ground
= false;
128 for(size_t collision_index
= 0; collision_index
< ARRAY_SIZE(collision_order
); ++collision_index
) {
129 if(collision_tile
[collision_order
[collision_index
]] == -1) {
133 rectangle tile_rect
= rect_from_tile(&lv
->tiles
[collision_tile
[collision_order
[collision_index
]]]);
135 collision_displace(desired_position
, thing
, &tile_rect
, inertia_mod
);
138 rectangle_move_to(&thing
->current_box
, *desired_position
);