1 
2 #ifndef _SIF_H
3 #define _SIF_H
4 
5 #include "../common/misc.h" // stprintf
6 
7 // a sprite has certain settings global to the whole sprite.
8 // each sprite also contains a certain number of frames.
9 // each frame contains one or more directions, for example for when that
10 // frame is facing left or right, and sometimes up or down.
11 // the number of directions is settable per-sprite, but each frame in
12 // a given sprite always has the same number of directions.
13 
14 // this layout is somewhat wasteful of memory what with all static allocations and few pointers
15 // or dynamically-sized substructures. the reason I did it this way is for speed; hoping the
16 // tradeoff in memory will mean less indirections to access the sprite data, which is generally
17 // read several times per frame per sprite.
18 
19 #define SIF_MAX_DIRS 4
20 #define SIF_MAX_BLOCK_POINTS 4
21 
22 struct SIFPoint
23 {
24   int16_t x, y;
25 
setSIFPoint26   void set(int x, int y)
27   {
28     this->x = x;
29     this->y = y;
30   }
31 
offsetSIFPoint32   void offset(int dx, int dy)
33   {
34     x += dx;
35     y += dy;
36   }
37 
equSIFPoint38   bool equ(int x, int y)
39   {
40     return (this->x == x && this->y == y);
41   }
42 
ToStringSIFPoint43   const char *ToString()
44   {
45     return stprintf("[%d, %d]", this->x, this->y);
46   }
47 
48   bool operator==(const SIFPoint &other) const
49   {
50     return (this->x == other.x && this->y == other.y);
51   }
52 
53   bool operator!=(const SIFPoint &other) const
54   {
55     return (this->x != other.x || this->y != other.y);
56   }
57 };
58 
59 typedef SIFPoint Point;
60 
61 struct SIFRect
62 {
63   int16_t x1, y1, x2, y2;
64 
setSIFRect65   void set(int x1, int y1, int x2, int y2)
66   {
67     this->x1 = x1;
68     this->y1 = y1;
69     this->x2 = x2;
70     this->y2 = y2;
71   }
72 
offsetSIFRect73   void offset(int dx, int dy)
74   {
75     x1 += dx;
76     y1 += dy;
77     x2 += dx;
78     y2 += dy;
79   }
80 
equSIFRect81   bool equ(int x1, int y1, int x2, int y2)
82   {
83     return (this->x1 == x1 && this->y1 == y1 && this->x2 == x2 && this->y2 == y2);
84   }
85 
ToStringSIFRect86   const char *ToString()
87   {
88     return stprintf("[%d, %d] - [%d, %d]", this->x1, this->y1, this->x2, this->y2);
89   }
90 
91   bool operator==(const SIFRect &other) const
92   {
93     return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2);
94   }
95 
96   bool operator!=(const SIFRect &other) const
97   {
98     return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2);
99   }
100 };
101 
102 struct SIFPointList
103 {
104   SIFPoint point[SIF_MAX_BLOCK_POINTS];
105   int count;
106 
107   SIFPoint &operator[](const int nIndex)
108   {
109     return point[nIndex];
110   }
111 
112   bool operator==(const SIFPointList &other) const
113   {
114     if (other.count != count)
115       return false;
116 
117     for (int i = 0; i < count; i++)
118       if (point[i] != other.point[i])
119         return false;
120 
121     return true;
122   }
123 
124   bool operator!=(const SIFPointList &other) const
125   {
126     return !(*this == other);
127   }
128 
offsetSIFPointList129   void offset(int dx, int dy)
130   {
131     for (int i = 0; i < count; i++)
132     {
133       point[i].x += dx;
134       point[i].y += dy;
135     }
136   }
137 };
138 
139 struct SIFDir
140 {
141   // the offset on the sprite sheet where this frame is located.
142   SIFPoint sheet_offset;
143 
144   // when a sprite is drawn, it's sprite will be offset such that this pixel is
145   // placed at the (x,y) coordinates that were given for the sprite to be drawn at.
146   // i.e., it's a "hot point".
147   // this also offsets the bounding boxes and blockl/r/u/d points but not the
148   // action points or spawn point.
149   // it is not super-well tested and isn't intended to be frequently used on objects which
150   // interact with the world or are solid, etc. mostly it is for use with objects
151   // such as the caret effects etc, so that their o->x & o->y can represent their center
152   // point instead of their upper-left corner.
153   SIFPoint drawpoint;
154 
155   //	a pixel of "noteworthiness" on the sprite.
156   //  * for Player: position he holds his gun at
157   //  * for Guns: position to spawn the shots at
158   //	* for everything else: whatever they want it for
159   SIFPoint actionpoint;
160 
161   // optional secondary action point
162   SIFPoint actionpoint2;
163 
164   // optional additional/extra per-frame/dir bbox
165   // (has no effect to engine, it's just metadata. but object AI can copy the
166   //  per-frame bbox over the real bbox when changing the frame).
167   SIFRect pf_bbox;
168 };
169 
170 struct SIFFrame
171 {
172   SIFDir dir[SIF_MAX_DIRS];
173 };
174 
175 // a design goal here is that this structure MUST STAY POD so
176 // no virtuals, constructors, classes for members or anything else
177 // dodgy that might endanger that. we should able to zero out a SIFSprite
178 // with memset and worry about nothing. yes it has a few member functions
179 // but those are just a syntactical detail and should be harmless.
180 struct SIFSprite
181 {
182   void Init();
183   void Zero();
184   void FreeData();
185 
186   void AddFrame(SIFFrame *newframe);
187   void InsertFrame(SIFFrame *newframe, int insertbefore);
188   void DeleteFrame(int index);
189   void SetNumFrames(int newcount);
190   SIFDir *dir(int frame, int dir);
191 
192   void CopyFrom(SIFSprite *other);
193   SIFSprite *Duplicate();
194 
195   // ---------------------------------------
196 
197   int w, h;
198   uint8_t spritesheet; // # of spritesheet sprite is located on
199 
200   int nframes;
201   int ndirs;
202   SIFFrame *frame;
203 
204   SIFRect bbox[SIF_MAX_DIRS];     // bounding box for hit detection with other sprites
205   SIFRect solidbox; // bounding box for solidity w/ other objects
206   SIFRect slopebox; // bounding box for moving up and down slopes (generated at runtime)
207 
208   // when an object is spawned or changed from one type to another, this point is subtracted
209   // from it's x,y coordinates, so that this point ends up being centered on the given x,y coords.
210   SIFPoint spawn_point;
211 
212   // points to check for setting the corresponding block vars on the object
213   // (which determine whether it's blocked on that side by a solid wall or object).
214   SIFPointList block_l;
215   SIFPointList block_r;
216   SIFPointList block_u;
217   SIFPointList block_d;
218 };
219 
220 #endif
221