[49] | 1 | #include "level.hpp" |
---|
| 2 | #include "intsect.hpp" |
---|
| 3 | |
---|
| 4 | class collide_patch |
---|
| 5 | { |
---|
| 6 | public : |
---|
| 7 | long total,x1,y1,x2,y2; |
---|
| 8 | game_object **touch; |
---|
| 9 | collide_patch *next; |
---|
| 10 | collide_patch(long X1, long Y1, long X2, long Y2, collide_patch *Next) |
---|
| 11 | { |
---|
| 12 | x1=X1; y1=Y1; x2=X2; y2=Y2; |
---|
| 13 | next=Next; |
---|
| 14 | total=0; |
---|
| 15 | touch=NULL; |
---|
| 16 | } |
---|
| 17 | void add_collide(long X1, long Y1, long X2, long Y2, game_object *who); |
---|
| 18 | collide_patch *copy(collide_patch *Next); |
---|
| 19 | ~collide_patch() { if (total) jfree(touch); } |
---|
| 20 | } ; |
---|
| 21 | |
---|
| 22 | |
---|
| 23 | collide_patch *collide_patch::copy(collide_patch *Next) |
---|
| 24 | { |
---|
| 25 | collide_patch *p=new collide_patch(x1,y1,x2,y2,Next); |
---|
| 26 | p->total=total; |
---|
| 27 | if (total) |
---|
| 28 | { |
---|
| 29 | p->touch=(game_object **)jmalloc(total*sizeof(game_object *),"collide patches"); |
---|
| 30 | memcpy(p->touch,touch,total*(sizeof(game_object *))); |
---|
| 31 | } |
---|
| 32 | else |
---|
| 33 | p->touch=NULL; |
---|
| 34 | return p; |
---|
| 35 | } |
---|
| 36 | |
---|
| 37 | |
---|
| 38 | void add_collide(collide_patch *&first, long x1, long y1, long x2, long y2, |
---|
| 39 | game_object *who) |
---|
| 40 | { |
---|
| 41 | collide_patch *last=NULL,*next; |
---|
| 42 | for (collide_patch *p=first;p;p=next) |
---|
| 43 | { |
---|
| 44 | next=p->next; |
---|
| 45 | // first see if light patch we are adding is enclosed entirely by another patch |
---|
| 46 | if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2) |
---|
| 47 | { |
---|
| 48 | if (x1>p->x1) |
---|
| 49 | { |
---|
| 50 | first=p->copy(first); |
---|
| 51 | first->x2=x1-1; |
---|
| 52 | } |
---|
| 53 | if (x2<p->x2) |
---|
| 54 | { |
---|
| 55 | first=p->copy(first); |
---|
| 56 | first->x1=x2+1; |
---|
| 57 | } |
---|
| 58 | if (y1>p->y1) |
---|
| 59 | { |
---|
| 60 | first=p->copy(first); |
---|
| 61 | first->x1=x1; |
---|
| 62 | first->x2=x2; |
---|
| 63 | first->y2=y1-1; |
---|
| 64 | } |
---|
| 65 | if (y2<p->y2) |
---|
| 66 | { |
---|
| 67 | first=p->copy(first); |
---|
| 68 | first->x1=x1; |
---|
| 69 | first->x2=x2; |
---|
| 70 | first->y1=y2+1; |
---|
| 71 | } |
---|
| 72 | p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2; |
---|
| 73 | |
---|
| 74 | p->total++; |
---|
| 75 | p->touch=(game_object **)jrealloc(p->touch,sizeof(game_object *)*p->total,"object_patch_list"); |
---|
| 76 | p->touch[p->total-1]=who; |
---|
| 77 | return ; |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | // see if the patch completly covers another patch. |
---|
| 81 | if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2) |
---|
| 82 | { |
---|
| 83 | if (x1<p->x1) |
---|
| 84 | add_collide(first,x1,y1,p->x1-1,y2,who); |
---|
| 85 | if (x2>p->x2) |
---|
| 86 | add_collide(first,p->x2+1,y1,x2,y2,who); |
---|
| 87 | if (y1<p->y1) |
---|
| 88 | add_collide(first,p->x1,y1,p->x2,p->y1-1,who); |
---|
| 89 | if (y2>p->y2) |
---|
| 90 | add_collide(first,p->x1,p->y2+1,p->x2,y2,who); |
---|
| 91 | p->total++; |
---|
| 92 | p->touch=(game_object **)jrealloc(p->touch,sizeof(game_object *)*p->total,"object_patch_list"); |
---|
| 93 | p->touch[p->total-1]=who; |
---|
| 94 | return ; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | // see if we intersect another rect |
---|
| 98 | if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2)) |
---|
| 99 | { |
---|
| 100 | int ax1,ay1,ax2,ay2; |
---|
| 101 | if (x1<p->x1) |
---|
| 102 | { |
---|
| 103 | add_collide(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who); |
---|
| 104 | ax1=p->x1; |
---|
| 105 | } else |
---|
| 106 | ax1=x1; |
---|
| 107 | |
---|
| 108 | if (x2>p->x2) |
---|
| 109 | { |
---|
| 110 | add_collide(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who); |
---|
| 111 | ax2=p->x2; |
---|
| 112 | } |
---|
| 113 | else |
---|
| 114 | ax2=x2; |
---|
| 115 | |
---|
| 116 | if (y1<p->y1) |
---|
| 117 | { |
---|
| 118 | add_collide(first,x1,y1,x2,p->y1-1,who); |
---|
| 119 | ay1=p->y1; |
---|
| 120 | } else |
---|
| 121 | ay1=y1; |
---|
| 122 | |
---|
| 123 | if (y2>p->y2) |
---|
| 124 | { |
---|
| 125 | add_collide(first,x1,p->y2+1,x2,y2,who); |
---|
| 126 | ay2=p->y2; |
---|
| 127 | } else |
---|
| 128 | ay2=y2; |
---|
| 129 | |
---|
| 130 | |
---|
| 131 | add_collide(first,ax1,ay1,ax2,ay2,who); |
---|
| 132 | |
---|
| 133 | return ; |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | } |
---|
| 137 | |
---|
| 138 | first=new collide_patch(x1,y1,x2,y2,first); |
---|
| 139 | first->total=1; |
---|
| 140 | first->touch=(game_object **)jmalloc(sizeof(game_object *)*1,"object_patch_list"); |
---|
| 141 | first->touch[0]=who; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | |
---|
| 145 | |
---|
| 146 | |
---|
| 147 | void level::check_collisions() |
---|
| 148 | { |
---|
| 149 | game_object *target,*rec,*subject; |
---|
| 150 | collide_patch *f=NULL; |
---|
| 151 | long sx1,sy1,sx2,sy2,tx1,ty1,tx2,ty2,hitx,hity, |
---|
| 152 | s_centerx,t_centerx; |
---|
| 153 | |
---|
| 154 | for (int l=0;l<attack_total;l++) |
---|
| 155 | { |
---|
| 156 | subject=attack_list[l]; |
---|
| 157 | subject->picture_space(sx1,sy1,sx2,sy2); |
---|
| 158 | rec=NULL; |
---|
| 159 | |
---|
| 160 | |
---|
| 161 | for (int j=0;j<target_total && !rec;j++) |
---|
| 162 | { |
---|
| 163 | target=target_list[j]; |
---|
| 164 | target->picture_space(tx1,ty1,tx2,ty2); |
---|
| 165 | if (!(sx2<tx1 || sy2<ty1 || sx1>tx2 || sy1>ty2)) // check to see if picture spaces collide |
---|
| 166 | { |
---|
| 167 | |
---|
| 168 | try_pushback(subject,target); |
---|
| 169 | |
---|
| 170 | if (subject->can_hurt(target)) // see if we can hurt him before calculating |
---|
| 171 | { |
---|
| 172 | t_centerx=target->x_center(); |
---|
| 173 | point_list *s_hit,*t_damage; |
---|
| 174 | |
---|
| 175 | s_hit=subject->current_figure()->hit; |
---|
| 176 | |
---|
| 177 | if (target->direction>0) |
---|
| 178 | t_damage=target->current_figure()->f_damage; |
---|
| 179 | else |
---|
| 180 | t_damage=target->current_figure()->b_damage; |
---|
| 181 | |
---|
| 182 | unsigned char *s_dat=s_hit->data,*t_dat; |
---|
| 183 | int i,j; |
---|
| 184 | for (i=(int)s_hit->tot-1;i>0 && !rec;i--) |
---|
| 185 | { |
---|
| 186 | for (t_dat=t_damage->data,j=(int)t_damage->tot-1;j>0 && !rec;j--) |
---|
| 187 | { |
---|
| 188 | long x1,y1,x2,y2, // define the two line segments to check |
---|
| 189 | xp1,yp1,xp2,yp2; |
---|
| 190 | |
---|
| 191 | xp1=target->x+target->tx(*t_dat); t_dat++; |
---|
| 192 | yp1=target->y+target->ty(*t_dat); t_dat++; |
---|
| 193 | xp2=target->x+target->tx(*t_dat); |
---|
| 194 | yp2=target->y+target->ty(t_dat[1]); |
---|
| 195 | |
---|
| 196 | x1=subject->x+subject->tx(s_dat[0]); |
---|
| 197 | y1=subject->y+subject->ty(s_dat[1]); |
---|
| 198 | x2=subject->x+subject->tx(s_dat[2]); |
---|
| 199 | y2=subject->y+subject->ty(s_dat[3]); |
---|
| 200 | |
---|
| 201 | |
---|
| 202 | // ok, now we know which line segemnts to check for intersection |
---|
| 203 | // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2) |
---|
| 204 | int _x2=x2,_y2=y2; |
---|
| 205 | setback_intersect(x1, y1, x2, y2, xp1, yp1, xp2, yp2,0); |
---|
| 206 | |
---|
| 207 | |
---|
| 208 | if (x2!=_x2 || _y2!=y2) |
---|
| 209 | { |
---|
| 210 | rec=target; |
---|
| 211 | hitx=((x1+x2)/2+(xp1+xp2)/2)/2; |
---|
| 212 | hity=((y1+y1)/2+(yp1+yp2)/2)/2; |
---|
| 213 | } |
---|
| 214 | } |
---|
| 215 | s_dat+=2; |
---|
| 216 | } |
---|
| 217 | } |
---|
| 218 | } |
---|
| 219 | } |
---|
| 220 | if (rec) |
---|
| 221 | { |
---|
| 222 | rec->do_damage((int)subject->current_figure()->hit_damage,subject,hitx,hity,0,0); |
---|
| 223 | subject->note_attack(rec); |
---|
| 224 | } |
---|
| 225 | } |
---|
| 226 | } |
---|
| 227 | |
---|