Blame src/group.c

8535a3
8535a3
#include "private.h"
8535a3
#include "group.h"
d7d433
#include "window.h"
8535a3
8535a3
struct _Group {
8535a3
	HeliArray sprites;
44355f
	HeliArray spritesSorted;
8535a3
};
8535a3
8535a3
8535a3
Group createGroup() {
8eb855
	if (!heliInitialized) return NULL;
8535a3
	Group g = calloc(1, sizeof(*g));
8eb855
	heliObjectRegister(g, (HeliFreeCallback)&groupDestroy);
8535a3
	return g;
8535a3
}
8535a3
a359d6
Group createEdgesGroupEx(double x1, double y1, double x2, double y2, double borderWidth, int massLevel) {
8eb855
	if (!heliInitialized) return NULL;
8535a3
	if (x2 < x1) { double x = x2; x2 = x1; x1 = x; }
8535a3
	if (y2 < y1) { double y = y2; y2 = y1; y1 = y; }
8535a3
	if (borderWidth < 0.1) borderWidth = 0.1;
8535a3
	
8535a3
	double b = borderWidth;
8535a3
	double w = x2 - x1 + b*2;
8535a3
	double h = y2 - y1 + b*2;
8535a3
	x1 -= b;
8535a3
	y1 -= b;
8535a3
	
8535a3
	Group g = createGroup();
e8cb52
	groupAdd(g, createSprite(x1 + w/2, y1 + b/2, w, b));
e8cb52
	groupAdd(g, createSprite(x1 + w/2, y2 + b/2, w, b));
e8cb52
	groupAdd(g, createSprite(x1 + b/2, y1 + h/2, b, h));
e8cb52
	groupAdd(g, createSprite(x2 + b/2, y1 + h/2, b, h));
a359d6
	groupSetMassLevelEach(g, massLevel);
8535a3
	return g;
8535a3
}
8535a3
8535a3
Group createEdgesGroup()
d7d433
	{ return createEdgesGroupEx(0, 0, windowGetWidth(), windowGetHeight(), windowGetHeight(), 100); }
8535a3
8535a3
8535a3
void groupDestroy(Group group) {
87fe10
	groupClear(group);
8535a3
	heliArrayDestroy(&group->sprites);
44355f
	heliArrayDestroy(&group->spritesSorted);
87fe10
	heliObjectUnregister(group);
8535a3
	free(group);
8535a3
}
8535a3
8535a3
void groupDestroyEx(Group group, int destroySprites) {
8535a3
	groupClearEx(group, destroySprites);
8535a3
	groupDestroy(group);
8535a3
}
8535a3
8535a3
void groupAdd(Group group, Sprite sprite) {
8935bc
	if (!sprite) return;
8535a3
	if (groupContains(group, sprite)) return;
8535a3
	heliArrayInsert(&group->sprites, -1, sprite, NULL);
44355f
	heliArrayInsert(&group->spritesSorted, -1, sprite, NULL);
502515
	heliArrayInsert(heliSpriteGetGroups(sprite), -1, group, NULL);
8535a3
}
8535a3
8535a3
void groupRemove(Group group, Sprite sprite) {
8535a3
	for(int i = group->sprites.count-1; i >= 0; --i)
8535a3
		if (group->sprites.items[i].value == sprite)
8535a3
			heliArrayRemove(&group->sprites, i);
44355f
	for(int i = group->spritesSorted.count-1; i >= 0; --i)
44355f
		if (group->spritesSorted.items[i].value == sprite)
44355f
			heliArrayRemove(&group->spritesSorted, i);
8535a3
	HeliArray *groups = heliSpriteGetGroups(sprite);
8535a3
	for(int i = groups->count-1; i >= 0; --i)
8535a3
		if (groups->items[i].value == group)
8535a3
			heliArrayRemove(groups, i);
8535a3
}
8535a3
8535a3
void groupClearEx(Group group, int destroySprites) {
8535a3
	while(groupGetCount(group) > 0) {
8535a3
		Sprite s = groupGet(group, 0);
8535a3
		groupRemove(group, s);
8535a3
		if (destroySprites) spriteDestroy(s);
8535a3
	}
8535a3
}
8535a3
8535a3
void groupClear(Group group)
8535a3
	{ groupClearEx(group, FALSE); }
8535a3
void groupDestroyEach(Group group)
8535a3
	{ groupClearEx(group, TRUE); }
8535a3
8535a3
int groupContains(Group group, Sprite sprite) {
8535a3
	for(int i = group->sprites.count-1; i >= 0; --i)
8535a3
		if (group->sprites.items[i].value == sprite)
8535a3
			return TRUE;
8535a3
	return FALSE;
8535a3
}
8535a3
8535a3
int groupGetCount(Group group)
8535a3
	{ return group->sprites.count; }
8535a3
Sprite groupGet(Group group, int i)
07b70f
	{ return (Sprite)heliArrayGetValue(&group->sprites, i); }
8535a3
44355f
44355f
Sprite groupSpriteByPoint(Group group, double x, double y, int onlyVisible) {
44355f
	heliSpriteSort(&group->spritesSorted);
44355f
	for(int i = group->spritesSorted.count - 1; i >= 0; --i) {
44355f
		Sprite s = (Sprite)(group->spritesSorted.items[i].value);
44355f
		if ((!onlyVisible || spriteGetVisible(s)) && spriteIsPointInside(s, x, y)) return s;
44355f
	}
44355f
	return NULL;
44355f
}
44355f
f80a0a
6eadb0
void groupDraw(Group group) {
6eadb0
	heliSpriteSort(&group->spritesSorted);
6eadb0
	for(int i = 0; i < group->spritesSorted.count; ++i) {
6eadb0
		Sprite s = (Sprite)(group->spritesSorted.items[i].value);
6eadb0
		if (spriteGetVisible(s)) heliSpriteDraw(s);
6eadb0
	}
6eadb0
	for(int i = 0; i < group->spritesSorted.count; ++i) {
6eadb0
		Sprite s = (Sprite)(group->spritesSorted.items[i].value);
6eadb0
		if (spriteGetDebug(s)) heliSpriteDrawDebug(s);
6eadb0
	}
6eadb0
}
6eadb0
6eadb0
f80a0a
int groupOverlap(Group group, Sprite sprite) {
44355f
	for(int i = 0; i < groupGetCount(group); ++i)
f80a0a
		if (spriteOverlap(groupGet(group, i), sprite))
44355f
			return TRUE;
44355f
	return FALSE;
44355f
}
44355f
f80a0a
int groupCollide(Group group, Sprite sprite) {
07b70f
	int result = FALSE;
f80a0a
	for(int j = 0; j < 10; ++j) {
f80a0a
		int actualCollision = FALSE;
f80a0a
		Sprite bestSprite = NULL;
f80a0a
		HeliCollisionInfo bestInfo = {};
f80a0a
		for(int i = 0; i < groupGetCount(group); ++i) {
f80a0a
			Sprite s = groupGet(group, i);
f80a0a
			HeliCollisionInfo info = {};
f80a0a
			if (heliSpriteCollisionCheck(s, sprite, &info)) {
f80a0a
				if (info.actualCollision) actualCollision = TRUE;
f80a0a
				if (!bestSprite || bestInfo.distance <= info.distance) {
f80a0a
					bestSprite = s;
f80a0a
					memcpy(&bestInfo, &info, sizeof(bestInfo));
f80a0a
				}
f80a0a
			}
f80a0a
		}
f80a0a
		if (!bestSprite) break;
f80a0a
		heliSpriteCollisionApply(bestSprite, sprite, &bestInfo);
f80a0a
		if (!actualCollision) break;
f80a0a
		result = TRUE;
f80a0a
	}
07b70f
	return result;
8535a3
}
8535a3
f80a0a
int groupOverlapGroup(Group a, Group b) {
44355f
	for(int i = 0; i < groupGetCount(b); ++i)
f80a0a
		if (groupOverlap(a, groupGet(b, i)))
44355f
			return TRUE;
44355f
	return FALSE;
44355f
}
44355f
f80a0a
int groupCollideGroup(Group a, Group b) {
07b70f
	int result = FALSE;
8535a3
	for(int i = 0; i < groupGetCount(b); ++i)
f80a0a
		if (groupCollide(a, groupGet(b, i)))
07b70f
			result = TRUE;
07b70f
	return result;
8535a3
}
8535a3
f80a0a
int groupOverlapBetween(Group group) {
44355f
	for(int i = 0; i < groupGetCount(group); ++i)
44355f
		for(int j = i+1; j < groupGetCount(group); ++j)
f80a0a
			if (spriteOverlap(groupGet(group, i), groupGet(group, j)))
44355f
				return TRUE;
44355f
	return FALSE;
44355f
}
44355f
f80a0a
int groupCollideBetween(Group group) {
f8c1ea
	int result = FALSE;
f8c1ea
	for(int i = 0; i < groupGetCount(group); ++i)
f8c1ea
		for(int j = i+1; j < groupGetCount(group); ++j)
f80a0a
			if (spriteCollide(groupGet(group, i), groupGet(group, j)))
f8c1ea
				result = TRUE;
f8c1ea
	return result;
f8c1ea
}
f8c1ea
f80a0a
void groupResetTouch(Group group) {
f80a0a
	for(int i = 0; i < groupGetCount(group); ++i)
f80a0a
		spriteResetTouch(groupGet(group, i));
f80a0a
}
f80a0a
f8c1ea
8535a3
double groupGetMinDepth(Group group) {
8535a3
	if (groupGetCount(group) <= 0) return 0;
8535a3
	double md = spriteGetDepth(groupGet(group, 0));
8535a3
	for(int i = 1; i < groupGetCount(group); ++i) {
8535a3
		double d = spriteGetDepth(groupGet(group, i));
8535a3
		if (d < md) md = d;
8535a3
	}
8535a3
	return md;
8535a3
}
8535a3
8535a3
double groupGetMaxDepth(Group group) {
8535a3
	if (groupGetCount(group) <= 0) return 0;
8535a3
	double md = spriteGetDepth(groupGet(group, 0));
8535a3
	for(int i = 1; i < groupGetCount(group); ++i) {
8535a3
		double d = spriteGetDepth(groupGet(group, i));
8535a3
		if (d > md) md = d;
8535a3
	}
8535a3
	return md;
8535a3
}
8535a3
8535a3
07b70f
static void foreachInt(Group group, int value, HeliSpriteEashInt func)
8535a3
	{ for(int i = 0; i < groupGetCount(group); ++i) func(groupGet(group, i), value); }
d4e89f
static void foreachUInt(Group group, unsigned int value, HeliSpriteEashUInt func)
8535a3
	{ for(int i = 0; i < groupGetCount(group); ++i) func(groupGet(group, i), value); }
d4e89f
static void foreachDouble(Group group, double value, HeliSpriteEashDouble func)
8535a3
	{ for(int i = 0; i < groupGetCount(group); ++i) func(groupGet(group, i), value); }
8535a3
8535a3
8535a3
void groupDestroyTimerEach(Group group, double lifetime)
502515
	{ for(int i = groupGetCount(group) - 1; i >= 0; --i) spriteDestroyTimer(groupGet(group, i), lifetime); }
8535a3
8535a3
void groupSetVisibleEach(Group group, int visible)
8535a3
	{ foreachInt(group, visible, &spriteSetVisible); }
6eadb0
void groupSetFrozenEach(Group group, int frozen)
6eadb0
	{ foreachInt(group, frozen, &spriteSetFrozen); }
6eadb0
void groupSetDebugEach(Group group, int debug)
6eadb0
	{ foreachInt(group, debug, &spriteSetDebug); }
8535a3
void groupSetWidthEach(Group group, double width)
8535a3
	{ foreachDouble(group, width, &spriteSetWidth); }
8535a3
void groupSetHeightEach(Group group, double height)
8535a3
	{ foreachDouble(group, height, &spriteSetHeight); }
8535a3
void groupSetDepthEach(Group group, double depth)
8535a3
	{ foreachDouble(group, depth, &spriteSetDepth); }
f80a0a
void groupSetXEach(Group group, double x)
f80a0a
	{ foreachDouble(group, x, &spriteSetX); }
f80a0a
void groupSetYEach(Group group, double y)
f80a0a
	{ foreachDouble(group, y, &spriteSetY); }
8535a3
void groupSetVelocityXEach(Group group, double x)
8535a3
	{ foreachDouble(group, x, &spriteSetVelocityX); }
8535a3
void groupSetVelocityYEach(Group group, double y)
8535a3
	{ foreachDouble(group, y, &spriteSetVelocityY); }
f80a0a
void groupSetAccelerationXEach(Group group, double x)
f80a0a
	{ foreachDouble(group, x, &spriteSetAccelerationX); }
f80a0a
void groupSetAccelerationYEach(Group group, double y)
f80a0a
	{ foreachDouble(group, y, &spriteSetAccelerationY); }
8535a3
void groupSetRotateToDirectionEach(Group group, int rotateToDirection)
8535a3
	{ foreachInt(group, rotateToDirection, &spriteSetRotateToDirection); }
8535a3
void groupSetRotationEach(Group group, double rotation)
8535a3
	{ foreachDouble(group, rotation, &spriteSetRotation); }
8535a3
void groupSetRotationSpeedEach(Group group, double rotationSpeed)
8535a3
	{ foreachDouble(group, rotationSpeed, &spriteSetRotationSpeed); }
8535a3
void groupSetScaleEach(Group group, double scale)
8535a3
	{ foreachDouble(group, scale, &spriteSetScale); }
8535a3
void groupSetMirrorXEach(Group group, int mirrorX)
8535a3
	{ foreachInt(group, mirrorX, &spriteSetMirrorX); }
8535a3
void groupSetMirrorYEach(Group group, int mirrorY)
8535a3
	{ foreachInt(group, mirrorY, &spriteSetMirrorY); }
d4e89f
void groupSetShapeColorEach(Group group, unsigned int colorCode)
d4e89f
	{ foreachUInt(group, colorCode, &spriteSetShapeColor); }
d4e89f
void groupSetTintColorEach(Group group, unsigned int colorCode)
d4e89f
	{ foreachUInt(group, colorCode, &spriteSetTintColor); }
44355f
void groupSetUserTagEach(Group group, int tag)
44355f
	{ foreachInt(group, tag, &spriteSetUserTag); }
44355f
a359d6
void groupSetBouncinessEach(Group group, double bounciness)
44355f
	{ foreachDouble(group, bounciness, &spriteSetBounciness); }
a359d6
void groupSetBouncinessThresholdEach(Group group, double bouncinessThreshold)
44355f
	{ foreachDouble(group, bouncinessThreshold, &spriteSetBouncinessThreshold); }
a359d6
void groupSetFrictionEach(Group group, double friction)
f80a0a
	{ foreachDouble(group, friction, &spriteSetFriction); }
a359d6
void groupSetAirFrictionEach(Group group, double friction)
f80a0a
	{ foreachDouble(group, friction, &spriteSetAirFriction); }
a359d6
void groupSetMassLevelEach(Group group, int massLevel)
f80a0a
	{ foreachInt(group, massLevel, &spriteSetMassLevel); }
a359d6
void groupSetColliderSensitiveDistanceEach(Group group, double distance)
f80a0a
	{ foreachDouble(group, distance, &spriteSetColliderSensitiveDistance); }
44355f
8535a3
dba3fc
void groupSetAnimationEach(Group group, Animation animation) {
dba3fc
	for(int i = groupGetCount(group) - 1; i >= 0 ; --i)
dba3fc
		spriteSetAnimation(groupGet(group, i), animation);
dba3fc
}
dba3fc
8935bc
void groupSetNoAnimationEach(Group group) {
dba3fc
	for(int i = groupGetCount(group) - 1; i >= 0 ; --i)
8935bc
		spriteSetNoAnimation(groupGet(group, i));
8935bc
}
8935bc
8535a3
void groupPointToEach(Group group, double x, double y) {
07b70f
	for(int i = 0; i < groupGetCount(group); ++i)
8535a3
		spritePointTo(groupGet(group, i), x, y);
8535a3
}
8535a3
8535a3
void groupSetSpeedAndDirectionEach(Group group, double speed, double angle) {
07b70f
	for(int i = 0; i < groupGetCount(group); ++i)
8535a3
		spriteSetSpeedAndDirection(groupGet(group, i), speed, angle);
8535a3
}
8535a3
f80a0a
void groupSetXYEach(Group group, double x, double y) {
f80a0a
	for(int i = 0; i < groupGetCount(group); ++i)
f80a0a
		spriteSetXY(groupGet(group, i), x, y);
f80a0a
}
8535a3
void groupSetVelocityEach(Group group, double x, double y) {
07b70f
	for(int i = 0; i < groupGetCount(group); ++i)
8535a3
		spriteSetVelocityXY(groupGet(group, i), x, y);
8535a3
}
f80a0a
void groupSetAccelerationEach(Group group, double x, double y) {
f80a0a
	for(int i = 0; i < groupGetCount(group); ++i)
f80a0a
		spriteSetAccelerationXY(groupGet(group, i), x, y);
f80a0a
}
8535a3
44355f
44355f
void groupSetUserTextEach(Group group, const char *text) {
44355f
	for(int i = groupGetCount(group) - 1; i >= 0 ; --i)
44355f
		spriteSetUserText(groupGet(group, i), text);
44355f
}
44355f
44355f
void groupSetUserDataEach(Group group, void *data) {
44355f
	for(int i = groupGetCount(group) - 1; i >= 0 ; --i)
44355f
		spriteSetUserData(groupGet(group, i), data);
44355f
}
44355f
44355f
void groupSetDestroyEach(Group group, SpriteCallback destroy) {
44355f
	for(int i = groupGetCount(group) - 1; i >= 0 ; --i)
44355f
		spriteSetDestroy(groupGet(group, i), destroy);
44355f
}
44355f
44355f
f8c1ea
void groupSetColliderEach(Group group, Collider type, double xOffset, double yOffset, double rotationOffset)
f8c1ea
	{ groupSetColliderEachEx(group, type, xOffset, yOffset, rotationOffset, -1, -1, -1); }
f8c1ea
void groupSetColliderCircleEach(Group group, double xOffset, double yOffset, double radius)
f8c1ea
	{ groupSetColliderEachEx(group, COLLIDER_CIRCLE, xOffset, yOffset, 0, 0, 0, radius); }
f8c1ea
void groupSetColliderRectangleEach(
f8c1ea
	Group group, double xOffset, double yOffset, double rotationOffset,
f8c1ea
	double width, double height, double cornersRadius )
f8c1ea
{
f8c1ea
	groupSetColliderEachEx(
f8c1ea
		group, COLLIDER_RECTANGLE,
f8c1ea
		xOffset, yOffset, rotationOffset,
f8c1ea
		width, height, cornersRadius);
f8c1ea
}
f8c1ea
void groupSetColliderEachEx(
f8c1ea
	Group group, Collider type,
f8c1ea
	double xOffset, double yOffset, double rotationOffset,
f8c1ea
	double width, double height, double radius)
8535a3
{
07b70f
	for(int i = 0; i < groupGetCount(group); ++i)
f8c1ea
		spriteSetColliderEx(
f8c1ea
			groupGet(group, i), type,
f8c1ea
			xOffset, yOffset, rotationOffset,
f8c1ea
			width, height, radius );
8535a3
}