1 #include <shadowdive/rgba_image.h>
2 #include "game/protos/intersect.h"
3 #include "utils/log.h"
4 
intersect_object_object(object * a,object * b)5 int intersect_object_object(object *a, object *b) {
6     if(a->cur_sprite == NULL || b->cur_sprite == NULL) return 0;
7     vec2i pos_a = vec2i_add(object_get_pos(a), a->cur_sprite->pos);
8     vec2i pos_b = vec2i_add(object_get_pos(b), b->cur_sprite->pos);
9     vec2i size_a = object_get_size(a);
10     vec2i size_b = object_get_size(b);
11     return !(
12         pos_a.x > (pos_b.x + size_b.x) ||
13         pos_a.y > (pos_b.y + size_b.y) ||
14         (pos_a.x + size_a.x) < pos_b.x ||
15         (pos_a.y + size_a.y) < pos_b.y);
16 }
17 
intersect_object_point(object * obj,vec2i point)18 int intersect_object_point(object *obj, vec2i point) {
19     if(obj->cur_sprite == NULL) return 0;
20     vec2i pos = vec2i_add(object_get_pos(obj), obj->cur_sprite->pos);
21     vec2i size = object_get_size(obj);
22     return (
23         point.x < (pos.x + size.x) &&
24         point.y < (pos.y + size.y) &&
25         point.x > pos.x &&
26         point.y > pos.y);
27 }
28 
29 
intersect_sprite_hitpoint(object * obj,object * target,int level,vec2i * point)30 int intersect_sprite_hitpoint(object *obj, object *target, int level, vec2i *point) {
31     // Make sure both objects have sprites going
32     if(obj->cur_sprite == NULL || target->cur_sprite == NULL) {
33         return 0;
34     }
35     // Make sure there are hitpoints to check.
36     if(vector_size(&obj->cur_animation->collision_coords) == 0) {
37         return 0;
38     }
39 
40     int object_dir = OBJECT_FACE_RIGHT;
41     int target_dir = OBJECT_FACE_RIGHT;
42 
43     // Some useful variables
44     vec2i pos_a = vec2i_add(object_get_pos(obj), obj->cur_sprite->pos);
45     vec2i pos_b = vec2i_add(object_get_pos(target), target->cur_sprite->pos);
46     vec2i size_a = object_get_size(obj);
47     vec2i size_b = object_get_size(target);
48 
49     if ((object_get_direction(obj) == OBJECT_FACE_LEFT && !player_frame_isset(obj, "r")) ||
50             (object_get_direction(obj) == OBJECT_FACE_RIGHT && player_frame_isset(obj, "r"))) {
51         object_dir = OBJECT_FACE_LEFT;
52         pos_a.x = object_get_pos(obj).x + ((obj->cur_sprite->pos.x * -1) - size_a.x);
53     }
54 
55     if ((object_get_direction(target) == OBJECT_FACE_LEFT && !player_frame_isset(target, "r")) ||
56             (object_get_direction(target) == OBJECT_FACE_RIGHT && player_frame_isset(target, "r"))) {
57         target_dir = OBJECT_FACE_LEFT;
58         pos_b.x = object_get_pos(target).x + ((target->cur_sprite->pos.x * -1) - size_b.x);
59     }
60 
61 
62     // Iterate through hitpoints
63     vec2i hcoords[level];
64     int found = 0;
65     iterator it;
66     collision_coord *cc;
67     vector_iter_begin(&obj->cur_animation->collision_coords, &it);
68     while((cc = iter_next(&it)) != NULL) {
69         // Skip coords that don't belong to the frame we are checking
70         if(cc->frame_index != obj->cur_sprite->id) continue;
71 
72         // Convert coords to target sprite local space
73         int t = (object_dir == OBJECT_FACE_RIGHT)
74             ? (pos_a.x + cc->pos.x - obj->cur_sprite->pos.x)
75             : (pos_a.x + (size_a.x - cc->pos.x) + obj->cur_sprite->pos.x);
76 
77         // convert global coordinates to local coordinates by compensating for the other player's position
78         int xcoord = t - pos_b.x;
79         // Also note that the hit pixel position during jumps is innacurate because hacks
80         int ycoord = (pos_a.y + size_a.y + cc->pos.y) - pos_b.y;
81 
82         ycoord -= (obj->cur_sprite->pos.y + size_a.y);
83 
84         // Make sure that the hitpixel is within the area of the target sprite
85         if(xcoord < 0 || xcoord >= size_b.x) continue;
86         if(ycoord < 0 || ycoord >= size_b.y) continue;
87 
88         // Get hitpixel
89         surface *sfc = target->cur_sprite->data;
90         int hitpoint = (ycoord * sfc->w) + xcoord;
91         if (target_dir == OBJECT_FACE_LEFT) {
92             hitpoint = (ycoord * sfc->w) + (sfc->w - xcoord);
93         }
94         if(sfc->stencil[hitpoint] > 0) {
95             hcoords[found++] = vec2i_create(xcoord, ycoord);
96             if(found >= level) {
97                 vec2f sum = vec2f_create(0,0);
98                 for(int k = 0; k < level; k++) {
99                     sum.x += hcoords[k].x;
100                     sum.y += hcoords[k].y;
101                 }
102                 point->x = (sum.x / level) + pos_b.x;
103                 point->y = (sum.y / level) + pos_b.y;
104                 return 1;
105             }
106         }
107     }
108 
109     return 0;
110 }
111