source: abuse/trunk/src/collide.cpp @ 489

Last change on this file since 489 was 481, checked in by Sam Hocevar, 10 years ago

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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