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

Last change on this file since 512 was 512, checked in by Sam Hocevar, 7 years ago

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

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