3 uint8_t 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;
22 if(fixed_point_le(rectangle_top ( obstacle
), rectangle_top(&desired
)) &&
23 fixed_point_gt(rectangle_bottom( obstacle
), rectangle_top(&desired
)) &&
24 fixed_point_lt(rectangle_top (&desired
), rectangle_top(¤t
->current_box
))) {
26 coll_y
= JUMPNRUN_COLLISION_BOTTOM
;
27 y
= fixed_point_sub(rectangle_bottom(obstacle
), rectangle_top(&desired
));
28 dy
= rectangle_bottom(obstacle
);
30 } else if(fixed_point_gt(rectangle_bottom( obstacle
), rectangle_bottom(&desired
)) &&
31 fixed_point_le(rectangle_top ( obstacle
), rectangle_bottom(&desired
)) &&
32 fixed_point_gt(rectangle_top (&desired
), rectangle_top (¤t
->current_box
))) {
34 coll_y
= JUMPNRUN_COLLISION_TOP
;
35 y
= fixed_point_sub(rectangle_bottom(&desired
), rectangle_top ( obstacle
));
36 dy
= fixed_point_sub(rectangle_top ( obstacle
), rectangle_height(&desired
));
37 bottom_collision
= true;
41 if(fixed_point_le(rectangle_left ( obstacle
), rectangle_left(&desired
)) &&
42 fixed_point_gt(rectangle_right( obstacle
), rectangle_left(&desired
)) &&
43 fixed_point_lt(rectangle_left (&desired
), rectangle_left(¤t
->current_box
))) {
45 coll_x
= JUMPNRUN_COLLISION_RIGHT
;
46 x
= fixed_point_sub(rectangle_right(obstacle
), rectangle_left(&desired
));
47 dx
= rectangle_right(obstacle
);
49 } else if(fixed_point_gt(rectangle_right( obstacle
), rectangle_right(&desired
)) &&
50 fixed_point_le(rectangle_left ( obstacle
), rectangle_right(&desired
)) &&
51 fixed_point_gt(rectangle_left (&desired
), rectangle_left (¤t
->current_box
))) {
53 coll_x
= JUMPNRUN_COLLISION_LEFT
;
54 x
= fixed_point_sub(rectangle_right(&desired
), rectangle_left ( obstacle
));
55 dx
= fixed_point_sub(rectangle_left ( obstacle
), rectangle_width(&desired
));
59 if(fixed_point_eq(x
, y
)) {
62 coll
= coll_x
| coll_y
;
63 } else if(fixed_point_gt(x
, y
)) {
65 inertia_mod
->y
= FIXED_INT(0);
66 current
->touching_ground
= bottom_collision
;
70 inertia_mod
->x
= FIXED_INT(0);
77 bool collisions_tiles_displace(vec2d
*desired_position
,
78 jumpnrun_moveable
*thing
,
79 jumpnrun_level
const *lv
,
80 jumpnrun_tile_range
const *visible_tiles
,
83 int collision_tile
[] = { -1, -1, -1,
87 static int const collision_order
[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
89 vec2d midpoint
= rectangle_mid(&thing
->current_box
);
91 jumpnrun_tile_position midtile_pos
= {
92 fixed_point_cast_int(fixed_point_div(midpoint
.x
, FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH
))),
93 fixed_point_cast_int(fixed_point_div(midpoint
.y
, FIXED_INT(JUMPNRUN_TILE_PIXEL_HEIGHT
)))
98 for(tile
= visible_tiles
->first
; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
- 1; ++tile
)
100 for(; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
+ 2; ++tile
) {
101 int xdiff
= lv
->tiles
[tile
].pos
.x
- midtile_pos
.x
;
102 int ydiff
= lv
->tiles
[tile
].pos
.y
- midtile_pos
.y
;
108 case -1: collision_tile
[0] = tile
; break;
109 case 0: collision_tile
[1] = tile
; break;
110 case 1: collision_tile
[2] = tile
; break;
117 case -1: collision_tile
[3] = tile
; break;
118 case 0: collision_tile
[4] = tile
; break;
119 case 1: collision_tile
[5] = tile
; break;
126 case -1: collision_tile
[6] = tile
; break;
127 case 0: collision_tile
[7] = tile
; break;
128 case 1: collision_tile
[8] = tile
; break;
135 /* collision: sort by priority (top/bottom, left/right, then diagonal) */
137 thing
->touching_ground
= false;
139 for(size_t collision_index
= 0; collision_index
< ARRAY_SIZE(collision_order
); ++collision_index
) {
140 if(collision_tile
[collision_order
[collision_index
]] == -1) {
144 jumpnrun_tile
*tile_obj
= &lv
->tiles
[collision_tile
[collision_order
[collision_index
]]];
145 rectangle tile_rect
= rect_from_tile(tile_obj
);
147 uint8_t coll
= collision_displace(desired_position
, thing
, &tile_rect
, inertia_mod
);
148 if(coll
& tile_type(tile_obj
)->lethal_sides
) {
153 rectangle_move_to(&thing
->current_box
, *desired_position
);