source: abuse/tags/pd/abuse/src/collide.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 5.3 KB
Line 
1#include "level.hpp"
2#include "intsect.hpp"
3
4class 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
23collide_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
38void 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
147void 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
Note: See TracBrowser for help on using the repository browser.