Sprites in Repo geworfen (damit nichts verlorengeht)
[hackover2013-badge-firmware.git] / badge / jumpnrun / collision.c
1 #include "collision.h"
2
3 uint8_t collision_displace(vec2d *desired_pos,
4 jumpnrun_moveable *current,
5 rectangle const *obstacle,
6 vec2d *inertia_mod) {
7 rectangle desired = current->current_box;
8 rectangle_move_to(&desired, *desired_pos);
9
10 if(!rectangle_intersect(obstacle, &desired)) {
11 return 0;
12 }
13
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;
17
18 uint8_t coll_x = 0;
19 uint8_t coll_y = 0;
20 uint8_t coll = 0;
21
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(&current->current_box))) {
25
26 coll_y = JUMPNRUN_COLLISION_BOTTOM;
27 y = fixed_point_sub(rectangle_bottom(obstacle), rectangle_top(&desired));
28 dy = rectangle_bottom(obstacle);
29
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 (&current->current_box))) {
33
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;
38
39 }
40
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(&current->current_box))) {
44
45 coll_x = JUMPNRUN_COLLISION_RIGHT;
46 x = fixed_point_sub(rectangle_right(obstacle), rectangle_left(&desired));
47 dx = rectangle_right(obstacle);
48
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 (&current->current_box))) {
52
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 ));
56
57 }
58
59 if(fixed_point_eq(x, y)) {
60 desired_pos->x = dx;
61 desired_pos->y = dy;
62 coll = coll_x | coll_y;
63 } else if(fixed_point_gt(x, y)) {
64 desired_pos->y = dy;
65 inertia_mod->y = FIXED_INT(0);
66 current->touching_ground = bottom_collision;
67 coll = coll_y;
68 } else {
69 desired_pos->x = dx;
70 inertia_mod->x = FIXED_INT(0);
71 coll = coll_x;
72 }
73
74 return coll;
75 }
76
77 bool collisions_tiles_displace(vec2d *desired_position,
78 jumpnrun_moveable *thing,
79 jumpnrun_level const *lv,
80 jumpnrun_tile_range const *visible_tiles,
81 vec2d *inertia_mod)
82 {
83 int collision_tile[] = { -1, -1, -1,
84 -1, -1, -1,
85 -1, -1, -1
86 };
87 static int const collision_order[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
88
89 vec2d midpoint = rectangle_mid(&thing->current_box);
90
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)))
94 };
95
96 int tile;
97
98 for(tile = visible_tiles->first; (size_t) tile < visible_tiles->last && lv->tiles[tile].pos.x < midtile_pos.x - 1; ++tile)
99 ;
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;
103
104 switch(xdiff) {
105 case -1:
106 {
107 switch(ydiff) {
108 case -1: collision_tile[0] = tile; break;
109 case 0: collision_tile[1] = tile; break;
110 case 1: collision_tile[2] = tile; break;
111 }
112 break;
113 }
114 case 0:
115 {
116 switch(ydiff) {
117 case -1: collision_tile[3] = tile; break;
118 case 0: collision_tile[4] = tile; break;
119 case 1: collision_tile[5] = tile; break;
120 }
121 break;
122 }
123 case 1:
124 {
125 switch(ydiff) {
126 case -1: collision_tile[6] = tile; break;
127 case 0: collision_tile[7] = tile; break;
128 case 1: collision_tile[8] = tile; break;
129 }
130 break;
131 }
132 }
133 }
134
135 /* collision: sort by priority (top/bottom, left/right, then diagonal) */
136 bool lethal = false;
137 thing->touching_ground = false;
138
139 for(size_t collision_index = 0; collision_index < ARRAY_SIZE(collision_order); ++collision_index) {
140 if(collision_tile[collision_order[collision_index]] == -1) {
141 continue;
142 }
143
144 jumpnrun_tile *tile_obj = &lv->tiles[collision_tile[collision_order[collision_index]]];
145 rectangle tile_rect = rect_from_tile(tile_obj);
146
147 uint8_t coll = collision_displace(desired_position, thing, &tile_rect, inertia_mod);
148 if(coll & tile_type(tile_obj)->lethal_sides) {
149 lethal = true;
150 }
151 }
152
153 rectangle_move_to(&thing->current_box, *desired_position);
154
155 return lethal;
156 }
This page took 0.052192 seconds and 5 git commands to generate.