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

Last change on this file since 97 was 56, checked in by Sam Hocevar, 12 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
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.hpp"
13#include "intsect.hpp"
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) jfree(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 **)jmalloc(total*sizeof(game_object *),"collide patches");
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 **)jrealloc(p->touch,sizeof(game_object *)*p->total,"object_patch_list");
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 **)jrealloc(p->touch,sizeof(game_object *)*p->total,"object_patch_list");
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 **)jmalloc(sizeof(game_object *)*1,"object_patch_list");
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.