Probeweise mal mit Flashchip sprechen (Statusregister auslesen)
[hackover2013-badge-firmware.git] / badge / jumpnrun / collision.c
1 #include "collision.h"
2
3 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof*(arr))
4
5 void collision_displace(vec2d *desired_pos,
6 rectangle const *current,
7 rectangle const *obstacle,
8 vec2d *inertia,
9 bool *touching_ground) {
10 rectangle desired = *current;
11 rectangle_move_to(&desired, *desired_pos);
12
13 if(!rectangle_intersect(obstacle, &desired)) {
14 return;
15 }
16
17 fixed_point x = FIXED_POINT(1000, 0), y = FIXED_POINT(1000, 0);
18 fixed_point dx = desired_pos->x, dy = desired_pos->y;
19 bool bottom_collision = false;
20
21 if(fixed_point_le(rectangle_top ( obstacle), rectangle_top(&desired)) &&
22 fixed_point_gt(rectangle_bottom( obstacle), rectangle_top(&desired)) &&
23 fixed_point_lt(rectangle_top (&desired ), rectangle_top( current))) {
24
25 y = fixed_point_sub(rectangle_bottom(obstacle), rectangle_top(&desired));
26 dy = rectangle_bottom(obstacle);
27
28 } else if(fixed_point_gt(rectangle_bottom( obstacle), rectangle_bottom(&desired)) &&
29 fixed_point_le(rectangle_top ( obstacle), rectangle_bottom(&desired)) &&
30 fixed_point_gt(rectangle_top (&desired ), rectangle_top ( current))) {
31
32 y = fixed_point_sub(rectangle_bottom(&desired ), rectangle_top ( obstacle));
33 dy = fixed_point_sub(rectangle_top ( obstacle), rectangle_height(&desired ));
34 bottom_collision = true;
35
36 }
37
38
39 if(fixed_point_le(rectangle_left ( obstacle), rectangle_left(&desired)) &&
40 fixed_point_gt(rectangle_right( obstacle), rectangle_left(&desired)) &&
41 fixed_point_lt(rectangle_left (&desired ), rectangle_left( current))) {
42
43 x = fixed_point_sub(rectangle_right(obstacle), rectangle_left(&desired));
44 dx = rectangle_right(obstacle);
45
46 } else if(fixed_point_gt(rectangle_right( obstacle), rectangle_right(&desired)) &&
47 fixed_point_le(rectangle_left ( obstacle), rectangle_right(&desired)) &&
48 fixed_point_gt(rectangle_left (&desired ), rectangle_left ( current))) {
49
50 x = fixed_point_sub(rectangle_right(&desired ), rectangle_left ( obstacle));
51 dx = fixed_point_sub(rectangle_left ( obstacle), rectangle_width(&desired ));
52
53 }
54
55 if(fixed_point_eq(x, y)) {
56 desired_pos->x = dx;
57 desired_pos->y = dy;
58 } else if(fixed_point_gt(x, y)) {
59 desired_pos->y = dy;
60 inertia->y = FIXED_POINT(0, 0);
61
62 *touching_ground = bottom_collision;
63 } else {
64 desired_pos->x = dx;
65 inertia->x = FIXED_POINT(0, 0);
66 }
67
68 return;
69 }
70
71 void collisions_tiles_displace(vec2d *desired_position,
72 rectangle const *current,
73 jumpnrun_level const *lv,
74 jumpnrun_tile_range const *visible_tiles,
75 vec2d *inertia,
76 bool *touching_ground)
77 {
78 int collision_tile[] = { -1, -1, -1,
79 -1, -1, -1,
80 -1, -1, -1
81 };
82 static int const collision_order[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
83
84 vec2d midpoint = rectangle_mid(current);
85
86 jumpnrun_tile_position midtile_pos = {
87 fixed_point_cast_int(fixed_point_div(midpoint.x, FIXED_POINT(JUMPNRUN_TILE_PIXEL_WIDTH , 0))),
88 fixed_point_cast_int(fixed_point_div(midpoint.y, FIXED_POINT(JUMPNRUN_TILE_PIXEL_HEIGHT, 0)))
89 };
90
91 int tile;
92
93 for(tile = visible_tiles->first; (size_t) tile < visible_tiles->last && lv->tiles[tile].pos.x < midtile_pos.x - 1; ++tile)
94 ;
95 for(; (size_t) tile < visible_tiles->last && lv->tiles[tile].pos.x < midtile_pos.x + 2; ++tile) {
96 int xdiff = lv->tiles[tile].pos.x - midtile_pos.x;
97 int ydiff = lv->tiles[tile].pos.y - midtile_pos.y;
98
99 switch(xdiff) {
100 case -1:
101 {
102 switch(ydiff) {
103 case -1: collision_tile[0] = tile; break;
104 case 0: collision_tile[1] = tile; break;
105 case 1: collision_tile[2] = tile; break;
106 }
107 break;
108 }
109 case 0:
110 {
111 switch(ydiff) {
112 case -1: collision_tile[3] = tile; break;
113 case 0: collision_tile[4] = tile; break;
114 case 1: collision_tile[5] = tile; break;
115 }
116 break;
117 }
118 case 1:
119 {
120 switch(ydiff) {
121 case -1: collision_tile[6] = tile; break;
122 case 0: collision_tile[7] = tile; break;
123 case 1: collision_tile[8] = tile; break;
124 }
125 break;
126 }
127 }
128 }
129
130 /* collision: sort by priority (top/bottom, left/right, then diagonal) */
131 *touching_ground = false;
132
133 // printf("mid: %d, %d\n", midtile_pos.x, midtile_pos.y);
134 for(size_t collision_index = 0; collision_index < ARRAY_SIZE(collision_order); ++collision_index) {
135 if(collision_tile[collision_order[collision_index]] == -1) {
136 continue;
137 }
138
139 rectangle tile_rect = rect_from_tile(&lv->tiles[collision_tile[collision_order[collision_index]]]);
140
141 collision_displace(desired_position, current, &tile_rect, inertia, touching_ground);
142 }
143 }
This page took 0.054622 seconds and 5 git commands to generate.