3 uint8_t collision_displace(vec2d
*desired_pos
,
4 jumpnrun_moveable
*current
,
5 rectangle
const *obstacle
,
7 rectangle desired
= current
->hitbox
;
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
->hitbox
))) {
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
->hitbox
))) {
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
->hitbox
))) {
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
->hitbox
))) {
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);
67 if(bottom_collision
) {
68 current
->flags
|= JUMPNRUN_MOVEABLE_TOUCHING_GROUND
;
70 current
->flags
&= ~JUMPNRUN_MOVEABLE_TOUCHING_GROUND
;
76 inertia_mod
->x
= FIXED_INT(0);
83 bool collisions_tiles_displace(vec2d
*desired_position
,
84 jumpnrun_moveable
*thing
,
85 jumpnrun_level
const *lv
,
86 jumpnrun_tile_range
const *visible_tiles
,
89 int collision_tile
[] = { -1, -1, -1,
93 static int const collision_order
[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
95 vec2d midpoint
= rectangle_mid(&thing
->hitbox
);
97 jumpnrun_tile_position midtile_pos
= {
98 fixed_point_cast_int(fixed_point_div(midpoint
.x
, FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH
))),
99 fixed_point_cast_int(fixed_point_div(midpoint
.y
, FIXED_INT(JUMPNRUN_TILE_PIXEL_HEIGHT
)))
104 for(tile
= visible_tiles
->first
; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
- 1; ++tile
)
106 for(; (size_t) tile
< visible_tiles
->last
&& lv
->tiles
[tile
].pos
.x
< midtile_pos
.x
+ 2; ++tile
) {
107 int xdiff
= lv
->tiles
[tile
].pos
.x
- midtile_pos
.x
;
108 int ydiff
= lv
->tiles
[tile
].pos
.y
- midtile_pos
.y
;
114 case -1: collision_tile
[0] = tile
; break;
115 case 0: collision_tile
[1] = tile
; break;
116 case 1: collision_tile
[2] = tile
; break;
123 case -1: collision_tile
[3] = tile
; break;
124 case 0: collision_tile
[4] = tile
; break;
125 case 1: collision_tile
[5] = tile
; break;
132 case -1: collision_tile
[6] = tile
; break;
133 case 0: collision_tile
[7] = tile
; break;
134 case 1: collision_tile
[8] = tile
; break;
141 /* collision: sort by priority (top/bottom, left/right, then diagonal) */
143 thing
->flags
&= ~JUMPNRUN_MOVEABLE_TOUCHING_GROUND
;
145 for(size_t collision_index
= 0; collision_index
< ARRAY_SIZE(collision_order
); ++collision_index
) {
146 if(collision_tile
[collision_order
[collision_index
]] == -1) {
150 jumpnrun_tile
*tile_obj
= &lv
->tiles
[collision_tile
[collision_order
[collision_index
]]];
151 rectangle tile_rect
= rect_from_tile(tile_obj
);
153 uint8_t coll
= collision_displace(desired_position
, thing
, &tile_rect
, inertia_mod
);
154 if(coll
& tile_type(tile_obj
)->lethal_sides
) {
159 rectangle_move_to(&thing
->hitbox
, *desired_position
);