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