NXEngine v1.0.0.6
[NXEngine.git] / ObjManager.cpp
blob6ad7c53bc9972437264a8481e29231f039648f4f
2 #include "nx.h"
3 #include "common/llist.h"
4 #include "ObjManager.h"
5 #include "ObjManager.fdh"
7 static Object ZERO_OBJECT;
8 static Player ZERO_PLAYER;
10 Object *firstobject = NULL, *lastobject = NULL;
11 Object *lowestobject = NULL, *highestobject = NULL;
14 void c------------------------------() {}
17 Object *CreateObject(int x, int y, int type, int xinertia, int yinertia,
18 int dir, Object *linkedobject, uint32_t createflags)
20 Object *o;
22 // create the structure
23 if (type != OBJ_PLAYER)
25 o = new Object;
26 *o = ZERO_OBJECT; // safely clears all members
28 else
30 Player *p = new Player;
31 *p = ZERO_PLAYER;
32 o = (Object *)p;
35 // initialize
36 o->SetType(type);
37 o->flags = objprop[type].defaultflags;
38 o->DamageText = new FloatText(SPR_REDNUMBERS);
40 o->x = x - (sprites[o->sprite].spawn_point.x << CSF);
41 o->y = y - (sprites[o->sprite].spawn_point.y << CSF);
42 o->dir = dir;
43 o->xinertia = xinertia;
44 o->yinertia = yinertia;
45 o->linkedobject = linkedobject;
47 // add into list
48 LL_ADD_END(o, prev, next, firstobject, lastobject);
49 LL_ADD_END(o, lower, higher, lowestobject, highestobject);
51 // set it's initial blocked states, but do not update blockedstates on objects starting
52 // with nullsprite-- the reason is for objects whose sprite is set after being spawned
53 if (o->sprite != SPR_NULL)
54 o->UpdateBlockStates(ALLDIRMASK);
56 if (!(createflags & CF_NO_SPAWN_EVENT))
57 o->OnSpawn();
59 return o;
62 Object *CreateObject(int x, int y, int type)
64 return CreateObject(x, y, type, 0, 0, RIGHT, NULL, CF_DEFAULT);
68 void c------------------------------() {}
71 // update the blocked states of all objects
72 void Objects::UpdateBlockStates(void)
74 Object *o = firstobject;
75 while(o)
77 o->lastblockl = o->blockl;
78 o->lastblockr = o->blockr;
79 o->lastblocku = o->blocku;
80 o->lastblockd = o->blockd;
82 o->UpdateBlockStates(ALLDIRMASK);
83 o = o->next;
87 // returns true if the bounding boxes of the two given objects are touching
88 bool hitdetect(Object *o1, Object *o2)
90 SIFSprite *s1, *s2;
91 int32_t rect1x1, rect1y1, rect1x2, rect1y2;
92 int32_t rect2x1, rect2y1, rect2x2, rect2y2;
94 // get the sprites used by the two objects
95 s1 = o1->Sprite();
96 s2 = o2->Sprite();
98 // get the bounding rectangle of the first object
99 rect1x1 = o1->x + (s1->bbox.x1 << CSF);
100 rect1x2 = o1->x + (s1->bbox.x2 << CSF);
101 rect1y1 = o1->y + (s1->bbox.y1 << CSF);
102 rect1y2 = o1->y + (s1->bbox.y2 << CSF);
104 // get the bounding rectangle of the second object
105 rect2x1 = o2->x + (s2->bbox.x1 << CSF);
106 rect2x2 = o2->x + (s2->bbox.x2 << CSF);
107 rect2y1 = o2->y + (s2->bbox.y1 << CSF);
108 rect2y2 = o2->y + (s2->bbox.y2 << CSF);
110 // find out if the rectangles overlap
111 if ((rect1x1 < rect2x1) && (rect1x2 < rect2x1)) return false;
112 if ((rect1x1 > rect2x2) && (rect1x2 > rect2x2)) return false;
113 if ((rect1y1 < rect2y1) && (rect1y2 < rect2y1)) return false;
114 if ((rect1y1 > rect2y2) && (rect1y2 > rect2y2)) return false;
116 return true;
119 // returns true if the solidity boxes of the two given objects are touching
120 bool solidhitdetect(Object *o1, Object *o2)
122 SIFSprite *s1, *s2;
123 int32_t rect1x1, rect1y1, rect1x2, rect1y2;
124 int32_t rect2x1, rect2y1, rect2x2, rect2y2;
126 // get the sprites used by the two objects
127 s1 = o1->Sprite();
128 s2 = o2->Sprite();
130 // get the bounding rectangle of the first object
131 rect1x1 = o1->x + (s1->solidbox.x1 << CSF);
132 rect1x2 = o1->x + (s1->solidbox.x2 << CSF);
133 rect1y1 = o1->y + (s1->solidbox.y1 << CSF);
134 rect1y2 = o1->y + (s1->solidbox.y2 << CSF);
136 // get the bounding rectangle of the second object
137 rect2x1 = o2->x + (s2->solidbox.x1 << CSF);
138 rect2x2 = o2->x + (s2->solidbox.x2 << CSF);
139 rect2y1 = o2->y + (s2->solidbox.y1 << CSF);
140 rect2y2 = o2->y + (s2->solidbox.y2 << CSF);
142 // find out if the rectangles overlap
143 if ((rect1x1 < rect2x1) && (rect1x2 < rect2x1)) return false;
144 if ((rect1x1 > rect2x2) && (rect1x2 > rect2x2)) return false;
145 if ((rect1y1 < rect2y1) && (rect1y2 < rect2y1)) return false;
146 if ((rect1y1 > rect2y2) && (rect1y2 > rect2y2)) return false;
148 return true;
152 void c------------------------------() {}
155 // runs all entity AI routines
156 void Objects::RunAI(void)
158 Object *o;
160 // because we handle objects in order of their creation and have a separate list
161 // for display order, we can't ever run AI twice in a frame because of z-order
162 // rearrangement, and 2) objects created by other objects are added to the end of
163 // the list and given a chance to run their AI routine before being displayed.
164 FOREACH_OBJECT(o)
166 if (!o->deleted)
167 o->RunAI();
172 // the most important thing it does is apply x/y inertia to the objects.
173 void Objects::PhysicsSim(void)
175 Object *o;
176 int xinertia, yinertia;
178 FOREACH_OBJECT(o)
180 if (o != player && !o->deleted) // player is moved in PDoPhysics
182 if (!(o->flags & FLAG_IGNORE_SOLID) && \
183 !(o->nxflags & NXFLAG_NO_RESET_YINERTIA))
185 if (o->blockd && o->yinertia > 0) o->yinertia = 0;
186 if (o->blocku && o->yinertia < 0) o->yinertia = 0;
189 // apply inertia to X,Y position
190 xinertia = o->xinertia;
191 yinertia = o->yinertia;
192 if (o->shaketime)
194 if (o->nxflags & NXFLAG_SLOW_X_WHEN_HURT) xinertia >>= 1;
195 if (o->nxflags & NXFLAG_SLOW_Y_WHEN_HURT) yinertia >>= 1;
198 o->apply_xinertia(xinertia);
199 o->apply_yinertia(yinertia);
201 // flag_solid_brick objects push player as they move
202 if (o->flags & FLAG_SOLID_BRICK)
204 o->PushPlayerOutOfWay(xinertia, yinertia);
206 else if (o->damage > 0)
208 // have enemies hurt you when you touch them
209 // (solid-brick objects do this in PHandleSolidBrickObjects)
210 if (hitdetect(o, player))
211 o->DealContactDamage();
218 void c------------------------------() {}
221 // returns how many objects exist of the given type
222 int Objects::CountType(int objtype)
224 int count = 0;
225 Object *o;
227 FOREACH_OBJECT(o)
229 if (o->type == objtype)
230 count++;
233 return count;
236 // returns the first object of type objtype or NULL
237 Object *Objects::FindByType(int objtype)
239 Object *o;
240 FOREACH_OBJECT(o)
242 if (o->type == objtype)
243 return o;
246 return NULL;
250 void c------------------------------() {}
253 // free objects deleted earlier via ObjDel
254 void Objects::CullDeleted(void)
256 Object *o, *next;
258 o = firstobject;
259 while(o)
261 next = o->next;
263 if (o->deleted)
265 o->Destroy();
268 o = next;
272 // deletes all objects. if delete_player is true, also deletes the player.
273 // used by load_pxe to reset the game in preperation for loading a new maplayer->
274 void Objects::DestroyAll(bool delete_player)
276 Object *o, *next;
278 o = firstobject;
279 while(o)
281 next = o->next;
283 if (o != player)
285 o->Destroy();
288 o = next;
291 // must do this last to avoid crashes as player ptr gets invalidated
292 if (delete_player)
294 player->Destroy();
297 memset(ID2Lookup, 0, sizeof(ID2Lookup));