Blame src/sprite.c

Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
#include "private.h"
Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
#include "sprite.h"
Ivan Mahonin 3f9996
#include "world.h"
Ivan Mahonin 8535a3
#include "group.h"
Ivan Mahonin 3954ba
#include "drawing.h"
Ivan Mahonin dba3fc
#include "animation.h"
Ivan Mahonin 3f9996
Ivan Mahonin a20939
Ivan Mahonin 3f9996
struct _Sprite {
Ivan Mahonin 3f9996
	double x;
Ivan Mahonin 3f9996
	double y;
Ivan Mahonin 3f9996
	double rotation;
Ivan Mahonin 3f9996
	double width;
Ivan Mahonin 3f9996
	double height;
Ivan Mahonin 3f9996
	double scale;
Ivan Mahonin 3f9996
	
Ivan Mahonin 3f9996
	double vx;
Ivan Mahonin 3f9996
	double vy;
Ivan Mahonin f80a0a
	double ax;
Ivan Mahonin f80a0a
	double ay;
Ivan Mahonin 3f9996
	double rotationSpeed;
Ivan Mahonin 3f9996
	
Ivan Mahonin 3f9996
	HeliCollider collider;
Ivan Mahonin f80a0a
	double colliderSensitiveDistance;
Ivan Mahonin f80a0a
	int massLevel;
Ivan Mahonin f80a0a
	
Ivan Mahonin f80a0a
	double wx;
Ivan Mahonin f80a0a
	double wy;
Ivan Mahonin f80a0a
	double friction;
Ivan Mahonin f80a0a
	double airFriction;
Ivan Mahonin f80a0a
	double touchFriction;
Ivan Mahonin 3f9996
	
Ivan Mahonin 3f9996
	int rotateToDirection;
Ivan Mahonin 3f9996
	int mirrorX;
Ivan Mahonin 3f9996
	int mirrorY;
Ivan Mahonin 3f9996
	double depth;
Ivan Mahonin 3f9996
	double lifeTime;
Ivan Mahonin 8535a3
	int visible;
Ivan Mahonin 6eadb0
	int frozen;
Ivan Mahonin 3f9996
	int debug;
Ivan Mahonin 3f9996
	
Ivan Mahonin 8535a3
	double shapeColor[4];
Ivan Mahonin 8535a3
	double tintColor[4];
Ivan Mahonin 3f9996
	
Ivan Mahonin 8535a3
	HeliArray groups;
Ivan Mahonin 8535a3
	
Ivan Mahonin dba3fc
	Animation animation;
Ivan Mahonin 44355f
	
Ivan Mahonin 44355f
	int userTag;
Ivan Mahonin 44355f
	char *userText;
Ivan Mahonin 44355f
	void *userData;
Ivan Mahonin 44355f
	SpriteCallback destroyCallback;
Ivan Mahonin 3f9996
};
Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
static HeliArray sprites;
Ivan Mahonin 8535a3
static HeliArray spritesSorted;
Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
static void prepareCollider(Sprite sprite, HeliCollider *collider) {
Ivan Mahonin 44355f
	memcpy(collider, &sprite->collider, sizeof(*collider));
Ivan Mahonin 44355f
	collider->x += sprite->x;
Ivan Mahonin 44355f
	collider->y += sprite->y;
Ivan Mahonin 44355f
	collider->rotation += sprite->rotation;
Ivan Mahonin 1c7488
	
Ivan Mahonin f8c1ea
	// auto-size
Ivan Mahonin f8c1ea
	if (collider->type == COLLIDER_RECTANGLE) {
Ivan Mahonin f8c1ea
		if (collider->width < -HELI_PRECISION) collider->width = sprite->width;
Ivan Mahonin f8c1ea
		if (collider->height < -HELI_PRECISION) collider->height = sprite->height;
Ivan Mahonin f8c1ea
		if (collider->radius < -HELI_PRECISION) collider->radius = 0;
Ivan Mahonin f8c1ea
	} else
Ivan Mahonin f8c1ea
	if (collider->type == COLLIDER_CIRCLE) {
Ivan Mahonin f8c1ea
		collider->width = 0;
Ivan Mahonin f8c1ea
		collider->height = 0;
Ivan Mahonin f8c1ea
		if (collider->radius < -HELI_PRECISION) collider->radius = 0.5*sprite->width;
Ivan Mahonin f8c1ea
	}
Ivan Mahonin 1c7488
	
Ivan Mahonin f8c1ea
	// scale
Ivan Mahonin 1c7488
	collider->width *= sprite->scale;
Ivan Mahonin 1c7488
	collider->height *= sprite->scale;
Ivan Mahonin 1c7488
	collider->radius *= sprite->scale;
Ivan Mahonin f8c1ea
	
Ivan Mahonin f8c1ea
	// fix small values
Ivan Mahonin f8c1ea
	if (collider->width  < HELI_PRECISION) collider->width = HELI_PRECISION;
Ivan Mahonin f8c1ea
	if (collider->height < HELI_PRECISION) collider->height = HELI_PRECISION;
Ivan Mahonin f8c1ea
	if (collider->radius < HELI_PRECISION) collider->radius = HELI_PRECISION;
Ivan Mahonin f8c1ea
	
Ivan Mahonin f8c1ea
	// fix round corners
Ivan Mahonin f8c1ea
	if (collider->type == COLLIDER_RECTANGLE) {
Ivan Mahonin f8c1ea
		double rmax = 0.5*( collider->width < collider->height
Ivan Mahonin f8c1ea
						  ? collider->width : collider->height );
Ivan Mahonin f8c1ea
		if (collider->radius >= rmax - HELI_PRECISION)
Ivan Mahonin f8c1ea
			collider->radius = rmax;
Ivan Mahonin f8c1ea
		collider->width  -= 2*collider->radius;
Ivan Mahonin f8c1ea
		collider->height -= 2*collider->radius;
Ivan Mahonin f8c1ea
	}
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
Ivan Mahonin f80a0a
static void autoRotate(Sprite sprite) {
Ivan Mahonin f80a0a
	if (sprite->rotateToDirection)
Ivan Mahonin f80a0a
		sprite->rotation = spriteGetDirection(sprite);
Ivan Mahonin f80a0a
}
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
Ivan Mahonin 8535a3
Sprite createSpriteEx(double x, double y, double width, double height) {
Ivan Mahonin 8eb855
	if (!heliInitialized) return NULL;
Ivan Mahonin 8eb855
Ivan Mahonin 8535a3
	Sprite s = calloc(1, sizeof(*s));
Ivan Mahonin 8535a3
	s->x = x;
Ivan Mahonin 8535a3
	s->y = y;
Ivan Mahonin 8535a3
	s->width = width;
Ivan Mahonin 8535a3
	s->height = height;
Ivan Mahonin 8535a3
	
Ivan Mahonin 8535a3
	s->scale = 1;
Ivan Mahonin 8535a3
	s->collider.type = COLLIDER_RECTANGLE;
Ivan Mahonin f8c1ea
	s->collider.width = s->collider.height = -1;
Ivan Mahonin f80a0a
	s->colliderSensitiveDistance = 0.001;
Ivan Mahonin 44355f
	s->collider.bounciness = 1;
Ivan Mahonin f80a0a
	s->friction = 1;
Ivan Mahonin 8535a3
	
Ivan Mahonin 8535a3
	s->mirrorX = 1;
Ivan Mahonin 8535a3
	s->mirrorY = 1;
Ivan Mahonin 8535a3
	s->lifeTime = -1;
Ivan Mahonin 8535a3
	s->visible = TRUE;
Ivan Mahonin 8535a3
	
Ivan Mahonin 8535a3
	s->shapeColor[0] = s->shapeColor[1] = s->shapeColor[2] = 0.5;
Ivan Mahonin 8535a3
	s->shapeColor[3] = 1;
Ivan Mahonin 8535a3
	s->tintColor[0] = s->tintColor[1] = s->tintColor[2] = s->tintColor[3] = 1;
Ivan Mahonin 8535a3
	
Ivan Mahonin 44355f
	s->userText = heliStringCopy("");
Ivan Mahonin 44355f
	
Ivan Mahonin 8535a3
	heliArrayInsert(&sprites, -1, s, NULL);
Ivan Mahonin 8535a3
	heliArrayInsert(&spritesSorted, -1, s, NULL);
Ivan Mahonin 07b70f
	
Ivan Mahonin 8eb855
	heliObjectRegister(s, (HeliFreeCallback)&spriteDestroy);
Ivan Mahonin 07b70f
	return s;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
Sprite createSprite(double x, double y)
Ivan Mahonin 8535a3
	{ return createSpriteEx(x, y, 100, 100); }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
void spriteDestroy(Sprite sprite) {
Ivan Mahonin 44355f
	if (sprite->destroyCallback) sprite->destroyCallback(sprite);
Ivan Mahonin 1c7488
	spriteSetNoAnimation(sprite);
Ivan Mahonin 8535a3
	while(sprite->groups.count > 0)
Ivan Mahonin 8535a3
		groupRemove((Group)sprite->groups.items[0].value, sprite);
Ivan Mahonin 502515
	for(int i = sprites.count - 1; i >= 0; --i)
Ivan Mahonin 8535a3
		if (sprites.items[i].value == sprite)
Ivan Mahonin 502515
			heliArrayRemove(&sprites, i);
Ivan Mahonin 502515
	for(int i = spritesSorted.count - 1; i >= 0; --i)
Ivan Mahonin 8535a3
		if (spritesSorted.items[i].value == sprite)
Ivan Mahonin 502515
			heliArrayRemove(&spritesSorted, i);
Ivan Mahonin 502515
	heliArrayDestroy(&sprite->groups);
Ivan Mahonin 87fe10
	heliObjectUnregister(sprite);
Ivan Mahonin 44355f
	free(sprite->userText);
Ivan Mahonin 8535a3
	free(sprite);
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
void spriteDestroyTimer(Sprite sprite, double lifeTime) {
Ivan Mahonin 8535a3
	if (lifeTime <= 0) { spriteDestroy(sprite); return; }
Ivan Mahonin 8535a3
	sprite->lifeTime = lifeTime;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 53e18e
Sprite spriteClone(Sprite sprite) {
Ivan Mahonin 53e18e
	if (!heliInitialized) return NULL;
Ivan Mahonin 53e18e
	Sprite s = calloc(1, sizeof(*s));
Ivan Mahonin 53e18e
	memcpy(s, sprite, sizeof(*s));
Ivan Mahonin 53e18e
	s->lifeTime = -1;
Ivan Mahonin 53e18e
	memset(&s->groups, 0, sizeof(s->groups));
Ivan Mahonin 44355f
	s->userText = heliStringCopy(sprite->userText);
Ivan Mahonin 53e18e
	return s;
Ivan Mahonin 53e18e
}
Ivan Mahonin 53e18e
Ivan Mahonin 53e18e
Ivan Mahonin 8535a3
double spriteGetX(Sprite sprite) { return sprite->x; }
Ivan Mahonin 8535a3
void spriteSetX(Sprite sprite, double x) { sprite->x = x; }
Ivan Mahonin 8535a3
double spriteGetY(Sprite sprite) { return sprite->y; }
Ivan Mahonin 8535a3
void spriteSetY(Sprite sprite, double y) { sprite->y = y; }
Ivan Mahonin f80a0a
void spriteSetXY(Sprite sprite, double x, double y)
Ivan Mahonin f80a0a
	{ spriteSetX(sprite, x); spriteSetY(sprite, y); }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetVelocityX(Sprite sprite) { return sprite->vx; }
Ivan Mahonin 8535a3
void spriteSetVelocityX(Sprite sprite, double x)
Ivan Mahonin 8535a3
	{ spriteSetVelocityXY(sprite, x, sprite->vy); }
Ivan Mahonin 8535a3
double spriteGetVelocityY(Sprite sprite) { return sprite->vy; }
Ivan Mahonin 8535a3
void spriteSetVelocityY(Sprite sprite, double y)
Ivan Mahonin 8535a3
	{ spriteSetVelocityXY(sprite, sprite->vx, y); }
Ivan Mahonin f80a0a
void spriteSetVelocityXY(Sprite sprite, double x, double y) {
Ivan Mahonin f80a0a
	spriteResetTouch(sprite);
Ivan Mahonin f80a0a
	sprite->vx = x; sprite->vy = y;
Ivan Mahonin f80a0a
	autoRotate(sprite);
Ivan Mahonin f80a0a
}
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
double spriteGetAccelerationX(Sprite sprite) { return sprite->ax; }
Ivan Mahonin f80a0a
void spriteSetAccelerationX(Sprite sprite, double x) { sprite->ax = x; }
Ivan Mahonin f80a0a
double spriteGetAccelerationY(Sprite sprite) { return sprite->ay; }
Ivan Mahonin f80a0a
void spriteSetAccelerationY(Sprite sprite, double y) { sprite->ay = y; }
Ivan Mahonin f80a0a
void spriteSetAccelerationXY(Sprite sprite, double x, double y)
Ivan Mahonin f80a0a
	{ spriteSetAccelerationX(sprite, x); spriteSetAccelerationY(sprite, y); }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetScale(Sprite sprite) { return sprite->scale; }
Ivan Mahonin 8535a3
void spriteSetScale(Sprite sprite, double scale) { sprite->scale = scale; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetWidth(Sprite sprite) { return sprite->width; }
Ivan Mahonin 8535a3
void spriteSetWidth(Sprite sprite, double width)
Ivan Mahonin 8535a3
	{ sprite->width = width > 0 ? width : 0; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetHeight(Sprite sprite) { return sprite->height; }
Ivan Mahonin 8535a3
void spriteSetHeight(Sprite sprite, double height)
Ivan Mahonin 8535a3
	{ sprite->height = height > 0 ? height : 0; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
int spriteGetRotateToDirection(Sprite sprite) { return sprite->rotateToDirection; }
Ivan Mahonin 8535a3
void spriteSetRotateToDirection(Sprite sprite, int rotateToDirection) {
Ivan Mahonin 8535a3
	if (rotateToDirection) {
Ivan Mahonin 8535a3
		sprite->rotateToDirection = TRUE;
Ivan Mahonin 8535a3
		sprite->rotation = spriteGetDirection(sprite);
Ivan Mahonin 8535a3
	} else {
Ivan Mahonin 8535a3
		sprite->rotateToDirection = FALSE;
Ivan Mahonin 8535a3
	}
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetRotation(Sprite sprite) { return sprite->rotation; }
Ivan Mahonin 8535a3
void spriteSetRotation(Sprite sprite, double rotation)
Ivan Mahonin 8535a3
	{ if (!sprite->rotateToDirection) sprite->rotation = rotation; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetRotationSpeed(Sprite sprite) { return sprite->rotationSpeed; }
Ivan Mahonin 8535a3
void spriteSetRotationSpeed(Sprite sprite, double rotationSpeed)
Ivan Mahonin 8535a3
	{ sprite->rotationSpeed = rotationSpeed; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
int spriteGetMirrorX(Sprite sprite) { return sprite->mirrorX; }
Ivan Mahonin 8535a3
void spriteSetMirrorX(Sprite sprite, int mirrorX)
Ivan Mahonin 8535a3
	{ sprite->mirrorX = mirrorX < 0 ? -1 : 1; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
int spriteGetMirrorY(Sprite sprite) { return sprite->mirrorY; }
Ivan Mahonin 07b70f
void spriteSetMirrorY(Sprite sprite, int mirrorY)
Ivan Mahonin 8535a3
	{ sprite->mirrorY = mirrorY < 0 ? -1 : 1; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetDepth(Sprite sprite) { return sprite->depth; }
Ivan Mahonin 8535a3
void spriteSetDepth(Sprite sprite, double depth)
Ivan Mahonin 8535a3
	{ sprite->depth = depth; }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
int spriteGetVisible(Sprite sprite) { return sprite->visible; }
Ivan Mahonin 8535a3
void spriteSetVisible(Sprite sprite, int visible)
Ivan Mahonin 8535a3
	{ sprite->visible = visible != FALSE; }
Ivan Mahonin 8535a3
Ivan Mahonin 6eadb0
int spriteGetFrozen(Sprite sprite) { return sprite->frozen; }
Ivan Mahonin 6eadb0
void spriteSetFrozen(Sprite sprite, int frozen)
Ivan Mahonin 6eadb0
	{ sprite->frozen = frozen != FALSE; }
Ivan Mahonin 6eadb0
Ivan Mahonin 8535a3
int spriteGetDebug(Sprite sprite) { return sprite->debug; }
Ivan Mahonin 8535a3
void spriteSetDebug(Sprite sprite, int debug)
Ivan Mahonin 8535a3
	{ sprite->debug = debug != FALSE; }
Ivan Mahonin 8535a3
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
void heliSpriteCollisionApply(Sprite a, Sprite b, HeliCollisionInfo *info) {
Ivan Mahonin f80a0a
	if ( a->massLevel > b->massLevel) {
Ivan Mahonin f80a0a
		b->x -= info->dx;
Ivan Mahonin f80a0a
		b->y -= info->dy;
Ivan Mahonin f80a0a
		b->vx = a->vx - info->vx;
Ivan Mahonin f80a0a
		b->vy = a->vy - info->vy;
Ivan Mahonin f80a0a
		autoRotate(b);
Ivan Mahonin f80a0a
		if (b->wx*b->wx + b->wy*b->wy < info->ax*info->ax + info->ay*info->ay) {
Ivan Mahonin f80a0a
			b->wx = info->ax;
Ivan Mahonin f80a0a
			b->wy = info->ay;
Ivan Mahonin f80a0a
			b->touchFriction = a->friction;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
	} else
Ivan Mahonin f80a0a
	if ( b->massLevel > a->massLevel ) {
Ivan Mahonin f80a0a
		a->x += info->dx;
Ivan Mahonin f80a0a
		a->y += info->dy;
Ivan Mahonin f80a0a
		a->vx = b->vx + info->vx;
Ivan Mahonin f80a0a
		a->vy = b->vy + info->vy;
Ivan Mahonin f80a0a
		autoRotate(a);
Ivan Mahonin f80a0a
		if (a->wx*a->wx + a->wy*a->wy < info->ax*info->ax + info->ay*info->ay) {
Ivan Mahonin f80a0a
			a->wx = -info->ax;
Ivan Mahonin f80a0a
			a->wy = -info->ay;
Ivan Mahonin f80a0a
			a->touchFriction = b->friction;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
	} else {
Ivan Mahonin f80a0a
		double vxAvg = 0.5*(a->vx + b->vx);
Ivan Mahonin f80a0a
		double vyAvg = 0.5*(a->vy + b->vy);
Ivan Mahonin f80a0a
		double wx = info->ax;
Ivan Mahonin f80a0a
		double wy = info->ay;
Ivan Mahonin f80a0a
		double w = wx*wx + wy*wy;
Ivan Mahonin f80a0a
		
Ivan Mahonin f80a0a
		a->x += 0.5*info->dx;
Ivan Mahonin f80a0a
		a->y += 0.5*info->dy;
Ivan Mahonin f80a0a
		a->vx = vxAvg + 0.5*info->vx;
Ivan Mahonin f80a0a
		a->vy = vyAvg + 0.5*info->vy;
Ivan Mahonin f80a0a
		autoRotate(a);
Ivan Mahonin f80a0a
		if (a->wx*a->wx + a->wy*a->wy < w) {
Ivan Mahonin f80a0a
			a->wx = -wx;
Ivan Mahonin f80a0a
			a->wy = -wy;
Ivan Mahonin f80a0a
			a->touchFriction = b->friction;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
		
Ivan Mahonin f80a0a
		b->x -= 0.5*info->dx;
Ivan Mahonin f80a0a
		b->y -= 0.5*info->dy;
Ivan Mahonin f80a0a
		b->vx = vxAvg - 0.5*info->vx;
Ivan Mahonin f80a0a
		b->vy = vyAvg - 0.5*info->vy;
Ivan Mahonin f80a0a
		autoRotate(b);
Ivan Mahonin f80a0a
		if (b->wx*b->wx + b->wy*b->wy < w) {
Ivan Mahonin f80a0a
			b->wx = wx;
Ivan Mahonin f80a0a
			b->wy = wy;
Ivan Mahonin f80a0a
			b->touchFriction = a->friction;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
	}
Ivan Mahonin f80a0a
}
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
int heliSpriteCollisionCheck(Sprite a, Sprite b, HeliCollisionInfo *info) {
Ivan Mahonin f8c1ea
	if (a == b) return FALSE;
Ivan Mahonin 44355f
	HeliCollider ca = {}, cb = {};
Ivan Mahonin 1c7488
	prepareCollider(a, &ca);
Ivan Mahonin 1c7488
	prepareCollider(b, &cb);
Ivan Mahonin f80a0a
	memset(info, 0, sizeof(*info));
Ivan Mahonin f80a0a
	info->vx = a->vx - b->vx;
Ivan Mahonin f80a0a
	info->vy = a->vy - b->vy;
Ivan Mahonin f80a0a
	info->ax = a->ax - b->ax;
Ivan Mahonin f80a0a
	info->ay = a->ay - b->ay;
Ivan Mahonin f80a0a
	return heliCheckCollision(&ca, &cb, info, a->colliderSensitiveDistance + b->colliderSensitiveDistance);
Ivan Mahonin f80a0a
}
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
int spriteOverlap(Sprite a, Sprite b) {
Ivan Mahonin f80a0a
	HeliCollisionInfo info = {};
Ivan Mahonin f80a0a
	heliSpriteCollisionCheck(a, b, &info);
Ivan Mahonin f80a0a
	return info.actualCollision;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin f80a0a
int spriteCollide(Sprite a, Sprite b) {
Ivan Mahonin f80a0a
	HeliCollisionInfo info = {};
Ivan Mahonin f80a0a
	if (heliSpriteCollisionCheck(a, b, &info)) {
Ivan Mahonin f80a0a
		heliSpriteCollisionApply(a, b, &info);
Ivan Mahonin f80a0a
		return info.actualCollision;
Ivan Mahonin f80a0a
	}
Ivan Mahonin f80a0a
	return FALSE;
Ivan Mahonin f80a0a
}
Ivan Mahonin 44355f
Ivan Mahonin 8535a3
Ivan Mahonin 44355f
double spriteGetBounciness(Sprite sprite)
Ivan Mahonin 44355f
	{ return sprite->collider.bounciness; }
Ivan Mahonin 8535a3
void spriteSetBounciness(Sprite sprite, double bounciness)
Ivan Mahonin 44355f
	{ sprite->collider.bounciness = bounciness > 0 ? bounciness : 0; }
Ivan Mahonin 44355f
double spriteGetBouncinessThreshold(Sprite sprite)
Ivan Mahonin 44355f
	{ return sprite->collider.bouncinessThreshold; }
Ivan Mahonin 44355f
void spriteSetBouncinessThreshold(Sprite sprite, double bouncinessThreshold)
Ivan Mahonin 44355f
	{ sprite->collider.bouncinessThreshold = bouncinessThreshold > 0 ? bouncinessThreshold : 0; }
Ivan Mahonin 44355f
Ivan Mahonin f80a0a
double spriteGetFriction(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->friction; }
Ivan Mahonin f80a0a
void spriteSetFriction(Sprite sprite, double friction)
Ivan Mahonin f80a0a
	{ sprite->friction = friction > 0 ? friction : 0; }
Ivan Mahonin f80a0a
double spriteGetAirFriction(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->airFriction; }
Ivan Mahonin f80a0a
void spriteSetAirFriction(Sprite sprite, double friction)
Ivan Mahonin f80a0a
	{ sprite->airFriction = friction > 0 ? friction : 0; }
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
int spriteGetMassLevel(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->massLevel; }
Ivan Mahonin f80a0a
void spriteSetMassLevel(Sprite sprite, int massLevel)
Ivan Mahonin f80a0a
	{ sprite->massLevel = massLevel; }
Ivan Mahonin f80a0a
Ivan Mahonin f80a0a
double spriteGetTouchWeight(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sqrt(sprite->wx*sprite->wx + sprite->wy*sprite->wy); }
Ivan Mahonin f80a0a
double spriteGetTouchWeightX(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->wx; }
Ivan Mahonin f80a0a
double spriteGetTouchWeightY(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->wy; }
Ivan Mahonin f80a0a
double spriteGetTouchFriction(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->touchFriction; }
Ivan Mahonin f80a0a
void spriteResetTouch(Sprite sprite) {
Ivan Mahonin f80a0a
	sprite->wx = 0;
Ivan Mahonin f80a0a
	sprite->wy = 0;
Ivan Mahonin f80a0a
	sprite->touchFriction = 0;
Ivan Mahonin f80a0a
}
Ivan Mahonin 44355f
Ivan Mahonin f80a0a
double spriteGetColliderSensitiveDistance(Sprite sprite)
Ivan Mahonin f80a0a
	{ return sprite->colliderSensitiveDistance; }
Ivan Mahonin f80a0a
void spriteSetColliderSensitiveDistance(Sprite sprite, double distance)
Ivan Mahonin f80a0a
	{ sprite->colliderSensitiveDistance = distance > 10*HELI_PRECISION ? distance : 10*HELI_PRECISION; }
Ivan Mahonin 8535a3
Ivan Mahonin f8c1ea
void spriteSetCollider(Sprite sprite, Collider type, double xOffset, double yOffset, double rotationOffset)
Ivan Mahonin f8c1ea
	{ spriteSetColliderEx(sprite, type, xOffset, yOffset, rotationOffset, -1, -1, -1); }
Ivan Mahonin f8c1ea
void spriteSetColliderCircle(Sprite sprite, double xOffset, double yOffset, double radius)
Ivan Mahonin f8c1ea
	{ spriteSetColliderEx(sprite, COLLIDER_CIRCLE, xOffset, yOffset, 0, 0, 0, radius); }
Ivan Mahonin f8c1ea
void spriteSetColliderRectangle(
Ivan Mahonin f8c1ea
	Sprite sprite, double xOffset, double yOffset, double rotationOffset,
Ivan Mahonin f8c1ea
	double width, double height, double cornersRadius )
Ivan Mahonin f8c1ea
{
Ivan Mahonin f8c1ea
	spriteSetColliderEx(
Ivan Mahonin f8c1ea
		sprite, COLLIDER_RECTANGLE,
Ivan Mahonin f8c1ea
		xOffset, yOffset, rotationOffset,
Ivan Mahonin f8c1ea
		width, height, cornersRadius);
Ivan Mahonin f8c1ea
}
Ivan Mahonin f8c1ea
Ivan Mahonin f8c1ea
void spriteSetColliderEx(
Ivan Mahonin f8c1ea
	Sprite sprite, Collider type,
Ivan Mahonin f8c1ea
	double xOffset, double yOffset, double rotationOffset,
Ivan Mahonin f8c1ea
	double width, double height, double radius )
Ivan Mahonin 8535a3
{
Ivan Mahonin 8535a3
	sprite->collider.type = type;
Ivan Mahonin 8535a3
	sprite->collider.x = xOffset;
Ivan Mahonin 8535a3
	sprite->collider.y = yOffset;
Ivan Mahonin 8535a3
	sprite->collider.rotation = rotationOffset;
Ivan Mahonin f8c1ea
	if (type == COLLIDER_CIRCLE) {
Ivan Mahonin f8c1ea
		sprite->collider.width = 0;
Ivan Mahonin f8c1ea
		sprite->collider.height = 0;
Ivan Mahonin f8c1ea
		sprite->collider.radius = radius;
Ivan Mahonin f8c1ea
	} else
Ivan Mahonin f8c1ea
	if (type == COLLIDER_RECTANGLE) {
Ivan Mahonin f8c1ea
		sprite->collider.width = width;
Ivan Mahonin f8c1ea
		sprite->collider.height = height;
Ivan Mahonin f8c1ea
		sprite->collider.radius = radius;
Ivan Mahonin f8c1ea
	} else {
Ivan Mahonin f8c1ea
		sprite->collider.width = 0;
Ivan Mahonin f8c1ea
		sprite->collider.height = 0;
Ivan Mahonin f8c1ea
		sprite->collider.radius = 0;
Ivan Mahonin f8c1ea
	}
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 53e18e
int spriteIsPointInside(Sprite sprite, double x, double y) {
Ivan Mahonin 53e18e
	HeliCollider collider;
Ivan Mahonin 53e18e
	prepareCollider(sprite, &collider);
Ivan Mahonin 53e18e
	return heliPointCollision(&collider, x, y);
Ivan Mahonin 53e18e
}
Ivan Mahonin 53e18e
Ivan Mahonin f8dca4
Animation spriteGetAnimation(Sprite sprite)
Ivan Mahonin f8dca4
	{ return sprite->animation; }
Ivan Mahonin f8dca4
Ivan Mahonin dba3fc
void spriteSetAnimation(Sprite sprite, Animation animation)
Ivan Mahonin dba3fc
	{ sprite->animation = animation; }
Ivan Mahonin 8535a3
Ivan Mahonin dba3fc
void spriteSetNoAnimation(Sprite sprite)
Ivan Mahonin dba3fc
	{ spriteSetAnimation(sprite, NULL); }
Ivan Mahonin 3f9996
Ivan Mahonin 83acad
unsigned int spriteGetShapeColor(Sprite sprite) {
Ivan Mahonin 83acad
	return colorByRGBA(
Ivan Mahonin 83acad
		sprite->shapeColor[0],
Ivan Mahonin 83acad
		sprite->shapeColor[1],
Ivan Mahonin 83acad
		sprite->shapeColor[2],
Ivan Mahonin 83acad
		sprite->shapeColor[3] );
Ivan Mahonin 83acad
}
Ivan Mahonin d4e89f
void spriteSetShapeColor(Sprite sprite, unsigned int colorCode)
Ivan Mahonin d4e89f
	{ heliColorToDouble(colorCode, sprite->shapeColor); }
Ivan Mahonin 83acad
Ivan Mahonin 83acad
unsigned int spriteGetTintColor(Sprite sprite) {
Ivan Mahonin 83acad
	return colorByRGBA(
Ivan Mahonin 83acad
		sprite->tintColor[0],
Ivan Mahonin 83acad
		sprite->tintColor[1],
Ivan Mahonin 83acad
		sprite->tintColor[2],
Ivan Mahonin 83acad
		sprite->tintColor[3] );
Ivan Mahonin 83acad
}
Ivan Mahonin d4e89f
void spriteSetTintColor(Sprite sprite, unsigned int colorCode)
Ivan Mahonin d4e89f
	{ heliColorToDouble(colorCode, sprite->tintColor); }
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
void spriteSetSpeedAndDirection(Sprite sprite, double speed, double angle) {
Ivan Mahonin 8535a3
	double a = angle*(PI/180);
Ivan Mahonin 8535a3
	spriteSetVelocityXY(sprite, cos(a)*speed, sin(a)*speed);
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetSpeed(Sprite sprite)
Ivan Mahonin 8535a3
	{ return sqrt(sprite->vx*sprite->vx + sprite->vy*sprite->vy); }
Ivan Mahonin 8535a3
double spriteGetDirection(Sprite sprite) {
Ivan Mahonin 1c7488
	return fabs(sprite->vx) > HELI_PRECISION || fabs(sprite->vy) > HELI_PRECISION
Ivan Mahonin 8535a3
	     ? atan2(sprite->vy, sprite->vx)*(180/PI) : 0;
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
void spritePointTo(Sprite sprite, double x, double y)
Ivan Mahonin 981405
	{ spriteSetRotation( sprite, atan2(y - sprite->y, x - sprite->x)*(180/PI) ); }
Ivan Mahonin 909bc2
void spriteMoveBy(Sprite sprite, double dx, double dy)
Ivan Mahonin 909bc2
	{ spriteSetXY(sprite, spriteGetX(sprite) + dx, spriteGetY(sprite) + dy); }
Ivan Mahonin 909bc2
void spriteMoveToDirection(Sprite sprite, double distance, double angle) {
Ivan Mahonin 909bc2
	double a = angle*PI/180.0;
Ivan Mahonin 909bc2
	spriteMoveBy(sprite, cos(a)*distance, sin(a)*distance);
Ivan Mahonin 909bc2
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
double spriteGetScaledWidth(Sprite sprite)
Ivan Mahonin 8535a3
	{ return sprite->width * sprite->scale; }
Ivan Mahonin 8535a3
double spriteGetScaledHeight(Sprite sprite)
Ivan Mahonin 8535a3
	{ return sprite->height * sprite->scale; }
Ivan Mahonin 8535a3
Ivan Mahonin 3f9996
Ivan Mahonin 44355f
int spriteGetUserTag(Sprite sprite)
Ivan Mahonin 44355f
	{ return sprite->userTag; }
Ivan Mahonin 44355f
void spriteSetUserTag(Sprite sprite, int tag)
Ivan Mahonin 44355f
	{ sprite->userTag = tag; }
Ivan Mahonin 44355f
const char* spriteGetUserText(Sprite sprite)
Ivan Mahonin 44355f
	{ return sprite->userText; }
Ivan Mahonin 44355f
void spriteSetUserText(Sprite sprite, const char *text) {
Ivan Mahonin 44355f
	if (sprite->userText == text) return;
Ivan Mahonin 44355f
	free(sprite->userText);
Ivan Mahonin 44355f
	sprite->userText = heliStringCopy(text);
Ivan Mahonin 44355f
}
Ivan Mahonin 44355f
void* spriteGetUserData(Sprite sprite)
Ivan Mahonin 44355f
	{ return sprite->userData; }
Ivan Mahonin 44355f
void spriteSetUserData(Sprite sprite, void *data)
Ivan Mahonin 44355f
	{ sprite->userData = data; }
Ivan Mahonin 44355f
Ivan Mahonin 44355f
void spriteSetDestroy(Sprite sprite, SpriteCallback destroy)
Ivan Mahonin 44355f
	{ sprite->destroyCallback = destroy; }
Ivan Mahonin 44355f
Ivan Mahonin 3f9996
Ivan Mahonin 3f9996
int worldGetSpriteCount()
Ivan Mahonin 3f9996
	{ return sprites.count; }
Ivan Mahonin 07b70f
Sprite worldGetSprite(int i)
Ivan Mahonin 8535a3
	{ return (Sprite)heliArrayGetValue(&sprites, i); }
Ivan Mahonin 3f9996
Ivan Mahonin 8535a3
Ivan Mahonin 6eadb0
void heliSpriteDrawDebug(Sprite s) {
Ivan Mahonin deef1d
	saveState();
Ivan Mahonin deef1d
	translate(s->x, s->y);
Ivan Mahonin deef1d
	rotate(s->rotation);
Ivan Mahonin 8535a3
	
Ivan Mahonin deef1d
	strokeWidth(0.5);
Ivan Mahonin 8535a3
	
Ivan Mahonin deef1d
	double hw = 0.5 * s->scale * s->width;
Ivan Mahonin deef1d
	double hh = 0.5 * s->scale * s->height;
Ivan Mahonin 3954ba
	
Ivan Mahonin d4e89f
	noFill();
Ivan Mahonin d4e89f
	stroke(colorByRGBA(0, 0, 0, 0.75));
Ivan Mahonin 3954ba
Ivan Mahonin 3954ba
	// frame
Ivan Mahonin deef1d
	rect(-hw, -hh, 2*hw, 2*hh);
Ivan Mahonin 3954ba
	
Ivan Mahonin 3954ba
	// center cross
Ivan Mahonin deef1d
	line(-hw/4, 0, hw/4, 0);
Ivan Mahonin deef1d
	line(0, -hh/4, 0, hh/4);
Ivan Mahonin 3954ba
	
Ivan Mahonin 3954ba
	// depth
Ivan Mahonin 8535a3
	char buf[1024];
Ivan Mahonin 09c823
	snprintf(buf, sizeof(buf)-1, "%lf", s->depth);
Ivan Mahonin 981405
	double s1 = hw*0.25;
Ivan Mahonin 8535a3
	double s2 = hh*0.5;
Ivan Mahonin deef1d
	double ss = s1 < s2 ? s1 : s2;
Ivan Mahonin deef1d
	textSize(ss);
Ivan Mahonin deef1d
	textAlign(HALIGN_LEFT, VALIGN_BOTTOM);
Ivan Mahonin deef1d
	text(buf, 0.1*ss - hw, hh - 0.1*ss);
Ivan Mahonin 3954ba
	
Ivan Mahonin deef1d
	restoreState();
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 6eadb0
void heliSpriteDraw(Sprite s) {
Ivan Mahonin deef1d
	double w = 0.5*s->scale*s->width;
Ivan Mahonin deef1d
	double h = 0.5*s->scale*s->height;
Ivan Mahonin deef1d
	if (w < HELI_PRECISION || h < HELI_PRECISION) return;
Ivan Mahonin deef1d
	w *= s->mirrorX;
Ivan Mahonin deef1d
	h *= s->mirrorY;
Ivan Mahonin 8535a3
	
Ivan Mahonin deef1d
	unsigned int texid = s->animation ? animationGetGLTexId(s->animation) : 0u;
Ivan Mahonin a20939
	double color[4] = {
Ivan Mahonin a20939
		(texid ? 1.0 : s->shapeColor[0])*s->tintColor[0],
Ivan Mahonin a20939
		(texid ? 1.0 : s->shapeColor[1])*s->tintColor[1],
Ivan Mahonin a20939
		(texid ? 1.0 : s->shapeColor[2])*s->tintColor[2],
Ivan Mahonin a20939
		(texid ? 1.0 : s->shapeColor[3])*s->tintColor[3] };
Ivan Mahonin a20939
	if (color[3] < HELI_PRECISION) return;
Ivan Mahonin deef1d
Ivan Mahonin deef1d
	saveState();
Ivan Mahonin deef1d
	translate(s->x, s->y);
Ivan Mahonin deef1d
	rotate(s->rotation);
Ivan Mahonin deef1d
	noStroke();
Ivan Mahonin d4e89f
	fill(colorByRGBA(color[0], color[1], color[2], color[3]));
Ivan Mahonin f8dca4
	rectTextured(s->animation, -w, -h, 2*w, 2*h);
Ivan Mahonin deef1d
	restoreState();
Ivan Mahonin 8535a3
}
Ivan Mahonin 8535a3
Ivan Mahonin 44355f
void heliSpriteSort(HeliArray *sprites) {
Ivan Mahonin 3f9996
	int found = TRUE;
Ivan Mahonin 3f9996
	while(found) {
Ivan Mahonin 3f9996
		found = FALSE;
Ivan Mahonin 8535a3
		// forward
Ivan Mahonin 44355f
		for(int i = 1; i < sprites->count; ++i) {
Ivan Mahonin 44355f
			if ( ((Sprite)sprites->items[i-1].value)->depth
Ivan Mahonin 44355f
			   < ((Sprite)sprites->items[i  ].value)->depth )
Ivan Mahonin 07b70f
			{
Ivan Mahonin 44355f
				void *x = sprites->items[i].value;
Ivan Mahonin 44355f
				sprites->items[i].value = sprites->items[i-1].value;
Ivan Mahonin 44355f
				sprites->items[i-1].value = x;
Ivan Mahonin 3f9996
				found = TRUE;
Ivan Mahonin 3f9996
			}
Ivan Mahonin 3f9996
		}
Ivan Mahonin 8535a3
		if (!found) break;
Ivan Mahonin 8535a3
		// backward
Ivan Mahonin 8535a3
		found = FALSE;
Ivan Mahonin 44355f
		for(int i = sprites->count - 1; i > 0; --i) {
Ivan Mahonin 44355f
			if ( ((Sprite)sprites->items[i-1].value)->depth
Ivan Mahonin 44355f
			   < ((Sprite)sprites->items[i  ].value)->depth )
Ivan Mahonin 07b70f
			{
Ivan Mahonin 44355f
				void *x = sprites->items[i].value;
Ivan Mahonin 44355f
				sprites->items[i].value = sprites->items[i-1].value;
Ivan Mahonin 44355f
				sprites->items[i-1].value = x;
Ivan Mahonin 07b70f
				found = TRUE;
Ivan Mahonin 8535a3
			}
Ivan Mahonin 8535a3
		}
Ivan Mahonin 3f9996
	}
Ivan Mahonin 44355f
}
Ivan Mahonin 44355f
Ivan Mahonin 6eadb0
Ivan Mahonin 6eadb0
void spriteDraw(Sprite sprite) {
Ivan Mahonin 6eadb0
	if (sprite->visible) heliSpriteDraw(sprite);
Ivan Mahonin 6eadb0
	if (sprite->debug) heliSpriteDrawDebug(sprite);
Ivan Mahonin 6eadb0
}
Ivan Mahonin 6eadb0
Ivan Mahonin 6eadb0
Ivan Mahonin 44355f
void drawSprites() {
Ivan Mahonin 44355f
	heliSpriteSort(&spritesSorted);
Ivan Mahonin a20939
	for(int i = 0; i < spritesSorted.count; ++i) {
Ivan Mahonin a20939
		Sprite s = (Sprite)(spritesSorted.items[i].value);
Ivan Mahonin 6eadb0
		if (s->visible) heliSpriteDraw(s);
Ivan Mahonin a20939
	}
Ivan Mahonin a20939
	for(int i = 0; i < spritesSorted.count; ++i) {
Ivan Mahonin a20939
		Sprite s = (Sprite)(spritesSorted.items[i].value);
Ivan Mahonin 6eadb0
		if (s->debug) heliSpriteDrawDebug(s);
Ivan Mahonin 3f9996
	}
Ivan Mahonin 3f9996
}
Ivan Mahonin 3f9996
Ivan Mahonin 07b70f
void heliSpriteUpdate(double dt) {
Ivan Mahonin 8535a3
	// auto-remove
Ivan Mahonin 83acad
	for(int i = sprites.count - 1; i >= 0; --i) {
Ivan Mahonin 83acad
		if (i < sprites.count) {
Ivan Mahonin 83acad
			Sprite s = (Sprite)sprites.items[i].value;
Ivan Mahonin 83acad
			if (s->frozen) continue;
Ivan Mahonin 83acad
			if (s->lifeTime >= -HELI_PRECISION) {
Ivan Mahonin 83acad
				s->lifeTime -= dt;
Ivan Mahonin 83acad
				if (s->lifeTime <= HELI_PRECISION)
Ivan Mahonin 83acad
					s->lifeTime = 0;
Ivan Mahonin 83acad
			}
Ivan Mahonin 83acad
		}
Ivan Mahonin 83acad
	}
Ivan Mahonin 83acad
	for(int i = sprites.count - 1; i >= 0; --i) {
Ivan Mahonin 83acad
		if (i < sprites.count) {
Ivan Mahonin 83acad
			Sprite s = (Sprite)sprites.items[i].value;
Ivan Mahonin 83acad
			if (s->lifeTime == 0) spriteDestroy(s);
Ivan Mahonin 8535a3
		}
Ivan Mahonin 8535a3
	}
Ivan Mahonin 8535a3
	
Ivan Mahonin 8535a3
	// update
Ivan Mahonin 8535a3
	for(int i = 0; i < sprites.count; ++i) {
Ivan Mahonin 8535a3
		Sprite s = (Sprite)sprites.items[i].value;
Ivan Mahonin 6eadb0
		if (s->frozen) continue;
Ivan Mahonin f80a0a
		double vx = s->vx + s->ax*dt;
Ivan Mahonin f80a0a
		double vy = s->vy + s->ay*dt;
Ivan Mahonin f80a0a
		
Ivan Mahonin f80a0a
		double weight = spriteGetTouchWeight(s);
Ivan Mahonin f80a0a
		double dvf = fabs(weight*s->friction*s->touchFriction)*dt;
Ivan Mahonin f80a0a
		if (dvf > HELI_PRECISION) {
Ivan Mahonin f80a0a
			double nx = s->wx/weight;
Ivan Mahonin f80a0a
			double ny = s->wy/weight;
Ivan Mahonin f80a0a
			double vb = nx*vx + ny*vy;
Ivan Mahonin f80a0a
			double vs = ny*vx - nx*vy;
Ivan Mahonin f80a0a
			if (vs >  dvf + HELI_PRECISION) vs -= dvf; else
Ivan Mahonin f80a0a
			if (vs < -dvf - HELI_PRECISION) vs += dvf; else vs = 0;
Ivan Mahonin f80a0a
			vx = nx*vb + ny*vs;
Ivan Mahonin f80a0a
			vy = ny*vb - nx*vs;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
		
Ivan Mahonin f80a0a
		double dvaf = fabs(s->airFriction)*dt;
Ivan Mahonin f80a0a
		if (dvaf > HELI_PRECISION) {
Ivan Mahonin f80a0a
			double v = sqrt(vx*vx + vy*vy), vn = v;
Ivan Mahonin f80a0a
			if (v >  dvaf + HELI_PRECISION) vn -= dvaf; else
Ivan Mahonin f80a0a
			if (v < -dvaf - HELI_PRECISION) vn += dvaf; else vn = 0;
Ivan Mahonin f80a0a
			double k = vn > HELI_PRECISION ? vn/v : 0;
Ivan Mahonin f80a0a
			vx *= k;
Ivan Mahonin f80a0a
			vy *= k;
Ivan Mahonin f80a0a
		}
Ivan Mahonin f80a0a
		
Ivan Mahonin f80a0a
		s->vx = vx;
Ivan Mahonin f80a0a
		s->vy = vy;
Ivan Mahonin f80a0a
		autoRotate(s);
Ivan Mahonin f80a0a
		spriteResetTouch(s);
Ivan Mahonin f80a0a
		
Ivan Mahonin 3f9996
		s->x += s->vx*dt;
Ivan Mahonin 3f9996
		s->y += s->vy*dt;
Ivan Mahonin 8535a3
		if (!s->rotateToDirection)
Ivan Mahonin 8535a3
			s->rotation += s->rotationSpeed*dt;
Ivan Mahonin 3f9996
	}
Ivan Mahonin 3f9996
}
Ivan Mahonin 8535a3
Ivan Mahonin 8535a3
HeliArray* heliSpriteGetGroups(Sprite sprite)
Ivan Mahonin 8535a3
	{ return &sprite->groups; }
Ivan Mahonin 07b70f
Ivan Mahonin 07b70f
void heliSpriteFinish() {
Ivan Mahonin 07b70f
	while(worldGetSpriteCount())
Ivan Mahonin 07b70f
		{ spriteDestroy(worldGetSprite(0)); }
Ivan Mahonin 07b70f
	heliArrayDestroy(&sprites);
Ivan Mahonin 07b70f
	heliArrayDestroy(&spritesSorted);
Ivan Mahonin 07b70f
}
Ivan Mahonin 07b70f
Ivan Mahonin 07b70f